I have onClick event on somePanel. And I click on it and it works. But.. How to retrieve real click target? When I click on panel which is inside od somePanel it show me that I click on somePanel..
I know we have this:
Element e = Element.as( event.getNativeEvent().getEventTarget());
But i returns element - I want widget..
How to do this?
I would use the feature in gwtquery to get the widget associated with a given element: https://code.google.com/p/gwtquery/wiki/GettingStarted#Manipulating_your_widgets
Widget = $(e).widget();
The problem is that the element clicked couldn't be the element associated with the widget but a child. In this case you could use gquery selectors to traverse the dom until you get its parent widget based on some css property.
// Most gwt widgets contains a class .gwt- but this could fail
// so use a more accurate selector than the one in this example
Widget = $(e).closest("[class*='.gwt-']")
If you wanted to do it by yourself, taking a look to the method getAssociatedWidget
in GQuery
gives you the solution:
EventListener listener = DOM.getEventListener(e);
// No listener attached to the element, so no widget exist for this element
if (listener == null) {
return null;
}
if (listener instanceof Widget) {
// GWT uses the widget as event listener
return (Widget) listener;
}
EDITED: here you have a working example:
import static com.google.gwt.query.client.GQuery.*;
// A panel with some widgets
Panel panel = new VerticalPanel();
final HTML widget1 = new HTML("<span>Foo</span> <span>Bar</span");
final HTML widget2 = new HTML("<span>Foo</span> <span>Bar</span");
final HTML widget3 = new HTML("<span>Foo</span> <span>Bar</span");
panel.add(widget1);
panel.add(widget2);
panel.add(widget3);
// we need to wrap our panel with a widget supporting click events
FocusPanel wrapper = new FocusPanel();
wrapper.add(panel);
RootPanel.get().add(wrapper);
wrapper.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// The element is not the HTML widget clicked but the span element
Element e = event.getNativeEvent().getEventTarget().cast();
// Using gquery to get the closest widget to the clicked element
// We take advanrage of HTML widgets having gwt-HTML class
Widget w = $(e).closest(".gwt-HTML").widget();
if (w == widget1) {
Window.alert("Clicked on widget 1");
} else if (w == widget2) {
Window.alert("Clicked on widget 2");
} else if (w == widget3) {
Window.alert("Clicked on widget 3");
} else {
Window.alert("Clicked on a non GWT HTML widget");
}
}
});
This is an old question, but both answers are wrong. If you are using a GWT EventListener and want the widget that is the source of the event, then you simply use the event.getSource()
method of the event and cast it to the original object type.
Unless there is something that I am missing in the question here.
An alternative approach, if you already know all of the widgets that you want to check against, would be to use the DOM.isOrHasChild(Element) or Element.isOrHasChild(Node).
For example:
public void onClick(ClickEvent event) {
Element targetElem = Element.as(event.getNativeEvent().getEventTarget());
Widget targetWidget = null;
if (widgetA.getElement().isOrHasChild(targetElem) {
targetWidget = widgetA;
}
else if (widgetB.getElement().isOrHasChild(targetElem) {
targetWidget = widgetA;
}
.....
if (targetWidget != null) {
// You found you widget - Yay!
}
else {
// No widget found - Bummer!
}
}
This approach only works if you know the widgets you are testing against up front. The benefit is that you now have an particular widget reference rather then a generic reference to 'some' widget that you might have to do additional checks against.
For example, you could have done the following if widgetA was a subclass of TextBox called MySpecialTextBox:
MySpecialTextBox widgetA;
if (widgetA.getElement().isOrHasChild(targetElem) {
widgetA.someSpecialMethod();
}