From 7f291c046c441a54dbb92ba931160eea6b103d45 Mon Sep 17 00:00:00 2001 From: Manolo Carrasco Date: Fri, 26 Aug 2011 10:42:25 +0000 Subject: [PATCH] Fix val() methods to behave identical to jquery. This could break apps. Thanks to @arny.ok for realising the issue an sending code proposals --- .../com/google/gwt/query/client/GQuery.java | 130 ++++++++++----- .../gwt/query/client/GQueryCoreTest.java | 153 +++++++++++------- 2 files changed, 189 insertions(+), 94 deletions(-) diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java index fcf40172..97489f0f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java @@ -180,6 +180,13 @@ public class GQuery implements Lazy { public static GQuery $() { return new GQuery(JsNodeArray.create()); } + + /** + * Wrap a GQuery around an existing element. + */ + public static GQuery $(Function f) { + return new GQuery(f.getElement()); + } /** * Wrap a GQuery around an existing element. @@ -469,6 +476,10 @@ public class GQuery implements Lazy { return array; }-*/; + private static native void setElementValue(Element e, String value) /*-{ + e.value = value; + }-*/; + private static native void scrollIntoViewImpl(Node n) /*-{ if (n) n.scrollIntoView() @@ -3725,56 +3736,103 @@ public class GQuery implements Lazy { * array of all values in multivalues elements use vals() * * When the first element is a radio-button and is not checked, then it looks - * for a the first checked radio-button that has the same name in the list of + * for the first checked radio-button that has the same name in the list of * matched elements. + * + * When there are not matched elements it returns null. */ public String val() { + if (isEmpty()) { + return null; + } String[] v = vals(); - return (v != null && v.length > 0) ? v[0] : ""; + return v == null ? null : v.length > 0 ? v[0] : ""; } - + + /** + * Sets the value attribute of every matched element based in the return + * value of the function evaluated for this element. + * + * NOTE: in jquery the function receives the arguments in different + * way, first index and them the actual value, but we use the normal way + * in gquery Function, first the element and second the index. + */ + public GQuery val(Function f) { + for (int i = 0; i < size(); i++){ + eq(i).val(f.f(get(i), i).toString()); + } + return this; + } + + /** + * Sets the 'value' attribute of every matched element, but + * does not set the checked flag to checkboxes or radiobuttons. + * + * If you wanted to set values in collections of checkboxes o radiobuttons + * use val(String[]) instead + */ + public GQuery val(String value) { + for (Element e : elements) { + setElementValue(e, value); + } + return this; + } + /** - * Sets the value attribute of every matched element In the case of multivalue - * elements, all values are setted for other elements, only the first value is - * considered. + * Sets the value of every matched element. + * + * There is a different behaviour depending on the element type: + *
    + *
  • select multiple: options whose value match any of the passed values will be set. + *
  • select single: the last option whose value matches any of the passed values will be set. + *
  • input radio: the last input whose value matches any of the passed values will be set. + *
  • input checkbox: inputs whose value match any of the passed values will be set. + *
  • textarea, button, and other input: value will set to a string result of joining with coma, all passed values + *
+ * + * NOTE: if you wanted call this function with just one parameter, you have to + * pass an array signature to avoid call the overloaded val(String) method: + * + * $(...).val(new String[]{"value"}); */ public GQuery val(String... values) { + String value = values.length > 0 ? values[0] : ""; + for (int i = 1; i < values.length; i++) { + value += "," + values[i]; + } for (Element e : elements) { String name = e.getNodeName(); if ("select".equalsIgnoreCase(name)) { SelectElement s = SelectElement.as(e); s.setSelectedIndex(-1); - if (values.length > 1 && s.isMultiple()) { - for (String v : values) { + for (String v : values) { + if (s.isMultiple()) { for (int i = 0, l = s.getOptions().getLength(); i < l; i++) { if (v.equals(s.getOptions().getItem(i).getValue())) { s.getOptions().getItem(i).setSelected(true); } } + } else { + s.setValue(v); } - } else { - s.setValue(values[0]); } } else if ("input".equalsIgnoreCase(name)) { InputElement ie = InputElement.as(e); String type = ie.getType(); - if ("radio".equalsIgnoreCase((type)) || "checkbox".equalsIgnoreCase(type)){ ie.setChecked(false); - for (String val : values) { - if (ie.getValue().equals(val)) { + for (String v : values) { + if (ie.getValue().equals(v)) { ie.setChecked(true); break; } } } else { - ie.setValue(values[0]); + ie.setValue(value); } - } else if ("textarea".equalsIgnoreCase(name)) { - TextAreaElement.as(e).setValue(values[0]); - } else if ("button".equalsIgnoreCase(name)) { - ButtonElement.as(e).setValue(values[0]); + } else { + setElementValue(e, value); } } return this; @@ -3804,29 +3862,29 @@ public class GQuery implements Lazy { result.set(result.length(), oe.getValue()); } } - return jsArrayToString(result); + return result.length() > 0 ? jsArrayToString(result) : null; } else if (se.getSelectedIndex() >= 0) { return new String[]{se.getOptions().getItem(se.getSelectedIndex()).getValue()}; } } else if (e.getNodeName().equalsIgnoreCase("input")) { InputElement ie = InputElement.as(e); - if ("radio".equalsIgnoreCase(ie.getType())) { - for (Element e2 : elements) { - if ("input".equalsIgnoreCase(e2.getNodeName())) { - InputElement ie2 = InputElement.as(e2); - if ("radio".equalsIgnoreCase(ie2.getType()) && ie2.isChecked() - && ie.getName().equals(ie2.getName())) { - return new String[]{ie2.getValue()}; - } - } - } - } else if ("checkbox".equalsIgnoreCase(ie.getType())) { - if (ie.isChecked()) { - return new String[]{ie.getValue()}; - } - } else { - return new String[]{ie.getValue()}; - } + return new String[]{ie.getValue()}; +// if ("radio".equalsIgnoreCase(ie.getType())) { +// for (Element e2 : elements) { +// if ("input".equalsIgnoreCase(e2.getNodeName())) { +// InputElement ie2 = InputElement.as(e2); +// if ("radio".equalsIgnoreCase(ie2.getType()) && ie2.isChecked() +// && ie.getName().equals(ie2.getName())) { +// return new String[]{ie2.getValue()}; +// } +// } +// } +// if (ie.isChecked()) { +// return new String[]{ie.getValue()}; +// } +// } else { +// return new String[]{ie.getValue()}; +// } } else if (e.getNodeName().equalsIgnoreCase("textarea")) { return new String[]{TextAreaElement.as(e).getValue()}; } else if (e.getNodeName().equalsIgnoreCase("button")) { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java index 7a308d17..163dc03d 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTest.java @@ -265,7 +265,7 @@ public class GQueryCoreTest extends GWTTestCase { $("p", e).empty(); assertHtmlEquals(expected, $(e).html()); } - + public void testInputValueMethods() { // imput text $(e).html(""); @@ -286,8 +286,8 @@ public class GQueryCoreTest extends GWTTestCase { $(e).html( ""); gq = $("select", e); - assertEquals(0, gq.vals().length); - assertEquals("", gq.val()); + assertNull(gq.vals()); + assertNull(gq.val()); $(e).html( ""); @@ -307,22 +307,24 @@ public class GQueryCoreTest extends GWTTestCase { $(e).html( "12"); gq = $("input", e); - assertEquals("v2", gq.val()); - gq.val("v1"); assertEquals("v1", gq.val()); - gq.val("v2"); - assertEquals("v2", gq.val()); + assertEquals("v2", $("input:checked", e).val()); + gq.val(new String[]{"v1"}); + assertEquals("v1", $("input:checked", e).val()); + gq.val(new String[]{"v2"}); + assertEquals("v2", $("input:checked", e).val()); // input checkbox $(e).html( "12"); gq = $("input", e); - assertEquals("", gq.val()); - gq.val("v1"); assertEquals("v1", gq.val()); + assertEquals("v2", $("input:checked", e).val()); + gq.val(new String[]{"v1"}); + assertEquals("v1", $("input:checked", e).val()); } - - public void testIssue23() { + + public void testIssue23() { $(e).html( "
12
"); $("button").click(new Function() { @@ -897,57 +899,92 @@ public class GQueryCoreTest extends GWTTestCase { assertFalse(JsUtils.truth("")); } - public void testVal(){ - //HTML code used in this test - $(e).html("" - +"" - +" check1" - +" check2" - +" check3" - +" radio1" - +" radio2" - +""); - - $("#single",e).val("Single2"); - SelectElement single = SelectElement.as($("#single",e).get(0)); - assertEquals(1, single.getSelectedIndex()); - - $("#multiple",e).val("Multiple2", "Multiple3"); - NodeListoptions = SelectElement.as($("#multiple",e).get(0)).getOptions(); - - assertEquals(false, options.getItem(0).isSelected()); - assertEquals(true, options.getItem(1).isSelected()); - assertEquals(true, options.getItem(2).isSelected()); - - $("input",e).val("check1","check2", "radio1", "radio2" ); - assertEquals(true, InputElement.as($("#check1", e).get(0)).isChecked()); - assertEquals(true, InputElement.as($("#check2", e).get(0)).isChecked()); - assertEquals(false, InputElement.as($("#check3", e).get(0)).isChecked()); - - //radio1 should not be selected - assertEquals(false, InputElement.as($("#radio1", e).get(0)).isChecked()); - //radio1 should be selected - assertEquals(true, InputElement.as($("#radio2", e).get(0)).isChecked()); - - //radio1 should not be selected - assertEquals("check1", InputElement.as($("#text", e).get(0)).getValue()); - + public void testVal_issue98() { + $(e).html("" + +"" + +"" + +"" + + +"" + + +"
" + + +" check0" + +" check1" + +" check2" + + +" radio0" + +" radio1" + +" radio2" + ); + + assertNull($().val()); + assertEquals(0, $().vals().length); + + assertEquals("original", $("#inputText", e).val()); + assertEquals("original", $("#textArea", e).val()); + assertEquals("original", $("#button", e).val()); + $("#inputText, #textArea, #button", e).val("newval"); + assertEquals("newval", $("#inputText", e).val()); + assertEquals("newval", $("#textArea", e).val()); + assertEquals("newval", $("#button", e).val()); + + assertEquals("v0", $("#selectSingle", e).val()); + assertNull($("#selectMultiple", e).val()); + $("#selectSingle, #selectMultiple", e).val("v2"); + assertEquals("v2", $("#selectSingle", e).val()); + assertEquals("v2", $("#selectMultiple", e).val()); + + assertEquals("v0", $("input[type='checkbox']", e).val()); + assertNull($("input[type='checkbox']:checked", e).val()); + // val(String) changes the value attribute, but not set it as checked + $("input[type='checkbox']", e).eq(0).val("n0"); + assertEquals("n0", $("input[type='checkbox']", e).val()); + assertNull($("input[type='checkbox']:checked", e).val()); + // val(array) set the checked property to true if the value name matches + $("input[type='checkbox']", e).val(new String[]{"n0"}); + assertEquals("n0", $("input[type='checkbox']", e).val()); + assertNotNull($("input[type='checkbox']:checked", e).val()); + + assertEquals("v0", $("input[type='radio']", e).val()); + assertNull($("input[type='radio']:checked", e).val()); + $("input[type='radio']").eq(0).val("n0"); + assertEquals("n0", $("input[type='radio']", e).val()); + assertNull($("input[type='radio']:checked", e).val()); + +// evalJQuery("$('input, select, textarea, button').val(['whatever', 'v1', 'v2'])"); + $("input, select, textarea, button").val("whatever", "v1", "v2"); + + String joinVals = "whatever,v1,v2"; + assertEquals(joinVals, $("#inputText", e).val()); + assertEquals(joinVals, $("#textArea", e).val()); + assertEquals(joinVals, $("#button", e).val()); + assertEquals("v2", $("#selectSingle", e).val()); + assertEquals("v1", $("#selectMultiple", e).vals()[0]); + assertEquals("v2", $("#selectMultiple", e).vals()[1]); + assertEquals(2, $("input[type='checkbox']:checked", e).size()); + assertEquals("v1", $("input[type='checkbox']:checked", e).eq(0).val()); + assertEquals("v2", $("input[type='checkbox']:checked", e).eq(1).val()); + assertEquals(1, $("input[type='radio']:checked", e).size()); + assertEquals("v2", $("input[type='radio']:checked", e).val()); } + public void testCheckedAttr_Issue97() { $(e).html(""); - assertEquals("", $("#cb").val()); - $("#cb").attr("checked", "checked"); - assertEquals("1", $("#cb").val()); - $("#cb").removeAttr("checked"); - assertEquals("", $("#cb").val()); + assertNull($("#cb:checked", e).val()); + $("#cb", e).attr("checked", "checked"); + assertEquals("1", $("#cb:checked", e).val()); + $("#cb", e).removeAttr("checked"); + assertNull($("#cb:checked", e).val()); } public void testWidthHeight() { -- 2.39.5