Repository: wicket Updated Branches: refs/heads/master 2ec1b5524 -> 55b4cc937
WICKET-6067 Provide an Ajax Behavior that prevents form submit on ENTER Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/7fa6b469 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/7fa6b469 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/7fa6b469 Branch: refs/heads/master Commit: 7fa6b4695e0ca8fa54a36f0c2d349e3a4e1507fe Parents: 2ec1b55 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Sun Jan 10 22:24:17 2016 +0100 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Sun Jan 10 22:25:29 2016 +0100 ---------------------------------------------------------------------- .../wicket/ajax/AjaxPreventSubmitBehavior.java | 66 ++++++++++++++++++++ .../wicket/examples/ajax/builtin/FormPage.html | 19 +++++- .../wicket/examples/ajax/builtin/FormPage.java | 51 ++++++++++++--- .../src/main/webapp/js-test/lib/gym.js | 6 +- .../src/main/webapp/js-test/tests/ajax/form.js | 43 +++++++++++-- 5 files changed, 168 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/7fa6b469/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxPreventSubmitBehavior.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxPreventSubmitBehavior.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxPreventSubmitBehavior.java new file mode 100644 index 0000000..410c7dc --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxPreventSubmitBehavior.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.ajax; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.attributes.AjaxCallListener; +import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; +import org.apache.wicket.markup.html.form.TextField; + +/** + * <p> + * An Ajax behavior that could be used to prevent the form submit + * when the user presses the <em>ENTER</em> key while in an HTML + * <input type="text" > field. + * </p> + * <p> + * The behavior could be applied to a {@link TextField} or to a parent + * container that will apply this behavior to all children of type HTMLInputElement. + * </p> + * <p> + * This Ajax behavior is client-side only, i.e. it never fires an Ajax call to the server. + * </p> + */ +public class AjaxPreventSubmitBehavior extends AjaxEventBehavior { + + /** + * Constructor. + */ + public AjaxPreventSubmitBehavior() { + super("keydown"); + } + + @Override + protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) { + super.updateAjaxAttributes(attributes); + + Component component = getComponent(); + if (component instanceof TextField<?> == false) + { + attributes.setChildSelector("input"); + } + + AjaxCallListener listener = new AjaxCallListener(); + listener.onPrecondition("if (Wicket.Event.keyCode(attrs.event) === 13) {attrs.event.preventDefault();} return false;"); + attributes.getAjaxCallListeners().add(listener); + } + + @Override + protected final void onEvent(final AjaxRequestTarget target) { + // never called + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/7fa6b469/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.html ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.html index fe8a12b..1a9a1b0 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.html +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.html @@ -9,7 +9,7 @@ <br/> <div wicket:id="feedbackErrors">[[ feedback ]]</div> - <form wicket:id="form"> + <form wicket:id="form" class="validation"> <label wicket:id="name-label">[name label]</label>: <input type="text" wicket:id="name"/> <br/><label wicket:id="email-label">[email label]</label>: <input type="text" wicket:id="email"/> <br/> @@ -17,5 +17,22 @@ </form> <div wicket:id="feedbackSuccess"></div> + + <hr/> + <p> + This form uses <em>org.apache.wicket.ajax.AjaxPreventSubmitBehavior</em> to prevent the submit event + when <em>ENTER</em> key is pressed.<br/> + Without this special behavior the browser will trigger the <em>submit</em> JavaScript event on the first + <input type="submit"/> form element. + </p> + <form wicket:id="preventEnterForm" class="preventEnter"> + <label wicket:id="name-label">[name label]</label>: <input type="text" wicket:id="name"/> + <br/><label wicket:id="email-label">[email label]</label>: <input type="text" wicket:id="email"/> + <br/> + <input type="submit" value="Submit"/> + <br/> + </form> + + </wicket:extend> </html> http://git-wip-us.apache.org/repos/asf/wicket/blob/7fa6b469/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.java ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.java index a018d6a..e9d7405 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FormPage.java @@ -16,6 +16,7 @@ */ package org.apache.wicket.examples.ajax.builtin; +import org.apache.wicket.ajax.AjaxPreventSubmitBehavior; import org.apache.wicket.ajax.form.AjaxFormValidatingBehavior; import org.apache.wicket.feedback.ExactLevelFeedbackMessageFilter; import org.apache.wicket.feedback.FeedbackMessage; @@ -56,8 +57,14 @@ public class FormPage extends BasePage add(feedbackSuccess); // add form with markup id setter so it can be updated via ajax + addInstantValidationForm(); + + addPreventEnterSubmitForm(); + } + + private void addPreventEnterSubmitForm() { Bean bean = new Bean(); - Form<Bean> form = new Form<Bean>("form", new CompoundPropertyModel<>(bean)) + Form<Bean> form = new Form<Bean>("preventEnterForm", new CompoundPropertyModel<>(bean)) { @Override protected void onSubmit() @@ -66,18 +73,48 @@ public class FormPage extends BasePage info("Form successfully submitted!"); } }; - + + add(form); + form.setOutputMarkupId(true); + + addFormComponents(form); + + form.add(new AjaxPreventSubmitBehavior()); + } + + private void addInstantValidationForm() { + Bean bean = new Bean(); + Form<Bean> form = new Form<Bean>("form", new CompoundPropertyModel<>(bean)) + { + @Override + protected void onSubmit() + { + super.onSubmit(); + info("Form successfully submitted!"); + } + }; + add(form); form.setOutputMarkupId(true); - FormComponent fc; + addFormComponents(form); + + // attach an ajax validation behavior to all form component's keydown + // event and throttle it down to once per second + + form.add(new AjaxFormValidatingBehavior("keydown", Duration.ONE_SECOND)); + } - // add form components to the form as usual + private void addFormComponents(final Form<Bean> form) { - fc = new RequiredTextField<>("name"); + FormComponent<String> fc = new RequiredTextField<>("name"); fc.add(new StringValidator(4, null)); fc.setLabel(new ResourceModel("label.name")); + // add AjaxPreventSubmitBehavior to the text field if it mustn't submit + // the form when ENTER is pressed +// fc.add(new AjaxPreventSubmitBehavior()); + form.add(fc); form.add(new SimpleFormComponentLabel("name-label", fc)); @@ -88,10 +125,6 @@ public class FormPage extends BasePage form.add(fc); form.add(new SimpleFormComponentLabel("email-label", fc)); - // attach an ajax validation behavior to all form component's keydown - // event and throttle it down to once per second - - form.add(new AjaxFormValidatingBehavior("keydown", Duration.ONE_SECOND)); } /** simple java bean. */ http://git-wip-us.apache.org/repos/asf/wicket/blob/7fa6b469/wicket-examples/src/main/webapp/js-test/lib/gym.js ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/webapp/js-test/lib/gym.js b/wicket-examples/src/main/webapp/js-test/lib/gym.js index 15fbc53..ccabe9e 100644 --- a/wicket-examples/src/main/webapp/js-test/lib/gym.js +++ b/wicket-examples/src/main/webapp/js-test/lib/gym.js @@ -81,11 +81,11 @@ /** * Triggers an JS event on element and waits for an Ajax response * - * @param eventName The name of the JS event + * @param event {String | jQuery.Event } The event (name) * @param $el The target element * @returns A promise that will be fulfilled when the Ajax call returns */ - var ajaxEvent = function(eventName, $el) { + var ajaxEvent = function(event, $el) { var deferred = $.Deferred(); var iframeWindow = _getIframe()[0].contentWindow; @@ -93,7 +93,7 @@ deferred.resolve($$); }); - $el.trigger(eventName); + $el.trigger(event); return deferred.promise(); } http://git-wip-us.apache.org/repos/asf/wicket/blob/7fa6b469/wicket-examples/src/main/webapp/js-test/tests/ajax/form.js ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/webapp/js-test/tests/ajax/form.js b/wicket-examples/src/main/webapp/js-test/tests/ajax/form.js index 4393fa5..94d4d97 100644 --- a/wicket-examples/src/main/webapp/js-test/tests/ajax/form.js +++ b/wicket-examples/src/main/webapp/js-test/tests/ajax/form.js @@ -16,21 +16,22 @@ */ /*global module: true, ok: true, asyncTest: true, equal: true, expect: true, $q: true, - gym: true, start: true */ + gym: true, start: true, notOk: true */ $q(document).ready(function() { "use strict"; module('Ajax'); - asyncTest('successful ajax form submit', function () { + asyncTest('ajax form validation', function () { expect(6); var $nameInput, $emailInput; gym.load('/ajax/form').then(function($) { - $nameInput = $('input[name="p::name"]'); - $emailInput = $('input[name=email]'); + var $form = $('form.validation'); + $nameInput = $('input[name="p::name"]', $form); + $emailInput = $('input[name=email]', $form); // enter just the name field $nameInput.focus(); @@ -71,4 +72,38 @@ $q(document).ready(function() { }).always(start); }); + asyncTest('Prevent ajax form submit on ENTER key', function () { + expect(2); + + var $nameInput, $emailInput; + + gym.load('/ajax/form').then(function($) { + + var $form = $('form.preventEnter'); + $nameInput = $('input[name="p::name"]', $form); + $emailInput = $('input[name=email]', $form); + + // enter just the name field + $nameInput.focus(); + var name = 'abcdef'; + $nameInput.val(name); + + var evt = $q.Event("keydown"); + evt.keyCode = evt.which = 13; // ENTER key + var prevented = false; + evt.preventDefault = function() {prevented = true;}; + evt.isDefaultPrevented = function() {return prevented;}; + equal(evt.isDefaultPrevented(), false, "The JS event default behavior is not yet prevented!"); + + setTimeout(function() { + equal(evt.isDefaultPrevented(), true, "The JS event default behavior is not yet prevented!"); + start(); + }, 10); + + return gym.ajaxEvent(evt, $emailInput); + }).always(function() { + notOk(true, "Always must not be called!"); + }); + }); + });
