Introduction

This is a brief guide for programmers using the library. Library maintainers will obviously need to be familiar with this material as well as well as the material in the Maintainer's Guide.This guide complements the API reference documentation.


Programming Paradigms

The library uses what some would call "multi-paradigm" programming, which basically means that we aren't entirely OO or entirely non-OO.

Many of the files, such as burst/Alg.js are just collections of "static" functions. The so-called classes in those cases such as burst.Alg would be treated as namespaces in C++ since they exist only to group symbols, and cannot be instantiate. We refer to these as "scoping" classes in the Class List .

Other areas are object-oriented, such as the widget classes.

There is also support for functional programming in burst.Functional , and you could consider rolling your own paradigm with burst.MOP .

For more about how we implement some of these paradigms, see Emulating Programming Constructs in ECMAScript 262-3 .


Directory Structure

A release contains a snapshot of the source tree, as well as a "build" directory which was made by a maintainer.

To use the library, at run time you only need the "build/burst/" and "build/burststatic" directories, as discussed in "URL Mapping" below.

The rest of the release is only of interest for documentation, or for maintainers.

Source Tree

The structure of what is under source control is:

  Makefile
  index.html             # home for public web site. has some links pointing into build/
  burst/                 # the library source directory. may be tested in place by make target "testsrc".
     Alg.js              # core source files
     ...
     webui/
        widgets/
           SortTable.js  # widget files
           ...
  burststatic/           # static content used by source scripts
     images/             # image files used by widgets
        ...
     html/               # html files used by widgets or Log.js
        BurstLog.html 
        ...
  docsrc/                # source files for documentation
  demos/                 # widget demos (runs in place, depends on build/)
  tools/                 # tools (runs in place)
  tests/                 # various kinds of tests
     testscripts/        # unit tests for the library
       test_URI.js
       ...
       webui/
         widgets/
            test_SortTable.js
     testdata/           # data files used by test scripts
       iframe_text_data.txt
       ...
     testbrowser/        # html files with browser tests (not library tests)

Build Tree

No make target ever alters anything in a directory under source control. A "make all" will populate a top-level directory "build" with this structure:

  build/
    doc/                   # generated or copied from source docsrc/
      intro.html       
      ...
    tooldoc/               # doc generated from source tools/
      jsunit_wrap.html 
    testhtml/              # generated html files for running tests, made from tests/
    apidoc/                # generated by doxygen
      html/
    doxysrc/               # the intermediary Java or C++ when doing 2-stage doxygen
    burst/                 # copied from source burst/, plus the generated burstlib.js
      burstlib.js          # if we supported partial sub-core library file loading, they'd be copied here too
      webui/
        widgets/
          ...
    burststatic/           # copied from source burststatic/
      images/
        ... 
      html/
        ...

Various versioned release tarballs are kept in the "releases/" directory.

URL Mapping

A web application using the library needs to expose the "burst" and "burststatic" directories at runtime. They are intended to be sibling directories, though it is possible to change this by adjusting the global variables BU_IMAGES_ROOT and BU_HTML_ROOT before loading the library (see the source code to ScriptLoader.js).

A programmer who wants to run library demos, run browser tests, and so on, should expose the entire tree (the parent of "build").


Anatomy of a web page

To use the library, a web page might be:

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  <html>
    <head>
      <title>My Web Page</title>
      <script language="JavaScript" type="text/javascript">
        var bu_AppConfig = {'burst.logging.Log.maxLevel' : 'DEBUG'};
      </script>
      <script src="wherever/burst/burstlib.js" language="JavaScript" type="text/javascript"></script>
      ...
    </head>
    <body>
    ...
    </body>
  </html>

To cut down on repetition across web pages, you may want to consolidate your configuration into a script:

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  <html>
    <head>
      <title>My Web Page</title>
      <script src="myarea/burstWrapper.js" language="JavaScript" type="text/javascript"></script>
      <script src="wherever/burst/burstlib.js" language="JavaScript" type="text/javascript"></script>
      ...
    </head>
    <body>
    ...
    </body>
  </html>

where burstWrapper.js is a file that you write that might contain something like:

    var bu_AppConfig = {'burst.logging.Log.maxLevel' : 'DEBUG'};

You could even reduce it further by putting:

    document.write('<script src="wherever/burst/burstlib.js" language="JavaScript" type="text/javascript"></' + 'script>');

in your wrapper and taking out of the web page.

Note that setting or changing bu_AppConfig after the library is loaded has no effect.


Configuration of Class Properties

As demonstrated above, the bu_AppConfig global variable may be set to contain bindings for fully-qualified class properties. It must be set prior to loading the library.

In a browser environment, the library will also look for class property settings in the query string (if any) of the document's url. This can be turned off by setting

  var bu_AppConfig = {'burst.Config.urlConfigDisabled': 'true'}

If enabled, settings in the url take precedence over any in bu_AppConfig, which in turn take precedence over the builtin defaults.

As of this writing, some modules that define class properties are: The entire library may be disabled (despite being loaded) by setting 'burst.Config.allDisabled': 'true' in bu_AppConfig. If this is done, there is currently no way to re-enable it. This is intended as a mechanism for testing "fallback html" in widgets, without disabling all javascript.


script element language and type attributes

The current situation regarding the language and type attributes of the html script element is a tricky mess.We decidedly do not support "JavaScript1.2", which was an aberration released by Netscape starting with Netscape 4.0, prior to edition 3 standardization. It has many subtle but important differences, including interpretation of "==", Array.toString(), and condition tests of Object primitives. Even now, declaring language="JavaScript1.2" will cause a Mozilla family browser to use that different language. You should instead use language="JavaScript", or language="JavaScript1.3".

IE5.5 and IE6.0 will not execute script elements with language="JavaScript1.5" if the element has no type attribute, despite their ability to do so. They will execute any script with type="text/javascript" or type="text/ecmascript", regardless of the language attribute. IE5.x and IE6.x will not run type="application/javascript". No IANA assignments have been made yet for javascript or ecmascript, so the type attribute is still premature, even though it is now required for DTD validation.

In the end, our current recommendation is to use:

    <code>script language="JavaScript" type="text/ecmascript"</code>


XML declaration and doctype declaration

Your choice to use an XML declaration and/or a doctype declaration will affect your browser's use of "quirks" mode, which may have implications both for its CSS implementation as well as its DOM and parse tree. Some of this behavior is known only through anecdotal lore, but for more information see for example: Just as an example of some of the unexpected behavior: in IE6, with a doctype, the standards-compliant document.documentElement member becomes available instead of document.body (see www.quirksmode.org/js/doctypes.html ). Such matters will affect any client-side DOM javascript programming, and users of this library are not exempt.

We do generally try to behave correctly regardless of quirks mode.


Use of body.onload

You are free to provide a value for the onload attribute of your body element. That is because our means of registering our own onload behavior is happily independent of the presence of any inline onload attribute. Furthermore, our hook will execute before yours does (in practice, that seems to be what our supported browsers do).

If you want to add an onload handler via script, we suggest that you use: burst.web.WindowEvent.addWindowOnload not so much because of conflicts (because by the time you'd have access to the function we'd have already used it), but because it deals with the vagaries of window.addEventListener, window.attachEvent, window.onload, or document.body.onload being available.


Widgets

An example inline constructor in an HTML page might be:

  ...
  <table border="1" id="t1" buType="SortTable" sortOnLoad="true">
    <thead><tr><th sortComparator='integer:10'>Numbers</th><th>Strings</th></tr></thead>
    <tbody>
      <tr><td>17</td><td>b</td></tr>
      <tr><td>3</td><td>a</td></tr>
      <tr><td>11</td><td>c</td></tr>
    </tbody>
  </table>
  ...

The buType Marker Attribute

The buType attribute marks an inline constructor of a widget. It must be present. Its value is the name of the constructor function (aka class) of the widget. It is typically the same as the basename (no '.js' suffix) of a file in the 'widgets' directory of the distribution and available from a browser in the 'webui/widgets/' sub-url underneath the url wherever the library was loaded.

Note that the default namespace for widget classes is "burst.webui.widgets". It is possible to specify some other namespace in a buType value [TBD].

Finding Inline Constructors

There are several alternatives for how to get the library to find and process your inline constructors:

The approaches which do not iterate over the page are clearly preferable. Note that if you are dynamically generating html, you can use a server-side variable to accumulate the ids of inline constructors, and at the bottom of the page add a script element like:

  <script language="JavaScript">burst.webui.WidgetManager.getAndProcessConstructorNodes('id1 id2 id3')</script>

where the argument to the function is server-side generated.

Loading Widget Scripts

If the widget constructor function specified in buType is defined, then the library of course does not attempt to load the script defining it. If the value of buType is not a known function, in most environments the library is capable of dynamically loading the particular widget script required.

For now however, it is best if you explicitly put a script element in the head of the page, such as:

   <script src="wherever/burst/burstlib.js" language="JavaScript" type="text/javascript"></script>   
   <script src="wherever/burst/webui/widgets/SortTable.js" language="JavaScript" type="text/javascript"></script>

Of course, as discussed above, these might be combined into your own application specific script file, so that each page loads only one file.

Widget Properties

Each widget supports a certain number of widget properties. In the example above, "sortOnLoad" is a widget property. The particular ones supported by each widget are documented in the per-widget reference documentation.There are several different ways to set them, including just specifying attributes of the same name in the top-level element of the inline constructor. For more information, see the documentation for the function AbstractWidget.parseProperties.

Fallback HTML

At least for those widgets that construct a new DOM sub-tree to entirely replace the inline constructor, it generally does not matter what the element type (tag name) is for the top-level element or (often) the tag names of its children. This is deliberate, so that the inline constructors can support "fallback html". That is, if the library is disabled (and/or no javascript is available), the page will still provide some interaction.

If the widget constructor is executed, unless otherwise documented, all of the element tag names, and all the attributes in the HTML namespace in the inline constructor are ignored.

Styling of Widgets

Widgets that merely add behavior but do not replace the inline constructor will naturally preserve any styling that exists.

As for widgets that replace their inline constructor, an exception to the general rule of not copying HTML attributes is that any class attribute in the top-level element of an inline constructor is copied over. (Any style attribute is not copied over, so if you do want styling that is specific to fallback HTML, that is the way to do it.) Note that depending on how the style sheet is defined, and whether the widget implementation happens to use the same top-level element type as the inline constructor, this class may or may not have the intended effect.Each widget that replaces its constructor will define a set of CSS class names that can be used to style the generated HTML that implements the widget. The convention for the names of these classes are:
   'BU' + WidgetName + '-' + role + '-' tagname
An example would be "BUComboBox-choice-option". (The reason for specifying the tagname as part of the CSS class name is that allowed CSS properties are dependent on the HTML element type, and so unfortunately it is necessary to expose that much of the implementation choices within the widget.)

Child Widgets

Some widgets support child widgets. For example, the SortTable widget supports a SortHead child. Similarly, a tree widget might support some sort of a node child widget. These child widgets may or may not be instantiable as top-level widgets. In general they are not of the same type as their parent.Some widgets will automatically search for particular HTML children in the inline constructor and create appropriate child widgets, without the child widgets having to have the buType marker attribute. In the SortTable example above, the widget is documented to automatically create SortHead children from the thead/th or thead/td children in the inline constructor.

DOM hierarchy and widget hierarchy

As can be seen from the above discussion, at least for those widgets that replace their inline constructor (versus just adding behavior to it), the page's DOM structure prior to execution of the inline constructors may differ substantially from what it is afterwards.

The "fallback html" may be replaced with entirely different HTML. For example, the fallback HTML for a menu may use an HTML "select", but a replacing widget implementation may use something else.

Note also that the parent-to-child widget hierarchy is relatively unrelated to the containment hierarchy within the DOM. In particular, the widget containment hierarchy may skip levels present in the inline constructor.

Caveats

Some caveats apply:

  1. Constructors with sub-widgets will typically require a strictly valid structure. for example, a table must have a thead and tbody. In any event, the implementation of implied nodes varies per browser and according to its "quirks" mode, so it is best not to rely on that.
  2. Some browsers will suppress a self-closing constructor such as:
       <div buType="Button"/>
    
    This is presumably because it concludes that the element has no use. The library won't be able to find it in the DOM.
  3. Likewise, some browsers will suppress an inline constructor that is well-formed but not valid. For example:
      <select buType="Menu"><div buType="Item"></div></select>
    
    So far, this behavior appears to be specific to child containment; the invalid attributes seem not to be an issue.
  4. You have to read the widget documentation carefully to see whether attributes that specify textual content support html or just plain text. In either case, the widget may or may not expect character entities (such as for ampersand) to already be expanded. In the case of html, the widget may require a DOM node if it is more than just character content, or it may accept a string (which again, may or may not have entities expanded).


Debugging

In order to debug problems, there are various approaches:

  In any browser, enable javascript error popups and/or the javascript console.
  In Mozilla, turn on strict JavaScript warnings.
  In Mozilla, use the JavaScript Debugger to trace all errors. 
  Enable debug logging within the library itself.

Debugging with a Browser

Some general comments on debugging in browsers are in http://www.quirksmode.org/js/intro.html

Some quick instructions::

  IE:
    "Tools => Internet Options => Advanced => Disable script debugging"
    Also, download the "Script Debugger" from http://msdn.microsoft.com/downloads/list/webdev.asp
  Mozilla/Netscape:
    "Tools => JavaScript Console" or "Tools => JavaScript Debugger".
    You may want to also set strict warnings via url "about:config".
    (Or, in some builds, go to Edit, Preferences, Debug, and check the
    box for "Show strict JavaScript warnings".)
  Opera:
    check 'Open JavaScript console on error' in File => Preferences => Multimedia 
  Konqeror:
    nothing supported. 
  Safari: 
    See developer.apple.com/internet/safari/safari_faq.html
    To enable the Safari debug menu: 
       "defaults write com.apple.Safari IncludeDebugMenu 1"
    View the log using Applications/Utilities/Console
  Ice:
    java -jar ICEsculptor_5.4.0_Trial/lib/icesculptor_trial.jar -Dice.debug.debug=true ice.ri.swing.Main 
    java -jar ICEsculptorOCS_5.4.0_Trial/lib/icebrowser_ocs_trial.jar -Dice.debug.debug=true ice.ri.swing.Main

You may also want to disable the cache in your browser while testing.

Performance Analysis

We suggest using the profiling abilities in the Mozilla JavaScript Debugger (Venkman).

Also see Jprof http://lxr.mozilla.org/mozilla/source/tools/jprof/README.html


Error Handling

Some of the functions in the library do throw exceptions. These are generally documented if the exception condition is out of the control of the programmer or the library (for example, the availability of some remote resource).

Exceptions may also be thrown if a library function is called with bad arguments; these exceptions are not documented. They are always of type BurstError or a subclass of it.