Updated Branches:
  refs/heads/master e095f49f1 -> 5ea553b23

WICKET-4416 CheckGroup model in AjaxFormChoiceComponentUpdatingBehavior 
onUpdate contains only last checked item

Rework Wicket.Form.serializeXYZ methods to work with array of objects suitable 
for jQuery.param(). This way if there are several parameters with the same name 
all the values are properly serialized.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/5ea553b2
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/5ea553b2
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/5ea553b2

Branch: refs/heads/master
Commit: 5ea553b23017466c5068a7d2b5813c789095da32
Parents: e095f49
Author: Martin Tzvetanov Grigorov <[email protected]>
Authored: Mon Feb 20 12:07:47 2012 +0100
Committer: Martin Tzvetanov Grigorov <[email protected]>
Committed: Mon Feb 20 12:07:47 2012 +0100

----------------------------------------------------------------------
 .../AjaxFormChoiceComponentUpdatingBehavior.java   |   48 ++++++++----
 .../ajax/form/AjaxFormValidatingBehavior.java      |   54 ++++++++-----
 .../wicket/ajax/res/js/wicket-ajax-jquery.js       |   61 ++++++++++-----
 .../wicket/examples/ajax/builtin/FormPage.java     |    4 +-
 .../ajax/markup/html/AjaxEditableLabel.java        |    8 +-
 .../markup/html/AjaxEditableMultiLineLabel.java    |    6 +-
 6 files changed, 117 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
 
b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
index c045f95..f031417 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormChoiceComponentUpdatingBehavior.java
@@ -20,6 +20,7 @@ import org.apache.wicket.Component;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.OnLoadHeaderItem;
@@ -56,29 +57,46 @@ public abstract class 
AjaxFormChoiceComponentUpdatingBehavior extends AbstractDe
        {
                super.renderHead(component, response);
 
+               // a function that registers a click listener which dynamically
+               // extracts the currently selected checkboxes/radios on every 
click
                AppendingStringBuffer asb = new AppendingStringBuffer();
-               asb.append("function attachChoiceHandlers(markupId, attrs, 
callbackScript) {\n");
-               asb.append(" var inputNodes = 
Wicket.$(markupId).getElementsByTagName('input');\n");
-               asb.append(" for (var i = 0 ; i < inputNodes.length ; i ++) 
{\n");
-               asb.append(" var inputNode = inputNodes[i];\n");
-               asb.append(" if (!inputNode.type) continue;\n");
-               asb.append(" if 
(!(inputNode.className.indexOf('wicket-'+markupId)>=0)&&!(inputNode.id.indexOf(markupId+'-')>=0))
 continue;\n");
-               asb.append(" var inputType = inputNode.type.toLowerCase();\n");
-               asb.append(" if (inputType === 'checkbox' || inputType === 
'radio') {\n");
-               asb.append(" \tvar dataAttrs = jQuery.extend({}, attrs, {c: 
inputNode.id});\n");
-               asb.append(" \tWicket.Event.add(inputNode, 'click', 
callbackScript, dataAttrs);\n");
-               asb.append(" }\n");
-               asb.append(" }\n");
-               asb.append("}\n");
-
-               response.render(JavaScriptHeaderItem.forScript(asb, 
"attachChoice-"+component.getMarkupId()));
-
-               String onLoadScript = String.format("attachChoiceHandlers('%s', 
%s, function(event) { \n\tWicket.Ajax.ajax(event.data);\n})",
+               asb.append("function attachChoiceHandlers(markupId, attrs) 
{\n");
+               asb.append(" function getInputValues(groupId) {\n");
+               asb.append("  var result = [];\n");
+               asb.append("  var inputNodes = 
Wicket.$(groupId).getElementsByTagName('input');\n");
+               asb.append("  for (var i = 0 ; i < inputNodes.length ; i ++) 
{\n");
+               asb.append("   var inputNode = inputNodes[i];\n");
+               asb.append("   if (!inputNode.checked) continue;\n");
+               asb.append("   if (!inputNode.type) continue;\n");
+               asb.append("   if 
(!(inputNode.className.indexOf('wicket-'+markupId)>=0)&&!(inputNode.id.indexOf(markupId+'-')>=0))
 continue;\n");
+               asb.append("   var inputType = 
inputNode.type.toLowerCase();\n");
+               asb.append("   if (inputType === 'checkbox' || inputType === 
'radio') {\n");
+               asb.append("    var name = inputNode.name, value = 
inputNode.value;\n");
+               asb.append("    result.push({ name: name, value: value });\n");
+               asb.append("   }\n"); // if
+               asb.append("  }\n");  // for
+               asb.append("  return result;\n");
+               asb.append(" }\n"); // function getInputValues()
+               asb.append(" attrs.dep = [ function() { var deps = 
getInputValues(markupId); return deps; } ];\n");
+               asb.append(" Wicket.Ajax.post(attrs);\n");
+               asb.append("}\n"); // function attachChoiceHandlers()
+
+               response.render(JavaScriptHeaderItem.forScript(asb, 
"attachChoice-" + component.getMarkupId()));
+
+               String onLoadScript = String.format("attachChoiceHandlers('%s', 
%s)",
                                component.getMarkupId(), 
renderAjaxAttributes(component));
                response.render(OnLoadHeaderItem.forScript(onLoadScript));
 
        }
 
+       @Override
+       protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
+       {
+               super.updateAjaxAttributes(attributes);
+               attributes.setEventNames("click");
+               attributes.setAllowDefault(true);
+       }
+
        /**
         * Listener invoked on the ajax request. This listener is invoked after 
the component's model
         * has been updated.

http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormValidatingBehavior.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormValidatingBehavior.java
 
b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormValidatingBehavior.java
index 20a4d25..cb04abf 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormValidatingBehavior.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormValidatingBehavior.java
@@ -17,6 +17,7 @@
 package org.apache.wicket.ajax.form;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.IClusterable;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.attributes.ThrottlingSettings;
@@ -111,28 +112,41 @@ public class AjaxFormValidatingBehavior extends 
AjaxFormSubmitBehavior
        public static void addToAllFormComponents(final Form<?> form, final 
String event,
                final Duration throttleDelay)
        {
-               form.visitChildren(FormComponent.class, new IVisitor<Component, 
Void>()
+               form.visitChildren(FormComponent.class, new 
FormValidateVisitor(form, event, throttleDelay));
+       }
+       
+       private static class FormValidateVisitor implements IVisitor<Component, 
Void>, IClusterable
+       {
+               private final Form<?> form;
+               private final String event;
+               private final Duration throttleDelay;
+               
+               private FormValidateVisitor(Form<?> form, String event, 
Duration throttleDelay)
                {
-                       @Override
-                       public void component(final Component component, final 
IVisit<Void> visit)
-                       {
-                               AjaxFormValidatingBehavior behavior = new 
AjaxFormValidatingBehavior(form, event) {
-                                       @Override
-                                       protected void 
updateAjaxAttributes(AjaxRequestAttributes attributes)
-                                       {
-                                               
super.updateAjaxAttributes(attributes);
+                       this.form = form;
+                       this.event = event;
+                       this.throttleDelay = throttleDelay;
+               }
+               
+               @Override
+               public void component(final Component component, final 
IVisit<Void> visit)
+               {
+                       final AjaxFormValidatingBehavior behavior = new 
AjaxFormValidatingBehavior(form, event) {
+                               @Override
+                               protected void updateAjaxAttributes(final 
AjaxRequestAttributes attributes)
+                               {
+                                       super.updateAjaxAttributes(attributes);
 
-                                               if (throttleDelay != null)
-                                               {
-                                                       String id = "throttle-" 
+ component.getMarkupId();
-                                                       ThrottlingSettings 
throttlingSettings = new ThrottlingSettings(id, throttleDelay);
-                                                       
attributes.setThrottlingSettings(throttlingSettings);
-                                               }
+                                       if (throttleDelay != null)
+                                       {
+                                               String id = "throttle-" + 
component.getMarkupId();
+                                               ThrottlingSettings 
throttlingSettings = new ThrottlingSettings(id, throttleDelay);
+                                               
attributes.setThrottlingSettings(throttlingSettings);
                                        }
-                               };
-                               component.add(behavior);
-                               visit.dontGoDeeper();
-                       }
-               });
+                               }
+                       };
+                       component.add(behavior);
+                       visit.dontGoDeeper();
+               }
        }
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js 
b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index 4b17e62..24eae3d 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ 
b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -386,6 +386,30 @@
                },
 
                /**
+                * Converts an object (hash) to an array suitable for 
consumption
+                * by jQuery.param()
+                *
+                * @param {Object} parameters - the object to convert to an 
array of
+                *      name -> value pairs.
+                * @see jQuery.param
+                * @see jQuery.serializeArray
+                */
+               _asParamArray: function(parameters) {
+                       var result = [];
+                       if (jQuery.isArray(parameters)) {
+                               result = parameters;
+                       }
+                       else if (jQuery.isPlainObject(parameters)) {
+                               for (var name in parameters) {
+                                       var value = parameters[name];
+                                       result.push({name: name, value: value});
+                               }
+                       }
+
+                       return result;
+               },
+
+               /**
                 * Executes or schedules for execution #doAjax()
                 *
                 * @param {Object} attrs - the Ajax request attributes 
configured at the server side
@@ -414,7 +438,7 @@
                                },
 
                                // the request (extra) parameters
-                               data = attrs.ep || {},
+                               data = this._asParamArray(attrs.ep),
 
                                // keep a reference to the current context
                                self = this,
@@ -439,13 +463,14 @@
                                var deps = attrs.dep;
                                for (var i = 0; i < deps.length; i++) {
                                        var dep = deps[i],
-                                               extraParam = {};
+                                               extraParam;
                                        if (jQuery.isFunction(dep)) {
                                                extraParam = dep(attrs);
                                        } else {
                                                extraParam = new 
Function('attrs', dep)(attrs);
                                        }
-                                       data = jQuery.extend({}, data, 
extraParam);
+                                       extraParam = 
this._asParamArray(extraParam);
+                                       data = data.concat(extraParam);
                                }
                        }
 
@@ -458,22 +483,22 @@
                        if (attrs.f) {
                                // serialize the form with id == attrs.f
                                var form = Wicket.$(attrs.f);
-                               data = jQuery.extend({}, data, 
Wicket.Form.serializeForm(form));
+                               data = 
data.concat(Wicket.Form.serializeForm(form));
 
                                // set the submitting component input name
                                if (attrs.sc) {
                                        var scName = attrs.sc;
-                                       data = jQuery.extend({}, data, {scName: 
1});
+                                       data = data.concat({name: scName, 
value: 1});
                                }
 
                        } else if (attrs.c && !jQuery.isWindow(attrs.c)) {
                                // serialize just the form component with id == 
attrs.c
                                var el = Wicket.$(attrs.c);
-                               data = jQuery.extend({}, data, 
Wicket.Form.serializeElement(el));
+                               data = 
data.concat(Wicket.Form.serializeElement(el));
                        }
 
                        // convert to URL encoded string
-                       data = jQuery.param(data, true);
+                       data = jQuery.param(data);
 
                        // execute the request 
                        var jqXHR = jQuery.ajax({
@@ -1133,12 +1158,12 @@
                         *              or empty object if the form element is 
disabled.
                         */
                        serializeSelect: function (select){
-                               var result = {};
+                               var result = [];
                                if (select) {
                                        var $select = jQuery(select);
                                        if ($select.length > 0 && 
$select.prop('disabled') === false) {
                                                var name = $select.attr('name');
-                                               result[name] = $select.val();
+                                               result.push( { name: name, 
value: $select.val() } );
                                        }
                                }
                                return result;
@@ -1152,14 +1177,10 @@
                         * @return the URL encoded key=value pair or empty 
string if the form element is disabled.
                         */
                        serializeInput: function (input) {
-                               var result = {};
+                               var result = [];
                                if (input && input.type && !(input.type === 
'image' || input.type === 'submit')) { 
                                        var $input = jQuery(input);
-                                       var serialized = 
$input.serializeArray();
-                                       for (var i = 0; i < serialized.length; 
i++) {
-                                               var obj = serialized[i];
-                                               result[obj.name] = obj.value;
-                                       }
+                                       result = $input.serializeArray();
                                }
                                return result;
                        },
@@ -1172,14 +1193,14 @@
                        serializeElement: function(element) {
 
                                if (!element) {
-                                       return {};
+                                       return [];
                                }
                                else if (typeof(element) === 'string') {
                                        element = Wicket.$(element);
                                }
 
                                if (Wicket.Form.excludeFromAjaxSerialization && 
element.id && Wicket.Form.excludeFromAjaxSerialization[element.id] === "true") {
-                                       return {};
+                                       return [];
                                }
 
                                var tag = element.tagName.toLowerCase();
@@ -1188,17 +1209,17 @@
                                } else if (tag === "input" || tag === 
"textarea") {
                                        return 
Wicket.Form.serializeInput(element);
                                } else {
-                                       return {};
+                                       return [];
                                }
                        },
 
                        serializeForm: function (form) {
-                               var result = {},
+                               var result = [],
                                        elements = form.elements;
                                for (var i = 0; i < elements.length; ++i) {
                                        var el = elements[i];
                                        if (el.name && el.name !== "") {
-                                               result = jQuery.extend({}, 
result, Wicket.Form.serializeElement(el));
+                                               result = 
result.concat(Wicket.Form.serializeElement(el));
                                        }
                                }
                                return result;

http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/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 df819ac..536920b 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
@@ -74,10 +74,10 @@ 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 
onkeydown
+               // attach an ajax validation behavior to all form component's 
keydown
                // event and throttle it down to once per second
 
-               AjaxFormValidatingBehavior.addToAllFormComponents(form, 
"onkeyup", Duration.ONE_SECOND);
+               AjaxFormValidatingBehavior.addToAllFormComponents(form, 
"keydown", Duration.ONE_SECOND);
 
                // add a button that can be used to submit the form via ajax
                form.add(new AjaxButton("ajax-button", form)

http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableLabel.java
----------------------------------------------------------------------
diff --git 
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableLabel.java
 
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableLabel.java
index 1486b1d..f4430ce 100644
--- 
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableLabel.java
+++ 
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableLabel.java
@@ -314,19 +314,19 @@ public class AjaxEditableLabel<T> extends Panel
                                super.updateAjaxAttributes(attributes);
                                attributes.setEventNames("blur", "keyup");
 
-                               CharSequence dynamicExtraParameters = "var 
result = {}, "
+                               CharSequence dynamicExtraParameters = "var 
result = [], "
                                        + "kc=Wicket.Event.keyCode(event),"
                                        + "evtType=attrs.event.type;"
                                        + "if (evtType === 'keyup') {"
                                        +
                                        // ESCAPE key
-                                       "if (kc===27) { result.save = false }"
+                                       "if (kc===27) { result.push( { name: 
'save', value: false } ); }"
                                        +
 
                                        // ENTER key
-                                       "else if (kc===13) { result = 
Wicket.Form.serializeElement(attrs.c); result.save = true; }"
+                                       "else if (kc===13) { result = 
Wicket.Form.serializeElement(attrs.c); result.push( { name: 'save', value: true 
} ); }"
                                        + "}"
-                                       + "else if (evtType==='blur') { result 
= Wicket.Form.serializeElement(attrs.c); result.save = true; }"
+                                       + "else if (evtType==='blur') { result 
= Wicket.Form.serializeElement(attrs.c); result.push( { name: 'save', value: 
true } ); }"
                                        + "return result;";
                                
attributes.getDynamicExtraParameters().add(dynamicExtraParameters);
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/5ea553b2/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableMultiLineLabel.java
----------------------------------------------------------------------
diff --git 
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableMultiLineLabel.java
 
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableMultiLineLabel.java
index 3f67447..1556e11 100644
--- 
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableMultiLineLabel.java
+++ 
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxEditableMultiLineLabel.java
@@ -182,14 +182,14 @@ public class AjaxEditableMultiLineLabel<T> extends 
AjaxEditableLabel<T>
                                attributes.setMethod(Method.POST);
                                attributes.setEventNames("blur", "keyup");
                                CharSequence dynamicExtraParameters =
-                                               "var result = {}, " +
+                                               "var result = [], " +
                                                                
"kc=Wicket.Event.keyCode(event)," +
                                                                
"evtType=attrs.event.type;" +
                                                                "if (evtType 
=== 'keyup') {" +
                                                                        // 
ESCAPE key
-                                                                       "if 
(kc===27) { result.save = false }" +
+                                                                       "if 
(kc===27) { result.push( { name: 'save', value: false } ); }" +
                                                                "}" +
-                                                               "else if 
(evtType==='blur') { result = Wicket.Form.serializeElement(attrs.c); 
result.save = true; }" +
+                                                               "else if 
(evtType==='blur') { result = Wicket.Form.serializeElement(attrs.c); 
result.push( { name: 'save', value: true } ); }" +
                                                                "return 
result;";
                                List<CharSequence> dynamicParameters = 
attributes.getDynamicExtraParameters();
                                dynamicParameters.add(dynamicExtraParameters);

Reply via email to