Skip to main content

Create Web applets with Mozilla and XML

Mozilla's simple and flexible XUL saves time when building Java-less applets

Nigel McFarlane (nrm@kingtide.com.au), Analyst, programmer, writer
Nigel McFarlane is a science and technology writer, analyst, and programmer. His broad range of experience includes IT, software, telecommunications, the Internet, and physics. He is the author of numerous articles and several books on XML and scripting technologies; his latest book is Rapid Application Development with Mozilla. Nigel lives in Melbourne, Australia. You can reach him at nrm@kingtide.com.au.

Summary:  To go beyond simple HTML, historically the only options have been to use Java technology or plug-ins. Now, you have a new way -- write and display applications natively in XML. The Mozilla platform provides such a mechanism. In this article, Nigel McFarlane introduces XUL (the XML User-interface Language). XUL is set of GUI widgets with extensive cross-platform support that are designed for building GUI elements for applications that have traditional, non-HTML GUIs.

Date:  21 Oct 2003
Level:  Introductory
Activity:  3464 views

The Mozilla platform is a bundle of freely available open source technology that underlies many user-oriented software applications. Some of these applications are desktops and some are development tools, but the most famous ones are Web browsers, including Mozilla, AOL for the Macintosh, Galeon on Linux, and Netscape.

Although these browsers are mostly used to display HTML, the platform beneath them offers much more. In particular, the Mozilla platform's extensive support for XML provides an alternative to Java technology for the creation of applets and applications. In this article, I'll demonstrate how to create such applets using XML tags instead of Java classes. It is a refreshingly simple, yet powerful approach.

Although the Mozilla platform has its share of object classes (more than a thousand at last count), it is best known for its deep use of XML. For some flavors of XML (like XHTML), the platform provides full rendering support while for other flavors (like RDF), it provides support for data processing only. Rendering support is required if an XML document is to have a visual representation. The platform has rendering support for HTML/XHTML, MathML, optionally SVG, and also its own XUL, covered in this article.

Why XUL?

XUL, the XML User-interface Language, (pronounced "zool" when you're with the cool) is to the Mozilla Platform what Swing is to the Java environment or what Gtk is to X-Window. It is a set of GUI widgets. These widgets are suitable for applications that have traditional, non-HTML GUIs. The menus, toolbars, scrollbars, and dialog boxes of many Mozilla-based browsers are built using XUL documents.

XUL has extensive cross-platform support -- a Macintosh menu looks like a Macintosh menu and a GNOME button looks like a GNOME button. To perform this task, XUL relies heavily on the current platform's native widgets. This strategy is similar to that used by the IBM-backed Eclipse development tool. The similarity is limited though, because Eclipse ultimately expresses GUI widgets as Java classes, whereas Mozilla expresses them as tags in the XUL dialect of XML.

Why does XUL exist? Mostly because HTML is great for displaying hypertext documents, but terrible for displaying GUIs. Traditional Web-based applications use endless amounts of effort trying to shoehorn HTML into the look-and-feel of a traditional forms-and-menus application. That was never a purpose for which it was intended.

The addition of form elements to HTML (FORM) did little more than create a new way to implement thin-client block-mode applications in the style of the venerable 3270 terminal. Like the 3270, HTML provides batched-up form submission. Character-based applications ultimately gained efficient user-navigation systems, but that was all lost when GUI applications came along. Subsequently GUI applications added back their own navigation structures, using the mouse and widget feedback.

When HTML forms came on the scene, they copied the design of block-mode terminals, but without the tight navigation and without replacing it with a proper GUI equivalent. Under HTML, the user is left to guess which visual elements on a given page might be user controls and which are just decorations. Therefore, for GUI-driven applications, HTML isn't that great a starting point. That's the reason why Java applets were met with such positive market hysteria when they first appeared -- they presented an opportunity to provide a real GUI.

Now there is XUL. XUL takes the very-thin-client model of HTML and thickens it up a bit. Instead of a trivially few form elements, as any ultra-thin client might offer, XUL provides a full set of widgets typical of a more complex piece of client software.

In the past, such client software might have been written as a Java application, perhaps in Tcl/Tk or in Visual Basic. Now thicker clients can be implemented as one or more XUL documents and delivered over the Web (or just processed locally). The application is expressed to begin with as a document rather than as a set of objects. That document is read by a running copy of the Mozilla platform which displays the specified GUI for the user's consumption.

Thus, XUL combines the lightweight attractiveness of HTML with the structured usability of traditional GUIs.


A closer look at XUL

What does XUL look like? Look at any Mozilla window except the browser window (such as the e-mailer or the Address Book). In this article I illustrate XUL with a simple trouble-ticketing system, such as any support center might provide to its users. Those users can then supply feedback on documentation lodged on an intranet or extranet. Depending on your viewpoint, this is an applet, a dialog box, or an embedded application -- you'll see as I continue.

Listing 1 shows the XUL code behind this system.


Listing 1. The XUL code example for a trouble-ticket system
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="ticket.css" type="text/css"?>

<!DOCTYPE window>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <script src="init.js"/>
  <script src="commands.js"/>
  <script src="server.js"/>

  <toolbox>
    <menubar id="menubar" grippyhidden="true">
      <menu id="menu_login" accesskey="L" label="Login">
        <menupopup>
          <menuitem id="m10" label="Login" accesskey="L" 
                oncommand="cmd_login()"/>
          <menuitem id="m11" label="Logoff" accesskey="O" 
                oncommand="cmd_logoff()"/>
          <menuitem id="m12" label="Exit" accesskey="X" 
                oncommand="cmd_exit()"/>
        </menupopup>
      </menu>

      <menu id="menu_ticket" accesskey="N" label="New Ticket">
        <menupopup>
          <menuitem id="m20" label="User Ticket" accesskey="U" 
                oncommand="cmd_user()"/>
          <menuitem id="m21" label="Technical Ticket" accesskey="T" 
                oncommand="cmd_tech()"/>
          <menuitem id="m22" label="Reviewer's Ticket" accesskey="R" 
                oncommand="cmd_rev()"/>
        </menupopup>
      </menu>

      <menu id="menu_action" accesskey="A" label="Action">
        <menupopup>
          <menuitem id="m30" label="Clear" accesskey="C" 
                oncommand="cmd_clear()"/>
          <menuitem id="m31" label="Submit" accesskey="S" 
                oncommand="cmd_submit()"/>
        </menupopup>
      </menu>

      <spacer flex="1"/>

      <menu id="Help" accesskey="H" label="Help">
        <menupopup>
          <menuitem id="m40" label="Help Contents" accesskey="H" 
                oncommand="cmd_help()"/>
          <menuitem id="m41" label="Contact Details" accesskey="D" 
                oncommand="cmd_contact()"/>
          <menuitem id="m42" label="About" accesskey="A" 
                oncommand="cmd_about()"/>
        </menupopup>
      </menu>
    </menubar>
  </toolbox>

  <hbox class="title">
    <deck id="title">
      <label value=""/>
      <label value="User Problem"/>
      <label value="Technical Problem"/>
      <label value="Review Status"/>
    </deck>
    <spacer flex="1"/>
    <label value="Ticket #"/>
    <textbox id="f00" readonly="true" size="10"/>
  </hbox>

  <deck id="forms" flex="1">
    <vbox/>
    <vbox>
      <checkbox id="f10" label="Information Missing"/>
      <checkbox id="f11" label="Errors Discovered"/>
      <checkbox id="f12" label="Please Send Author's E-mail"/>
    </vbox>
    <vbox>
      <label>Please describe the nature of the problem.
        Your client's version will be automatically reported</label>
      <textbox id="f20" multiline="true" rows="6"/>
    </vbox>
    <vbox>
      <radiogroup>
        <radio id="f30" label="draft approval"/>
        <radio id="f31" label="final draft"/>
        <radio id="f32" label="publication approval"/>
      </radiogroup>
    </vbox>
  </deck>

  <statusbar id="sbar">
    <description>Current Status:</description>
    <deck id="stext" selectedIndex="0">
      <description id="sb0" class="warn">Disconnected</description>
      <description id="sb1" class="ok">Logged On</description>
      <description id="sb2" class="ok">Delivered</description>
      <description id="sb3" class="warn">Delivery Failed</description>
    </deck>
    <spacer flex="1"/>
  </statusbar>
</window>

This listing is hardly larger than a single Java class, and yet it is an application's entire GUI. XUL provides convenient brevity. The tags, like toolbar, menu, textbox, and radiogroup are refreshingly simple -- no 3GL calls are required to XCreatePixmapFromBitmapData() or other low-level agony.

Many of the tags provide invisible structure: toolbox, hbox, and vbox are container tags that affect layout of their collected elements (for example, "vbox" is short for "vertical box"). This containership appears frequently in XUL: a toolbox contains a menubar which contains several menus, each of which provides a menupopup drop-down menu, and that menupopup holds a number of menuitem menu items. Of the other tags, the spacer tag is used to create extra gaps between screen elements. The label and description tags are specialized equivalents to HTML's <p>. Unfortunately, I don't have room to cover every possible XUL tag here.

Some of the attributes used in XUL tags are shared with HTML, such as id, class, value, accesskey, readonly, and selectedIndex. Others are special to XUL, like grippyhidden (which stops a menu bar from being hidden by the user) and oncommand (which is an event handler that fires when a menu option is chosen).

Mozilla's registered name for the XML application is given by the URL in the window tag at the top; this is a product identifier and is not loaded from anywhere. Some of the content of this XUL document can be seen in Figure 1:


Figure 1. The opening XUL page
The opening XUL page

This plain XHTML document deploys the applet in three ways:

  • A hyperlink.
  • A button.
  • An XHTML iframe

The embedded applet appears in the bottom half of the shot. You can see that its menu bar looks similar to the menu bar of the entire browser window. In fact, they are implemented as different instances of the menubar tag. Just as for the main browser menu bar, the applet menu bar is responsive to the mouse, tab-key-style navigation, and hot-key combinations. This integration comes for free, something that doesn't happen with a Java applet. A Java applet doesn't have a URL of its own either; it must always be initialized by an applet or an object tag.

The XHTML that hosts this applet is shown in Listing 2 and is just a trivial use of HTML event handlers and iframe.


Listing 2. The XHTML that hosts the applet
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script>

      var flags = "toolbar=no,locationbar=no,menubar=no,width=275,height=275";

      function show()
      {
        window.open('ticket.xul', '_blank', flags);
      }
    </script>
  </head>
  <body>
    <h2>Test Page</h2>
      <p>
          A hyperlink that starts the example
          in a separate window:
          <a href="about:blank" 
                onclick="show(); return false">Lodge Ticket</a>.
      </p>
      <p>
          A button that starts the example
          in a separate window:
          <button onclick="show()">Lodge Ticket</button>.
      </p>
      <p>
        Here is the ticket entry system displayed in
        an <iframe>:
      </p>
        <iframe width="275" height="275" src="ticket.xul"/>
  </body>
</html>


Integration between XUL and XHTML

Some of the integration between XUL and XHTML is quite beautiful:

  • First, since the Mozilla platform is responsible for rendering both XML dialects, the dreaded delay that occurs when Java's applet system initializes never occurs.
  • Second, navigation is the same for the XUL applet as it is for the entire browser -- the user does not need to learn a new set of interactions.
  • Third, Mozilla's excellent CSS2 stylesheet support, originally intended for XHTML, also applies to XUL. This means that such an applet normally picks up the default look-and-feel of the browser (in this case the Modern theme).

The required stylesheets are hauled in using the ?xml-stylesheet? declarations from the top of Listing 1. The first declaration hauls in the standard stylesheet for the current theme and the second declaration adds a stylesheet that is custom-created for the applet. Its code looks like this:


Listing 3. The simple cascading stylesheet code
.ok { color : green; }
.warn { color : red; }

.title { margin-bottom : 20px; }

hbox { -moz-box-align : end; }

This is standard CSS2, except for -moz-box-align which is a Mozilla extension that provides an XUL layout hint. In this case, that hint says to right-justify the content.

In the case of a Java applet, a CSS-rendering library separate from Mozilla's library is required if stylesheet support is to be available. Use of such a library radically expands the size of the applet.

Figures 2 and 3 are two more screen shots of the applet at hand, one embedded and the other as a separate dialog window.


Figure 2. The applet embedded
The applet embedded

Figure 3. The applet as a separate dialog window
The applet as a separate dialog window

XUL ignores several irritating restrictions of HTML. You can stack form elements atop each other and the ones beneath are properly hidden (the deck tag does that, much like a hypercard stack). That is how this applet allows several sets of content to alternate in one pane. In HTML, that is impossible to specify statically and requires messy Dynamic HTML if it is to be achieved at all. You can change the color or content of the status bar at the bottom, another task that's also not possible in HTML.

XUL is not some faked-up form of Dynamic HTML either; the menu system can overlay surrounding HTML that's outside the iframe area and it can flood over onto the desktop like a normal popup menu. In short, XUL is a real GUI. Not shown in this example is XUL and HTML mixed together in the one document -- that is also possible using XML Namespaces.


Support for scripting

The flip side of the XUL coin is scripting. Although XUL is a bit more user-responsive than HTML, it won't do business logic for you. As with HTML, that role is handled by JavaScript code. Such scripts can be light and simplistic as in HTML, or they can interact quite deeply with the Mozilla platform's many objects. To support download and back-connection of the applet to a remote server, the example in this article performs light scripting only. Mozilla's support for light scripting is quite advanced, so a great deal is still possible.

The script tags in Listing 1 add this functionality to the XUL applet. The applet works as follows:

  1. All menu items except the Login and Help menu are disabled until the user logs in. Logging in means acquiring a session ID from the Web server of origin.
  2. Once logged in, the Ticket menu is enabled.
  3. Once a specific ticket is chosen from that menu, the related form elements appear in the body of the widget and the Action menu is enabled.
  4. The server is queried for a ticket number that can be used for that ticket.
  5. If Submit is chosen from the Action menu, the ticket is sent to the server using an ordinary HTTP GET request, where it is processed as for any other HTTP submission.

I'm not examining the mundane server code required to accept that submission in this article.

To enable all this logic requires less than 200 lines of JavaScript code. Three source files are included to do this work, using XUL's version of the HTML script tag. The script file init.js performs sundry initialization, while commands.js implements all the menu options, and server.js acts as the nuts and bolts of the client-server interactions.

The init.js file, shown in Listing 4, reveals the environment in which XUL scripts run.


Listing 4. init.js performs initialization
// ---- Global variables ----

var session = null;            // log in identifier, or null

var ticket = {
  id : null,                   // set to server-supplied number.
  url : null                   // set to the page in question.
};

// ---- Perform initialisation when the page has loaded ----

window.addEventListener("load", initialise, false);

function initialise()
{
  var node;
  var cookie = window.parent.document.cookie;

  // do we have an existing session?
  if ( cookie && cookie.substr("sessionID") )
  {
    //chop up the cookie string
    session = cookie.search(/sessionID=[^;]{1,};/);
    session = session.replace(/^.*sessionID=/,"");
    session = session.replace(/;.*/,"");
    session = parseInt(session);

    document.getElementById("stext").selectedIndex = 1;
  }
  else
  {
    document.getElementById("menu_ticket").setAttribute("disabled","true");
    document.getElementById("menu_action").setAttribute("disabled","true");
  }
  
  // don't support "exit" if we're inside an <iframe>.
  if ( window.parent.location.href != window.location.href )
  {
    document.getElementById("m12").setAttribute("disabled","true");  // "Exit"
    window.focus();
  }
}

Since XUL is a flavor of XML, the many W3C standard DOM interfaces are available. These interfaces make the XUL and HTML document available as an apparent tree of Element nodes, including DOM 0 features such as cookie support and the navigator object.

Scripts can store their own state in ordinary JavaScript variables or interact with the DOM. The powerful getElementById() is the standard version of Microsoft's document.all() functionality. The objects made available by the DOM standards are entirely separate to the thousand objects that are supplied by the Mozilla platform. Only the former are used here.

In the Listing 5, the DOM is used to lodge an onload event handler which fires the initialize() function once the XUL page is fully received. The initialize() function gropes through the DOM of the applet and its parent HTML document looking for an existing session ID in the form of a cookie, and disabling menus appropriately. Unlike with a Java applet, no awkward conversion takes place between Java and JavaScript objects and types -- everything is navigable from JavaScript. Security is still enforced using automated checking.

The second listing, commands.js, is routine. It provides an event handler for each menu option. In Listing 5, the example snippet of that file shows how the panel content of the applet's deck tags can be flipped with basic DOM-style operations:


Listing 5. Flipping deck tags
function cmd_user()
{
  init_ticket();
  document.getElementById("title").selectedIndex = 1;
  document.getElementById("forms").selectedIndex = 1;
}

Here, selectedIndex for the two decks starts with zero (which is a blank pane) and is flipped to one (a set of checkboxes) if the Ticket|User Ticket menu option is picked. See the full listing for commands.js to see how these form elements are queried to extract the user's data and to construct a parameter string suitable for a HTTP GET request. Technically, a submitted ticket should use an HTTP POST request, since it's not a retrieval action, but GET is used here for simplicity.

The final script, server.js, uses the special XMLHttpRequest object that is now a standard feature of modern browsers. This allows an XUL applet (or any JavaScript code) to connect back to its server of origin through HTTP without disturbing the currently displayed page.

Mozilla supports other protocols as well, such as SOAP and WSDL, and also raw sockets. This functionality means that XML-based interfaces are now as network-enabled as Java-based interfaces. Listing 6 shows a snippet of the network-oriented code:


Listing 6. server.js lets the applet connect to server of origin
// fake ticket ID request for the purposes of this demo.
function init_ticket()
{
  ticket.id = Math.floor(Math.random()*10000);
  ticket.url = window.parent.location.href;
  document.getElementById("menu_action").removeAttribute("disabled");
  document.getElementById("f00").value = ticket.id;
}

// real implementation for a ticket request, using an HTTP server.
function init_ticket_real()
{
  var req    = new XMLHttpRequest(); // Request
  var params = window.encodeURI("action=new-ticket-id");

  // ---- HTTP GET request for the ticket id.

  req.open("GET", "id-generator.cgi" + "?" + params);
  req.send("");

  // ---- Server results for HTTP GET
  if ( req.status / 100 == 2 )  // HTTP 2xx Response?
  {
    ticket.id = req.getResponseHeader("X-Ticket-Sequence-Number")
    ticket.url = window.parent.location.href;
    document.getElementById("menu_action").removeAttribute("disabled");
  }
  else
  {
    alert("Failed to construct a new ticket. Contact support.");
  }
}

The first implementation of init_ticket() allows the applet to be played with, without any real server support. The second implementation shows how a request can be silently processed (subject to security restrictions) with the aid of a server. The req object constructs the request with open() and sends the request using send(), which blocks until a response is received.

send() can also be called in a non-blocking way. When the response is received, error checking ensures that the server succeeded. In this case, I rely on the server setting a special HTTP header named X-Ticket-Sequence-Number, which holds the unique identifier for the ticket the user is constructing. This approach is also used for acquiring a session ID and for submitting the final ticket. Feedback is provided to the user in the form of status bar messages: Green for good news, red for bad news.


A feel for XUL

The interesting thing about XUL applets is their lightweight, interpreted nature. XUL, JavaScript, and CSS code are all interpreted languages, and each lacks the formality of fully object-oriented languages. The simplicity and ease of expression of XUL makes it a great technology for GUI prototyping. Its flexibility makes it easy to rip apart and re-organize such GUIs.

Although restricted to the Mozilla platform, a number of business scenarios can benefit from this approach, particularly intranets where client software is configuration controlled in the first place. Other examples are delivery of analysis or data entry software terminals to power users. The features of XUL illustrated in this article are just the tip of the iceberg.



Download

DescriptionNameSizeDownload method
Source code with commands.js and server.js fileswa-appmozx.zip4KB HTTP

Information about download methods


Resources

  • Download the full source code used in this article, including the commands.js file and the server.js file.

  • Visit the XulPlanet site for a tutorial that describes completely the uses of XUL and its components.

  • Read the "Getting started with PyXPCOM" series about the cross-platform component object model (XPCOM), the component system developed in the Mozilla project (developerWorks, June 2001).

  • Discover a multitude of resources on such open source technologies as Eclipse, SashXB, and Jikes at IBM's Open Source Projects site.

  • Visit the developerWorks XML zone, a compendium of articles and tutorials to help developers leverage the power of XML when crafting effective, efficient Web applications.

  • Try Eclipse, a kind of universal tool platform and an open extensible IDE designed for just about anything.

  • Get a deeper understanding of developing applications with the Mozilla platform in Rapid Application Development with Mozilla, as Nigel McFarlane elaborates on the techniques used in this article (Prentice Hall, October 2003).

About the author

Nigel McFarlane is a science and technology writer, analyst, and programmer. His broad range of experience includes IT, software, telecommunications, the Internet, and physics. He is the author of numerous articles and several books on XML and scripting technologies; his latest book is Rapid Application Development with Mozilla. Nigel lives in Melbourne, Australia. You can reach him at nrm@kingtide.com.au.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, XML
ArticleID=11849
ArticleTitle=Create Web applets with Mozilla and XML
publish-date=10212003
author1-email=nrm@kingtide.com.au
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers