Hooking a GWT event onto an element in an external iframe

273 views
Skip to first unread message

tin

unread,
Jul 16, 2009, 7:27:07 PM7/16/09
to Google Web Toolkit


Hi everyone,

I am writing a GWT app that involves interacting with an external
document in an iframe. As a proof of concept, I am trying to attach a
click handler to a button.

The following works in javascript

var iframe = document.getElementById("rawJSIFrame");
var doc = iframe.contentDocument;
var body = doc.body;
var button = doc.getElementsByTagName("input").namedItem("submit");
button.onclick = function() {
alert("Clicked!");
};

Trying to do the equivalent in GWT, I did the following:

public void addClickHandlerToSubmitButton(String buttonElementName,
ClickHandler clickHandler) {
IFrameElement iframe = IFrameElement.as(frame.getElement());
Document frameDocument = getIFrameDocument(iframe);
if (frameDocument != null) {
Element buttonElement = finder(frameDocument).tag("input").name
(buttonElementName).findOne();
ElementWrapper wrapper = new ElementWrapper(buttonElement);
HandlerRegistration handlerRegistration =
wrapper.addClickHandler(clickHandler);
}
}

private native Document getIFrameDocument(IFrameElement iframe)/*-{
return iframe.contentDocument;
}-*/;


The following is the ElementWrapper class:

public class ElementWrapper extends Widget implements HasClickHandlers
{

public ElementWrapper(Element theElement) {
setElement(theElement);
}

public HandlerRegistration addClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}


}

The code to find the button works fine but the actual click event
handler is not getting invoked. Has anybody had a similar issue
before, and how did you resolve it?

Thanks in advance,

Tin

Mat Gessel

unread,
Jul 19, 2009, 10:11:10 PM7/19/09
to Google-We...@googlegroups.com
Hi Tin,

There is a potential for memory leaks via event listeners due to
cyclical references between DOM and JS. To avoid this, GWT manages the
event listeners via the Widget lifecycle. When the widget is attached
to the DOM (i.e. it or it's ancestor is attached to a RootPanel) the
widget's event listener is initialized. When the widget is detached
(or the page is unloaded) the event listener is cleaned up. You can
see the code in Widget.onAttach() and Widget.onDetach().

I'd say it is erroneous to use Widget outside of the normal Widget
containment hierarchy. Instead, we can set an event listener directly:

DOM.setEventListener(buttonElement, new EventListener()
{
// you will only get the events you sink
void onBrowserEvent(Event event)
{
// references in this method can result in a memory leak
Window.alert("GWT-hacky-clicked!");
}
});

// connect the foreign element to the GWT event dispatcher
DOM.sinkEvents(buttonElement, Event.ONCLICK);

Also consider adding a Window CloseHandler to prevent the memory leak.
Window.addCloseHandler(new CloseHandler<Window>() {
public void onClose(CloseEvent<Window> event)
{
DOM.setEventListener(buttonElement, null);
}
});

You can also look at HandlerManager and DomEvent.fireNativeEvent() to
see how to translate Event into a ClickEvent, but IMO that is
overkill.

-= Mat

tin

unread,
Jul 20, 2009, 7:07:34 PM7/20/09
to Google Web Toolkit
Hi Mat,

Thanks for your reply. That was really helpful.

Tin



On Jul 20, 2:11 pm, Mat Gessel <mat.ges...@gmail.com> wrote:
> HiTin,
Reply all
Reply to author
Forward
0 new messages