nawfel bgh
nawfel bgh

Reputation: 1552

How to run javascript code in JavaFx.WebView after the page is loaded?

i used this code

public WebMap() {
    webView = new WebView();
    final WebEngine webEngine = webView.getEngine();
    String url = getClass().getResource("map.html").toExternalForm();
    webEngine.load(url);

    final Deferred d = new Deferred();
    webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            @Override
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    d.resolve(webEngine);
                }
            }
        }
    );
    readyWebEngine = d.promise();
}

I don't call webEngine.executeScript directly but i use

readyWebEngine.then(new PromiseFunc() {
            @Override
    public Promise apply(Object oWebEngine) {
        WebEngine webEngine = (WebEngine)oWebEngine;
        webEngine.executeScript(script); // <=============================
                // return value doesn't matter
        return (new Deferred()).promise();
    }
});

So that the script string isn't evaluated until the promise is resolved (fulfilled) by the call to d.resolve()

Let's assume that the promise library is correct

The code works well for me, but a colleague of mine gets this error which is frustrating

netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng
[com.sun.webpane.platform.WebPage.twkExecuteScript(Native Method), com.sun.webpane.platform.WebPage.executeScript(WebPage.java:1438), javafx.scene.web.WebEngine.executeScript(WebEngine.java:811), packagename.WebMap.WebMap$1.apply(WebMap.java:36), packagename.WebMap.promise.Deferred$1$1.apply(Deferred.java:23), packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100), javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195), javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161), javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130), javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163), javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:975), javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1086), javafx.scene.web.WebEngine$LoadWorker.access$600(WebEngine.java:968), javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:955), com.sun.webpane.platform.WebPage.fireLoadEvent(WebPage.java:2356), com.sun.webpane.platform.WebPage.fwkFireLoadEvent(WebPage.java:2204), com.sun.webpane.webkit.network.URLLoader.twkDidFinishLoading(Native Method), com.sun.webpane.webkit.network.URLLoader.access$1300(URLLoader.java:44), com.sun.webpane.webkit.network.URLLoader$6.run(URLLoader.java:691), com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76), com.sun.glass.ui.win.WinApplication._runLoop(Native Method), com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17), com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67), java.lang.Thread.run(Thread.java:744)]

The html page containing the javascript code is well tested. Let's assume there is no javascript errors there

The error netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng doesn't occure to me because javascript code is executed after the loadWorker's newState == State.SUCCEEDED.

The probleme is that in the stack trace of my coworker's program , we can see that the WebEngine.executeScript(WebEngine.java:811) was called by

packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100), 

So, executeScript is called by the listener of the load changed event when newState == State.SUCCEEDED which means that the page is completely loaded and javascript inside s is loaded (variables should be defined).

Sorry because i don't have access to my coworker's code, but it's based on mine. Now i am not sure whether this code executes javascript code at the right moment

webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            @Override
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    webEngine.executeScript(script);
                }
            }
        }
    );

Any help?

Upvotes: 3

Views: 3412

Answers (1)

Volodymyr Gubarkov
Volodymyr Gubarkov

Reputation: 2183

How about

$(function(){
    alert("command:ready");
});

And then

engine.onAlert = new EventHandler<WebEvent<String>>() {
    @Override
    void handle(WebEvent<String> event) {
        if("command:ready".equals(event.getData())){
        //TODO: initialize
        }
    }
}

(seen here http://habrahabr.ru/company/codeorchestra/blog/198776/)

Upvotes: 4

Related Questions