You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2012/02/20 12:08:02 UTC

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

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 <mg...@apache.org>
Authored: Mon Feb 20 12:07:47 2012 +0100
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
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);