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
+ *     &lt;input type="text" &gt; 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
+            &lt;input type="submit"/&gt; 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!");
+               });
+       });
+
 });

Reply via email to