使用JavaFX WebEngine.executeScript时如何获取延迟JavaScript执行的结果?

时间:2016-04-28 12:39:44

标签: javascript dom javafx javafx-8 javafx-webengine

在WebEngine中执行JavaScript时,如何在任何延迟脚本执行结果后使用WebEngine.getDocument获取DOM?这是展示问题的最小代码。

在标准浏览器中呈现时,以下HTML执行以下操作:

  1. 运行一个动态添加外联脚本元素的内联脚本
  2. 然后,外线脚本将DOM元素添加到正文
  3. 以下是起始HTML:

    <html>
      <head>
        <script>var y=document.createElement('script');
                y.src = 'http://example.com/js/bar.js';
                document.head.appendChild(y);
        </script>
      </head>
      <body>
      </body>
    </html>
    

    以下是out-of-line脚本bar.js包含的内容:

    var x=document.createElement('div'); x.id='bar'; document.body.appendChild(x);
    

    在标准浏览器中执行上述HTML之后,这就是DOM在真实浏览器中的样子,但这不是我在WebEngine中所获得的(我稍后会展示):

    <html>
      <head>
        <script>var y=document.createElement('script'); y.src = 'http://example.com/js/bar.js'; document.head.appendChild(y);</script>
        <script src="http://example.com/js/bar.js"></script>
      </head>
      <body>
      <div id="bar"></div>
      </body>
    </html>
    

    我试图使用无头JavaFX WebEngine使用以下代码模拟上述代码(这是完整的Java 8代码,减去导入):

    public class StackOverflowQuestion extends Application {
        @Override
        public void start(Stage primaryStage) throws Exception {
            final WebView browser = new WebView();
            final WebEngine webEngine = browser.getEngine();
            webEngine.setJavaScriptEnabled(true);
            webEngine.loadContent("<html><head></head><body></body></html>");
    
            webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener() {
                @Override public void changed(ObservableValue o,Object oldVal, Object newVal) {
                    if (newVal == State.SUCCEEDED) {
                        webEngine.executeScript("var y=document.createElement('script'); y.src = 'http://example.com/js/bar.js'; document.head.appendChild(y);");
                        Document document = webEngine.getDocument();
                        printDOM(document);
                    } else {
                        System.out.println("Did not succeed");
                    }
                }
            });
        }
    
        private void printDOM(Document document) {
            Transformer transformer;
            try {
                transformer = TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
                transformer.setOutputProperty(OutputKeys.METHOD, "html");
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
                transformer.transform(new DOMSource(document), new StreamResult(new OutputStreamWriter(System.out, "UTF-8")));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        static public void main(String [] args) {
            try {
                Application.launch(args);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    以上代码输出以下DOM结构。请注意,DOM包含executeScript调用的结果,但不包含外部脚本生成的结果。如何让DOM包含带有id bar的动态添加的div元素?

    <HTML xmlns="http://www.w3.org/1999/xhtml">
        <HEAD>
            <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <SCRIPT src="http://example.com/js/bar.js"></SCRIPT>
        </HEAD>
        <BODY></BODY>
    </HTML>
    

0 个答案:

没有答案