I am trying to manipulate an WebView document, I can happily add new elements, update existing attributes; but I don't seem to be able to remove them.
In this simple example, I open up a really simple page with hyperlink on the bottom right icon. The code as attached tried to remove the href attribute, and hence disable the hyperlink on the icon. This does appear to work. If instead I just try to update the attribute value this does work and I can redirect the link to another location.
package webview;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.html.HTMLCollection;
import org.w3c.dom.html.HTMLDocument;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
private Scene scene;
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("Web View");
scene = new Scene(new Browser(), 750, 500, Color.WHITE);
stage.setScene(scene);
stage.show();
}
private static class Browser extends Region {
private WebView browser = new WebView();
private WebEngine webEngine = browser.getEngine();
public Browser() {
getStyleClass().add("browser");
// We want to monitor the state change so we can fiddle with the model
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue,
Worker.State newValue) {
if (newValue == State.SUCCEEDED) {
// Inject JavaScript object
JSObject win = (JSObject)webEngine.executeScript("window");
win.setMember("webview_context", new ClickContext());
//
HTMLDocument doc = (HTMLDocument)webEngine.getDocument();
// Check we can inject some code
Element someText = doc.createElement("p");
Attr attr = doc.createAttribute("style");
someText.setAttributeNode(attr);
attr.setValue("text-align:center");
String alignText = someText.getAttribute( "style");
someText.appendChild(doc.createTextNode("This is some injected text"));
doc.getBody().appendChild(someText);
HTMLCollection links = doc.getLinks();
for (int i = 0; i < links.getLength(); i++) {
Element item = (Element)links.item(i);
if (item.hasAttribute("href"))
{
Attr hrefAttr = item.getAttributeNode("href");
String href = hrefAttr.getNodeValue();
// hrefAttr.setValue("");
// Remove attribute from the model, this doesn't work and isn't reflected in this displayed document
item.removeAttributeNode(hrefAttr);
}
}
}
}
});
webEngine.load("http://www.exmaple.com/");
getChildren().add(browser);
}
private Node createSpacer() {
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
@Override
protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
layoutInArea(browser, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
}
@Override
protected double computePrefWidth(double d) {
return 750;
}
@Override
protected double computePrefHeight(double d) {
return 500;
}
}
private static class ClickContext {
public void onClick(String href) {
System.out.println("Clicked href " + href);
}
}
}
In this simple example, I open up a really simple page with hyperlink on the bottom right icon. The code as attached tried to remove the href attribute, and hence disable the hyperlink on the icon. This does appear to work. If instead I just try to update the attribute value this does work and I can redirect the link to another location.
package webview;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.html.HTMLCollection;
import org.w3c.dom.html.HTMLDocument;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
private Scene scene;
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("Web View");
scene = new Scene(new Browser(), 750, 500, Color.WHITE);
stage.setScene(scene);
stage.show();
}
private static class Browser extends Region {
private WebView browser = new WebView();
private WebEngine webEngine = browser.getEngine();
public Browser() {
getStyleClass().add("browser");
// We want to monitor the state change so we can fiddle with the model
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue,
Worker.State newValue) {
if (newValue == State.SUCCEEDED) {
// Inject JavaScript object
JSObject win = (JSObject)webEngine.executeScript("window");
win.setMember("webview_context", new ClickContext());
//
HTMLDocument doc = (HTMLDocument)webEngine.getDocument();
// Check we can inject some code
Element someText = doc.createElement("p");
Attr attr = doc.createAttribute("style");
someText.setAttributeNode(attr);
attr.setValue("text-align:center");
String alignText = someText.getAttribute( "style");
someText.appendChild(doc.createTextNode("This is some injected text"));
doc.getBody().appendChild(someText);
HTMLCollection links = doc.getLinks();
for (int i = 0; i < links.getLength(); i++) {
Element item = (Element)links.item(i);
if (item.hasAttribute("href"))
{
Attr hrefAttr = item.getAttributeNode("href");
String href = hrefAttr.getNodeValue();
// hrefAttr.setValue("");
// Remove attribute from the model, this doesn't work and isn't reflected in this displayed document
item.removeAttributeNode(hrefAttr);
}
}
}
}
});
webEngine.load("http://www.exmaple.com/");
getChildren().add(browser);
}
private Node createSpacer() {
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
@Override
protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
layoutInArea(browser, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
}
@Override
protected double computePrefWidth(double d) {
return 750;
}
@Override
protected double computePrefHeight(double d) {
return 500;
}
}
private static class ClickContext {
public void onClick(String href) {
System.out.println("Clicked href " + href);
}
}
}