reiern70 commented on code in PR #1651:
URL: https://github.com/apache/wicket/pull/1651#discussion_r4193986811


##########
wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java:
##########
@@ -551,7 +554,7 @@ public final CharSequence getJsForListenerUrl(CharSequence 
url)
                }
                buffer.append(String.format("var f = 
document.getElementById('%s');", root.getMarkupId()));
                buffer.append(String.format("f.action='%s';", action));
-               buffer.append("Wicket.Event.fire(f, 'submit');");
+               buffer.append("if (Wicket.Event.triggerSubmit(f)) { f.submit(); 
}");

Review Comment:
   `f.submit()` throws when the form contains a control named `submit`: a form 
control's name shadows the form's property, so `f.submit` is that element, not 
the method. In Wicket a control's `name` is its component path, so a button or 
field with the id `submit` directly in the form is enough (a common id; 
`AjaxFormSubmitBehaviorTest` uses it too). A `FormComponentUpdatingBehavior` 
then fails with `TypeError: f.submit is not a function` and the form is not 
submitted, with either Ajax engine. Before, the jQuery engine's `trigger()` 
only called the native method when it was a function.
   
   Suggestion: `HTMLFormElement.prototype.submit.call(f);`



##########
wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax.js:
##########
@@ -2785,6 +2785,47 @@
                        }
                },
 
+               /**
+                * Fires a submit event on the given form, so that its submit 
handlers run, without
+                * submitting the form: an Ajax request submits it instead. 
Firefox submits a form for
+                * a submit event fired by a script unless the event is 
cancelled, so the event is
+                * cancelled once the handlers on the form have run, as the 
last listener on the form.
+                *
+                * @param form {HTMLFormElement} the form
+                * @returns {boolean} false if a handler on the form, or one 
capturing the event on its
+                *      way there, cancelled the event
+                */
+               triggerSubmit: function(form) {
+                       const event = new Event('submit', { cancelable: true, 
bubbles: true });
+                       let cancelledByHandler = null;
+                       const cancel = function () {
+                               if (cancelledByHandler === null) {
+                                       cancelledByHandler = 
event.defaultPrevented;
+                                       event.preventDefault();
+                               }
+                       };
+                       const cancelOwnEvent = function (e) {
+                               if (e === event) {
+                                       cancel();
+                               }
+                       };
+                       // a handler stopping the immediate propagation keeps 
cancelOwnEvent from running
+                       const stopImmediatePropagation = 
event.stopImmediatePropagation;

Review Comment:
   Only `stopImmediatePropagation()` is covered. A capturing `submit` listener 
on an ancestor (`document`, `body`) that calls `event.stopPropagation()` 
without cancelling keeps the event from reaching the form, so `cancelOwnEvent` 
never runs and the event is never cancelled: `triggerSubmit` returns `true`, 
the Ajax request goes out, and Firefox submits the form as well, the double 
submission this PR is about. Wrapping `event.stopPropagation` the same way 
would close it (with the caveat that other listeners on that same element still 
run afterwards and could no longer cancel the request).



##########
wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js:
##########
@@ -2505,6 +2505,47 @@
                                }
                        },
 
+                       /**
+                        * Fires a submit event on the given form, so that its 
submit handlers run, without
+                        * submitting the form: an Ajax request submits it 
instead. Firefox submits a form for
+                        * a submit event fired by a script unless the event is 
cancelled, so the event is
+                        * cancelled once the handlers on the form have run, as 
the last listener on the form.
+                        *
+                        * @param form {HTMLFormElement} the form
+                        * @returns {boolean} false if a handler on the form, 
or one capturing the event on its
+                        *      way there, cancelled the event
+                        */
+                       triggerSubmit: function(form) {
+                               const event = new Event('submit', { cancelable: 
true, bubbles: true });
+                               let cancelledByHandler = null;
+                               const cancel = function () {
+                                       if (cancelledByHandler === null) {
+                                               cancelledByHandler = 
event.defaultPrevented;
+                                               event.preventDefault();
+                                       }
+                               };
+                               const cancelOwnEvent = function (e) {
+                                       if (e === event) {
+                                               cancel();
+                                       }
+                               };
+                               // a handler stopping the immediate propagation 
keeps cancelOwnEvent from running
+                               const stopImmediatePropagation = 
event.stopImmediatePropagation;

Review Comment:
   Same as in wicket-ajax.js: `stopPropagation()` by a capturing ancestor isn't 
covered, so Firefox still submits the form besides the Ajax request.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to