Is it possible to retrieve HTML element in web engine without using Javascript?

余生长醉 提交于 2020-01-02 08:10:09

问题


Is there a way to identify the type of the clicked element in webView (like Textbox/Radio/Button etc) using the webEngine.getDocument()?

Suppose I click on a textfield, I can get the x,y coordinates of the clicked position. Is it possible to identify the element present in that particular location? Something like the document.elementFromPoint() method in Javascript.

I can do it using Jquery/Javascript. But since we have access to Document object and its elements, is there a way to identify using JavaFX itself?


回答1:


You can probably use the Java Language Binding for Dom Level 2 events on the document retrieved from the WebEngine. These are bindings to access the same functionality as the JavaScript event bindings that people use when programming events for web pages in browsers.

The referenced classes are shipped with the JDK.

Just make sure the document is fully loaded (by monitoring the worker state or the document property) before accessing it.

Note: The particular method you reference in your question document.elementFromPoint(), is not part of the DOM level 2 specification, but is instead defined as an extension to the Document Interface in the CSSOM View Module which "provide authors with a way to inspect and manipulate the visual view of a document". Whilst the DOM level 2 specification is implemented in the JDK with the org.w3c module, the CSSOM View Module extensions are not.


OK, so this next part is a bit off-reservation as it is not documented in the official standard JDK Javadoc. So caveats, such as, "may not apply to all JavaFX implementations" or "may not always be supported by or Oracle" or "may break in future Java versions" apply. But anyway, on to the interesting stuff...

The document property in WebView is actually an implementation of the org.w3c.dom.html.HTMLDocument interface which is documented at this weird location: https://docs.oracle.com/javase/8/docs/jre/api/plugin. This interface and all of the supporting Java HTML document modeling classes are shipped with Oracle Java Runtime 8 along with JavaFX. The HTMLDocument interface and associated classes form a far richer API than the plain org.w3c.Document interfaces documented in the standard JDK documentation.

So you could cast the document to a HTMLDocument and you would get more functionality.

However, even then, there is lots of functionality in a browser (and a WebView document) that isn't exposed by a pure HTMLDocument interface.

So, you can get at this "hidden" functionality, by casting the document to a com.sun.webkit.dom.HTMLDocumentImpl. Then you expose a veritable orgy of APIs.

So let's do that... here I capture a mouse event over a HTML div element.

This is a (really) simple web inspector, like Firebug. Mouse over an element in a JavaFX WebView and some minimal info on the element will be displayed in a JavaFX Label at the top of the screen.

import com.sun.webkit.dom.HTMLDocumentImpl;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.events.MouseEvent;

public class WebViewClicker extends Application {

    public static final String LOC =
            "http://stackoverflow.com/questions/31957218/is-it-possible-to-retrieve-html-element-in-web-engine-without-using-javascript";

    @Override
    public void start(Stage stage) throws Exception {
        Label elementInfo = new Label();
        WebView webview = new WebView();

        webview.getEngine().documentProperty().addListener((observable, oldDoc, newDoc) -> {
            HTMLDocumentImpl realMcCoy = (HTMLDocumentImpl) newDoc;
            realMcCoy.setOnmousemove(event -> {
                MouseEvent expertMouser = (MouseEvent) event;

                elementInfo.setText(
                        realMcCoy.elementFromPoint(
                                expertMouser.getClientX(),
                                expertMouser.getClientY()
                        ).toString()
                );
            });
        });

        webview.getEngine().load(LOC);
        stage.setScene(new Scene(
                new VBox(
                        elementInfo,
                        webview
                )
        ));
        stage.show();
    }

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

You might notice that even your desired elementFromPoint method is available... though it isn't strictly needed here, as you could just get the event target directory from the expert mouser.

The sample just treats the retrieved element as a standard w3c dom element, which has (for me) a particularly cryptic API. However you can cast the element to an appropriate com.sun.webkit.dom.HTMLElementImpl subclass to get more easily accessible functionality and a nicer, more direct API that reflects something that you might be used to when you work with the HTML DOM using JavaScript.



来源:https://stackoverflow.com/questions/31957218/is-it-possible-to-retrieve-html-element-in-web-engine-without-using-javascript

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