[Contents] [Previous] [Next] [Index]

## Chapter 3
Creating JavaScript Components

This document describes how to create, package, and import modular and reusable JavaScript components into Visual JavaScript (VJS) for use as application building blocks. The concept of JavaScript "components" is new. A JavaScript component is an encapsulation of a JavaScript object and its supporting properties, methods, and event in a text file called a JavaScript Bean (JSB) file. A JSB file makes a component transportable across tools that understand the JSB format, and it permits viewing and setting of component properties at design time, including establishment of property connections.

This document describes how to define a JavaScript component--and its properties, methods, and events--in a JSB file.

This document includes the following sections:

- What Is a JavaScript Component?
- Requirements for Creating JavaScript Components
- Understanding JavaScript Objects
- Creating a JavaScript Component
- JavaScript Component Examples

## What Is a JavaScript Component?

A JavaScript component is a set of related JavaScript functions, properties, and events and a JavaScript object that are encapsulated in a JavaScript Bean (JSB) file. The JSB file makes the JavaScript code it contains modular, reusable, and transportable. A JSB file both specifies the relationship between the main JavaScript object and its functions, properties, and events, and makes it possible for design time tools, such as VJS and Acadia JSBean Builder, to examine and set property values and connections through a visual property and event inspector.

The JSB file structure is modeled on the Java `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.

## Requirements for Creating JavaScript Components

To create JavaScript components you should be familiar with VJS, the JavaScript language, JavaScript objects, and the general principles of object-based programming. In particular, you should know how to use VJS to create applications, and you should understand the types of connections used by VJS. If you plan to create server-side components, you should also be familiar with server-side JavaScript and LiveWire.

To create JavaScript components, you must have a text editor, and you must install VJS on your machine. If you create multifile components, you also need the Sun Java Developer's Kit (JDK) 1.1 JAR packager. To test client-side components, you must also have Netscape Navigator 3.02 or Netscape Communicator 4.xx. To test server-side components, you must have Netscape Enterprise Server 2.0 or 3.x.

> 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. §

## Understanding JavaScript Objects

In JavaScript, components are implemented as custom JavaScript objects. In JavaScript you can define an object and its properties and methods using a constructor function, and then create instances of the object with the `new` operator. For example, the following script fragment defines the `my_person_obj` object, and then creates two instances of it:

    function print_person() {
       // 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)

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:

    person1_age = person1.age  // read a value from a property
    person2.name = person2_name  // set a property value
    person1.print()  // call a method

JavaScript 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.

## Translating Objects Into Components

You translate a JavaScript object into a modular, reusable component by encapsulating it in a JavaScript Bean (JSB) file. A JSB file identifies an object's properties, methods, and events in such a way that you can inspect them, set property values, and establish property connections among them using developer design-time tools, such as VJS or Acadia JSBean Builder, that recognize the JSB format

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 of a component, and encapsulates the JavaScript constructor function necessary to create a JavaScript component.

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 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>
       <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>

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.

> NOTE: The `my_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. §

## Creating a JavaScript Component

Creating a JavaScript component for VJS is an iterative, three-step process:

1. Creating a JSB File for a Component.

2. Packaging a Component into a JAR file. Note that this step is required only for multifile JavaScript components, such as those that use supporting JavaScript functions or Java classes located in other files.

3. Loading and Testing a Component.To install components into VJS from the Edit menu choose Edit Component Palette, and then choose Install JavaScript.

### Creating a JSB File for a Component

To define a reusable JavaScript component for VJS, you must create a JSB file that defines the component's properties, events, methods, constructor function, and listener interfaces. You can create a JSB file using any text editor.

> 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:

- Properties of the object. Depending on the component, some properties can be queried and set directly. Others require `Get` and `Set` methods. Properties are defined in a JSB file using property descriptors.

- Methods of the object, and parameters of the method. Methods are defined in a JSB file using method descriptors.

- Events to which scripts can be assigned, and that are evaluated by JavaScript when the trigger condition occurs. Events are defined in a JSB file using event-set descriptors

- Interfaces, that are used to process events. There is typically one interface for each event.

- A constructor that initializes the component and that either contains the actual code for the component's methods and events, or a constructor with a `SRC` attribute that points to the JS file containing the code.

Typically, a skeleton JSB file looks like this:

    <JSB>
       <JSB_DESCRIPTOR ...>
       <JSB_PROPERTY ...>
       ...
       <JSB_EVENT ...>
       ...
       <JSB_METHOD ...>
       ...
          <JSB_PARAMETER>
          ...
       </JSB_METHOD>
       ...
       <JSB_CONSTRUCTOR ...> </JSB_CONSTRUCTOR>
    </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_INTERFACE>` tag.

    <JSB>
       ...
       <JSB_INTERFACE> ...
       ...
    >/JSB>

For example, here are the contents of the `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:

1. Add a `<JSB_PROPERTY>` tag to the JSB file. The tag defines the name, property type, and data type of the property.

2. Assign the property to the component object via the constructor function. Often, the constructor also uses the property in some manner at run time.

To define properties in a JSB file, use the `<JSB_PROPERTY>` tag. At a minimum, a property definition has the following attributes:

- `NAME`, which specifies a unique name for the property in this component. The name you specify should not duplicate any JavaScript or JSB reserved words.

- `PROPTYPE`, which specifies how a property's value is bound.

- `TYPE`, which indicates the data type of the property. This can be a JavaScript data type, or a fully-qualified Java class.

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.

Depending on how you declare a property in a JSB file, other components can access the property in one of two ways:

- Directly, using the syntax `<objectid>.<property name>`. This is the default access method.

- Indirectly, through `Get` and `Set` methods that you specify with the `READMETHOD` and `WRITEMETHOD` attributes, respectively. If you specify these methods, you must also use `<JSB_METHOD>` tags to create matching method definitions.

For example, VJS accesses a component property when a property connection is made from one component to another. In this case, the property of the target component is set by a Write method, if one exists. If a Write method is not specified, you can assign a property value using standard JavaScript syntax, as follows:

    object id.property name = value

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 the `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 )

##### Creating Properties with Read/Write Methods

JavaScript component properties are read and written using the standard JavaScript "dot" notation syntax:

    some_variable = my_obj.property
    my_obj.property = some_other_variable

Sometimes, 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:

1. Add a `READMETHOD` or `WRITEMETHOD` attribute to the property's `<JSB_PROPERTY>` tag.

2. Create the named Read or Write methods.

The `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"
       PROPTYPE="JS"
    WRITEMETHOD="setMsg"
    ISBOUND
    DISPLAYNAME="Message"
    SHORTDESCRIPTION="Text message to scroll in status bar">

The Read and Write methods are themselves defined using `<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:

1. Mark the property as a bound property.

2. Create and trigger an `onChange` event whenever the property value should be propagated.

To mark a property as bound, add the `ISBOUND` attribute to the property's `<JSB_PROPERTY>` tag. For example:

    <JSB_PROPERTY NAME="msg" TYPE="java.lang.String"
    PROPTYPE="JS"
    WRITEMETHOD="setMsg"
    ISBOUND
    DISPLAYNAME="Message"
    SHORTDESCRIPTION="Text message to scroll in status bar">

When the value of a bound property changes, the component calls an `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:

    ...
    <JSB_INTERFACE="myhandler.onChangeListener">

    </JSB>

For more information about events, see Creating Events for a Component.

#### 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

1. Create the method definition using the `<JSB_METHOD>` tag. If the method takes parameters, embed each parameter definition in the method definition using `<JSB_PARAMETER>` tags.

2. Script the method function, and assign the function as a property in the component's constructor.

A method definition must specify the method name. If a method returns a value, the method definition must use the TYPE attribute to specify the data type of the return value. A method that takes parameters also contains embedded parameter definitions. For example, the following code defines a method that has three parameters and returns a value:

    <JSB_METHOD NAME="directionChange" TYPE="java.lang.String">
       <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>

This method returns a value that is 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>.

The method function is the 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.

> 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. §

#### Creating Events for a Component

Properties and methods allow your component to interact with other components. Other components can read and write your properties and call your methods, but not the other way around.

You can, however, denote events and create events handlers for your components that can respond to specific application events. An event is something that happens in the application, often as the result of a user action, such as clicking a button. An event handler is a function (and corresponding method definition) that is triggered when the event occurs. Usually event names take the form `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:

- Define the event and its interface.

- Define the event function that is called when the event is triggered.

- Trigger the event function from your constructor and methods when appropriate.

A JavaScript component can be defined as the source of zero or more events. An event is a component-defined trigger that can be used to initiate application activities. They are analogous to the JavaScript events produced by HTML objects, such as the `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"
       LISTENERTYPE="directionChangeListener"
       LISTENERMETHODS="directionChange">

An event model must be specified for every event definition. There are two ways to define an event model:

- Declare a default event model for the entire component in the `<JSB_DESCRIPTOR>` tag using the `EVENTMODEL` attribute.

- Override the default event model, or declare a specific event model type for each event by using the `EVENTMODEL` attribute with the `<JSB_EVENT>` tag.

Regardless of where you define `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, named `onChange`, for a component to be the source for property connections. The `onChange` event is the trigger that is used to indicate that a property value has changed. §

#### Creating an Interface for a Component

One goal of VJS is to allow the seamless interaction between JavaBeans and JavaScript components. The JavaBeans specification defines a specific mechanism for the firing and receiving events. This mechanism is based on the concept of event producers that trigger events, and event listeners, that respond to triggered events. To allow for the future integration of JavaScript and Java components, events produced by JavaScript components are also based on the same producer and listener concept.

In the JavaBeans model, event propagation works as follow:

- A source component that produces, or triggers, an event specifies a listener interface that defines the name and signature of the event method that should respond to the event.

- A target component that should receive an event registers as an event listener with the source component that fires the event. It also implements the event method, defined by the source component's listener interface, that handles--or responds to-- the event.

- When the source component fires the event, it calls its predefined event method for each registered listener. More than one event handler can respond to a single triggered event.

Because Java is a strongly typed language, the compiler can detect whether a component has implemented the correct interface to be the listener for a particular event. On the other hand, because JavaScript is dynamically typed, it is up to VJS to make certain that event producers and event listeners are properly matched. VJS uses the JSB `<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.

#### Defining a Constructor Function

A JavaScript constructor function defines a new JavaScript object, either in the client or server environment. This object represents the JavaScript component's functionality at run time. Each JavaScript component you create must have a constructor function defined in its JSB file, or the constructor tag must include a `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:

- a function name that must be in the form`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`.

- a single argument that is a JavaScript object with a set of parameters that correspond to the component's properties (each of which is previously defined in `<JSB_PROPERTY>` tags that appear before the `<JSB_CONSTRUCTOR>` tag in the JSB file).

- an optional return value.

For example, here is the constructor function for The MailToLink JSB File, a client component that creates a hyperlink to display an email composition window:

    <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>

In this example, `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();
    _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);

This code is automatically generated by VJS.

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 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>
       .
       .
       .
       document.write("<SCRIPT SRC=myfile.js><\/SCRIPT>");
       .
       .
       .
    </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.

> 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. §

#### Permitting a Component to Run on the Server or Client

You can create a component capable of running either on the server or on the client. If you do so, you must:

1. Place the code for the `<JSB_CONSTRUCTOR> </JSB_CONSTRUCTOR>` tag pair in a separate JS file, and specify that file in the `SRC` attribute of the constructor in the JSB file.

2. Set the `ENV` attribute for the `<JSB_DESCRIPTOR>` tag to "`either`".

You must store the JS file in the package root on the server so that when the server compiles a web file containing your component the server can find the necessary constructor code.

For example, suppose you create the SampleScrollingBanner.js to contain the constructor code for the sample scrolling banner component. The constructor in the corresponding JSB file must look like this:

    <JSB_CONSTRUCTOR SRC="SampleScrollingBanner.js">
    </JSB_CONSTRUCTOR>

### Packaging the JSB file into a JAR file

You must create a Java archive (JAR) file for JavaScript components only if they comprise more than one file. Putting a component and its supporting files, if any, in a JAR file enables VJS to import the support files when the component is imported to the palette, and to deploy them when a project is deployed. For example, if a JavaScript component or its constructor or helper methods make use of functions you have defined in external JavaScript (JS) files on the client- or server-sides, you must package the component and its supporting files in a JAR file prior to import.

> 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.

Typically, you will fix and refine your component a number of times before you consider it ready for production use. Although you can make changes to the original JSB file, repackage it into a new JAR file, and load the new version of the component into VJS, you can also avoid repackaging and reloading by following these steps:

1. Locate your JSB file under the VJS `install` directory. It is located in a sub-directory tree named after the component's package name, off the install directory. For example, if your component exists in the `acme.components` package, the component's corresponding JSB is placed in the directory `<INSTALLROOT>/acme/components`.

2. Edit the JSB file directly under the VJS `install` directory.

3. Restart VJS after each revision.

## JavaScript Component Examples

VJS contains ready-made JavaScript components that you can study and use. The JSB files for the JavaScript components packaged with VJS are also included in the CDK. These examples demonstrate common and sophisticated uses of JavaScript components.

[Contents] [Previous] [Next] [Index]

Last Updated: 11/20/97 13:56:32

Copyright © 1997 Netscape Communications Corporation