BeanInfo
class for Java components. Each JSB file describes the properties, events, methods of a single component. It also usually describes one or more interfaces that can be used to process events, especially when the events are managed by other objects. Finally, each JSB file also contains a constructor function, which creates the component and defines its behavior at run time.
After you create a JSB file, you install the component on the VJS palette for use. If a component uses other files for support (such as JavaScript files or Java classes), then before you can install it on the palette, you must package the component into a JAR file, and install the JAR to the palette. Once a JavaScript component is installed on the palette you can use it without being concerned about its source. You can always examine the source for the component. From the View menu, choose Source.
You can develop client-side and server-side JavaScript components, and you can develop components that can run on either the client or server, or that run on both the client and server as needed. You can also develop components that make use of external Java objects to handle events. This document describes how to create these JavaScript components, and how to deploy them on the VJS palette so you can use them to build applications for your end users.
NOTE: On Windows platforms, the CDK ships with the Acadia JSBean Builder that you can also use to create JS components. The Acadia JSBean Builder is not described in this document, but it and its supporting documentation is delivered as part of the CDK. §
new
operator. For example, the following script fragment defines the my_person_obj
object, and then creates two instances of it:
function print_person() {Once you instantiate a custom object, you can access its properties and methods using the same notation you use for built-in JavaScript objects, such as
// The "this.name" notation in the next line references the "name"
//property of the object from which this method was called.
document.write(this.name + " is " + this.age + " years old")
}
function my_person_obj(name, age) {
this.name = name // Set the "name" property
this.age = age // Set the "age" property
this.print = print_person // Specify the "print_person" method
}
person1 = new my_person_obj("Walter", 54)
person2 = new my_person_obj("Betty", 35)
document
and window
. For example:
person1_age = person1.age // read a value from a propertyJavaScript is, however, an instance-based object model. Unlike Java, JavaScript does not have classes, inheritance, or a built-in component model. VJS, however, provides the JSB files as a mechanism for creating a custom JavaScript component once, packaging it, and installing it on a VJS palette where you can use it in any VJS application merely by dragging it to the application and optionally setting its property values in the inspector.
person2.name = person2_name // set a property value
person1.print() // call a method
BeanInfo
class for Java components. If you know and understand the BeanInfo
class, then you already know much about the JSB file structure. A JSB file also contains additional information, specific to VJS, that is not part of the standard BeanInfo
class.
For example, the following text illustrates how the JavaScript my_person_obj
described earlier might partially appear in a JSB file:
<JSB>As this example illustrates, a JSB file describes a single component in terms of its properties and methods. The JSB file also contains a constructor function, that is the JavaScript source of the component.
<JSB_DESCRIPTOR NAME="my_person_obj">
<JSB_PROPERTY NAME="fullname" TYPE="string">
<JSB_PROPERTY NAME="age" TYPE="string">
<JSB_METHOD NAME="print" TYPE="void"> </JSB_METHOD>
<JSB_CONSTRUCTOR>
function print_person() {
document.write(this.name + " is " + this.age + " years old")
}
function my_person_obj(params) {
this.fullname = params.fullname // Set the "fullname" property
this.age = params.age // Set the "age" property
this.print = print_person // Set the "print_person" method
}
</JSB_CONSTRUCTOR>
</JSB>
NOTE: Themy_person_obj
does not have any events associated with it. If it did, the events would also be described in the JSB file with<JSB_EVENT>
tags. For each event there would also be a corresponding interface (<JSB_INTERFACE>
). Interfaces process events, especially when those events are managed by other objects. §
NOTE: You can also use Acadia JSBean Builder to create JavaScript components. Acadia JSBean Builder ships with the CDK, and is available only on Windows platforms. §A JSB file consists of text tags that encapsulate a single component definition. The file format is plain text that can be parsed according to SGML rules. Tags are enclosed in angle brackets, and can be nested as appropriate. A component definition in a JSB file is enclosed by a
<JSB>
and </JSB>
tag pair. This pair encompasses all other tags that define meta information for the component. For example, all components defined in a JSB file have tags that define:
Typically, a skeleton JSB file looks like this:
<JSB>Depending on a component's event definitions, the JSB file usually also contains interface definitions that enable an external object, such as another Java component, to handle events. Interface definitions follow a component's definition. Each interface definition is placed in a
<JSB_DESCRIPTOR ...>
<JSB_PROPERTY ...>
...
<JSB_EVENT ...>
...
<JSB_METHOD ...>
...
<JSB_PARAMETER>
...
</JSB_METHOD>
...
<JSB_CONSTRUCTOR ...> </JSB_CONSTRUCTOR>
</JSB>
<JSB_INTERFACE>
tag.
<JSB>For example, here are the contents of the
...
<JSB_INTERFACE> ...
...
>/JSB>
MailToLink
JSB file, a very simple JavaScript component that provides an email interface for an application. For more examples, look at the JSB files provided as part of the CDK.
The MailToLink JSB File
<JSB>
<JSB_DESCRIPTOR NAME="netscape.peas.MailToLink" ENV="client"
DISPLAYNAME="MailTo Link"
SHORTDESCRIPTION="E-mail Hyperlink">
<JSB_PROPERTY NAME="to" PROPTYPE="JS" TYPE="string"
DISPLAYNAME="addressee (to)"
SHORTDESCRIPTION="Comma-separated list of addressees">
<JSB_PROPERTY NAME="cc" PROPTYPE="JS" TYPE="string"
DISPLAYNAME="copies (cc)"
SHORTDESCRIPTION="Comma-separated list of addressees">
<JSB_PROPERTY NAME="bcc" PROPTYPE="JS" TYPE="string"
DISPLAYNAME="blind copies(bcc)"
SHORTDESCRIPTION="Comma-separated list of invisible addressees">
<JSB_PROPERTY NAME="subject" PROPTYPE="JS" TYPE="string"
DISPLAYNAME="Subject"
SHORTDESCRIPTION="Subject of message">
<JSB_PROPERTY NAME="text" PROPTYPE="JS" TYPE="string"
DISPLAYNAME="Link text"
SHORTDESCRIPTION="Text displayed in link">
<JSB_EVENT NAME="onclick" EVENTMODEL="HTML"
LISTENERTYPE="onClickListener"
LISTENERMETHODS="onClick">
<JSB_METHOD NAME="onclick"> </JSB_METHOD>
<JSB_INTERFACE>="onClickListener"
<JSB_CONSTRUCTOR>
function netscape_peas_MailToLink(params) {
str = "<A HREF='mailto:" + params.to + "?subject=" +
params.subject + "&cc=" + params.cc + "&bcc=" +
params.bcc + "' ONCLICK ='" + params.onclick + "'>" +
params.text + "</A>"
document.write(str)
}
</JSB_CONSTRUCTOR>
</JSB>For a complete description of the structure of a JSB file and a reference to the tags it can contain, see JSB File Structure Reference.
Creating Properties for a Component
A JavaScript component can have zero or more public properties. A property is essentially a public data member of the component. Creating a property is a two-step process:
<JSB_PROPERTY>
tag. At a minimum, a property definition has the following attributes:
For a full description of the <JSB_PROPERTY>
tag and its attributes, see <JSB_PROPERTY>.
After you define a property in a property tag, you must write code in the constructor function to assign the property to the component object. If you expect other components to access the object's properties at run time, you can also, optionally, initialize the property values in the constructor. If you do not, you should initialize them in the VJS Inspector. The constructor function is wrapped by the <JSB_CONSTRUCTOR>
tag. For information about creating a constructor function, see Defining a Constructor Function.
For some properties, it makes sense to assign values only at run time. For example, the property that stores the current row number in a table, cannot be set at design time when a table is not being accessed. To designate a property that is set only at run time, specify theobject id.property name
=value
ISRUNTIME
attribute when defining the property.
VJS uses property definitions to construct an instance of a component. For example, if a component is defined with three properties named prop_a
, prop_b
, and prop_c
, then VJS automatically generates the following script for the component:
var params = new JSObject()
params.prop_a = "value user entered for a"
params.prop_b = "value user entered for b"
params.prop_c = "value user entered for c"
params.id = "MyComp1"
MyComp1 = new com_xxx_MyComp( params )
some_variable = my_obj.propertySometimes, however, it is be better to set a property set through a method call rather than directly. To do so, define a Write method for the property. You might also want to read a property's value with a method call rather than directly. For example, you should use a method to read a property value if the property value is calculated based upon other inputs, or when it is a constantly changing value outside the control of the component, such as a cursor position. In these cases, a Read method can be defined for the property, so that the property value can be correctly calculated and returned. You might also prefer to use Read and Write methods to trigger an event when a property's value changes. Defining a Read or Write method for a property is a two-step process: The
my_obj.property = some_other_variable
READMETHOD
and WRITEMETHOD
attributes should be set to the name of the methods that implement the Read and Write methods for the property.
For example, here is a definition for a msg
property, which contains a WRITEMETHOD
attribute:
<JSB_PROPERTY NAME="msg" TYPE="java.lang.String"The Read and Write methods are themselves defined using
PROPTYPE="JS"
WRITEMETHOD="setMsg"
ISBOUND
DISPLAYNAME="Message"
SHORTDESCRIPTION="Text message to scroll in status bar">
<JSB_METHOD>
tags as explained at Creating Methods for a Component. The signatures of the functions should adhere to the following pattern, assuming the property type is java.lang.
XXX:
READMETHOD: java.lang.XXX <read-method>()
WRITEMETHOD: java.lang.Void <write-method>(java.lang.XXX)
A Read method must always be prefaced with get
and a Write method must always be prefaced with set
, as in these examples:
getMsg()
setMsg() Making a Property the Source of a Property Connection
When a property is marked bound, it means that the value of that property may be linked to the property of another component. It is an indication that an onChange
event is triggered when the value of the property has changed or needs to be propagated.
To enable a property to be the source of a property connection is a two-step process:
onChange
event whenever the property value should be propagated.
ISBOUND
attribute to the property's <JSB_PROPERTY>
tag. For example:
<JSB_PROPERTY NAME="msg" TYPE="java.lang.String"When the value of a bound property changes, the component calls an
PROPTYPE="JS"
WRITEMETHOD="setMsg"
ISBOUND
DISPLAYNAME="Message"
SHORTDESCRIPTION="Text message to scroll in status bar">
onChange
event. An onChange
event is defined as follows:
<JSB>
...
<JSB_EVENT NAME="onChange" EVENTMODEL="JS"
LISTENERTYPE="onChangeListener"
LISTENERMETHODS="onChange">
...
</JSB>If the event model is "AWT11", then you must also include an interface declaration that specified the Java package and class that implements the event handler, such as:
...For more information about events, see Creating Events for a Component.
<JSB_INTERFACE="myhandler.onChangeListener">
</JSB>
Creating Methods for a Component
A JavaScript component can have zero or more public methods. Methods provide a way for other components to modify or control the behavior of the component through a defined interface. Methods are defined in <JSB_METHOD>
tags, and implemented in the <JSB_CONSTRUCTOR>
.
Adding a method to a component is a two-step process
<JSB_METHOD NAME="directionChange" TYPE="java.lang.String">This method returns a value that is a Java
<JSB_PARAMETER NAME="propertyName" TYPE="java.lang.String">
<JSB_PARAMETER NAME="oldValue" TYPE="java.lang.String">
<JSB_PARAMETER NAME="newValue" TYPE="java.lang.String">
</JSB_METHOD>
String
data type. Each of its parameters is also a Java String
data type. Return values and parameters can be based on Java classes, as in this example, or they can be JavaScript data types.
For a full description of the <JSB_METHOD>
tag and its attributes, see <JSB_METHOD> </JSB_METHOD>. For a complete description of parameter tags, see <JSB_PARAMETER>.Tip To view the methods associated with a component at design time in VJS, put a temporary button on a page, make a connection from the button to the component whose methods you want to examine, and choose View Parameters on the button. The Action drop-down lists the methods of the component. Select a method from the list to see its parameters. §The script between the
<JSB_CONSTRUCTOR>
tags must define all the functions, including the constructor function. The constructor function must assign the other functions to appropriate property. For example, a class that includes the methods next
and previous
would define <JSB_METHOD>
tags for these functions, embedding parameter tags as necessary. The constructor script would implement the methods as follows:
<JSB_CONSTRUCTOR>
function com_xxx_MyComp_next() {
//put code here
}
function com_xxx_MyComp_previous() {
//put code here
}
function com_xxx_MyComp( params ) {
this.next = com_xxx_MyComp_next
this.previous = com_xxx_MyComp_previous
}
</JSB_CONSTRUCTOR>Methods have access to all of a component's properties defined in the JSB file.
NOTE: The JSB file may be a wrapper for a non-JavaScript component (for example, a JavaBeans component). Not all of the component's actually properties are defined in the JSB file; methods also have access to those "private" properties not exposed in the JSB file. §
on
Eventname. For example, the event handler for a mouse button click is typically called onClick
.
Adding an event to a component is a three-step process:
onChange
and onFocus
events produced by text fields, but they represent component-specific conditions. Events are defined in a JSB file using the <JSB_EVENT>
tag. Events must be defined with a unique NAME
attribute. For a full description of the <JSB_EVENT>
tag and its attributes, see <JSB_EVENT>. The following code illustrates a typical event declaration:
<JSB_EVENT NAME="directionChange" EVENTMODEL="JS"
An event model must be specified for every event definition. There are two ways to define an event model:
LISTENERTYPE="directionChangeListener"
LISTENERMETHODS="directionChange">
EVENTMODEL
, its value can be JS
, AWT11
, or HTML
. JS
indicates a JavaScript event model where VJS creates an event method for you on the fly.Set EVENTMODEL
to AWT11
for events that use listener methods to connect components. You can also set EVENTMODEL
to HTML
when an event triggers an HTML-specific action, as in the MailToLink
example, Listing 3.1 The MailToLink JSB File.
If you create components that handle events through Java, then you must also specify the package containing the event handler methods using the <JSB_INTERFACE>
tag. To learn about defining this interface, see Creating an Interface for a Component.
If you set EVENTMODEL
to JS
, then VJS automatically generates the function whenever the user makes a connection to that event, and it assigns the function to the object as a method. Multicasting is supported because the generated function can contain any number of resulting function calls.You needs to call this function only when the event should be fired. For example, suppose a component defines an event called onRowChange
that is triggered every time the next
and previous
functions are called. The constructor script might look like this:
<JSB_CONSTRUCTOR>
function com_xxx_MyComp_next() {
. . .
this.onRowChange(0,0,0)
}
function com_xxx_MyComp_previous() {
. . .
this.onRowChange(0,0,0)
}
function com_xxx_MyComp( params ) {
this.next = com_xxx_MyComp_next
this.previous = com_xxx_MyComp_previous
}
</JSB_CONSTRUCTOR>
NOTE: Events allow a component to be the source of property connections. You must implement a special event, namedonChange
, for a component to be the source for property connections. TheonChange
event is the trigger that is used to indicate that a property value has changed. §
<JSB_EVENT>
and <JSB_INTERFACE>
tags to ensure this match.
For example, consider the following <JSB_EVENT>
and <JSB_INTERFACE>
definitions.
<JSB>
. . .
<JSB_EVENT NAME="directionChange" EVENTMODEL="JS"
LISTENERTYPE="directionChangeListener"
LISTENERMETHODS="directionChange">
. . .
</JSB>
<JSB_INTERFACE="myhandler.directionChangeListener"The
<JSB_EVENT>
tag defines the event name, the event model, the listener interface name, and the event method name of the event that occurs. The <JSB_INTERFACE>
tag identifies the Java package and class that defines the event handler.
SRC
attribute that points to a JS file that contains the necessary code.
A constructor function is defined between <JSB_CONSTRUCTOR>
and </JSB_CONSTRUCTOR>
tags. The parts of a constructor function include:
packagename_componentname
, where componentname
must match the name of the component specified in the NAME
attribute of the <JSB_DESCRIPTOR>
tag, except that all dots in that name must be replaced by underscores. For example, in Listing 3.1 The MailToLink JSB File, the <JSB_DESCRIPTOR>
has a NAME
attribute of netscape.peas.MailToLink
, so the corresponding constructor function name is netscape_peas_MailToLink
.
<JSB_CONSTRUCTOR>
In this example,
function netscape_peas_MailToLink(params) {
str = "<A HREF='mailto:" + params.to + "?subject=" +
params.subject + "&cc=" + params.cc + "&bcc=" +
params.bcc + "' ONCLICK ='" + params.onclick + "'>" +
params.text + "</A>"
document.write(str)
}
</JSB_CONSTRUCTOR>params
is the JavaScript object that represents the component's properties. The constructor function gets initial property values based on values you enter in the VJS Inspector at design time.You should always initialize the values of component properties in the constructor function. Such initialization prevents errors caused when another object attempts to retrieve property values for your component and the property values are not already set.
When you place a component on a page, VJS automatically embeds the constructor function within the <SCRIPT>
or <SERVER>
tags, depending on whether a component runs on the client or the server, respectively. The constructor function is called when an instance of the component is placed on the page. VJS sets the properties of each instance using the settings of the object passed as an argument to the constructor call, for example:
_params_ = new Object();
This code is automatically generated by VJS.
A constructor function may return an object or not, depending on its purpose. The example
_params_.to = "you@wherever.com";
_params_.subject = "Something Very Important";
_params_.cc = "foo@bar.com";
_params_.bcc = "";
_params_.onclick = "";
link1 = new netscape_peas_MailToLink(_params);MailToLink
component creates a result string and writes out HTML. Constructor functions for other JavaScript components may return objects and generate output.
Improving Application Speed with Smaller Constructors
At run time, the constructor code contained in a JSB file is duplicated on every application page that uses the component. If your constructor script is large, you can improve application performance by moving most of the script to a separate JS file. Then create a constructor that writes out the HTML to include the script. For example, the following code writes out a script contained myfile.js
:
<JSB_CONSTRUCTOR>
When you use this technique, the JS file is still read for every page that uses the component. After the first page is read, however, the script is read from the browser's cache rather than being downloaded again.
.
.
.
document.write("<SCRIPT SRC=myfile.js><\/SCRIPT>");
.
.
.
</JSB_CONSTRUCTOR>
NOTE:
If you use this technique, be sure to put both the JSB and JS files into a JAR file before
importing the component to the palette. Using a JAR file to package the component and
its supporting script file ensures that the FILEREFS
attribute for the component includes
the supporting file when you deploy your application. §
<JSB_CONSTRUCTOR SRC="SampleScrollingBanner.js">
</JSB_CONSTRUCTOR>
NOTE: If you create a JavaScript component that is contained in a single JSB file and does not have additional support files, you do not need to package the component in a JAR file before importing it.To create a JAR file, you need the Java Developer's Kit (JDK) version 1.1. Ordinarily, at least one of the files you put into a JAR file must be a JavaBeans component as defined in the JDK 1.0.2 transitional bean specification. A JavaScript component is considered a JavaBeans component for purposes of JAR file construction. For a complete set of instructions for packaging a JSB and its supporting files into a JAR file, see Packaging a Component.
When you install a JavaScript component that has support files into a VJS palette, VJS automatically adds a FILEREFS
attribute to the <SCRIPT>
tag containing the component code. Ordinarily you should not need to change the file list contained in the FILEREFS
attribute, but on rare occasion you may need to edit the list directly. For example, if you create a JavaScript component for handling image rollovers, you may well want to specify a different set of images for a component without needing to recreate the component itself. In this case, edit the FILEREFS
attribute directly.
Loading and Testing a Component
Once you package a JavaScript component into a JAR file, you can easily load the component into a VJS palette for testing, debugging, and use. The VJS Developer's Guide describes how to load a component into the palette. After installation, your component should now appear as an icon on the palette, where you can test and debug it.
Last Updated: 11/20/97 13:56:32