Fixing ActionCell and ButtonCell clicks outside of the Button element are ignored.
Issue: 5641
Author: hekke, jlabanca
Review at http://gwt-code-reviews.appspot.com/1371810
Review by: pdr@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9828 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/cell/client/ActionCell.java b/user/src/com/google/gwt/cell/client/ActionCell.java
index c72c63d..fec102c 100644
--- a/user/src/com/google/gwt/cell/client/ActionCell.java
+++ b/user/src/com/google/gwt/cell/client/ActionCell.java
@@ -16,6 +16,7 @@
package com.google.gwt.cell.client;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
@@ -76,7 +77,14 @@
NativeEvent event, ValueUpdater<C> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
- onEnterKeyDown(context, parent, value, event, valueUpdater);
+ EventTarget eventTarget = event.getEventTarget();
+ if (!Element.is(eventTarget)) {
+ return;
+ }
+ if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
+ // Ignore clicks that occur outside of the main element.
+ onEnterKeyDown(context, parent, value, event, valueUpdater);
+ }
}
}
diff --git a/user/src/com/google/gwt/cell/client/ButtonCell.java b/user/src/com/google/gwt/cell/client/ButtonCell.java
index cabd39e..03a56c4 100644
--- a/user/src/com/google/gwt/cell/client/ButtonCell.java
+++ b/user/src/com/google/gwt/cell/client/ButtonCell.java
@@ -16,6 +16,7 @@
package com.google.gwt.cell.client;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
@@ -48,7 +49,14 @@
NativeEvent event, ValueUpdater<String> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
- onEnterKeyDown(context, parent, value, event, valueUpdater);
+ EventTarget eventTarget = event.getEventTarget();
+ if (!Element.is(eventTarget)) {
+ return;
+ }
+ if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
+ // Ignore clicks that occur outside of the main element.
+ onEnterKeyDown(context, parent, value, event, valueUpdater);
+ }
}
}
diff --git a/user/test/com/google/gwt/cell/client/ActionCellTest.java b/user/test/com/google/gwt/cell/client/ActionCellTest.java
index 474375e..2ad8372 100644
--- a/user/test/com/google/gwt/cell/client/ActionCellTest.java
+++ b/user/test/com/google/gwt/cell/client/ActionCellTest.java
@@ -16,9 +16,7 @@
package com.google.gwt.cell.client;
import com.google.gwt.cell.client.ActionCell.Delegate;
-import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
/**
@@ -47,14 +45,22 @@
public void testOnBrowserEvent() {
MockDelegate<String> delegate = new MockDelegate<String>();
ActionCell<String> cell = new ActionCell<String>("hello", delegate);
- Element parent = Document.get().createDivElement();
- NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false,
- false, false, false);
- Context context = new Context(0, 0, DEFAULT_KEY);
- cell.onBrowserEvent(context, parent, "test", event, null);
+ NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
+ testOnBrowserEvent(cell, getExpectedInnerHtml(), event, "test", null, true);
delegate.assertLastObject("test");
}
+ /**
+ * Test that events outside of the button element are ignored.
+ */
+ public void testOnBrowserEventOutsideButton() {
+ MockDelegate<String> delegate = new MockDelegate<String>();
+ ActionCell<String> cell = new ActionCell<String>("hello", delegate);
+ NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
+ testOnBrowserEvent(cell, getExpectedInnerHtml(), event, "test", null, false);
+ delegate.assertLastObject(null);
+ }
+
@Override
protected Cell<String> createCell() {
Delegate<String> delegate = new MockDelegate<String>();
diff --git a/user/test/com/google/gwt/cell/client/ButtonCellTest.java b/user/test/com/google/gwt/cell/client/ButtonCellTest.java
index 103d98f..a4fbeef 100644
--- a/user/test/com/google/gwt/cell/client/ButtonCellTest.java
+++ b/user/test/com/google/gwt/cell/client/ButtonCellTest.java
@@ -24,11 +24,18 @@
public class ButtonCellTest extends CellTestBase<String> {
public void testOnBrowserEvent() {
- NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false,
- false, false, false);
+ NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
testOnBrowserEvent(getExpectedInnerHtml(), event, "clickme", "clickme");
}
+ /**
+ * Test that events outside of the button element are ignored.
+ */
+ public void testOnBrowserEventOutsideButton() {
+ NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
+ testOnBrowserEvent(createCell(), getExpectedInnerHtml(), event, "clickme", null, false);
+ }
+
@Override
protected Cell<String> createCell() {
return new ButtonCell();
diff --git a/user/test/com/google/gwt/cell/client/CellTestBase.java b/user/test/com/google/gwt/cell/client/CellTestBase.java
index 733b1e5..dcc851e 100644
--- a/user/test/com/google/gwt/cell/client/CellTestBase.java
+++ b/user/test/com/google/gwt/cell/client/CellTestBase.java
@@ -229,7 +229,7 @@
* Test
* {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)}
* with the specified conditions.
- *
+ *
* @param startHtml the innerHTML of the cell before the test starts
* @param event the event to fire
* @param value the cell value
@@ -237,16 +237,39 @@
* null if none expected
* @return the parent element
*/
- protected Element testOnBrowserEvent(String startHtml, NativeEvent event,
- final T value, T expectedValue) {
+ protected Element testOnBrowserEvent(String startHtml, NativeEvent event, final T value,
+ T expectedValue) {
+ return testOnBrowserEvent(createCell(), startHtml, event, value, expectedValue, true);
+ }
+
+ /**
+ * Test
+ * {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)}
+ * with the specified conditions.
+ *
+ * @param cell the cell to use
+ * @param startHtml the innerHTML of the cell before the test starts
+ * @param event the event to fire
+ * @param value the cell value
+ * @param expectedValue the expected value passed to the value updater, or
+ * null if none expected
+ * @param dispatchToFirstChild true to dispatch to the first child of the
+ * rendered parent element, if one is available
+ * @return the parent element
+ */
+ protected Element testOnBrowserEvent(final Cell<T> cell, String startHtml, NativeEvent event,
+ final T value, T expectedValue, boolean dispatchToFirstChild) {
// Setup the parent element.
final com.google.gwt.user.client.Element parent = Document.get().createDivElement().cast();
parent.setInnerHTML(startHtml);
Document.get().getBody().appendChild(parent);
// If the element has a child, use it as the event target.
- Element child = parent.getFirstChildElement();
- Element target = (child == null) ? parent : child;
+ Element target = parent;
+ if (dispatchToFirstChild) {
+ Element child = parent.getFirstChildElement();
+ target = (child == null) ? parent : child;
+ }
// Pass the event to the cell.
final MockValueUpdater valueUpdater = new MockValueUpdater();
@@ -255,13 +278,11 @@
try {
DOM.setEventListener(parent, null);
Context context = new Context(0, 0, DEFAULT_KEY);
- createCell().onBrowserEvent(context, parent, value, event,
- valueUpdater);
+ cell.onBrowserEvent(context, parent, value, event, valueUpdater);
parent.removeFromParent();
} catch (Exception e) {
// We are in an event loop, so events may not propagate out to JUnit.
- fail("An exception occured while handling the event: "
- + e.getMessage());
+ fail("An exception occured while handling the event: " + e.getMessage());
}
}
});