Adding HTML Content to JavaFX Applications

Previous
Next

Beta Draft: 2013-09-17

6 Making Upcalls from JavaScript to JavaFX

Now you know how to invoke JavaScript from JavaFX. In this chapter, you can explore the opposite functionality — calling from web content to JavaFX.

The general concept is to create an interface object in the JavaFX application and make it known to JavaScript by calling the JSObject.setMember() method. After that, you can call public methods and access public fields of this object from JavaScript.

Using a JavaScript Command to Exit JavaFX Application

For the WebViewSample application, you create the Help toolbar item that leads to the help.html file, where a user can preview reference material about Oracle web sites. By clicking the Exit the Application link in the help.html file, the user exits the WebViewSample application. Modify the application, as shown in Example 6-1, to implement this functionality.

Example 6-1 Closing JavaFX Application by Using JavaScript

import javafx.application.Application;
import javafx.application.Platform;
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;
import netscape.javascript.JSObject;
 
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",
        "help.png"
    };
    final private static String[] captions = new String[]{
        "Products",
        "Blogs",
        "Documentation",
        "Partners",
        "Help"
    };
    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",
        WebViewSample.class.getResource("help.html").toExternalForm()
    };
    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) {
                            JSObject win = 
                                (JSObject) webEngine.executeScript("window");
                            win.setMember("app", new JavaApp());
                            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);
    }
 
    // JavaScript interface object
    public class JavaApp {
 
        public void exit() {
            Platform.exit();
        }
    }
 
    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;
    }
}

Examine the bold lines in Example 6-1. The exit() method of the JavaApp interface is public; therefore, it can be accessed externally. When this method is called, it causes the JavaFX application to terminate.

Adding an Exit Command to the HTML Page

The JavaApp interface in Example 6-1 is set as a member of the JSObject instance, so that JavaScript becomes aware of that interface. It becomes known to JavaScript under the name window.app, or just app, and its only method can be called from JavaScript as app.exit(). See Example 6-2 to evaluate how this call is implemented in the help.html file.

Example 6-2 Making a Call to the WebViewSample Application from the Help File

<html lang="en">
<body>
<p>Help</p>    
<ul>
  <li>Products - Extensive overview of Oracle hardware and software products, 
      and summary Oracle consulting, support, and educational services. </li>
  <li>Blogs - Oracle blogging community (use the Hide All and Show All buttons 
      to collapse and expand the list of topics).</li>
  <li>Documentation - Landing page to start learning Java. The page contains
      links to the Java tutorials, developer guides, and API documentation.
      various Oracle products and solution.</li>
  <li>Partners - Oracle partner solutions and programs. Popular resources and 
      membership opportunities.</li>
</ul>
<p><a href="about:blank" onclick="app.exit()">Exit the Application</a></p>    
</body>
</html>

When you compile and run the WebViewSample application, the new icon appears, as shown in Figure 6-1.

Click Help to load the help.html file. Examine the content of the file, then click the Exit the Application link, shown in Figure 6-2, to close the WebViewSample application.

Figure 6-2 Help.html file

Description of Figure 6-2 follows
Description of "Figure 6-2 Help.html file"

Previous
Next