Search code examples
javascriptgwtjsni

GWT: Can Java method be called from external JavaScript instead of JSNI?


I'm trying to move most of my native JavaScript code out of JSNI methods and into scripts, and just leveraging the native JSNI methods to call those external methods.

Right now I'm having difficulties with one of my click handlers. When the user clicks a particular element, a JSNI method does some JQuery-based animation, and then calls a Java method in the callback. A simple example is this:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
    $wnd.jQuery("#theElement").click(function() {
        // some JQuery animation logic here...
        $wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() {
            [email protected]::doSomething()();
        });
        // some other code here...
    });
}-*/;

This code works. It compiles and works as expected. I want to move this into an external JavaScript. I tried the following. I put this in the external JavaScript:

function attachClickAction(customPanel) {
    $("#theElement").click(function() {
        // other stuff...
        $("#theElement").animate({ top: "500px" }, 500, function() {
            [email protected]::doSomething()();
        });
        // other stuff...
    });
}

And modified the native function like this:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
    $wnd.attachClickAction(customPanel);
}-*/;

But is incorrect. The JavaScript file won't even load because this is not correct JavaScript. (Chome's dev tools give me the error message "Uncaught SyntaxError: Unexpected identifier".)

Is there a way to call a Java method from an external JavaScript file, not from a JSNI method?

I'm in GWT 2.4, if it matters.


Solution

  • The answer is no, you cannot call Java methods explicitly from the external JavaScript function.

    However, you can be clever and take advantage of the fact that JavaScript allows you to pass functions themselves as parameters.

    I modified my JavaScript function like so:

    function attachClickAction(callbackFunction) {
        $("#theElement").click(function() {
            // other stuff...
            $("#theElement").animate({ top: "500px" }, 500, callbackFunction);
        // other stuff...
        });
    }
    

    And in my Java code I explicitly passed the Java method as a callback function parameter:

    public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
        $wnd.attachClickAction(function() {
            [email protected]::doSomething()();
        });
    }-*/;
    

    This way, when the JSNI method compiles, it correctly calls the doSomething() Java method, and that method call is correctly passed in its entirety to the external JavaScript function.