JavaFX webview window.onload started before loadworker succeeds

I am using JavaFX webview in my application. With the following code I am setting the element after the page has loaded

webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
    @Override
    public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
        if (newState == Worker.State.SUCCEEDED) {
            JSObject window = (JSObject) webEngine.executeScript("window");
            window.setMember("mymember", new JavaScriptBridge(this));
        }
    }
});

      

Now in javascript I can call mymember.doSomething()

eg. when i click the button and it succeeds, but if i add the following code to html

<script>
function startup() {
    mymember.doSomething();
}
window.onload=startup;
</script>

      

It does not run automatically on page load. Seems to be window.onload

running before notification LoadWorker

. So it mymember

's not installed yet. But on the other hand, I cannot install mymember

before the html has been loaded, right?

Any idea when I need to install mymember

so that it is ready when executed window.onload

?

Thank!

0


source to share


1 answer


It may be too late to answer this problem, but after answering this question, I was trying to find the reason why it executeScript

should be after the web page has fully loaded.

So, I did this test:

    public class EarlyWebEngineTest extends Application {

    @Override
    public void start(Stage stage) {
        final WebView webView = new WebView();
        final WebEngine webEngine = webView.getEngine();

        // Early call of executeScript to get a JavaScript object, a proxy for the 
        // Java object to be accessed on the JavaScript environment
        JSObject window = (JSObject) webEngine.executeScript("window");
        window.setMember("app", new JavaApplication());

        webEngine.getLoadWorker().stateProperty().addListener((ov,oldState,newState)->{
            if(newState==State.SCHEDULED){
                System.out.println("state: scheduled");
            } else if(newState==State.RUNNING){
                System.out.println("state: running");
            } else if(newState==State.SUCCEEDED){
                System.out.println("state: succeeded");
            }
        });

        Button button=new Button("Load Content");
        button.setOnAction(e->webEngine.loadContent("<html>"
                + " <script>function initialize() {"
                + " var nameVar = \"This is a JS var\"; " 
                + " app.callJavascript(nameVar);"
                + "} </script>"
                + "    <body onLoad=\"initialize()\">Hi, this is a test!</body>"
                + "</html>"));

        VBox vbox = new VBox(10,button,webView);
        Scene scene = new Scene(vbox,400,300);

        stage.setScene(scene);
        stage.show();

    }

    public class JavaApplication {

        public void callJavascript(String msg){
            System.out.println("JS>> "+msg);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

}

      

The content doesn't load until the button is clicked, but we've already created a JavaScript object in the browser.



There is nothing on the output console before the button is pressed. But if we click the button ... this is the output:

state: scheduled
state: running
JS>> This is a JS var
state: succeeded

      

As we can see, the Java object is efficiently passed to the script before the latter is executed, and app.callJavascript

successfully invoked while the content is loading.

Note that for the general purpose of accessing the loaded DOM it is generally a good idea to use a normal call executeScript

after call State.SUCCEEDED

.

+3


source







All Articles