NOTE: Visual JavaScript PR2 ships with the Acadia JavaScriptBean Builder which you can also use to create JS components. The Acadia JavaScriptBean Builder is not described in this document, but it and its supporting documentation is delivered as part of the CDK.
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 document and window. For example:
// The "this.name" notation in the next line references the "name"
//property of the object this method was called from
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)
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. Visual JavaScript, however, provides the JSB files as a mechanism for creating a custom JavaScript component once, packaging it, and installing it on a Visual JavaScript palette where you can use it in any Visual JavaScript application merely by dragging it to the application and optionally setting its property values in the inspector. A JSB file is an SGML-based text file that formalizes the definition of a custom JavaScript object so that it can be used in different applications without requiring you to recreate it over and over again. The JSB file defines the properties, events, and methods for a component, and encapsulates the JavaScript constructor function necessary to create a JavaScript component. As previously noted, the JSB file structure is modeled on the Java 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 Visual JavaScript, that is not in a BeanInfo. For example, the following text illustrates how the JavaScript my_person_obj describes above might partially appear in a JSB file:
person2.name = person2_name // set a property value
person1.print() // call a method
<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, which is the JavaScript source of the component.
<JSB_DESCRIPTOR NAME="my_person_obj">
<JSB_PROPERTY NAME="name" 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.name = params.name // Set the "name" property
this.age = params.age // Set the "age" property
this.print = print_person // Set the "print_person" method
}
</JSB_CONSTRUCTOR>
</JSB>
NOTE: The my_person_obj does not have any events associated with it, but if it did, they would also be described in the JSB file with <JSB_EVENT> tags. For each event there would also be a corresponding listener interface (<JSB_LISTENER>). Listener interfaces process events, especially when those events are managed by other objects.
NOTE: In Visual JavaScript PR2 you can also use Acadia JavaScriptBean Builder to create JavaScript components.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. Within this pair, are embedded tags that define meta information for the component. For example, all components defined in a JSB file have tags that define:
<JSB>Depending on a component's event definitions, the JSB file usually also contains interface definitions that enable handling a component's events through an external object, such as another Java component. Interface definitions follow a component's definition. Each interface definition is placed within <JSB_LISTENER> and
<JSB_DESCRIPTOR ...>
<JSB_PROPERTY ...>
...
<JSB_EVENT ...>
...
<JSB_METHOD ...>
...
<JSB_PARAMETER>
...
</JSB_METHOD>
...
<JSB_CONSTRUCTOR ...> </JSB_CONSTRUCTOR>
</JSB>
...For example, here is the contents of the MailToLink JSB file. This is a very simple JavaScript component. For more examples, look at the JSB files provided as part of the CDK.
</JSB>
<JSB_LISTENER ...> </JSB_LISTENER>
...
<JSB>
<JSB_DESCRIPTOR NAME="netscape.sample.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_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>
<JSB_LISTENER NAME="onClickListener"For a complete description of the structure of a JSB file and a reference to the tags in can contain, see "JSB File Structure Reference".
<JSB_METHOD NAME="onClick" TYPE="java.lang.Void"
</JSB_LISTENER>
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:
After you define a property in a property tag, you must assign it to the component object in the constructor function for the component. If you expect other components will 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 Visual JavaScript inspector. The constructor function is wrapped by the <JSB_CONSTRUCTOR> tag. For information about creating a constructor function, see "Defining a Constructor Function".
For example, Visual JavaScript accesses a component property when a property connection is made from one component to another. In this case, the property on the target component is set using a write method, if one exists, or the syntax <object id>.<property name> = XXXX if a write method is not specified. Assigning values for some properties only makes sense 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 the ISRUNTIME attribute when defining the property. Visual JavaScript 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 Visual JavaScript 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.propertyThere are times, however, when it would be better to set a property set through a method call rather than directly. This can be accomplished by defining a write-method for the property. In other situations, you might want to have a property's value read through a method call rather than directly. For example, this would be useful when 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 READMETHOD and WRITEMETHOD attributes should be set to the name of the methods which implement the read and/or write-methods for the property. For example, here is a definition for a "msg" property, which contains a WRITEMETHOD attribute:
my_obj.property = some_other_variable
<JSB_PROPERTY NAME="msg" TYPE="java.lang.String"The read and write methods are themselves defined using the <JSB_METHOD> tags as illustrated above. The signatures of the functions should adhere to the following pattern, assuming the property type is java.lang.XXX:
PROPTYPE="JS"
WRITEMETHOD="setMsg"
ISBOUND
DISPLAYNAME="Message"
SHORTDESCRIPTION="Text message to scroll in status bar">
READMETHOD: java.lang.XXX <read-method>()
WRITEMETHOD: java.lang.Void <write-method>(java.lang.XXX)Read methods must always be prefaced with "get" and write methods must always be prefaced with "set". For example
getMsg()
setMsg()
<JSB_PROPERTY NAME="msg" TYPE="java.lang.String"Whenever the value for a bound property changes, the component must call an onChange event, defined as follows:
PROPTYPE="JS"
WRITEMETHOD="setMsg"
ISBOUND
DISPLAYNAME="Message"
SHORTDESCRIPTION="Text message to scroll in status bar">
<JSB>
...
<JSB_EVENT NAME="onChange" EVENTMODEL="JS"
LISTENERTYPE="onChangeListener"
LISTENERMETHODS="onChange">
...
</JSB>As this code illustrates, the onChange event method takes three parameters:
<JSB_LISTENER NAME="onChangeListener">
<JSB_METHOD NAME="onChange" TYPE="java.lang.Void">
<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>
</JSB_LISTENER>
<JSB_METHOD NAME="directionChange" TYPE="java.lang.String">This method returns a Java 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>".
<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>
The method function is the actual JavaScript function that implements the named method. There are no restrictions on the name of the function, as long as it is uniquely named on the page. To avoid naming conflicts, it is strongly recommended that the name of the method function match the name of the component itself, with a unique prefix or suffix attached. The method's signature must match the signature defined by the corresponding <JSB_METHOD> tags.
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, and 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: If the JSB file is actually a wrapper for a non-JavaScript component (e.g., a JavaBean component), and 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.
<JSB_EVENT NAME="directionChange" EVENTMODEL="JS"
Event definitions must also specify the EVENTMODEL attribute, which indicates to Visual JavaScript how it should connect components at run time in response to the triggering of the event. EVENTMODEL can be "JS" indicating a JavaScript event model where Visual JavaScript creates an event method on the fly, "AWT11" for events that use listener methods to connect components, or "HTML", as in the MailToLink example described earlier in this document. Components that define events that use the JavaBean event model interface, must also define listener methods using the <JSB_LISTENER> tag. To learn about defining the listener interface, see "Creating a Listener Interface for a Component".
LISTENERTYPE="directionChangeListener"
LISTENERMETHODS="directionChange">
If the EVENTMODEL is JS, then Visual JavaScript 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. The component developer needs only call this function whenever the conditions exist that the event should be fired. For example, suppose a component defines an event called "onRowChange" that is triggered every time a row in a database table changes, which happens anytime a next() or previous() function is 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 for event and property connections. A special event, named onChange, must be implemented for a component to be the source for property connections, as this is the trigger that is used to indicate that a property value has changed.
<JSB>
. . .
<JSB_EVENT NAME="directionChange" EVENTMODEL="JS"
LISTENERTYPE="directionChangeListener"
LISTENERMETHODS="directionChange">
. . .
</JSB>
<JSB_LISTENER NAME="directionChangeListener">The <JSB_EVENT> tag defines the event name, listener interface name and event method name of the event that occurs. The <JSB_LISTENER> tag is used to define the listener interface itself. It specifies the name of the listener interfaces, and always surrounds one or more <JSB_METHOD> tags that define the event methods within the interface. For more information about defining methods, see "Creating Methods for a Component".
<JSB_METHOD NAME="directionChange" TYPE="java.lang.Void">
<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>
</JSB_LISTENER>
Note that the <JSB_LISTENER> tag is contained outside of the <JSB> tag, at the top level of the JSB file. <JSB_LISTENER> is the only tag that is placed outside the scope of the <JSB> tag. The reason for this is to make the definition more like a Java Bean, where the listener interface would normally be created in a file separate from the BeanInfo.
Defining a Constructor Function
A JavaScript constructor function creates a new JavaScript object, either in the client or server environment. The name of the constructor function for a JavaScript component is the same as the name of the component in the <JSB_DESCRIPTOR> tag, except that package names are separated by underscores instead of periods. For example, the MailToLink constructor function is named netscape_peas_MailToLink, because it is in the netscape.peas package.
By convention, a constructor function takes a single argument that is a JavaScript object with properties that correspond to the component's properties as specified in the JSB. For example, here is the constructor function for MailToLink, a client component that creates a hyperlink to pop up a mail composition window:
function netscape_peas_MailToLink(params) {
Visual JavaScript automatically embeds the constructor function within the <SCRIPT> or <SERVER> tags, depending on whether a component runs on the client or the server, respectively.
Normally, the constructor function gets the property values based on what the user enters in the VJS Inspector. You should always initialize the value of a component's properties in the constructor function to prevent errors if another object attempts to retrieve property values from your component and the property values are not already set. The constructor function is called when an instance of the component is placed on the page. Visual JavaScript sets the properties of each instance using the settings of the object passed as an argument to the constructor call, for example:
str = "<A HREF='mailto:" + params.to + "?subject=" +
params.subject + "&cc=" + para "&bcc=" +
params.bcc + "` ONCLICK ='" + params.onclick + "`>" +
params.text + "</A>
document.write(str)
}_params_ = new Object();
This code is generated by Visual JavaScript.
A constructor function may return an object or not, depending on its purpose. The example MailToLink component creates a result string and writes out HTML. Constructor functions for other JavaScript components may return an object as well as t generating output.
_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); Packaging the JSB file into a JAR file
You must create a JAR (Java archive) file for JavaScript components, only if they comprise more than one file. Otherwise, creating a JAR file for a component is optional. Putting a component and its supporting files, if any, in a JAR file enables Visual JavaScript to import them when the component is imported to the palette, and to deploy them when a project is deployed.
To create a JAR file, you need the Java Developer's Kit (JDK) version 1.1, which you can download from the Javasoft site. Ordinarily, at least one of the files you put into a JAR file must be a JavaBean as defined in the JDK 1.0.2 transitional bean specification. A JavaScript component is considered a JavaBean for purposes of JAR file construction.
NOTE: You can also include external JavaScript (.JS) files (both server-side and client-side) in a JAR file.To create the JAR file using the JAR packager in the JDK, follow these steps:
Manifest-Version: 1.0
Name: sunw/demo/molecule/Molecule.class
Java-Bean: True
jar cfm jar-name manifest-name bean-name1 bean-name2...
jar cfm Avogadro.jar MANIFEST.MF sunw/demo/molecule/Molecule.classIf you did not need to create a manifest file in step 3, then the command to create a JAR file takes the form:
jar cfm jar-name bean-name..
jar tf jar-name
Last Updated: 07/08/97 10:46:14