将javascript文件添加到已经运行的Java FX Web引擎

时间:2017-04-06 20:25:21

标签: javascript java html javafx-webengine

我有一个运行Java FX webengine的Java应用程序(所有这一切的最终目标是动态绘制D3.js图)。我希望能够在它已经运行时添加新的javascript文件,然后在javascript告诉它时理想地再次卸载它们。

这样可以使用户可以使用某些功能(绘制某些功能),而无需立即加载所有代码。它还可以帮助我避免在我的javascript中使用脆弱的if / then语句森林的未来头痛。

问题1:是否可以从正在运行的Web引擎中“卸载”文件?至少,没有重绘整个事情是可能的。我很确定使用我的新文件路径调用loadContent()会使它们以我想要的方式可用,但我没有谈到如何从HTML块中删除现有源代码。

问题2:有关如何优雅地将额外资源投入webView的任何建议?我现在的思维过程仍然停留在蛮力上,但我甚至没有能够通过一种有效的解决方案,所以也许我正在咆哮错误的树。

问题3:这是一个好主意吗?可以仅在Javascript中执行此操作,但我希望选项的外观和消失直接与java端功能相关联,后者将从类Bridge执行,我正在尝试从中加载新内容现在。

我问了很多问题,但感谢任何帮助!

现在我正在设置webengine的内容:

final ResourceExtractor RESOURCE_EXTRACTOR
                = new ResourceExtractor(JavaScriptPlot.class);

    // prepare the local URI for d3.js
    final URI D3_JS_URI = RESOURCE_EXTRACTOR
            .extractResourceAsPath("d3.min.js")
            .toUri();

    // prepare the local URI for numeric.js
    final URI NUMERIC_JS_URI = RESOURCE_EXTRACTOR
            .extractResourceAsPath("numeric.min.js")
            .toUri();

    // prepare the local URI for topsoil.js
    final URI TOPSOIL_JS_URI = RESOURCE_EXTRACTOR
            .extractResourceAsPath("topsoil.js")
            .toUri();

    // build the HTML template (comments show implicit elements/tags)
    HTML_TEMPLATE = (""
            + "<!DOCTYPE html>\n"
            // <html>
            // <head>
            + "<style>\n"
            + "body {\n"
            + "  margin: 0; padding: 0;\n"
            + "}\n"
            + "</style>\n"
            // </head>
            + "<body>"
            + "<script src=\"" + D3_JS_URI + "\"></script>\n"
            + "<script src=\"" + NUMERIC_JS_URI + "\"></script>\n"
            + "<script src=\"" + TOPSOIL_JS_URI + "\"></script>\n"
            + "<script src=\"%s\"></script>\n" // JS file for plot
            // </body>
            // </html>
            + "").replaceAll("%20", "%%20");

此处创建了替换%s的源路径:

public class BasePlot extends JavaScriptPlot {

    private static final ResourceExtractor RESOURCE_EXTRACTOR
            = new ResourceExtractor(BasePlot.class);

    private static final String RESOURCE_NAME = "BasePlot.js";

    public BasePlot() {
        super(
                RESOURCE_EXTRACTOR.extractResourceAsPath(RESOURCE_NAME),
                new BasePlotDefaultProperties());
    }

}

然后我将已经提取的文件路径作为资源sourcePath,并将其插入到HTML块中:

String buildContent() {
        return String.format(HTML_TEMPLATE, sourcePath.toUri());
}

然后我使用buildContent()

的返回值构建我的Web视图
private void initializeWebView() {
    runOnFxApplicationThread(() -> {
        // initialize webView and associated variables
        webView = new WebView();
        webView.setContextMenuEnabled(false);

        WebEngine webEngine = webView.getEngine();

        webEngine.getLoadWorker().stateProperty().addListener(
                (observable, oldValue, newValue) -> {
                    if (newValue == SUCCEEDED) {
                        if (new IsBlankImage().test(screenCapture())) {
                            webEngine.loadContent(buildContent());
                        }

                        topsoil = (JSObject) webEngine.executeScript("topsoil");
                        topsoil.setMember("bridge", new Bridge());
                    }
                });

        // asynchronous
        webEngine.loadContent(buildContent());
    });
}

Javascript可以触发下面类中的方法来触发更改。现在它正在手动创建一个硬编码资源,但是一旦我弄错了,我会让这部分更加优雅/逻辑有序。

//loads appropriate JS files into webview based on BasePlot's isotope type
public class Bridge {
        final URI ISOTOPE_URI = ISOTOPE_RESOURCE_EXTRACTOR
                .extractResourceAsPath("Concordia.js")
                .toUri();

        String finalHtml = buildContent().concat("<script src=\""+ISOTOPE_URI.toString()+"\"></script>\n");
        webView.getEngine().loadContent(finalHtml);
    }
}

上面的loadContent()给我一个应用程序线程错误:“ReferenceError:找不到变量:topsoil”

0 个答案:

没有答案