How to catch return value from javascript in javafx?

我们两清 提交于 2019-12-17 20:43:35

问题


I am executing a javascript code in my webview of JavaFX application. I need to make it execute repeatedly whenever there is a mouse click and get the element details into a java variable. I'm using the below code and using Firebug Lite. In Firebug console, required items are printing. But I want it returned to java application.

engine.documentProperty().addListener(new ChangeListener<Document>() {
            @Override public void changed(ObservableValue<? extends Document> prop, Document oldDoc, Document newDoc) {
                enableFirebug(engine);
                Object obj=engine.executeScript("var lastElement = null; "
                        + "document.addEventListener('click', function(e) {"
                        + "if (e.target != lastElement) {"
                        + "lastElement = e.target;"
                        + "console.log(lastElement.name);"
                        + "return lastElement.name;"
                        + "}}, false);");
                System.out.println(obj.toString());
            }
        });

It is getting executed when the page is loaded, but not after every mouse click. Please suggest me how to modify it.


回答1:


Try calling this the other way around. Assuming you're loading your page as

final WebEngine webEngine = webview.getEngine();
webEngine.load("http://localhost/demo/clickHandler/");

We're going to set a listener for the successful state - basically we're going to inject a Java class into the JavaScript and have it call us back. Let's create a WebController that checks what is passed in and prints out the ID:

public class WebController {
    public void printId(Object object) {
        if (org.w3c.dom.html.HTMLElement.class.isAssignableFrom(object.getClass())) {
            org.w3c.dom.html.HTMLElement it = (org.w3c.dom.html.HTMLElement) object;
            System.out.println("Id is " + it.getId());
        }
    }
}

Now on successful load, we inject this into the app as clickController.

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

Now we need some JavaScript on the page to call us back. Assuming you're using jQuery, add this code to your page:

$(function () {
    $('*').click(function (event) {
        event.preventDefault();
        event.stopPropagation();
        clickController.printId(this);
    });
});

Now when anything is clicked on, a call back will be made to webController, which will check that the object is an HTMLElement and print out its ID (or null if there is no ID).

Not using jQuery makes it a bit harder but you can add this to the end of your document:

var nonJQuery = function (event) {
    clickController.printId(this);
    event.preventDefault();
    event.stopPropagation();
};
var elements = document.querySelectorAll("*");
for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener("click", nonJQuery, false);
}

If adding content to the document is not possible, you can execute the script to add the click handler in the succeeded function. Update the succeeded function to look as follows:

    webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
          @Override
          public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
              if (newState == State.SUCCEEDED) {
                  JSObject window = (JSObject) webEngine.executeScript("window");
                  webEngine.executeScript("var nonJQuery = function (event) {\n" +
                          "    clickController.printId(this);\n" +
                          "    event.preventDefault();\n" +
                          "    event.stopPropagation();\n" +
                          "};\n" +
                          "var elements = document.querySelectorAll(\"*\");\n" +
                          "for (var i = 0; i < elements.length; i++) {\n" +
                          "    elements[i].addEventListener(\"click\", nonJQuery, false);\n" +
                          "}");
                  window.setMember("clickController", new WebController());
              }
          }
      }
    );

Finally, if you want to prevent page navigation eg. from links, you can add return false; to the JavaScript:

    webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
          @Override
          public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
              if (newState == State.SUCCEEDED) {
                  JSObject window = (JSObject) webEngine.executeScript("window");
                  webEngine.executeScript("var nonJQuery = function (event) {\n" +
                          "    clickController.printId(this);\n" +
                          "    event.preventDefault();\n" +
                          "    event.stopPropagation();\n" +
                          "    return false;\n" +
                          "};\n" +
                          "var elements = document.querySelectorAll(\"*\");\n" +
                          "for (var i = 0; i < elements.length; i++) {\n" +
                          "    elements[i].addEventListener(\"click\", nonJQuery, false);\n" +
                          "}");
                  window.setMember("clickController", new WebController());
              }
          }
      }
    );


来源:https://stackoverflow.com/questions/30390257/how-to-catch-return-value-from-javascript-in-javafx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!