Search code examples
gwtjsni

GWT: Window.onResize() triggered in JSNI only called once


In my GWT application, I have a button to which I've attached a click handler via JSNI and jQuery. The JSNI looks something like this:

private native void attachClickActions() /*-{
    $wnd.jQuery("#theButton").click(function() {
        // ...
        $wnd.jQuery(this).animate({
            // ...
        }, 500, function() {
            @com.google.gwt.user.client.Window::onResize()();
        });
    });
}-*;

(No, we cannot do this via a ClickHandler in the Java code for various reasons which are not up for discussion.)

In essence, when the user clicks the button, a jQuery animate() is called and when it finishes, the callback function calls Window.onResize(). Pretty simple.

And it works, the first time. When the user clicks the button, the animation occurs, and the onResize is called. But all subsequent clicks do not fire the onResize action, even though the animate() function completes successfully. Any other code I put in the callback, such as alert(), happens every time the animation completes, so it's not an issue with the callback. I know that the onResize() is not called subsequent times because the animate action applies a bunch of changes to the size of the element, and when the onResize() is triggered you can see the change occur.

Why does the Window.onResize() only get called the first time, with subsequent calls ignored?


Solution

  • The reason this was happening is due to how the GWT team wrote the onResize() event in the Window class. Apparently, certain browser engines like Trident (IE) and Webkit (Chrome, Safari), there are some cases where the onResize event is triggered multiple times when it should only happen once. To handle this situation, the implementation of the onResize() method includes a check of the browser window's current size: if the size hasn't changed since the last onResize() call, it's not triggered again.

    Since I was essentially trying to call the onResize() event multiple times on a window that hadn't actually resized, this IE/Webkit "fix" was stopping the event from firing.

    Here's the actual code of the onResize() method if anyone's curious:

    static void onResize() {
        if (resizeHandlersInitialized) {
            // On webkit and IE we sometimes get duplicate window resize events.
            // Here, we manually filter them.
            int width = getClientWidth();
            int height = getClientHeight();
            if (lastResizeWidth != width || lastResizeHeight != height) {
                lastResizeWidth = width;
                lastResizeHeight = height;
                ResizeEvent.fire(getHandlers(), width, height);
            }
        }
    }