PopupPanel is a class within GWT written (akhem) a long time ago (which is why it sucks so much) that allows for showing popups with content. One of the options is autoHide where if there’s a certain event outside of the popup it closes the popup. It works well on anything EXCEPT Safari Mobil (SM). Reason is SM doesn’t fire click events on touch. It fires touch events. PopupPanel is hard coded to look for ClickEvents.
Specifically, the code says:
case Event.ONMOUSEDOWN:
...
if (!eventTargetsPopupOrPartner && autoHide) {
hide(true);
...
Obviously this isn’t complete and it should also include Event.ONTOUCHSTART
Problem is, all the methods and fields are private so I cannot add this functionality. That’s a big boo-boo on the part of GWT team but not really a concern since I could just make my own class and copy contents of PopupPanel. The big problem is that nativeEventPreview doesn’t capture Touch Events!
I tried adding the following to Event Preview the following:
private static NativePreviewHandler nativePreviewHandler = new NativePreviewHandler() {
public void onPreviewNativeEvent(NativePreviewEvent event) {
Event nativeEvent = Event.as(event.getNativeEvent());
switch (nativeEvent.getTypeInt()) {
case Event.ONTOUCHSTART:
case Event.ONMOUSEDOWN:
EventTarget target = nativeEvent.getEventTarget();
if (!Element.is(target) || !popup.getElement().isOrHasChild(Element.as(target))) {
popup.hide();
} break;
}
}
};
Where ‘popup’ is the PopupPanel I’m trying to get to close on outside touch events.
Sad thing is it works for mouse down when testing in any other browser on Earth, but not on iPad.
Another thing I tried was adding a TouchStartHandler to the glass of the PopupPanel (the gray looking thing behind it). I war hoping that I could catch the touch events that way, but I was unable to get events to fire on glass since it’s attached to DOM in some funny way. My code:
private static class ProperPopupPanel extends PopupPanel {
public ProperPopupPanel() {
super();
}
void setHideOnGlassTouch() {
setGlassEnabled(true);
TouchableLabeThatDoesntCrashOnWrap glass = new TouchableLabeThatDoesntCrashOnWrap(getGlassElement());
glass.addTouchStartHandler(new TouchStartHandler() {
@Override
public void onTouchStart(TouchStartEvent event) {
hide();
}
});
glass.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
hide();
}
});
}
private class TouchableLabeThatDoesntCrashOnWrap extends Label {
public TouchableLabeThatDoesntCrashOnWrap(Element element) {
super(element);
super.onAttach();
}
}
}
In my mind this should work, but it doesn’t. I don’t know why. Any ideas or suggestions are welcome. Thanks.
Not enough GWT users here… well I made my own class that adds touch handlers through JSNI …