Back Forward CDK Home Reference Samples Resources
HelloWorldJSB

 Building the HelloWorldJSB Component

This simple example illustrates how easy it is to take JavaScript code and package it as a JavaScript Bean. By simply adding a couple of lines of HTML-like (SGML) descriptive tags around your JavaScript functions, it is possible to create a JavaScript Bean (JSB) re-usable component which can be used in visual web-application development tools like Netscape's Visual JavaScript.

Take a look at the JavaScript below to popup an alert:

        alert("Hello World!");

This is placed in a JSB by first creating a pair of JSB tags (these are similar to the <HTML> and </HTML> tags that go at the top and bottom of an HTML page:

<JSB>

</JSB>

A JSB Descriptor tag is used to reflect the name of the JSB, which must match the name of the file:

<JSB>
    <JSB_DESCRIPTOR NAME="HelloWorld">

</JSB>

Next comes the JSB Constructor, which contains the heart of your JSB.

<JSB>
    <JSB_DESCRIPTOR NAME="HelloWorld">
    <JSB_CONSTRUCTOR>
    function HelloWorld(params) {
        alert("Hello World!");
    }
    </JSB_CONSTRUCTOR>
</JSB>

The constructor gets called whenever an instance of HelloWorld appears on a page, therefore simply placing this component on a page and loading the page in a browser will cause the JavaScript Alert "Hello World!" to appear.

Take a look at the first completed file:

The real power of JSBs is when object oriented techniques are used. The first step is to place the HelloWorld JSB into a namespace which allows the component to be re-used along with other components without having to be overly concerned about naming conflicts. The name becomes extended to reflect the location of the file in a directory. Proper namespace practices are an extremely important part of building re-usable, modular components; namespace conflicts can limit the reusability of your component.

Here the HelloWorld JSB is placed into a package called "netscape.samples.helloworld" which must sit in a directory structure of "netscape/samples/helloworld". The actual JSB file is located in "netscape/samples/helloworld/HelloWorld.jsb". This is very similar to the Java method of creating package namespaces. Any JavaScript functions in the JSB should now be prepended with an underscored version of the package namespace. For example, the constructor function:

becomes:

This way, if another JSB wanted to use a HelloWorld constructor on the same page as this component, it could as long as the JSB used a different namespace.

<JSB>
    <JSB_DESCRIPTOR NAME="netscape.samples.helloworld.HelloWorld">
    <JSB_CONSTRUCTOR>
    function netscape_samples_helloworld_HelloWorld(params) {
        alert("Hello World!");
    }
    </JSB_CONSTRUCTOR>
</JSB>

Next, lets add a private method to also write a string to the Java console, and move the alert to a function called "displayMessage" which writes the message to the console and pops up an alert.

A "JSB_METHOD" tag is introduced below, to indicate that the "displayMessage" method is public and can be called by other components. The JSB_METHOD tag appears below the descriptor, and outside of the JSB_CONSTRUCTOR tags. Its purpose is to declare the types and names of public methods in order for them to be exposed in visual application building environments. The private function "_netscape_samples_helloworld_sysout" starts with an underscore to keep it in a distinguished namespace while also denoting its private nature; it is not declared with a JSB_METHOD tag (if it were, it should not start with an underscore) and is not meant to be called by other components.

Also note that Java-style comments are also included -- this is so that the JSB can use the JSBDoc tool included in the CDK to build JavaDoc style documentation for the component.

<JSB>
    <JSB_DESCRIPTOR NAME="netscape.samples.helloworld.HelloWorld">

    <JSB_METHOD NAME="displayMessage" TYPE="void"> </JSB_METHOD>

    <JSB_CONSTRUCTOR>


    function netscape_samples_helloworld_HelloWorld_displayMessage(messageString) {
        alert(messageString);
        netscape_samples_helloworld_HelloWorld_displayMessage(messageString);
    }

    /**
     * This is the constructor
     */
    function netscape_samples_helloworld_HelloWorld(params) {
        netscape_samples_helloworld_HelloWorld_displayMessage("Hello World!");
    }

    /**
     * This is a private function to output
     * text to the Java console.
     */
    function _netscape_samples_helloworld_HelloWorld_sysout(tempString) {
        java.lang.System.out.println(tempString);
    }

    </JSB_CONSTRUCTOR>
</JSB>

It would be convenient to have a property that could be set by other components that contained the message to be displayed. Now we need to start worrying about actually following the JSB spec and creating an instance of our object in the constructor, which is done below in addition to adding a JSB_PROPERTY tag which describes the "theMessage" property. This property gets passed in via the "params" object which gets passed to all constructors by default; attached will be values for all the parameters declared by parameter tags -- in most cases, the user of your component will use a visual tool like Visual Javascript to set these properties visually (a Customizer can also be packaged with you component which can make it even easier for end-users of your component to set properties -- see the Custom JSB sample for more information). Default values may also be included in a parameter tag. Comments for a JSB Property should go directly above the JSB_PROPERTY tag.

<JSB>
    <JSB_DESCRIPTOR NAME="netscape.samples.helloworld.HelloWorld">

    /**
     * The message displayed by this JSB
     */
    <JSB_PROPERTY NAME="theMessage" TYPE="string" DEFAULT_VALUE="Hello World!">

    <JSB_METHOD NAME="displayMessage" TYPE="void"> </JSB_METHOD>

    <JSB_CONSTRUCTOR>

    /**
     * Displays the currently set message and
     * writes it to the Java Console.
     * This is called once in the constructor,
     * and can then be called again by other components.
     * @see theMessage
     */
    function netscape_samples_helloworld_HelloWorld_displayMessage() {
        alert(this.theMessage);
        this.sysout(this.theMessage);
    }

    /**
     * This is the constructor
     */
    function netscape_samples_helloworld_HelloWorld(params) {
        // Assign the params.theMessage value
        // to a "message" property for the "this" object
        // which it is the constructor's responsibility
        // to populate with all properties and methods
        // declared in the JSB_PROPERTY and JSB_METHOD
        // tags above.
        this.theMessage = params.theMessage;

        // Notice that the namespace is eliminated
        // when assigning the method -- this
        // makes it easier to reference methods through
        // the instance of this JSB object, while
        // preserving namespace collision protection
        this.displayMessage = netscape_samples_helloworld_displayMessage;

        // It is a good idea, though not mandatory, to assign
        // private functions as well; it is only mandatory if they
        // must be instance as opposed to static functions.
        // This also allows us to call
        //      this.sysout
        // instead of
        //      _netscape_samples_helloworld_HelloWorld_sysout
        //
        this.sysout = _netscape_samples_helloworld_HelloWorld_sysout;

        // Now, to pop up a message on construction
        // one writes:
        this.displayMessage(this.message);
    }

    /**
     * This is a private function to output
     * text to the Java console.
     */
    function _netscape_samples_helloworld_HelloWorld_sysout(tempString) {
        java.lang.System.out.println(tempString);
    }

    </JSB_CONSTRUCTOR>
</JSB>

All this extra work makes it possible for the end-user of the component to drag and drop the component easily onto a page and wire it up into a web application, all without further programming. See how easy it is to wire a textfield's property change event to set the string displayed by our component:

Similarly a button can be wired up to trigger the display of the current message:

Take a look at the packaged and slightly expanded version:

To make it easier for developers to add professionalism to a JSB, it is easy to package a JSB into a JAR file. This way, the JSB and any supporting elements (icons, documentation, AWT Customizers, images and HTML pages used by more complex JavaScript Beans) can be packaged together in one convenient format.

Adding a HELP_URL to the JSB_DESCRIPTOR and packaging the component in a JAR file allows end-users of the component to get more help easily within a tool.

The help that is brought up can contain more information about the component, perhaps even a link to the JSBDoc for the JavaScript Bean (see the JSBDoc Tool for more information):

<JSB>
    <JSB_DESCRIPTOR NAME="netscape.samples.helloworld.HelloWorld"

     HELP_URL="netscape/samples/helloworld/HelloWorld.html">
...

Now all that one needs is a Manifest file to indicate which file is the JavaScript Bean component:

Manifest-Version: 1.0

Name: netscape/samples/helloworld/HelloWorld.jsb
Java-Bean: True

If we put the above manifest in a file called HelloWorld.mf, we can create a batch file or shell script that does the following:

jar cfm HelloWorldJSB.jar HelloWorld.mf netscape/samples/helloworld/*

Take a look at the CustomJSB example for more information on packaging JavaScript Beans into professional components that make it easier than ever for end-users to visually assemble Crossware Web Applications.


( return to the top of the page )