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
Int32is 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"
Alla is a technical writer for Oracle. She lives in St. Petersburg, Russia, and develops tutorials and technical articles for Java and JavaFX technologies. Prior to her assignment at Oracle, she worked as a technical writer in different IT companies. 

