3

My company is looking to switch up our embedded browser to JavaFx. However, our current browser currently has functionality that listens to a javascript function, and calls back to java whenever it is called. It looks like this:

embeddedBrowser.registerFunction("ajavascriptFunction", new BrowserFunction() {

public JSValue invoke(JSValue... args) {
    //Do callback work
}
});

This requires no modification of the html side (a requirement) and in fact only requires knowledge of the javascript function name (I might be able to research more information, but this is highly preferred).

Is there anyway to use JavaFx in the same way?

4
  • The WebEngine javadocs have sections "Evaluating JavaScript expressions" and "Calling back to Java from Javascript". Do the techniques there address your needs? Commented Mar 20, 2015 at 17:05
  • As far as I can tell they do not. They all require modifying the html, as you need to match the javascript functions to the objects you setup on the Java side. Commented Mar 20, 2015 at 18:52
  • See the executejQuery function in this sample which takes a JavaScript function and executes it - this approach uses the webEngine.executeScript function and does not require modification of the HTML. Does this approach works for you? Commented Mar 20, 2015 at 23:18
  • What is new BrowserFunction()? Do you have links to javadocs for that or can you describe its functionality specification in your question? Commented Mar 20, 2015 at 23:18

1 Answer 1

6

I think this does what you need. I borrowed an idea from this question to figure out the javascript:

import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;

public class JavaScriptFunctionListener extends Application {

    @Override
    public void start(Stage primaryStage) {
        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();

        engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
            if (newState == Worker.State.SUCCEEDED) {
                addFunctionHandlerToDocument(engine);
            }
        });

        // Just a demo: in real life can load external HTML resource:
        engine.loadContent(
                "<html><head><script>"
                + "var count = 0 ;"
                + "function someFunction(x) {"
                + "    count ++ ;"
                + "    document.getElementById(x).innerHTML = 'Count: '+count ;"
                + "}"
                + "</script></head>"
                + "<body>"
                + "    <input type=\"button\" value=\"Click Me\" onclick=\"someFunction('display');\"/>"
                + "    <div id='display'></div>"
                + "</body>"
                + "</html>"
        );

        Button registerButton = new Button("Register handler for 'someFunction'");
        registerButton.setOnAction(event -> {
            registerFunction("someFunction", engine);
            // registering the same function twice will break everything
            // so don't allow this to happen again:
            registerButton.setDisable(true);
        });

        HBox controls = new HBox(5, registerButton);
        controls.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);

        BorderPane root = new BorderPane(webView, null, null, controls, null);
        Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    private void registerFunction(String functionName, WebEngine engine) {
        engine.executeScript(
            "var fun = " + functionName + " ;"
            + functionName + " = function() {"
            + "    app.functionCalled('" + functionName + "');"
            + "    fun.apply(this, arguments)"
            + "}"
        );
    }

    private void addFunctionHandlerToDocument(WebEngine engine) {
        JSObject window = (JSObject) engine.executeScript("window");
        window.setMember("app", this);
    }

    public void functionCalled(String name) {
        System.out.println(name + " was called");
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.