}
}
- private void handleClickEvent(Event event) {
+ private void handleClickEvent(Event event, Element targetTdOrTr) {
if (emitClickEvents) {
- boolean dbl = DOM.eventGetType(event) == Event.ONDBLCLICK;
- final Element tdOrTr = DOM.getParent(DOM
- .eventGetTarget(event));
+ boolean doubleClick = (DOM.eventGetType(event) == Event.ONDBLCLICK);
+
+ /* This row was clicked */
client.updateVariable(paintableId, "clickedKey", ""
+ rowKey, false);
- if (getElement() == tdOrTr.getParentElement()) {
- int childIndex = DOM
- .getChildIndex(getElement(), tdOrTr);
+
+ if (getElement() == targetTdOrTr.getParentElement()) {
+ /* A specific column was clicked */
+ int childIndex = DOM.getChildIndex(getElement(),
+ targetTdOrTr);
String colKey = null;
colKey = tHead.getHeaderCell(childIndex).getColKey();
client.updateVariable(paintableId, "clickedColKey",
colKey, false);
}
+
MouseEventDetails details = new MouseEventDetails(event);
// Note: the 'immediate' logic would need to be more
// involved (see #2104), but iscrolltable always sends
paintableId,
"clickEvent",
details.toString(),
- !(!dbl
+ !(!doubleClick
&& selectMode > Table.SELECT_MODE_NONE && immediate));
}
}
*/
@Override
public void onBrowserEvent(Event event) {
- final Element tdOrTr = DOM.getParent(DOM.eventGetTarget(event));
- if (getElement() == tdOrTr
- || getElement() == tdOrTr.getParentElement()) {
+ Element targetTdOrTr = getEventTargetTdOrTr(event);
+ if (targetTdOrTr != null) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
- handleClickEvent(event);
+ handleClickEvent(event, targetTdOrTr);
if (selectMode > Table.SELECT_MODE_NONE) {
toggleSelection();
// Note: changing the immediateness of this might
}
break;
case Event.ONDBLCLICK:
- handleClickEvent(event);
+ handleClickEvent(event, targetTdOrTr);
break;
case Event.ONCONTEXTMENU:
showContextMenu(event);
super.onBrowserEvent(event);
}
+ /**
+ * Finds the TD that the event interacts with. Returns null if the
+ * target of the event should not be handled. If the event target is
+ * the row directly this method returns the TR element instead of
+ * the TD.
+ *
+ * @param event
+ * @return TD or TR element that the event targets (the actual event
+ * target is this element or a child of it)
+ */
+ private Element getEventTargetTdOrTr(Event event) {
+ Element targetTdOrTr = null;
+
+ final Element eventTarget = DOM.eventGetTarget(event);
+ final Element eventTargetParent = DOM.getParent(eventTarget);
+ final Element eventTargetGrandParent = DOM
+ .getParent(eventTargetParent);
+
+ final Element thisTrElement = getElement();
+
+ if (eventTarget == thisTrElement) {
+ // This was a click on the TR element
+ targetTdOrTr = eventTarget;
+ // rowTarget = true;
+ } else if (thisTrElement == eventTargetParent) {
+ // Target parent is the TR, so the actual target is the TD
+ targetTdOrTr = eventTarget;
+ } else if (thisTrElement == eventTargetGrandParent) {
+ // Target grand parent is the TR, so the parent is the TD
+ targetTdOrTr = eventTargetParent;
+ } else {
+ /*
+ * This is a workaround to make Labels and Embedded in a
+ * Table clickable (see #2688). It is really not a fix as it
+ * does not work for a custom component (not extending
+ * ILabel/IEmbedded) or for read only textfields etc.
+ */
+ Element tdElement = eventTargetParent;
+ while (DOM.getParent(tdElement) != thisTrElement) {
+ tdElement = DOM.getParent(tdElement);
+ }
+
+ Element componentElement = tdElement.getFirstChildElement()
+ .getFirstChildElement().cast();
+ Widget widget = (Widget) client
+ .getPaintable(componentElement);
+ if (widget instanceof ILabel || widget instanceof IEmbedded) {
+ targetTdOrTr = tdElement;
+ }
+ }
+
+ return targetTdOrTr;
+ }
+
public void showContextMenu(Event event) {
if (enabled && actionKeys != null) {
int left = event.getClientX();
--- /dev/null
+package com.itmill.toolkit.tests.components.table;
+
+import com.itmill.toolkit.data.Item;
+import com.itmill.toolkit.event.ItemClickEvent;
+import com.itmill.toolkit.event.ItemClickEvent.ItemClickListener;
+import com.itmill.toolkit.terminal.ThemeResource;
+import com.itmill.toolkit.tests.components.TestBase;
+import com.itmill.toolkit.ui.Component;
+import com.itmill.toolkit.ui.Embedded;
+import com.itmill.toolkit.ui.Label;
+import com.itmill.toolkit.ui.Table;
+
+public class LabelEmbeddedClickThroughForTable extends TestBase {
+
+ @Override
+ protected String getDescription() {
+ return "Clicking on a Label or Embedded inside a Table should select the row in the same way that clicking on a text selects the row.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 2688;
+ }
+
+ @Override
+ protected void setup() {
+ Table table = new Table();
+ table.setSelectable(true);
+ table.addContainerProperty("Column 1", String.class, "");
+ table.addContainerProperty("Column 2", Component.class, "");
+ table.addContainerProperty("Column 3", Component.class, "");
+ table.addContainerProperty("Column 4", Component.class, "");
+
+ Item item = table.addItem("Item 1 (row 1)");
+ item.getItemProperty("Column 1").setValue("String A");
+ item.getItemProperty("Column 2").setValue(new Label("Label A"));
+ item.getItemProperty("Column 3").setValue(
+ new Label("<b>Label A</b>", Label.CONTENT_XHTML));
+ item.getItemProperty("Column 4").setValue(
+ new Embedded("An embedded image", new ThemeResource(
+ "icons/32/ok.png")));
+
+ item = table.addItem("Item 2 (row 2)");
+ item.getItemProperty("Column 1").setValue("String B");
+ item.getItemProperty("Column 2").setValue(new Label("Label B"));
+ item
+ .getItemProperty("Column 3")
+ .setValue(
+ new Label(
+ "<a href=\"http://www.itmill.com\" target=_blank>Label A</a>",
+ Label.CONTENT_XHTML));
+ item.getItemProperty("Column 4").setValue(
+ new Embedded("", new ThemeResource("icons/32/cancel.png")));
+
+ table.addListener(new ItemClickListener() {
+
+ @Override
+ public void itemClick(ItemClickEvent event) {
+ getMainWindow().showNotification(
+ "Clickevent on item " + event.getItemId()
+ + ", column: " + event.getPropertyId());
+
+ }
+
+ });
+ addComponent(table);
+ }
+
+}