问题
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