Applets may also be constructed to use techexplorer indirectly. Rather than
being passed a reference to a techexplorerPlugin or techexplorerControl
object, the applet may rely on JavaScript to handle communication with the external
techexplorer component. In this design, the applet only needs to provide
accessor methods to relevant data. For example, a get and set
method pair would be sufficient to modify or retrieve a TeX-formatted string from the applet,
which JavaScript would send to techexplorer.
It is not uncommon to write the Java source code simultaneously with JavaScript and HTML code. To help distinguish the different languages, blue will represent Java code, red will represent JavaScript code, and green will represent HTML code in this description page.
Note: This design can be used in all current versions of Internet Explorer and in Netscape 4. While later versions of Netscape support many features of Netscape 4 plugins, support for the LiveConnect technology used to implement techexplorer scripting is no longer available. See the Compatibility section for details.
Note: JavaScript calls to techexplorer in later versions of Netscape fail silently, returning empty strings without reporting errors or exceptions to the browser console windows. Plugin scripting support for these versions of Netscape is planned for a future release of techexplorer.
In creating an applet to interact with techexplorer via
JavaScript, the application can be arranged so the applet is not
technically aware that techexplorer exists. It provides
public methods to access certain data, but does not know what
code or objects are calling those methods. Minimally, the applet needs to
provide a get method so JavaScript can pull data from the
applet and hand it to techexplorer. A set
method should also be added to allow external control of the applet.
Additionally, we'd like the applet to display this raw data. In this
example, a java.awt.TextArea member named textarea
takes care of the display. The code for the creation and insertion of the
TextArea can be found in the
Java source file, along
with additional comments that have been removed from the methods displayed
in this page. The accessor methods used are copied below.
public String getCurrentString()
{
return this.textarea.getText();
} // ends getCurrentString(void)
public void setCurrentString(final String tex)
{
this.textarea.setText(tex);
} // ends setCurrentString(String)
In order to accommodate both the Netscape plugin model and the Microsoft ActiveX model, we use the traditional object/embed pair to place our target techexplorer component into the page.
<object classid="clsid:5AFAB315-AD87-11D3-98BB-002035EFB1A4"
name="te_control" width="400" height="200">
<param name="DataType" value="0" />
<param name="Data" value="\LaTeX sample" />
<embed type="application/x-techexplorer"
name="te_plugin" width="400" height="200"
pluginspage="http://www.integretechpub.com/techexplorer/"
texdata="\LaTeX sample">
<noembed>
<p>
Integre techexplorer Hypermedia Browser not installed!
Please visit the <a href="http://www.integretechpub.com/techexplorer/"
target="_blank">techexplorer home page</a>
for more information.
</p>
</noembed>
</embed>
</object>
We wrap the object tag around the embed tag so
Internet Explorer sees the object and therefore ignores the
internal embed tag. Similarly, Netscape doesn't understand
the object tag and so it continues inward to find the
embed tag. If the browser understands neither of these tags,
or does not have techexplorer installed, the
noembed contents will be displayed.
It's generally a good idea to have the attributes match up in both the
object and the embed tags. The width,
height, and texdata attributes will all affect
the initial appearance of the techexplorer component, and
you probably want them the same in whatever browser is being used. The
exception here is the name attribute, which
must be different in the two models. The object tag
refers to the techexplorer ActiveX Control as
"te_control", while the embed tag
refers to the techexplorer Plugin as
"te_plugin".
Of course, we'll also need an applet tag in the page somewhere. In our
example, the Java applet class name is AltCommLayer.
<applet code="AltCommLayer" width="400" height="150" mayscript="true">
<param name="texdata" value="\LaTeX sample" />
<p>
Java is either not installed or not enabled.
Please visit <a href="http://java.sun.com/"
target="_blank">Java's homepage</a>
for install information.
</p>
</applet>
As usual, we provide some text inside the applet tag in case the user either doesn't have Java, or has disabled it. If Java is enabled, the text will not be displayed.
The first task of the JavaScript is to determine which of the two
techexplorer components is being used in the HTML page.
To this end, we use a single global variable (which we initialize to
null) to house the reference to the component.
te=null;
Unfortunately, the system may not be completely ready when the JavaScript first executes. To allow for load-time synchronization, we'll shift the inspection code to a JavaScript function, which we may call whenever we're unsure of the component type or presence.
function assign_te()
{
if (document.te_plugin)
te = document.te_plugin;
else if (document.te_control)
te = document.te_control;
else
{
alert("Integre techexplorer not found. Please visit\n" +
"http://www.integretechpub.com/techexplorer/\n" +
"for the latest version.");
} // ends else
} // ends function assign_te(void)
Now we attempt to call this function using the onload event of the HTML body tag.
<body onload="assign_te();">
Additionally, and in case of initial failure due to load-time synchronization,
we can test the validity of the te variable and potentially
attempt to re-execute assign_te() whenever we need to access
techexplorer. Here is the method used to pass a new string
into the techexplorer component:
function setTeXString(latex)
{
if (te == null)
{
assign_te();
if (te == null)
return;
} // ends if
te.reloadFromTeXString(latex);
} // ends function setTeXString(String)
reloadFromTeXString is the method that replaces the
techexplorer content. Since we want to be able
to round-trip the data, we will use the printTeXInput
method to extract the current data from techexplorer.
function getTeXString()
{
if (te == null)
{
assign_te();
if (te == null)
return "techexplorer not found";
} // ends if
return te.printTeXInput();
} // ends function getTeXString(void)
Finally, there is the question of how to initiate an update using new data entered by the user. Since data can flow in to and out from the applet, the new data may be either in the applet's text area, or the techexplorer content may have been changed using the "Control properties..." option from the techexplorer right-click context menu. In our example we are interested in two different events: one to send data from the applet to techexplorer, and one to send data from techexplorer to the applet.
There are at least two ways to trigger the update events. The simplest is to insert HTML buttons
in the page which, when pressed, call the functions outlined above and interact with the applet.
We would have to provide the applet a name in the applet tag to use this design.
Assuming the name was foo, the HTML for the buttons may look something like this:
<input type="button" value="Update techexplorer"
onclick="setTeXString(foo.getCurrentString());" />
<input type="button" value="Update applet"
onclick="foo.setCurrentString(getTeXString());" />
In our example, we elected to use a slightly more complicated approach: the buttons to initiate
the update events reside within the applet itself. One benefit of this approach is that you
can make the buttons blend into your applet design, or have the event triggered automatically from a
Java TextEvent. In this design, the applet needs to be able to communicate with
the containing HTML page, which can be done using the netscape.javascript.JSObject
Java class. (Note that this technique will work in both Netscape and Internet Explorer.) We begin by
asking the JSObject class for a reference to the surrounding page.
JSObject html = JSObject.getWindow(this);
We should store this reference in a member variable so we can make calls out to JavaScript
whenever we'd like. Using the ActionListener interface, we could expect to see a method
similar to the following example to handle our button events:
public void actionPerformed(final ActionEvent ae)
{
final String command = ae.getActionCommand();
if (command == null || command.equals(""))
return;
else if (command.equals("broadcast"))
{
this.html.call("setTeXString",
new Object[] { this.getCurrentString() });
} // ends else if
else if (command.equals("receive"))
{
this.setCurrentString((String) this.html.call("getTeXString",
null));
} // ends else if
} // ends actionPerformed(ActionEvent)
The complete Java source for the AltCommLayer class can be found
here, and contains additional comments
for your assistance. The compiled example can be executed using the button below.
Integre techexplorer Hypermedia Browser is a trademark of Integre Technical Publishing.
Send comments and questions to
techexplorer@integretechpub.com.
Visit the official techexplorer home page at
http://www.integretechpub.com/techexplorer/.