繁体   English   中英

JavaFX WebView:链接到文档中的锚点无法使用 loadContent()

[英]JavaFX WebView: link to anchor in document doesn't work using loadContent()

注意:这是关于 JavaFX WebView,而不是 Android WebView(即我已经看到“ Android Webview 锚链接(跳转链接)不起作用”)。


我在javafx.scene.web.WebView中显示一个生成的 HTML 页面,其中包含锚点和指向这些锚点的链接,如下所示:

<p>Jump to <a href="#introduction">Introduction</a></p>
some text ...
<h1 id="introduction">Introduction</h1>
more text ...

我使用此代码将 HTML 加载到 WebView 中:

public void go(String location) {
    try {
        // read the content into a String ...
        String html = NetUtil.readContent(new URL(location), StandardCharsets.UTF_8);
        // ... and use loadContent()
        webview.getEngine().loadContent(html);
    } catch (IOException e) {
        LOG.error(e);
    }
}

一切都正确呈现,但如果我单击名为“介绍”的链接,则没有任何反应。

然而,HTML 是正确的,我使用以下代码进行了检查:

public void go(String location) {
    // use load() to directly load the URL
    webview.getEngine().load(location);
}

现在,一切正常。

问题似乎是因为 WebView 的文档 URL 在使用loadContent()时为null ,但由于它是只读属性,我不知道如何使其工作。

我需要使用loadContent() ,因为 HTML 是动态生成的,如果可能的话,我不想为了使锚链接工作而将它写到文件中。 有没有办法来解决这个问题?


编辑我为 JavaFX 提交了一个错误

这可能是另一个 WebEngine错误 很多代码只是封装在 api 中的本机库,因此我们无法在运行时修改它以修复某些缺陷。

如果您能够更改生成文件的结构,您可以在 js 中实现滚动到元素:

<script>
function scrollTo(elementId) {
    document.getElementById(elementId).scrollIntoView(); 
}
</script>

<a href='#' onclick=scrollTo('CX')>Jump to Chapter X</a>
<h2 id="CX">Chapter X</h2>

如果你不能改变结构,我已经采取了一些步骤来尝试修复它并提出一些建议 - 首先我肯定在loadContent之后通过反射设置了location的值:

Field locationField = WebEngine.class.getDeclaredField("location");
locationField.setAccessible(true);

ReadOnlyStringWrapper location = (ReadOnlyStringWrapper) locationField.get(engine);
location.set("local");

但事实上,保持实际位置的状态只是给你的一个信息,操纵它没有任何改变。 我还找到了一种从 js 设置 url 的方法(只是一个远景,我们没有任何具体细节为什么它不起作用):

window.history.pushState("generated", "generated", '/generated');

我们当然不能,因为:

SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.

我认为你应该忘记loadContent() 您说您不想将生成的内容写入文件。 有点脏,但对您真的很有帮助,可以将 http 服务器包装在您的应用程序中的随机和未使用的端口上。 你甚至不需要外部库,因为 Java 有这样的简单实用程序:

HttpServer server = HttpServer.create(new InetSocketAddress(25000), 0);
server.createContext("/generated", httpExchange -> {
    String content = getContent();
    httpExchange.sendResponseHeaders(200, content.length());
    OutputStream os = httpExchange.getResponseBody();
    os.write(content.getBytes());
    os.close();
});

server.setExecutor(null);
server.start();

您还可以使用其他浏览器来显示您的页面,例如JCEFJava Chromium Embedded Framework )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM