by Rick Darnell and William Robert Stanek
In Chapters 29 through 31, you learned about how to make Java and JavaScript a part of your web pages. Standing alone, they are significant developments in their capability to stretch the behavior of your pages far beyond what was ever imagined for the
World Wide Web.
They can become even more powerful when harnessed together. As you'll recall in earlier discussions, although Java is powerful enough to add animation, sound, and other features within the confines of an applet, it's very cumbersome to directly
interact with an HTML page. JavaScript isn't big or powerful enough to match Java's programming power, but it is uniquely suited to work directly with the elements that comprise an HTML document.
By combining the best features of both, your applet can interact with your Web page, offering a new level of interactivity for Java and JavaScript.
In order for Java and JavaScript to interact on your Web pages, they both have to be active and enabled in the user's browser.
To make sure both features are active in Netscape Navigator, follow these simple steps.
Figure 33.1. The Languages tab from the Preferences dialog controls whether Java applets and JavaScript commands are processed for HTML documents.
The process to make sure both languages are active in Microsoft Internet Explorer is similar to the steps for Navigator.
Figure 33.2. Internet Explorer controls which language features are enabled from the Security tab in the Options dialog box.
NOTE
Netscape Navigator also includes a Java Console for displaying applet-generated messages (see Figure 33.3). In addition to showing system messages, such as errors and exceptions, the console displays any messages generated by the applet using the java.lang.System package, including System.out.println. To display the console, select Options | Show Java Console from the menu bar.
Microsoft Internet Explorer can show the results of system messages also but not in real time like the Navigator Java Console can. All messages are saved in javalog.txt in C:\Windows\Java.
To make sure this feature is active, select the Advanced tab from View, Options, and make sure the Java Logging box is selected.
Figure 33.3. The Java Console displays any system messages generated by the applet.
The first and most commonly used feature of communication is modifying applet behavior from JavaScript. This is really quite easy to do with the right information, and it allows your applet to respond to events on the HTML page, including interaction
with forms.
JavaScript-to-Java syntax is identical to other JavaScript object syntax, so if you're already familiar with this scripting language, adding Java control is an easy step.
Using the JavaScript Packages object, JavaScript can invoke native Java methods directly. Groups of related classes are combined in a construct called a package. Classes from a package are usable by outside classes by using
the import command.
TIP
Although a collection of packages is technically a package library, you'll see package collections also referred to as packages. For example, JavaSoft has several general package libraries. You learned about the JDK's package libraries in the previous chapter. Most of these packages are preceded by the key word java, which identifies the highest level package. The JDK also contains a package called sun.tools.debug. For this package, the key word sun identifies the highest level package. Netscape also has a package library, and as you might expect, their package library is identified with the key word netscape. For normal use, the java package is all you need. The netscape package includes methods and properties for Java to reach out to JavaScript and HTML and is covered later in this chapter. The last package, sun, includes platform-specific and system utility classes.
The syntax to call a Java package directly is
[Packages.]packageName.className.methodName
An example in all applets is the java package. One section of the package, java.awt.Graphics, is imported into every applet to give the paint method the additional
methods it needs to add items to the applet screen. Because all applets are outside the java package, its classes or subsets of those classes are imported into the applet for local use.
The object name is optional for the three default packagesjava, sun, and netscape. These three can be referenced by their package name alone:
java.className.methodName sun.className.methodName netscape.className.methodName
Together with the package name, the object and class names can result in some unwieldy and error-prone typing. This is why you can also create new variables using the Package product:
var System = Package.java.lang.System; System.out.println("Hello from Java in JavaScript.");
CAUTION
Invoking Java methods from JavaScript is only possible within browsers that support JavaScript version 1.1. These browsers include Netscape Navigator 3.0 and the final release version of Microsoft Internet Explorer 3.0. If you do not have the most recent version of either Navigator or Internet Explorer, visit www.microsoft.com or home.netscape.com to obtain a trial version of the latest and greatest version.
Controlling an applet with a script is a fairly easy matter, but it does require a knowledge of the applet you're working with. Any public variable, method, or property within the applet is accessible through JavaScript.
TIP
If you're changing the values of variables within an applet, the safest way is to create a new method within the applet for the purpose. This method can accept the value from JavaScript, perform any error checking, and then pass the new value along to the rest of the applet. This helps prevent unexpected behavior or applet crashes.
You'll need to know which methods, properties, and variables are public. Only the public items in an applet are accessible to JavaScript. You can always use the two public methods that are common to all appletsstart
and stop. These provide a handy means to control when the applet is active and running.
NOTE
There are five basic activities common to all applets, as opposed to one basic activity for applications. An applet has more activities to correspond to the major events in its life cycle on the user's browser. None of the activities has any definitions. You must override the methods with a subclass within your applet. The basic activities are
InitializationOccurs after the applet is first loaded. This can include creating objects, setting state variables, and loading images.
StartingAfter initialization or stopping, an applet is started. The difference between initialization and starting is that the former only happens once, whereas the latter can occur many times.
PaintingThis method is how the applet actually gets information to the screen, from simple lines and text to images and colored backgrounds. Painting can occur many times in the course of an applet's life.
StoppingStopping suspends the applet execution and stops it from utilizing system resources. This can be important because an applet continues to run even after a user leaves the page.
DestroyingThis is the extreme form of stopping. Destroying an applet begins a clean-up process where running threads terminate and release objects.
With this information in hand, getting started begins with opening a communication channel between JavaScript and Java. Just as you name forms and other objects so you can interact with them, you can also name your Java applet so it can interact with
JavaScript. In this way, you can easily make reference to a particular applet running in your page.
The Name property is an extended attribute of an applet. After you define the applet in the Java Applet Properties box, click the Extended button. Click the Add button of the Extended Attributes dialog box. You can define a new attribute for the text
box. In the Name field, enter Name. In the Value field, enter a name for your applet. Write down this name so you can easily refer to it later.
NOTE
Naming the applet isn't absolutely necessary because JavaScript creates an array of applets when the page is loaded. However, it does make a script more readable.
To use a method or set a property of an applet from JavaScript, you can use the following syntax:
document.appletName.methodOrProperty
To better understand how you can set methods, take another look at an applet created in the previous chapter called MyApplet. As you may recall, this applet uses a parameter called message to
set the text to display to the reader. Listing 33.1 shows the complete source for this applet.
Listing 33.1. An applet that accepts a parameter.
import java.awt.Graphics; import java.awt.Font; import java.awt.Color; public class MyApplet extends java.applet.Applet { Font f = new Font("TimesRoman",Font.ITALIC,24); String message; public void init() { this.message = getParameter("message"); if (this.message == null) { this.message = "Your message here."; } this.message = "A note from Java: " + this.message; } public void paint(Graphics g) { g.setFont(f); g.setColor(Color.red); g.drawString(this.message,50,25); } }
Usually, to set your own display message, you must set a parameter for the applet. Using JavaScript, you can update or change this message based on user input. If you name the applet appletA, you can change the message
property as follows:
document.appletA.message = "You just changed the message."
TIP
Netscape Navigator 3.0 includes an applets array, which references all the applets on a page. The applets array is used according to the following syntax:
document.applets[index].methodOrProperty document.applets[appletName].methodOrPropertyThese two methods also identify the applet you want to control, but the method using the applet's name without the applets array is the easiest to read and requires the least amount of typing.
Like the other arrays, a property of applets is length, which returns how many applets are in the document.
This array of applets is not currently available in the Microsoft Internet Explorer implementation of JavaScript.
One of the easy methods of controlling applet behavior is starting and stopping its execution. This can be accomplished using the start and stop methodscommon to every applet. To do this,
you use two buttons controls to call the applet methods directly when they are clicked.
Here are the steps you can use to control a Java applet directly with button controls and JavaScript:
Figure 33.4 shows a page with button controls that start and stop an applet.
Figure 33.4. An easy way to control an applet is to use buttons to start and stop it.
You can also call other methods, depending on their visibility to the world outside the applet. Any method or variable with a public declaration can be called by JavaScript.
TIP
Any variable or method within the applet that doesn't include a specific declaration of scope is protected by default. If you don't see the public declaration, it's not.
The following syntax to call applet methods from JavaScript is simple and can be integrated with browser events, such as the previous button control example:
document.appletName.methodName(arg1,arg2,arg3)
With the addition of a new set of classes provided with Netscape Navigator 3.0, Java can take a direct look at your HTML page through JavaScript objects. This requires the use of the netscape.javascript.JSObject class when
the applet is created.
TIP
netscape.javascript.JSObject is included with the other class files under the Netscape directory. In Windows, this is \Program Files\Netscape\Navigator\Program\java\classes. You can copy this file to the same directory as your other Java class files for ease of use. It extends the standard Java Object class, so the newly create JSObjects are treated as other Java objects.
To include the JSObject class as part of your applet, use the import command as you would usually include any other class package:
import netscape.javascript.JSObject;
You also need to make an important addition to the applet tag, the MAYSCRIPT property. This is a security feature that gives specific permission for the applet to access JavaScript objects.
The MAYSCRIPT property is an extended attribute of an applet. However, it takes no value. After you define the applet in the Java Applet Properties box, click the Extended button. Click the Add button of the Extended
Attributes dialog box. In the Name field, enter MAYSCRIPT. Leave the Value field blank and deselect the Specify Value checkbox. Deselecting the Specify Value checkbox ensures that no value is assigned to this property.
Without the MAYSCRIPT property, any attempt to access JavaScript from the applet results in an exception. If you want to exclude an applet from accessing the page, simply leave out the MAYSCRIPT
parameter.
JSObject gives Java the capability to look at and change objects defined through JavaScript. This requires certain assumptions, especially when passing or receiving values from Java. Every JavaScript value is assigned some
form from java.lang.Object to ensure compatibility. Here are how the object types are handled:
NOTE
A Java float is a 32-bit floating-point number. A version for larger numbers or greater precision behind the decimal point is the double, which is 64 bits long. Bytes, shorts, ints. and longs are all integers of various bit lengths, beginning with 8 bits for the byte and going up to 64 bits for the long. A char is a 16-bit number representing a single Unicode character.
In order to get a handle on JavaScript objects, including form items and frames, you must first create an object to hold the current Navigator window. getWindow provides the means.
First, you need to create a new variable of type JSObject:
JSObject jsWin;
Then, using the JSObject class, assign the window to the variable:
jsWin = JSObject.getWindow(this);
TIP
This type of work is typically accomplished within the applet's init() method.
After you have a handle on the window, you can start to break it apart into its various components with getMember. This method returns a specific object from the next level of precedence. For example, to get a handle on a
form on a Web page with a form called response, you can use the following set of statements:
jsWin = JSObject.getWindow(this); JSObject jsDoc = (JSObject) jsWin.getMember("document"); JSObject responseForm = (JSObject) jsDoc.getMember("response");
In JavaScript, this form is referred to as window.document.response. Note that each JavaScript object is assigned to its own variable in Java and is not a property of a parent object. The form in Java is contained in responseForm, not jsWin.jsDoc.responseForm.
NOTE
All parts of an HTML document exist in JavaScript in set relationships to each other. This is called instance hierarchy because it works with specific items on the page, rather than general classes of items. At the top of the pyramid is the window object. It is the parent of all other objects. Its children include document, location, and history, which share a precedence level. document's children include objects specific to the page, such as forms, links, anchors, and applets.
The Java netscape package recognizes and utilizes this hierarchy through its getWindow and getMethod methods. The first gets the window object (the highest object), whereas the latter returns individual members of the next level.
So far, you've only retrieved broad objects, such as windows and forms. Getting a specific value from JavaScript follows the same principles, although you need a Java variable of the proper type to hold the results instead of an instance of JSObject.
TIP
Don't forget about passing numbers between JavaScript and Java. All JavaScript numbers are converted to a float. You can cast it to another Java type if needed once it's in the applet.
Using the preceding form, suppose there's a text field (name), a number (idNum), and a checkbox (member). Each of these values is retrieved from JavaScript using the
following commands:
jsWin = JSObject.getWindow(this); JSObject jsDoc = (JSObject) jsWin.getMember("document"); JSObject responseForm = (JSObject) jsDoc.getMember("response"); JSObject nameField = (JSObject) responseForm.getMember("name"); JSObject idNumField = (JSObject) responseForm.getMember("idNum"); JSObject memberField = (JSObject) responseForm.getMember("memberField"); String nameValue = (String) nameField.getMember("value"); Float idNumValue = (Float) idNumField.getMember("value"); Boolean memberValue = (Boolean) memberField.getMember("checked");
This chunk of code becomes a bit unwieldy, especially when you need several values from JavaScript. If you need to access more than several elements on a page, it can help to create a new method to handle the process:
protected JSObject getElement(String formName, String elementName) { JSObject jsDoc = (JSObject) JSObject.getWindow().getMember("document"); JSObject jsForm = (JSObject) jsDoc.getMember(formName); JSObject jsElement = (JSObject) jsElement.gerMember(elementName); return jsElement; }
This simple method creates the intervening JSObjects needed to get to the form element, making the retrieval as easy as knowing the form and element name.
To change a JavaScript value, use the JSObject method setMember in Java. The syntax is setMember(name,
value) with the name of the JavaScript object and its new value:
JSObject nameField = getElement("response","name"); nameField.setMember("name","Your Name Here");
This snippet uses the getElement method just defined to get the name element from the response form and then uses the JSObject method
setMember to set its value to Your Name Here. This is equivalent to this.name = newValue in JavaScript.
The two methods covered in this section (getWindow and getMember) are the basic methods used when interfacing with JavaScript. Together, it makes receiving values from an HTML page via
JavaScript a straightforward task, even if it is a little cumbersome in the number of statements needed to accomplish it.
If your applet is designed to work with a variety of HTML pages that might contain different names for forms and elements, you can utilize the JavaScript arrays with the JSObject slot methods. If the desired form is always
the first to appear on the document and the element is the third, then the form name is forms[0] and the element is elements[2].
After retrieving the document object using getWindow and getMember, use getSlot(index) to return a value within it. For example,
in an HTML document containing three forms, the second is retrieved into Java using the following commands:
JSObject jsWin = JSObject.getWindow(this); JSObject jsDoc = (JSObject) jsWin.getMember("document"); JSObject jsForms = (JSObject) jsDoc.getMember("forms"); JSObject jsForm1 = (JSObject) jsForms.getSlot(1);
Using setSlot, the same process is used to load a value into an array. The syntax is
JSObject.setSlot(index,value);
index is an integer and value is a string, boolean, or float.
TIP
The one rule that must stand firm in this case is the placement of the form and elements within it. When the applet is used with more than one document, the forms and elements must be in the same relative place every time to avoid exceptions and unpredictable results.
The netscape class package provides two methods to call JavaScript methods from within an appletcall and eval. The syntax between the two is slightly
different, but the outcome is the same.
TIP
You need a handle for the JavaScript window before you can use these methods.
There are two ways to invoke these methods. The first uses a specific window instance, whereas the second uses getWindow to create a JavaScript window just for the expression:
jsWin.callOrEval(arguments) JSObject.getWindow().callOrEval(arguments)
The call method separates the method from its arguments. This is useful for passing Java values to the JavaScript method. The syntax is call("method", args), where method is the name of the method you want to call and the arguments you want to pass are contained in an array.
eval, on the other hand, uses a string that appears identical to the way a method is called within JavaScript. The syntax is eval("expression"), where expression is a complete method name and its arguments, such as document.writeln("Your name here.'"). Including it in the eval expression looks like eval("document.writeln(\"Your name here.\");").
TIP
To pass quotation marks as quotation marks to JavaScript within a Java string, use the backslash character before each occurrence.
Now you have a whole set of tools to get from JavaScript to Java and back again. The marriage of these two Web technologies can open a whole new world of how to interact with your users. Using simple statements and definitionsalready a part of
both languagesa previously static Web page can communicate with an applet embedded in it and in return react to the output of the applet. It's just one more set of capabilities in your toolbox that you can use to meet your users' needs.