Adding HTML Content to JavaFX Applications
Beta Draft: 2013-09-17
5 Processing JavaScript Commands
This chapter extends the WebViewSample application and explains how to call JavaScript commands from JavaFX code.
The WebEngine
class provides API to run a script within the context of the current HTML page.
Understanding the executeScript method
The executeScript
method of the WebEngine
class enables executing any JavaScript commands declared in the loaded HTML page. Use the following string to call this method on a web engine: webEngine.executeScript("<function name>");
.
The method execution result is converted to a java.lang.Object
instance by using the following rules:
-
JavaScript
Int32
is converted tojava.lang.Integer
-
JavaScript numbers are converted to
java.lang.Double
-
JavaScript string values are converted to
java.lang.String
-
JavaScript boolean values are converted to
java.lang.Boolean
Refer to the API documentation for the WebEngine
class for more information about the conversion results.
Calling JavaScript Commands from JavaFX Code
Extend the WebViewSample application to execute a JavaScript command that toggles the list of documents on the Java SE documentation page.
The modified application code shown in Example 5-1 creates an additional button to hide and show the Java SE documentation for the previous releases. The button is added to the toolbar only when the Documentation page is selected.
Example 5-1 Adding the Toggle Previous Docs button
import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker.State; import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; import javafx.geometry.HPos; import javafx.geometry.Pos; import javafx.geometry.VPos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Hyperlink; import javafx.scene.image.Image; import javafx.scene.image.ImageView; 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; public class WebViewSample extends Application { private Scene scene; @Override public void start(Stage stage) { // create scene stage.setTitle("Web View"); scene = new Scene(new Browser(), 900, 600, Color.web("#666970")); stage.setScene(scene); // apply CSS style scene.getStylesheets().add("webviewsample/BrowserToolbar.css"); // show stage stage.show(); } public static void main(String[] args) { launch(args); } } class Browser extends Region { private HBox toolBar; final private static String[] imageFiles = new String[]{ "product.png", "blog.png", "documentation.png", "partners.png", }; final private static String[] captions = new String[]{ "Products", "Blogs", "Documentation", "Partners", }; final private static String[] urls = new String[]{ "http://www.oracle.com/products/index.html", "http://blogs.oracle.com/", "http://docs.oracle.com/javase/index.html", "http://www.oracle.com/partners/index.html", }; final ImageView selectedImage = new ImageView(); final Hyperlink[] hpls = new Hyperlink[captions.length]; final Image[] images = new Image[imageFiles.length]; final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); final Button showPrevDoc = new Button("Toggle Previous Docs"); private boolean needDocumentationButton = false; public Browser() { //apply the styles getStyleClass().add("browser"); for (int i = 0; i < captions.length; i++) { // create hyperlinks Hyperlink hpl = hpls[i] = new Hyperlink(captions[i]); Image image = images[i] = new Image(getClass().getResourceAsStream(imageFiles[i])); hpl.setGraphic(new ImageView(image)); final String url = urls[i]; final boolean addButton = (hpl.getText().equals("Documentation")); // process event hpl.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { needDocumentationButton = addButton; webEngine.load(url); } }); } // create the toolbar toolBar = new HBox(); toolBar.setAlignment(Pos.CENTER); toolBar.getStyleClass().add("browser-toolbar"); toolBar.getChildren().addAll(hpls); toolBar.getChildren().add(createSpacer()); //set action for the button showPrevDoc.setOnAction(new EventHandler() { @Override public void handle(Event t) { webEngine.executeScript("toggleDisplay('PrevRel')"); } }); // process page loading webEngine.getLoadWorker().stateProperty().addListener( new ChangeListener<State>() { @Override public void changed(ObservableValue<? extends State> ov, State oldState, State newState) { toolBar.getChildren().remove(showPrevDoc); if (newState == State.SUCCEEDED) { if (needDocumentationButton) { toolBar.getChildren().add(showPrevDoc); } } } } ); // load the home page webEngine.load("http://www.oracle.com/products/index.html"); //add components getChildren().add(toolBar); 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(); double tbHeight = toolBar.prefHeight(w); layoutInArea(browser,0,0,w,h-tbHeight,0,HPos.CENTER, VPos.CENTER); layoutInArea(toolBar,0,h-tbHeight,w,tbHeight,0,HPos.CENTER,VPos.CENTER); } @Override protected double computePrefWidth(double height) { return 900; } @Override protected double computePrefHeight(double width) { return 600; } }
Loading always happens on a background thread. Methods that initiate loading return immediately after scheduling a background job. The getLoadWorker()
method provides an instance of the Worker
interface to track the loading progress. If the progress status of the Documentation page is SUCCEEDED
, the Toggle Previous Docs button is added to the toolbar, as shown in Figure 5-1.
The setOnAction
method shown in Example 5-2 defines behavior for the Toggle Previous Docs button.
Example 5-2 Executing a JavaScript Command
showPrevDoc.setOnAction(new EventHandler() {
@Override
public void handle(Event t) {
webEngine.executeScript("toggleDisplay('PrevRel')");
}
});
When the user clicks the Toggle Previous Doc button, the executeScript
method runs the toggleDisplay
JavaScript function for the Documentation page, and the documents for the previous Java releases appear, as shown in Figure 5-2. When the user performs another click, the toggleDisplay
function hides the lists of the documents.
Figure 5-2 Showing the Java SE Documentation
Description of "Figure 5-2 Showing the Java SE Documentation"