RSS RSS feed
November 21, 2009
Hot Topics:

Accomplishing, in Java, the JavaScript "document.write()" function

  • March 26, 1998
  • By Carl Dreher
  • Send Email »
  • More Articles »

JavaScript programmers know that the most powerful command in that interpreted language is "document.write()". This command accepts a String as its input parameter and writes the String to the browser as if it came from a static HTML page. That simple concept allows JavaScript authors to dynamically create HTML Web pages. Unfortunately, Java does not contain a similar class or method. This article will explain a way around this deficiency.

Before we begin, a fair question is, "Why would I want an equivalent Java method?" After all, Java allows you to control everything on the screen through applets, so why would you want to mix in anything as crude as HTML? As an answer, I'll give you a real-life example. I wrote a large Web-based cost-of-ownership application for buyers of programmable logic chips. This Java program has over 40 different variables entered by the user, and I wanted a way for the user to print them in a nicely formatted table. Using pure Java in an applet, I could create the table, but neither the Netscape nor Internet Explorer browsers can print the results displayed in a Java applet. Printing hardcopy of the same table built in HTML is simply a click of the Print button.

Here's another example. Suppose you have an existing, complex Web-based catalog of all of your company's products. The look of each page has been carefully crafted by commercial Web artists and is uniform across the site. Your job is to create a custom welcome page containing links to new products, where the links are chosen based on individual customer's buying profile supplied by a Java-accessible database. Rather than trying to completely duplicate the existing page format with Java, it is far easier to write a tiny applet that works inside the proven HTML code and adds only a few commands for the new links.

The best of both worlds

The technique we'll be using combines JavaScript and Java. We aren't actually going to reproduce document.write() in Java. Instead, we'll keep the proven JavaScript function and simply find a way of sending data to it from Java. Here's the technique is a nutshell: First, we'll write our main Java application. That program creates a String containing the new HTML commands that we want to display in the browser. The Java application then downloads and opens a special HTML "carrier" page in a second browser window. This carrier page contains a tiny Java applet whose sole purpose is to get the new HTML commands from the main Java application and pass them to a tiny JavaScript program also running on the carrier page. The JavaScript program then displays the newly minted HTML commands via a call to JavaScript's document.write() function.

The HTML carrier

The HTML code in listing "JavaWrite.htm" is the simple carrier page for our Java applet and the JavaScript document.write() function. There's not much to it! Down in the body of the HTML code is a single line that loads the Java applet "JavaWrite.class". The applet is in a tiny 2x2 box, which is the minimum size an applet can have on an HTML page. (Some browsers allow a 2x1 applet size, but for some reason, all crash on anything smaller!) The applet is given an arbitrary name, in this case, "JavaWriteApplet". This name is important because it is the reference we will use later to call methods in the applet.

Listing JavaWrite.htm

In the head of the document is a JavaScript function named WritePage(), which is called when the page loads by the "onLoad=WritePage()" statement. This function first checks to see if the applet is loaded. If it is, the function then invokes the getString() method of the applet, using Netscape's LiveConnect JavaScript-to-Java calling convention. LiveConnect allows a JavaScript program to access Java programs with "document..". The applet name is NOT the name of the class; it is the arbitrary name we gave it in the HTML document. LiveConnect is supported by both Netscape 3/4 and IE 3/4, so you can be sure this technique works for most of your browser audience.

The getString() method returns a String to the JavaScript function. (JavaScript is not very strongly typed, so it is sufficient to declare the variable "input" as type "var".) This String contains all the new HTML code we want the browser to display. This String is passed to the JavaScript document.write() function, which dutifully tells the browser to display our new HTML commands.

The embedded Java applet

Now let's look at the JavaWrite applet that we embedded in the HTML carrier page. This applet (in listing "JavaWrite.java") is even simpler than the HTML page! It only does two things: (1) It instantiates an object called GlobalString, and (2) it provides the getString() method which was called via LiveConnect in the JavaScript function. The only thing getString() does is get a String from the GlobalString object and return it. The String contains the HTML code.

Listing JavaWrite.java
import java.applet.*;

public class JavaWrite extends Applet
{
   // instance of the object with a static string
   GlobalString gs = new GlobalString();

   // method to read the string
   public String getString()
   {
       return gs.getString();
   }

   // method to write the string
   public void putString(String str)
   {
       gs.putString(str);
   }
}

Global memory

The GlobalString object in listing "GlobalString.java" is the heart of our technique. It is the magic portal through which we communicate, and its heart is a static String. Whenever a variable is declared static in an object, every instantiation of the object has access to that variable. It becomes a global variable that everyone who instantiates the object can read or write -- even totally separate applets. This is the trick that makes everything work.

Listing GlobalString.java
import java.util.*;

public class GlobalString
{
   private static String globalstring;

   String getString()
   {
      return globalstring;
   }

   void putString(String str)
   {
      globalstring = str;
   }
}

Here's what happens: When the main Java application runs, it performs its duties (accessing company databases, etc.) and then generates the HTML code and data to display in the new HTML page. It then instantiates a GlobalString object and writes the new code/data to the object's static String. Finally, the main application uses Java's "showDocument" method to command the browser to download and display the carrier HTML page.

When the carrier page loads, it runs the JavaWrite applet, which also instantiates a GlobalString object. The static String is now global to both applets. JavaWrite reads the String and passes the data to JavaScript, which then calls document.write(), as previously described.

You may be wondering why we jumped through so many hoops to pass the data. Why not have the carrier HTML page use LiveConnect to get the new HTML description directly from our main application? The reason we can't do it directly is because the new HTML page isn't aware of the main Java application. It resides on a totally separate page in the browser, and it can't pass its data outside the page.

An example

The following simple example, in listing "HealthTest.htm", collects data about the eating habits of the user and then displays a summary of the data in a table on an HTML page. Obviously, this is a contrived example. For anything this simple it would be easier to write the entire program in JavaScript. In a real application, the Java program would be used to do some heavy-duty data crunching, such as gathering information from multiple, secure, remote databases and generating sales projections. The HTML code was purposely kept simple so you can see how it works.

Note the use of back-slash characters inside the HTML String. They are necessary to embed quotes in the HTML commands. Leaving out even one will result in broken HTML code. When debugging your own version of this program, the JavaScript alert() method is a handy tool for finding errors in the HTML code. Use it to display the raw HTML String you are passing to the carrier page. That makes it easy to spot problems.

Listing HealthTest.html

Another debugging technique is to first use an HTML editor to create the page you want, putting dummy values where your dynamic data will go. When you're satisfied with how the page looks, import the HTML code into your Java String, put backslashes in front of the quote characters, and then replace the dummy values with String representations of your data.

Check out this example(please only enter integers in the fields provided), then have your own fun with this technique! It really is very, very powerful. How powerful? Consider that you now can use Java to dynamically create HTML pages that dynamically create JavaScript code, and that JavaScript code can run other Java programs that dynamically create other pages that dynamically modify the JavaScript code that...Whew. Like I said, have fun!

Carl Dreher is a contract electrical engineer specializing in digital design and embedded systems. He holds Bachelors degrees in Physics and Electrical Engineering from Rose-Hulman Institute of Tech., and a Master and Ph.D. in E.E. from University of Virginia. When not behind a keyboard, he can be found on the dance floor teaching English and Scottish Country Dancing or in the garage restoring a 1933 Morgan. You may contact him directly at FocusRsrch@aol.com.


1 2 3




Networking Solutions





Partners

  • Partner With Us














More for Developers

internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs