Menu

Fooling with XUL - Part 2

March 15, 2000

Edd Dumbill


Table of Contents

The Finished Product
Creating the User Interface
Layout Mechanism
Adding Behavior
Adding Data to the Interface
Datasources and Templates
Making it Work
Conclusions

Adding Data to the Interface

I had reached the point of defining what I wanted my interface to look like. I needed to use the tree widget to show my list of headlines and so roughed out an interface description. You can download the full XUL file here, but here's an extract demonstrating the tree widget:

Interface mockup

<tree style="height: 100%; width: 100%" flex="2">

  <treehead>

    <treerow>

      <treecell value="Headlines"/>

    </treerow>

  </treehead>



  <treecol/>



  <treechildren>

    <treeitem>

      <treerow>

        <treecell 

          src="chrome://bookmarks/skin/bookmark-item.gif" 

          value="Story 1"/>

      </treerow>

    </treeitem>



   ...



  </treechildren>

</tree>

Notice that I used the browser's bookmark icon at this point instead of my own. This is one of the big advantages of Mozilla's open approach: the actual interface components themselves can be used for learning. In particular the chrome/bookmarks/content/default/bm-panel.xul file proved a great source of information in my experiment. This is the interface description for the sidebar bookmarks panel.

However, I did not want to create the .xul file each time with different contents; rather I wanted to be able to merge a data file with the XUL layout, in much the same way I would merge XML with XSLT to generate HTML. The way Mozilla handles this is to use RDF datasources. Arbitrary data, described in RDF, can be used to populate user interface elements.

Yes, I said "RDF." For one reason or another this specification has acquired a reputation as being unwieldy and difficult to understand. The good news is, you don't need to understand everything in order to be able to use it. I started from the point of an example RDF file, and with a little RDF knowledge, created what I needed for my purposes.

So here's the RDF primer: RDF is basically a way of describing things. The "things" are known as resources. A resource is associated with a URI. Here's an example description of me:


<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

         xmlns:ORN="http://www.oreillynet.com/rdf#">

  <RDF:Description about="urn:oreillynet:editors:edd">

    <ORN:Email>edd@xml.com</ORN:Email>

    <ORN:Site>http://xml.com/</ORN:Site>

  </RDF:Description>

</RDF:RDF>

RDF provides constructs such as Description, Seq (sequence), and Alt (alternatives) to make describing resources easier and more portable. In the above example, I simply invented the http://www.oreillynet.com/rdf namespace to contain my Email and Site properties. In practice there are some established vocabularies for metadata, such as Dublin Core, which you can use to improve the interoperability of your descriptions (see also Using the Dublin Core with RDF).

For my XMLhack project, the next task was to create an RDF description of all the headlines on the front of the web site. I constructed a small vocabulary to describe each story. Here's an extract for one story:


<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

         xmlns:s="http://xmlhack.com/stories/rdf#">

  <RDF:Description about="urn:xmlhack:story:207">

    <s:title>Oracle adds new functionality to XSQL Pages</s:title>

    <s:time>08:00, 10 Jan 2000</s:time>

    <s:author>Edd Dumbill</s:author>

    <s:url>http://xmlhack.com/read.php?item=207</s:url>

    <s:icon>http://xmlhack.com/images/s_tools.gif</s:icon>

  </RDF:Description>

  ...

</RDF:RDF>

You will note again that I could have profitably used elements from the Dublin Core to describe things such as "title," but as the sole intention of this particular RDF is to populate my user interface I preferred to take the simplest route.

Having described each story, I also wanted to describe a resource that would be my "headlines" list. For this, I used an RDF sequence I gave the ID headlines:


<RDF:Seq ID="headlines">

  <RDF:li resource="urn:xmlhack:story:207"/>

  <RDF:li resource="urn:xmlhack:story:206"/>

  ...

</RDF:Seq>

XMLhack is based on PHP and MySQL, so I had little difficulty writing the PHP script to generate this RDF. The remaining problem was inserting the data into the XUL.

Datasources and Templates

From within a XUL file, you can associate an RDF data source with a user interface item:


<tree id="xmlhack-tree"

  datasources="http://myserver.com/headlines.rdf"

  ref="http://myserver.com/headlines.rdf#headlines"

  style="height: 100%; width: 100%">

The datasources attribute signifies the source of the data, and ref says where in the data source I want to get data from. Here I indicate I want to read the sequence of headlines.

The template and rule elements are then used to merge the data with the interface:


<template>

 <rule>

  <treechildren>

   <treeitem uri="rdf:*">

    <treerow>

     <treecell

       src="rdf:http://xmlhack.com/stories/rdf#icon"

       value="rdf:http://xmlhack.com/stories/rdf#title"

       s:url="rdf:http://xmlhack.com/stories/rdf#url"/>

    </treerow>

   </treeitem>

  </treechildren>

 </rule>

</template>

This code replaces everything below the <treecol/> from my interface mockup above. Its purpose is quite self explanatory: the uri attribute matches each resource URI in the headlines list, making that the starting point. Thereafter, the rdf:-style attribute values select properties of the resource: we described these properties in the individual story descriptions earlier. Deeper understanding of what is going on can be gleaned from reading the RDF Syntax Recommendation from the W3C.

One subtlety here that I didn't find explicitly stated in the XUL documentation is the security model. Much as with Java applets, you can only retrieve data sources served from the same place as the XUL. For instance, this means you can't have a filesystem data source in a XUL description served by a web server. I found this out the hard way.

Making it Work

From studying the template above, you will note I added the s:url attribute to my tree cell. As the full XUL file shows, I earlier bound the s: prefix to another namespace of my own. This is so I could communicate to my JavaScript the URL to which the browser ought to navigate when it is double-clicked. To tie in the script, I added this attribute to the tree element:

onclick="return clicked(event, event.target);"

Again, I must acknowledge the value of the existing browser chrome files for providing me with shortcuts to write this script. Here's the definition of clicked():

function clicked(event, item) {

  if (event.clickCount == 2 && event.button == 1) {

    var tURL=item.getAttribute('s:url');

    if (window.content == null) {

      window.openDialog(

        "chrome://navigator/content/navigator.xul",

        "_blank", "chrome,all,dialog=no", tURL ); 

    } else {

      window.content.location = tURL;

    }

    return(true);

  }

  return(false);

}

On a double-click from the left mouse button, this script navigates to the destination URL, opening a new window if needed.

The final piece of the jigsaw is to allow the user to add the XMLhack panel to their sidebar. A short piece of Mozilla-specific JavaScript suffices:

<a href="javascript:sidebar.addPanel('&lt;?xmlhack?&gt;',

  'http://xmlhack.com/mozPanel.xul','')">Add XMLhack 

   Panel To Sidebar</a>

Here's the link for you to try yourself: Add XMLhack Panel To Sidebar. I've tested this in M14 and later nightly builds of Mozilla. On Windows you may need to open and close the sidebar to get it to display properly.

Conclusions

Apart from having a lot of fun, what did I discover playing with Mozilla? (I will lay aside the obvious fact that there are numerous bugs, as the browser has not even reached beta release stage yet.)

Mozilla could mean widespread RDF

I am of the opinion that what RDF needs is a "killer-app." Although lauded by many (especially Tim Berners-Lee), it has failed to break through in the same way XML has. Arbitrary data can be integrated into Mozilla interfaces via RDF with ease: the smallest part of my project was writing the RDF serialization of the data. Mozilla could well turn out to be a huge popularizer of RDF, leading to many sources of RDF information on the Web.

Mozilla provides a richer interface to online applications

The richer widget set provided by XUL compares well with those available for years in desktop applications. HTML has historically been woefully poor in its user interface elements, contributing to a Web in which "read" is much more common than "write." Mozilla could provide a truly cross-platform, network-aware framework for applications.

One proof of this is that the browser user interface itself is largely written in XUL and Javascript (and consequently the source code is a good place to explore how this stuff works!).

Having been involved in constructing online applications for several years, mainly in web content management, I'm excited by the prospect of more efficient web-enabled interfaces that are truly integrated with the browser. XUL delivers where Java never quite managed to.

Mozilla needs support

Microsoft's Internet Explorer is still ahead of Mozilla in terms of functionality, and way ahead in terms of adoption. Several otherwise free-spirited developers tell me that they use IE5 simply because it is the better browser and their altruism has run out of steam. Mozilla certainly faces tough challenges. However, it's important that it get the support of the XML and open source communities, for these reasons among others:

Resources

Mozilla Developer Docs
Cross-Platform Front End Project
Neil Deakin's XUL Tutorial
Mozilla Source Tree
XUL Reference Manual
RDF Syntax Recommendation
Guidance on expressing the Dublin Core within the Resource Description Framework (RDF)

  • Faithful standards implementation: Mozilla provides the opportunity for 100% implementations of W3C standards in a production environment. While not a "crowd-puller," this is important to ensure the long term openness of client-side web technologies.
  • Keeping the web open in a world of online applications: such applications are on the increase, and represent the future in both Internet and intranet situations. Current HTML can barely support the required flexibility in the user interface. Unless an open alternative is available, online applications will increasingly become browser or platform-specific.
  • Encouraging the "semantic web": more widespread use of RDF will enhance the prospects of a more "intelligent" web, where automated processes can be used to aid users in finding and processing information.

Details on participating in the Mozilla project can be found at Mozilla.org.

Related Stories