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);
