Fixes issue #950 "Can not select multiple items on Listbox programmatically"
Review by: tobyr, bruce (pair programmed and desk reviewed)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1006 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/DOM.java b/user/src/com/google/gwt/user/client/DOM.java
index 0f5c974..d9a0bae 100644
--- a/user/src/com/google/gwt/user/client/DOM.java
+++ b/user/src/com/google/gwt/user/client/DOM.java
@@ -244,12 +244,24 @@
}
/**
- * Creates an HTML SELECT element.
+ * Creates a single-selection HTML SELECT element. Equivalent to
+ * <pre>
+ * createSelect(false)
+ * </pre>
*
* @return the newly-created element
*/
public static Element createSelect() {
- return impl.createElement("select");
+ return DOM.createSelect(false);
+ }
+
+ /**
+ * Creates an HTML SELECT element.
+ *
+ * @return the newly-created element
+ */
+ public static Element createSelect(boolean multiple) {
+ return impl.createSelectElement(multiple);
}
/**
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImpl.java b/user/src/com/google/gwt/user/client/impl/DOMImpl.java
index 4069ab9..c6b4f88 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImpl.java
@@ -43,6 +43,14 @@
public abstract Element createInputRadioElement(String group);
+ public Element createSelectElement(boolean multiple) {
+ Element select = createElement("select");
+ if (multiple) {
+ setElementPropertyBoolean(select, "multiple", true);
+ }
+ return select;
+ }
+
public native void eventCancelBubble(Event evt, boolean cancel) /*-{
evt.cancelBubble = cancel;
}-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
index 4fd4a2f..f3094da 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
@@ -36,6 +36,18 @@
return $doc.createElement("<INPUT type='RADIO' name='" + group + "'>");
}-*/;
+ /**
+ * Supports creating a select control with the multiple attribute to work
+ * around a bug in IE6 where changing the multiple attribute in a
+ * setAttribute call can cause subsequent setSelected calls to misbehave.
+ * Although this bug is fixed in IE7, this DOMImpl specialization is used
+ * for both IE6 and IE7, but it should be harmless.
+ */
+ public native Element createSelectElement(boolean multiple) /*-{
+ var html = multiple ? "<SELECT MULTIPLE>" : "<SELECT>";
+ return $doc.createElement(html);
+ }-*/;
+
public native int eventGetMouseWheelVelocityY(Event evt) /*-{
return -evt.wheelDelta / 40;
}-*/;
diff --git a/user/src/com/google/gwt/user/client/ui/ListBox.java b/user/src/com/google/gwt/user/client/ui/ListBox.java
index 36fec34..d26b083 100644
--- a/user/src/com/google/gwt/user/client/ui/ListBox.java
+++ b/user/src/com/google/gwt/user/client/ui/ListBox.java
@@ -44,10 +44,20 @@
private ChangeListenerCollection changeListeners;
/**
- * Creates an empty list box.
+ * Creates an empty list box in single selection mode.
*/
public ListBox() {
- super(DOM.createSelect());
+ this(false);
+ }
+
+ /**
+ * Creates an empty list box. The preferred way to enable multiple selections
+ * is to use this constructor rather than {@link #setMultipleSelect(boolean)}.
+ *
+ * @param isMultipleSelect specifies if multiple selection is enabled
+ */
+ public ListBox(boolean isMultipleSelect) {
+ super(DOM.createSelect(isMultipleSelect));
sinkEvents(Event.ONCHANGE);
setStyleName("gwt-ListBox");
}
@@ -60,7 +70,8 @@
}
/**
- * Adds an item to the list box. This method has the same effect as
+ * Adds an item to the list box. This method has the same effect as
+ *
* <pre>
* addItem(item, item)
* </pre>
@@ -128,7 +139,7 @@
}
/**
- * Gets the value associated with the item at a given index.
+ * Gets the value associated with the item at a given index.
*
* @param index the index of the item to be retrieved
* @return the item's associated value
@@ -152,7 +163,8 @@
}
/**
- * Inserts an item into the list box. Has the same effect as
+ * Inserts an item into the list box. Has the same effect as
+ *
* <pre>
* insertItem(item, item, index)
* </pre>
@@ -165,7 +177,8 @@
}
/**
- * Inserts an item into the list box, specifying an initial value for the item.
+ * Inserts an item into the list box, specifying an initial value for the
+ * item.
*
* @param item the text of the item to be inserted
* @param value the item's value, to be submitted if it is part of a
@@ -253,11 +266,15 @@
}
/**
- * Sets whether this list allows multiple selections.
+ * Sets whether this list allows multiple selections. <em>NOTE: The preferred
+ * way of enabling multiple selections in a list box is by using the
+ * {@link #ListBox(boolean)} constructor. Using this method can spuriously
+ * fail on Internet Explorer 6.0.</em>
*
* @param multiple <code>true</code> to allow multiple selections
*/
public void setMultipleSelect(boolean multiple) {
+ // TODO: we can remove the above doc admonition once we address issue 1007
DOM.setElementPropertyBoolean(getElement(), "multiple", multiple);
}
diff --git a/user/test/com/google/gwt/user/client/ui/ListBoxTest.java b/user/test/com/google/gwt/user/client/ui/ListBoxTest.java
index 8ad2489..25ca950 100644
--- a/user/test/com/google/gwt/user/client/ui/ListBoxTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ListBoxTest.java
@@ -37,12 +37,31 @@
}
public void testSelection() {
- ListBox box = new ListBox();
- box.addItem("a");
- box.setSelectedIndex(-1);
- assertEquals(-1, box.getSelectedIndex());
- box.setSelectedIndex(0);
- assertEquals("a", box.getItemText(box.getSelectedIndex()));
+ {
+ ListBox box = new ListBox();
+ box.addItem("a");
+ box.setSelectedIndex(-1);
+ assertEquals(-1, box.getSelectedIndex());
+ box.setSelectedIndex(0);
+ assertEquals("a", box.getItemText(box.getSelectedIndex()));
+ }
+
+ // Testing multiple selection
+ {
+ ListBox box = new ListBox(true);
+ box.setMultipleSelect(true);
+ box.addItem("a");
+ box.addItem("b");
+ box.addItem("c");
+
+ for (int j = 0; j < box.getItemCount(); j++) {
+ box.setItemSelected(j, true);
+ }
+
+ for (int j = 0; j < box.getItemCount(); j++) {
+ assertTrue(box.isItemSelected(j));
+ }
+ }
}
public void testSetStyleNames() {