Author: hlship
Date: Tue Jul  5 18:30:49 2011
New Revision: 1143161

URL: http://svn.apache.org/viewvc?rev=1143161&view=rev
Log:
TAP5-1451: Form component should indicate that a form submission was canceled 
on the client side

Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/SubmitMode.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
 Tue Jul  5 18:30:49 2011
@@ -48,14 +48,14 @@ public class EventConstants
 
     /**
      * Invoked before {@link #PREPARE} when rendering out the form.
-     * 
+     *
      * @see org.apache.tapestry5.corelib.components.Form
      */
     public static final String PREPARE_FOR_RENDER = "prepareForRender";
 
     /**
      * Invoked before {@link #PREPARE} when the form is submitted.
-     * 
+     *
      * @see org.apache.tapestry5.corelib.components.Form
      */
     public static final String PREPARE_FOR_SUBMIT = "prepareForSubmit";
@@ -63,7 +63,7 @@ public class EventConstants
     /**
      * Invoked to let the containing component(s) prepare for the form 
rendering or the form
      * submission.
-     * 
+     *
      * @see org.apache.tapestry5.corelib.components.Form
      */
     public static final String PREPARE = "prepare";
@@ -72,14 +72,17 @@ public class EventConstants
      * Event type for a notification after the form has submitted. This event 
notification occurs on
      * any form submit,
      * without respect to "success" or "failure".
-     * 
+     *
      * @see org.apache.tapestry5.corelib.components.Form
      */
     public static final String SUBMIT = "submit";
 
     /**
-     * Event type associated with clicking the cancel button inside a {@link 
BeanEditForm}.
-     * 
+     * Event triggered when a client-side form is canceled. This occurs after 
page activation, and after
+     * the prepare events for the form, but before any stored {@link 
ComponentAction}s for the form are triggered.
+     *
+     * @see org.apache.tapestry5.corelib.SubmitMode#CANCEL
+     *
      * @since 5.2.0
      */
     public static final String CANCELED = "canceled";
@@ -88,7 +91,7 @@ public class EventConstants
      * Event type for a notification after the form has submitted, when there 
are no errors in the
      * validation tracker.
      * This occurs before the {@link #SUBMIT} event.
-     * 
+     *
      * @see org.apache.tapestry5.corelib.components.Form
      */
     public static final String SUCCESS = "success";
@@ -148,7 +151,7 @@ public class EventConstants
      * all the values that were supplied from the client during a form 
submission. The event handler
      * method should have
      * a single parameter, of type Object[] or type List, to receive the 
values.
-     * 
+     *
      * @since 5.1.0.0
      */
     public static final String SYNCHRONIZE_VALUES = "synchronizeValues";
@@ -158,7 +161,7 @@ public class EventConstants
      * container of what context (if any) is available. The event handler may 
return a renderable
      * object or null. If
      * null is returned, the component renders its own body as the partial 
markup response.
-     * 
+     *
      * @since 5.1.0.1
      */
     public static final String PROGRESSIVE_DISPLAY = "progressiveDisplay";
@@ -167,7 +170,7 @@ public class EventConstants
      * Event triggered by an {@link 
org.apache.tapestry5.corelib.mixins.Autocomplete} mixin to
      * request completions of
      * the current input. The context is the partial string provided by the 
client.
-     * 
+     *
      * @since 5.1.0.4
      */
     public static final String PROVIDE_COMPLETIONS = "provideCompletions";
@@ -176,7 +179,7 @@ public class EventConstants
      * Event triggered by {@link 
org.apache.tapestry5.corelib.components.Select} component to inform
      * its
      * container that Select's value has changed.
-     * 
+     *
      * @since 5.2.0
      */
     public static final String VALUE_CHANGED = "valueChanged";
@@ -185,7 +188,7 @@ public class EventConstants
      * Event triggered during page render link generation. The first context 
parameter is the {@link Link} object, the
      * second is the {@link PageRenderRequestParameters} from which the Link
      * was created. The event is triggered on the actively rendering page.
-     * 
+     *
      * @since 5.2.0
      */
     public static final String DECORATE_PAGE_RENDER_LINK = 
"decoratePageRenderLink";
@@ -195,7 +198,7 @@ public class EventConstants
      * the second is the {@link ComponentEventRequestParameters} from which 
the Link
      * was created. The event is triggered on the actively rendering page, not 
necessarily the page
      * containing the component.
-     * 
+     *
      * @since 5.2.0
      */
     public static final String DECORATE_COMPONENT_EVENT_LINK = 
"decorateComponentEventLink";
@@ -204,7 +207,7 @@ public class EventConstants
      * Name of a event triggered by the form component on the {@linkplain 
ComponentSource#getActivePage() active page}
      * to allow it to pre-allocate the names of any query parameters that 
might be used by the page for its own purposes
      * and should not be allocated to components. An {@link IdAllocator} is 
passed as the event context.
-     * 
+     *
      * @since 5.2.0
      */
     public static final String PREALLOCATE_FORM_CONTROL_NAMES = 
"preallocateFormControlNames";
@@ -218,19 +221,18 @@ public class EventConstants
     public static final String NODE_SELECTED = "nodeSelected";
 
     /**
-     *  Event  triggered by the {@link 
org.apache.tapestry5.corelib.components.Tree}
-     *  component when a leaf node is unselected.
+     * Event  triggered by the {@link 
org.apache.tapestry5.corelib.components.Tree}
+     * component when a leaf node is unselected.
      *
-     *  @since 5.3
+     * @since 5.3
      */
     public static final String NODE_UNSELECTED = "nodeUnselected";
-    
+
     /**
-     * Event triggered by {@link 
org.apache.tapestry5.corelib.mixins.ZoneRefresh ZoneRefresh} to refresh the 
+     * Event triggered by {@link 
org.apache.tapestry5.corelib.mixins.ZoneRefresh ZoneRefresh} to refresh the
      * {@link org.apache.tapestry5.corelib.components.Zone Zone}
-     * 
+     *
      * @since 5.3
      */
-   public static final String REFRESH = "refresh";
-
+    public static final String REFRESH = "refresh";
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/SubmitMode.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/SubmitMode.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/SubmitMode.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/SubmitMode.java
 Tue Jul  5 18:30:49 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2011 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -20,16 +20,19 @@ import org.apache.tapestry5.corelib.comp
 
 /**
  * Defines the client and server-side behavior of a {@link Submit} or {@link 
LinkSubmit} component.
- * 
+ *
  * @since 5.2.0
  */
 public enum SubmitMode
 {
-    /** Submit the form normally, with full validation on the client and 
server side. */
+    /**
+     * Submit the form normally, with full validation on the client and server 
side.
+     */
     NORMAL,
 
     /**
-     * Cancel the form; bypass client-side form validation. Validation still 
occurs
+     * Cancel the form; bypass client-side form validation. Fires the {@link 
EventConstants#CANCELED} event.
+     * If the event handler for that event allows the submission to proceed, 
then server-side validation still occurs
      * on the server, though generally the data is discarded by the event 
listener
      * (listening to the Submit component's {@link EventConstants#SELECTED} 
event).
      */

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
 Tue Jul  5 18:30:49 2011
@@ -14,21 +14,8 @@
 
 package org.apache.tapestry5.corelib.components;
 
-import java.io.IOException;
-
-import org.apache.tapestry5.BindingConstants;
-import org.apache.tapestry5.ClientElement;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventConstants;
-import org.apache.tapestry5.Field;
-import org.apache.tapestry5.FormValidationControl;
-import org.apache.tapestry5.TrackableComponentEventCallback;
-import org.apache.tapestry5.annotations.Component;
-import org.apache.tapestry5.annotations.Environmental;
-import org.apache.tapestry5.annotations.Events;
-import org.apache.tapestry5.annotations.Parameter;
-import org.apache.tapestry5.annotations.Property;
-import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.*;
+import org.apache.tapestry5.annotations.*;
 import org.apache.tapestry5.beaneditor.BeanModel;
 import org.apache.tapestry5.internal.beaneditor.BeanModelUtils;
 import org.apache.tapestry5.ioc.annotations.Inject;
@@ -49,12 +36,12 @@ import org.apache.tapestry5.services.Bea
  * <p/>
  * BeanEditForm contains a {@link 
org.apache.tapestry5.corelib.components.Form} component and will trigger all the
  * events of a Form.
- * 
+ *
+ * @tapestrydoc
  * @see org.apache.tapestry5.beaneditor.BeanModel
  * @see org.apache.tapestry5.services.BeanModelSource
  * @see org.apache.tapestry5.corelib.components.PropertyEditor
  * @see org.apache.tapestry5.beaneditor.DataType
- * @tapestrydoc
  * @see Form
  * @see Errors
  * @see BeanEditor
@@ -124,7 +111,7 @@ public class BeanEditForm implements Cli
      * If set to true, then the form will include an additional button after 
the submit button labeled "Cancel".
      * The cancel button will submit the form, bypassing client-side 
validation. The BeanEditForm will fire a
      * {@link EventConstants#CANCELED} event (before the form's {@link 
EventConstants#VALIDATE} event).
-     * 
+     *
      * @since 5.2.0
      */
     @Property
@@ -147,10 +134,6 @@ public class BeanEditForm implements Cli
     @Inject
     private BeanModelSource beanModelSource;
 
-    @SuppressWarnings("unchecked")
-    @Environmental
-    private TrackableComponentEventCallback eventCallback;
-
     boolean onPrepareFromForm()
     {
         resources.triggerEvent(EventConstants.PREPARE, null, null);
@@ -199,13 +182,4 @@ public class BeanEditForm implements Cli
     {
         form.recordError(errorMessage);
     }
-
-    boolean onSelectedFromCancel() throws IOException
-    {
-        resources.triggerEvent(EventConstants.CANCELED, null, eventCallback);
-
-        // Prevent further event handlers.
-
-        return true;
-    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
 Tue Jul  5 18:30:49 2011
@@ -14,48 +14,15 @@
 
 package org.apache.tapestry5.corelib.components;
 
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-
-import org.apache.tapestry5.BindingConstants;
-import org.apache.tapestry5.CSSClassConstants;
-import org.apache.tapestry5.ClientElement;
-import org.apache.tapestry5.ComponentAction;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventConstants;
-import org.apache.tapestry5.EventContext;
-import org.apache.tapestry5.Field;
-import org.apache.tapestry5.FormValidationControl;
-import org.apache.tapestry5.Link;
-import org.apache.tapestry5.MarkupConstants;
-import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.PersistenceConstants;
-import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.TrackableComponentEventCallback;
-import org.apache.tapestry5.ValidationDecorator;
-import org.apache.tapestry5.ValidationException;
-import org.apache.tapestry5.ValidationTracker;
-import org.apache.tapestry5.ValidationTrackerImpl;
-import org.apache.tapestry5.ValidationTrackerWrapper;
-import org.apache.tapestry5.annotations.Environmental;
-import org.apache.tapestry5.annotations.Events;
-import org.apache.tapestry5.annotations.HeartbeatDeferred;
-import org.apache.tapestry5.annotations.Log;
-import org.apache.tapestry5.annotations.Mixin;
-import org.apache.tapestry5.annotations.OnEvent;
-import org.apache.tapestry5.annotations.Parameter;
-import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.*;
+import org.apache.tapestry5.annotations.*;
 import org.apache.tapestry5.corelib.ClientValidation;
 import org.apache.tapestry5.corelib.internal.ComponentActionSink;
 import org.apache.tapestry5.corelib.internal.FormSupportImpl;
 import org.apache.tapestry5.corelib.internal.InternalFormSupport;
 import org.apache.tapestry5.corelib.mixins.RenderInformals;
 import org.apache.tapestry5.dom.Element;
-import org.apache.tapestry5.internal.BeanValidationContext;
-import org.apache.tapestry5.internal.BeanValidationContextImpl;
-import org.apache.tapestry5.internal.InternalSymbols;
-import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.*;
 import org.apache.tapestry5.internal.services.HeartbeatImpl;
 import org.apache.tapestry5.internal.util.AutofocusValidationDecorator;
 import org.apache.tapestry5.ioc.Location;
@@ -66,39 +33,52 @@ import org.apache.tapestry5.ioc.internal
 import org.apache.tapestry5.ioc.internal.util.TapestryException;
 import org.apache.tapestry5.ioc.util.ExceptionUtils;
 import org.apache.tapestry5.ioc.util.IdAllocator;
+import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.runtime.Component;
-import org.apache.tapestry5.services.ClientBehaviorSupport;
-import org.apache.tapestry5.services.ClientDataEncoder;
-import org.apache.tapestry5.services.ComponentSource;
-import org.apache.tapestry5.services.Environment;
-import org.apache.tapestry5.services.FormSupport;
-import org.apache.tapestry5.services.Heartbeat;
-import org.apache.tapestry5.services.Request;
+import org.apache.tapestry5.services.*;
 import org.apache.tapestry5.services.javascript.InitializationPriority;
 import org.apache.tapestry5.services.javascript.JavaScriptSupport;
 import org.slf4j.Logger;
 
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
 /**
  * An HTML form, which will enclose other components to render out the various
  * types of fields.
- * <p/>
+ * <p>
  * A Form emits many notification events. When it renders, it fires a
  * {@link org.apache.tapestry5.EventConstants#PREPARE_FOR_RENDER} 
notification, followed by a
- * {@link EventConstants#PREPARE} notification.
- * <p/>
+ * {@link EventConstants#PREPARE} notification.</p>
+ * <p>
  * When the form is submitted, the component emits several notifications: 
first a
  * {@link EventConstants#PREPARE_FOR_SUBMIT}, then a {@link 
EventConstants#PREPARE}: these allow the page to update its
- * state as necessary to prepare for the form submission, then (after 
components enclosed by the form have operated), a
- * {@link EventConstants#VALIDATE} event is emitted, to allow for cross-form 
validation. After that, either a
+ * state as necessary to prepare for the form submission.</p>
+ * <p>
+ * The Form component determines if the form was cancelled (see {@link 
org.apache.tapestry5.corelib.SubmitMode#CANCEL}. If so,
+ * an {@link EventConstants#CANCELED} event is emitted.</p>
+ * <p>
+ * Next come notifications to contained components (or more accurately, the 
execution of stored {@link ComponentAction}s), to allow each component to 
retrieve and validate
+ * submitted values, and update server-side properties.  This is based on the 
{@code t:formdata} query parameter,
+ * which contains serialized object data (generated when the form initially 
renders).
+ * </p>
+ * <p>Once the form data is processed, the next step is to emit the
+ * {@link EventConstants#VALIDATE}, which allows for cross-form validation. 
After that, either a
  * {@link EventConstants#SUCCESS} OR {@link EventConstants#FAILURE} event 
(depending on whether the
  * {@link ValidationTracker} has recorded any errors). Lastly, a {@link 
EventConstants#SUBMIT} event, for any listeners
- * that care only about form submission, regardless of success or failure.
- * <p/>
- * For all of these notifications, the event context is derived from the 
<strong>context</strong> parameter. This
+ * that care only about form submission, regardless of success or failure.</p>
+ * <p>
+ * For all of these notifications, the event context is derived from the 
<strong>context</strong> component parameter. This
  * context is encoded into the form's action URI (the parameter is not read 
when the form is submitted, instead the
  * values encoded into the form are used).
- * 
+ * </p>
+ * <p>
+ * While rendering, or processing a Form submission, the Form component places 
a {@link FormSupport} object into the {@linkplain Environment environment},
+ * so that enclosed components can coordinate with the Form component.
+ * </p>
+ *
  * @tapestrydoc
  * @see BeanEditForm
  * @see Errors
@@ -106,8 +86,8 @@ import org.slf4j.Logger;
  * @see Label
  */
 @Events(
-{ EventConstants.PREPARE_FOR_RENDER, EventConstants.PREPARE, 
EventConstants.PREPARE_FOR_SUBMIT,
-        EventConstants.VALIDATE, EventConstants.SUBMIT, 
EventConstants.FAILURE, EventConstants.SUCCESS })
+        {EventConstants.PREPARE_FOR_RENDER, EventConstants.PREPARE, 
EventConstants.PREPARE_FOR_SUBMIT,
+                EventConstants.VALIDATE, EventConstants.SUBMIT, 
EventConstants.FAILURE, EventConstants.SUCCESS})
 public class Form implements ClientElement, FormValidationControl
 {
     /**
@@ -119,7 +99,8 @@ public class Form implements ClientEleme
     /**
      * Used by {@link Submit}, etc., to identify which particular client-side 
element (by element id)
      * was responsible for the submission. An empty hidden field is created, 
as needed, to store this value.
-     * 
+     * Starting in Tapestry 5.3, this is a JSONArray with two values: the 
client id followed by the client name.
+     *
      * @since 5.2.0
      */
     public static final String SUBMITTING_ELEMENT_ID = "t:submit";
@@ -162,7 +143,7 @@ public class Form implements ClientEleme
      * cursor into the form. The field to
      * receive focus is the first rendered field that is in error, or required,
      * or present (in that order of priority).
-     * 
+     *
      * @see SymbolConstants#FORM_CLIENT_LOGIC_ENABLED
      */
     @Parameter
@@ -190,7 +171,7 @@ public class Form implements ClientEleme
      * Prefix value used when searching for validation messages and 
constraints.
      * The default is the Form component's
      * id. This is overridden by {@link 
org.apache.tapestry5.corelib.components.BeanEditForm}.
-     * 
+     *
      * @see org.apache.tapestry5.services.FormSupport#getFormValidationId()
      */
     @Parameter
@@ -289,10 +270,10 @@ public class Form implements ClientEleme
      * persistent field and be stored into the session). This means that if no 
errors are recorded,
      * the tracker parameter is not updated and (in the default case) no data 
is stored into the
      * session.
-     * 
-     * @see <a 
href="https://issues.apache.org/jira/browse/TAP5-979";>TAP5-979</a>
+     *
      * @return a tracker ready to receive data (possibly a previously stored 
tracker with field
      *         input and errors)
+     * @see <a 
href="https://issues.apache.org/jira/browse/TAP5-979";>TAP5-979</a>
      */
     private ValidationTracker getWrappedTracker()
     {
@@ -442,23 +423,23 @@ public class Form implements ClientEleme
      * Creates an {@link 
org.apache.tapestry5.corelib.internal.InternalFormSupport} for
      * this Form. This method is used
      * by {@link org.apache.tapestry5.corelib.components.FormInjector}.
-     * <p>
+     * <p/>
      * This method may also be invoked as the handler for the 
"internalCreateRenderTimeFormSupport" event.
-     * 
+     *
      * @param clientId
-     *            the client-side id for the rendered form
-     *            element
+     *         the client-side id for the rendered form
+     *         element
      * @param actionSink
-     *            used to collect component actions that will, ultimately, be
-     *            written as the t:formdata hidden
-     *            field
+     *         used to collect component actions that will, ultimately, be
+     *         written as the t:formdata hidden
+     *         field
      * @param allocator
-     *            used to allocate unique ids
+     *         used to allocate unique ids
      * @return form support object
      */
     @OnEvent("internalCreateRenderTimeFormSupport")
     InternalFormSupport createRenderTimeFormSupport(String clientId, 
ComponentActionSink actionSink,
-            IdAllocator allocator)
+                                                    IdAllocator allocator)
     {
         return new FormSupportImpl(resources, clientId, actionSink, 
clientBehaviorSupport,
                 clientValidation != ClientValidation.NONE, allocator, 
validationId);
@@ -497,7 +478,7 @@ public class Form implements ClientEleme
     }
 
     @SuppressWarnings(
-    { "unchecked", "InfiniteLoopStatement" })
+            {"unchecked", "InfiniteLoopStatement"})
     @Log
     Object onAction(EventContext context) throws IOException
     {
@@ -525,6 +506,14 @@ public class Form implements ClientEleme
 
             resources.triggerContextEvent(EventConstants.PREPARE, context, 
eventCallback);
 
+            if (isFormCancelled())
+            {
+                resources.triggerContextEvent(EventConstants.CANCELED, 
context, eventCallback);
+                if (eventCallback.isAborted())
+                    return true;
+            }
+
+
             environment.push(BeanValidationContext.class, new 
BeanValidationContextImpl(validate));
 
             if (eventCallback.isAborted())
@@ -565,8 +554,7 @@ public class Form implements ClientEleme
             resources.triggerContextEvent(EventConstants.SUBMIT, context, 
eventCallback);
 
             return eventCallback.isAborted();
-        }
-        finally
+        } finally
         {
             environment.pop(Heartbeat.class);
             environment.pop(FormSupport.class);
@@ -579,13 +567,39 @@ public class Form implements ClientEleme
         }
     }
 
+    private boolean isFormCancelled()
+    {
+        // The "cancel" query parameter is reserved for this purpose; if it is 
present then the form was canceled on the
+        // client side.  For image submits, there will be two parameters: 
"cancel.x" and "cancel.y".
+
+        if (request.getParameter(InternalConstants.CANCEL_NAME) != null ||
+                request.getParameter(InternalConstants.CANCEL_NAME + ".x") != 
null)
+        {
+            return true;
+        }
+
+        // When JavaScript is involved, it's more complicated. In fact, this 
is part of HLS's desire
+        // to have all forms submit via XHR when JavaScript is present, since 
it would provide
+        // an opportunity to get the submitting element's value into the 
request properly.
+
+        String raw = request.getParameter(SUBMITTING_ELEMENT_ID);
+
+        if (raw != null &&
+                new 
JSONArray(raw).getString(1).equals(InternalConstants.CANCEL_NAME))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+
     private void fireValidateEvent(String eventName, EventContext context, 
TrackableComponentEventCallback callback)
     {
         try
         {
             resources.triggerContextEvent(eventName, context, callback);
-        }
-        catch (RuntimeException ex)
+        } catch (RuntimeException ex)
         {
             ValidationException ve = ExceptionUtils.findCause(ex, 
ValidationException.class);
 
@@ -645,18 +659,15 @@ public class Form implements ClientEleme
 
                     component = null;
                 }
-            }
-            catch (EOFException ex)
+            } catch (EOFException ex)
             {
                 // Expected
-            }
-            catch (Exception ex)
+            } catch (Exception ex)
             {
                 Location location = component == null ? null : 
component.getComponentResources().getLocation();
 
                 throw new TapestryException(ex.getMessage(), location, ex);
-            }
-            finally
+            } finally
             {
                 InternalUtils.close(ois);
             }
@@ -732,9 +743,8 @@ public class Form implements ClientEleme
         {
 
             
activePageResources.triggerEvent(EventConstants.PREALLOCATE_FORM_CONTROL_NAMES, 
new Object[]
-            { idAllocator }, null);
-        }
-        catch (RuntimeException ex)
+                    {idAllocator}, null);
+        } catch (RuntimeException ex)
         {
             logger.error(
                     String.format("Unable to obtrain form control names to 
preallocate: %s",

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
 Tue Jul  5 18:30:49 2011
@@ -14,19 +14,14 @@
 
 package org.apache.tapestry5.corelib.components;
 
-import org.apache.tapestry5.BindingConstants;
-import org.apache.tapestry5.ClientElement;
-import org.apache.tapestry5.ComponentAction;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventConstants;
-import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.TrackableComponentEventCallback;
+import org.apache.tapestry5.*;
 import org.apache.tapestry5.annotations.Environmental;
 import org.apache.tapestry5.annotations.Events;
 import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.annotations.SupportsInformalParameters;
 import org.apache.tapestry5.corelib.SubmitMode;
 import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.FormSupport;
 import org.apache.tapestry5.services.Heartbeat;
@@ -38,7 +33,7 @@ import org.apache.tapestry5.services.jav
  * Generates a client-side hyperlink that submits the enclosing form. If the 
link is clicked in the browser, the
  * component will trigger an event ({@linkplain EventConstants#SELECTED 
selected} by default) , just like {@link Submit}
  * .
- * 
+ *
  * @tapestrydoc
  */
 @SupportsInformalParameters
@@ -62,7 +57,7 @@ public class LinkSubmit implements Clien
      * Defines the mode, or client-side behavior, for the submit. The default 
is {@link SubmitMode#NORMAL}; clicking the
      * button submits the form with validation. {@link SubmitMode#CANCEL} 
indicates the client-side validation
      * should be omitted (though server-side validation still occurs).
-     * 
+     *
      * @since 5.2.0
      */
     @Parameter(allowNull = false, defaultPrefix = BindingConstants.LITERAL)
@@ -80,7 +75,7 @@ public class LinkSubmit implements Clien
     /**
      * The list of values that will be made available to event handler method 
of this component when the form is
      * submitted.
-     * 
+     *
      * @since 5.2.0
      */
     @Parameter
@@ -126,7 +121,9 @@ public class LinkSubmit implements Clien
     {
         this.clientId = clientId;
 
-        if (clientId.equals(request.getParameter(Form.SUBMITTING_ELEMENT_ID)))
+        String raw = request.getParameter(Form.SUBMITTING_ELEMENT_ID);
+
+        if (raw != null && new JSONArray(raw).getString(0).equals(clientId))
         {
             Runnable notification = new Runnable()
             {
@@ -153,7 +150,7 @@ public class LinkSubmit implements Clien
 
             writer.element("span",
 
-            "id", clientId);
+                    "id", clientId);
 
             resources.renderInformalParameters(writer);
         }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
 Tue Jul  5 18:30:49 2011
@@ -20,8 +20,9 @@ import org.apache.tapestry5.annotations.
 import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.annotations.SupportsInformalParameters;
 import org.apache.tapestry5.corelib.SubmitMode;
-import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.internal.InternalConstants;
 import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.services.FormSupport;
 import org.apache.tapestry5.services.Heartbeat;
 import org.apache.tapestry5.services.Request;
@@ -31,7 +32,7 @@ import org.apache.tapestry5.services.jav
  * Corresponds to &lt;input type="submit"&gt; or &lt;input type="image"&gt;, a 
client-side element that can force the
  * enclosing form to submit. The submit responsible for the form submission 
will post a notification that allows the
  * application to know that it was the responsible entity. The notification is 
named "selected" and has no context.
- * 
+ *
  * @tapestrydoc
  */
 @SupportsInformalParameters
@@ -64,7 +65,7 @@ public class Submit implements ClientEle
     /**
      * The list of values that will be made available to event handler method 
of this component when the form is
      * submitted.
-     * 
+     *
      * @since 5.1.0.0
      */
     @Parameter
@@ -72,7 +73,7 @@ public class Submit implements ClientEle
 
     /**
      * If provided, the component renders an input tag with type "image". 
Otherwise "submit".
-     * 
+     *
      * @since 5.1.0.0
      */
     @Parameter(defaultPrefix = BindingConstants.ASSET)
@@ -82,7 +83,7 @@ public class Submit implements ClientEle
      * Defines the mode, or client-side behavior, for the submit. The default 
is {@link SubmitMode#NORMAL}; clicking the
      * button submits the form with validation. {@link SubmitMode#CANCEL} 
indicates the client-side validation
      * should be omitted (though server-side validation still occurs).
-     * 
+     *
      * @since 5.2.0
      */
     @Parameter(allowNull = false, defaultPrefix = BindingConstants.LITERAL)
@@ -138,7 +139,11 @@ public class Submit implements ClientEle
     {
         clientId = javascriptSupport.allocateClientId(resources);
 
-        String name = formSupport.allocateControlName(resources.getId());
+        boolean isCancel = mode == SubmitMode.CANCEL;
+
+        String name =
+                isCancel ? InternalConstants.CANCEL_NAME :
+                        formSupport.allocateControlName(resources.getId());
 
         // Save the element, to see if an id is later requested.
 
@@ -146,29 +151,36 @@ public class Submit implements ClientEle
 
         writer.element("input",
 
-        "type", type,
+                "type", type,
 
-        "name", name,
+                "name", name,
 
-        "id", clientId);
+                "id", clientId);
 
         if (disabled)
+        {
             writer.attributes("disabled", "disabled");
+        }
 
         if (image != null)
+        {
             writer.attributes("src", image.toClientURL());
+        }
 
         formSupport.store(this, new ProcessSubmission(clientId, name));
 
         resources.renderInformalParameters(writer);
+
+        if (isCancel)
+        {
+            javascriptSupport.addInitializerCall("cancelButton", 
getClientId());
+        }
+
     }
 
     void afterRender(MarkupWriter writer)
     {
         writer.end();
-
-        if (mode == SubmitMode.CANCEL)
-            javascriptSupport.addInitializerCall("cancelButton", 
getClientId());
     }
 
     void processSubmission(String clientId, String elementName)
@@ -199,8 +211,13 @@ public class Submit implements ClientEle
     {
         // Case #1: via JavaScript, the client id is passed up.
 
-        if (clientId.equals(request.getParameter(Form.SUBMITTING_ELEMENT_ID)))
+        String raw = request.getParameter(Form.SUBMITTING_ELEMENT_ID);
+
+        if (raw != null &&
+                new JSONArray(raw).getString(0).equals(clientId))
+        {
             return true;
+        }
 
         // Case #2: No JavaScript, look for normal semantic (non-null value 
for the element's name).
         // If configured as an image submit, look for a value for the x 
position. Ah, the ugliness
@@ -215,7 +232,7 @@ public class Submit implements ClientEle
 
     /**
      * Returns the component's client id. This must be called after the 
component has rendered.
-     * 
+     *
      * @return client id for the component
      */
     public String getClientId()

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
 Tue Jul  5 18:30:49 2011
@@ -92,21 +92,21 @@ public final class InternalConstants
      * useful when the code opening the response stream wants to explicitly 
control whether GZIP
      * compression occurs or
      * not.
-     * 
+     *
      * @since 5.1.0.0
      */
     public static final String SUPPRESS_COMPRESSION = 
"tapestry.supress-compression";
 
     /**
      * Name of response header for content encoding.
-     * 
+     *
      * @since 5.1.0.0
      */
     public static final String CONTENT_ENCODING_HEADER = "Content-Encoding";
 
     /**
      * Response content encoding value indicating use of GZIP compression.
-     * 
+     *
      * @since 5.1.0.0
      */
     public static final String GZIP_CONTENT_ENCODING = "gzip";
@@ -128,16 +128,24 @@ public final class InternalConstants
     /**
      * Name of the core {@link JavaScriptStack}, which supplies the basic 
JavaScript infrastructure
      * on the client.
-     * 
+     *
      * @since 5.2.0
      */
     public static final String CORE_STACK_NAME = "core";
 
     /**
      * The names of the standard controlled subpackages.
-     * 
+     *
      * @since 5.3
      */
     public static final String[] SUBPACKAGES =
-    { PAGES_SUBPACKAGE, COMPONENTS_SUBPACKAGE, MIXINS_SUBPACKAGE, 
BASE_SUBPACKAGE };
+            {PAGES_SUBPACKAGE, COMPONENTS_SUBPACKAGE, MIXINS_SUBPACKAGE, 
BASE_SUBPACKAGE};
+
+    /**
+     * The element name for a submit input element used to cancel the form 
(rather than
+     * submit it normally).
+     *
+     * @since 5.3
+     */
+    public static final String CANCEL_NAME = "cancel";
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 Tue Jul  5 18:30:49 2011
@@ -2377,7 +2377,7 @@ public final class TapestryModule
 
         configuration.add(SymbolConstants.BLACKBIRD_ENABLED, false);
 
-        configuration.add(InternalSymbols.PRE_SELECTED_FORM_NAMES, 
"reset,submit,select,id,method,action,onsubmit");
+        configuration.add(InternalSymbols.PRE_SELECTED_FORM_NAMES, 
"reset,submit,select,id,method,action,onsubmit," + 
InternalConstants.CANCEL_NAME);
 
         configuration.add(SymbolConstants.COMPONENT_RENDER_TRACING_ENABLED, 
false);
 

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.tml?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.tml
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanEditForm.tml
 Tue Jul  5 18:30:49 2011
@@ -1,5 +1,5 @@
 <form t:id="form" validate="object"
-      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";>
     <t:errors/>
 
     <div class="t-beaneditor">

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 Tue Jul  5 18:30:49 2011
@@ -1550,7 +1550,7 @@ Tapestry.FormEventManager = Class.create
                                this.submitHidden = hiddens.first();
                }
 
-               this.submitHidden.value = element == null ? null : 
$(element).id;
+               this.submitHidden.value = element == null ? null : 
Object.toJSON([$(element).id, $(element).name]);
        },
 
        handleSubmit : function(domevent) {

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java?rev=1143161&r1=1143160&r2=1143161&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java
 Tue Jul  5 18:30:49 2011
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008, 2010 The Apache Software Foundation
+// Copyright 2007, 2008, 2010, 2011 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public class SubmitTest extends Internal
 
         // Also: test for the alternate, JavaScript oriented way, of 
determining the
         // element/component that triggered the submission.
-        train_getParameter(request, Form.SUBMITTING_ELEMENT_ID, "xyz");
+        train_getParameter(request, Form.SUBMITTING_ELEMENT_ID, "[ 'xyz', 
'pdq' ]");
 
         replay();
 


Reply via email to