Introduction to XUL

Warning: The content of this article may be out of date.

Preamble

Mozilla has configurable, downloadable chrome, meaning that the arrangement and even presence or absence of controls in the main window is not hardwired into the application, but loaded from a separate UI description. In fact, most of Mozilla's windows (and dialogs) will be described using this mechanism. XUL (pronounced "zool," as if that spelling helped any, and short for "XML User Interface Language") is our name for the language in which these UI descriptions are built.

Window chrome is displayed and managed by the same layout engine that manages HTML content in the browser. UI descriptions, then, look a great deal like HTML 4. XUL is an application of XML. In fact, it is just XML with specific meaning defined for a few element types, and into which HTML can be scattered.

Terms

"XPFE" is the term Mozilla-the-organization is using to describe Mozilla-the-browser's Cross Platform Front End, because X and C look similar if you beat them long and hard with a hammer. The intention is to build cross-platform applications like browsers and mail clients from a set of tools designed for that purpose. The intention is not to implement a generic cross-platform application framework. That's been done, and is a great deal of work. We intend to provide a subset of cross-platform functionality suitable for building network applications like browsers, leveraging the cross-platform functionality already built into Gecko, Mozilla's HTML layout engine.

The term "cross-platform UI" is somewhat misleading. UI designers will be able to create UI descriptions which will work on multiple platforms. But proper UI descriptions which take into account various platforms' differing ideas about proper placement of such things as dialog buttons will require some platform-specific work. A single XUL specification can only cross-platform to a degree. UI designers and build engineers will need to maintain separate, platform-specific versions of at least some XUL documents.

"XPToolkit" is rather synonymous with XPFE. Though the former term seems more concrete than the other, and therefore is not an exact replacement, no one is completely certain why we have both.

"XUL" already introduced, is an application of XML used to describe the layout of most windows in the Mozilla browser, including and especially the main, browser window.

Scope

This paper makes no attempt to explain requirements. We don't have a current "requirements" document. XPToolkit Architecture is a better place to gain an understanding of such things. This paper contains a short introduction to Mozilla front-end architecture, concentrating on the task of building UIs. It is, as always, incomplete.

Mozilla applications will be built of "small" components like dialog buttons and mail inbox folders, which we collectively term "widgets." Within a widget, drawing and user interactions are completely under control of the individual widget, and set when the widget was built. Relative placement of widgets, their interactions with each other, and optionally some of their configuration, will be controlled by a UI layout specified in a script whose structure is defined in this and related documents.

Widgets are pieces of the application largely self-contained, generally corresponding to a rectangle of window real estate. Widgets will generally live grouped in separate, dynamically loaded libraries. A widget may expect to own a piece of a window (a toolbar or toolbar set), or it may be expected to work within or without a window (menubars, depending on the platform). It may not be a part of the application UI at all.

Widgets will have predefined behaviour, set at compilation. Buttons will respond to the mouse; toolbars will act as containers for buttons. The effect a widget will have on its application will be defined as a combination of predefined application behaviour and linkage between the widgets. This linkage can be accomplished by including JavaScript in the XUL, or by application code which walks the content model after it has been built from XUL, and hooks up event listeners. Generally a real application will use some combination of the two.

Applications, for instance, will have preconceived notions of what to do when they receive an "open file" command. An "open" button is simply a button. It will send its command to the application for processing, generally using some simple JavaScript for linkage.

We are at first primarily concerned with the obvious UI components: toolbars, menus and dialogs. Conceptually, the XUL language will allow someone with a text editor, given a package of components which can work together, the ability to put together an application by specifying something like this (for an application on an OS using menubars across the top of its applications' windows):

main window containing
  menubar area at top across width of window containing
    menubar (and its contents)
  toolbar area below menubar across width of window containing
    main toolbar (and its contents)
  application-specific content area below toolbar area

Structure of a XUL File

Our language of choice is XML, flavoured with CSS stylistic information. Having said that, the details of a particular application of XML; say, the syntax for specifying a toolbar, are left to separate documents describing those particular applications. Check the XPToolkit index for the most recent list.

Since XUL is a language for describing window layout, there is some overlap in the topics covered by this document and a separate document describing XUL windows. The task of writing a XUL window description is basically the same as the task of writing an HTML content description, with these exceptions: the syntax is XML (not that different from HTML 4), and there are some elements unique to XUL. These elements are widgets and certain infrastructure associated with the behaviour of the window, explained below.

Most of the details of writing a XUL document are identical to those for writing an XML document, a description of which we will leave to other excellent XML documentation which we assume must exist but have never seen. This document will concentrate on XUL-specific features.

A Word on Case and Namespaces, and Filetypes

XML is of course case sensitive. XUL is equally so. Our current code tends not to be strict about enforcing this, especially for tags and attributes in the HTML namespace. This will change: tags and attributes will, as a rule, always be lower case as suggested in the XHTML Working Draft.

Mozilla gives a special meaning to XUL files; it expects to find UI descriptions within. For this reason, we've defined a MIME type "text/xul" mapped to files with the extension ".xul". (For standards purposes, we will probably need to change the the mime type to something like "text/x-xul".) These files are processed using the same parser as "text/xml" files (and therefore subject to XML syntax rules, as they should be). It's possible to load a XUL document from an XML file (one named *.xml). The resulting UI will be created using an XML content model. A XUL content model is generated from *.xul files. XML documents support the basic DOM Level 1 Core APIs. XUL documents support an extended set, much as HTML documents support DOM Level 1 HTML APIs. Mozilla's XUL content models also support nifty features like local/remote merging; see the XUL and RDF document for details. In general, you will want to store XUL in *.xul files.

A XUL file can contain XML elements and HTML elements, as well as special elements unique to XUL: XUL elements. Namespace declarations for XUL (and HTML, if HTML elements are used) must be included in the file. Namespaces must be treated carefully. Correct namespace usage dictates that the namespace be used only for the tag, not in individual attributes. Rare exceptions to this rule are bugs.

XUL File Preamble

XUL is XML, and a good XUL file begins with the standard XML version and DOCTYPE statements.

Since XML has no implicit display semantics, there must always be associated stylesheets. Mozilla includes a standard stylesheet, "xul.css". You can load as many style sheets as you wish using repeated processing directives, although you should always make sure to load the xul.css file initially. And finally, any namespaces used in the document must be declared. So a XUL file will begin

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

The HTML namespace is of course the standard one. The XUL namespace is obviously a temporary one, but at least serves to explain the pronunciation. Note that the above example is using an implicit XUL namespace. This is optional; other examples in this document will on occasion belabor the namespace issue by declaring each use explicitly.

The chrome protocol is another Mozilla extension allowing the exact location of files involved in the chrome description to be moved without affecting the XUL source. So it's just an indirection.

Someday, there will be a complete description of this mechanism at packages, but for now there's a good but somewhat out of date document at Configurable Chrome available for more information.

Scripting

A XUL interface is only a collection of disconnected widgets until it has been programmed. "Programming" can be as simple as some JavaScript to tie the widgets together and perhaps to give them extra functionality, or as complex as application (C++) code which is free to do ... anything. This paper will concentrate on JavaScript, deeming application programming to be beyond its scope.

JavaScript

XUL can contain HTML content, including JavaScript. JavaScript functions may be added in a fashion similar to HTML. There is no <head> section of a XUL file, so script is just mixed in with the other content, delimited by a script element in the HTML namespace.

<html:script type="application/javascript">
  // dialog initialization code
  function InitWindow() {
    var checkbox = document.getElementById("remember");
    if (checkbox)
      checkbox.checked = true;
  }
</html:script>

JavaScript can be referenced as in HTML documents: as onClick handlers and the like. See individual widget documentation referenced at the index for a list of attributes accepting JavaScript values.

JavaScript is most safely kept in a separate file and included in the XUL file

<html:script language="javascript" src="our.js"/>

or relegated to the contents of a CDATA section, to prevent the XML parser from choking on JavaScript which may look like XML content (a < character, for instance.)

<html:script type="application/javascript">
  <![CDATA[
    function lesser(a,b) {
      return a < b ? a : b;
    }
  ]]>
</html:script>

JavaScript Extensions

Mozilla has found it necessary to make a few extensions to JavaScript, to support new features not conceived of in a strictly browser environment. These are currently nonstandard, of course, and subject to change for now. Individual extensions are described in individual documents dedicated to the features requiring the extensions.

DOM Extensions

Since XUL is not the same thing as HTML, while XUL documents will support the DOM Level 1 Core API, they will not support the DOM Level 1 HTML API. However, Mozilla supports extended DOM functionality for the XUL content model, patterned after the HTML extensions. At this time these additional DOM methods are available, though the code is of course the most accurate place to look for this information. These interfaces can be found in the directory mozilla/rdf/content/public/idl.

XULDocument

XULDocument extends Document in a fashion similar to HTMLDocument's extension

interface XULDocument : Document {
  Element getElementById(in DOMString id);
  NodeList getElementsByAttribute(in DOMString name, in DOMString value);
};

getElementById works like HTML's getElementById.

getElementsByAttribute returns a list of Elements for which the named attribute has the given value. A value of "*" is a wildcard signifying all elements with the attribute.

XULElement

XULElement extends Element.

interface XULElement : Element {
  NodeList getElementsByAttribute(in DOMString name, in DOMString value);
};

getElementsByAttribute functions as does its namesake in XULDocument, though this version returns only those elements which match the criteria and are descendants (in CSS selector terminology) of the given element.

XULElement also supports other methods for hooking up broadcasters; a function performed automatically by the XUL document loader and therefore not normally used in JavaScript.

XUL Elements

As mentioned above, a XUL file is mostly an HTML file with XML syntax. A XUL file may contain nothing but HTML elements and be completely functional. But XUL defines several element types unique to itself, which add functionality to the window.

Widgets

Widgets are generally objects like form controls: buttons, text boxes, tree controls and the like. A window can just as easily contain HTML form elements (using the html namespace) like any HTML content (though there is no need to put them within a FORM element). In fact, XUL largely uses extant widgets from HTML, with a few extensions and additions. Each widget will define a unique XML syntax for describing itself; see the widget documentation referenced at the index for details.

Other Infrastructure

Widgets may have JavaScript event handlers just as in HTML, and are tied together using JavaScript and broadcaster nodes. Broadcaster nodes are declared as <broadcaster> elements in the XUL description, and are involved with the communication of changes of state between widgets. A widget or several widgets can arrange to have the value of one of their attributes be tied to a broadcaster node. This tie is defined within the XUL:

<xul:window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <broadcaster id="canGoBack"/>
 <titledbutton src="resource:/res/toolbar/TB_Back.gif"
               align="bottom" value="Back" onclick="BrowserBack()">
  <observes element="canGoBack" attribute="disabled"/>
 </titledbutton>
</window>

But it is up to the application code to locate the broadcasters within a window so it can punch them when necessary.

Broadcasters can broadcast any change of state, which can be tied to the value of any attribute in another XUL widget. For more complete documentation, see Broadcasters and Observers.

An Example Window

Below is a complete sample XUL document that describes a window with a menu bar and an HTML content area. The menu bar has a menu, File, with a single menu item that dumps "Hello world!" to the debug console when selected. The content area will display the contents of the file contentframe.html. This code introduces several concepts useful for creating real world windows not explicitly covered in this document. Follow the links for details.

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
<!DOCTYPE window>
<window id="main-window" xmlns:html="http://www.w3.org/1999/xhtml"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <menubar>
      <menu label="File">
      <menupopup>
        <menuitem label="Hello World!" onclick="alert('Hello world!\n');"/>
      </menupopup>
      </menu>
  </menubar>
 <html:iframe id="content-frame" src="contentframe.html" flex="100%"/>
</window>

The beginning of this example, down through the window tag, is the standard preamble.

Notice that the example window tag has an id attached to it. Strictly speaking, that is unnecessary for this example. However in practice, most nodes in XUL have these identifiers, which enable the nodes to be retrieved easily using the AOM's getElementById method. Identifiers are also useful for CSS, since rules can be applied to individual elements in XUL using the same # syntax that is possible for HTML elements.

#main-window {
  display: block;
  width: 100%;
  height: 100%;
}

For example, the above style rule would apply to the main window and dictates that the window should consume the full width and height available to it in a content area.

The next element in the example declares the menubar. The menubar contains a single menu called "File". This menu contains a single menu item that has a simple JavaScript onclick handler attached to it. This handler fires when the menu is selected by the user, and it dumps the text "Hello world!" to the debug console. (See Menu Bars and Menus for details.)

Finally there is an HTML iframe. Note that the frame is qualified with the prefix html:, since it is an HTML object being used inside a default XUL namespace. The frame also has a special attribute called flex, which indicates how much the frame is allowed to stretch to consume available space inside its window. (See The Box System for details).

Idealistic Future Direction

Ideally, packages of XUL UI descriptions could be shipped in a single file something like

<?xml version="1.0"?>
<?xml-stylesheet href="xul.css" type="text/css"?>
<!DOCTYPE package>
<package xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <window id="main">
    ...
  </window>
  <window id="help">
    ...
  </window>
</package>

And a window (or other service) could be instantiated by first parsing the whole package and then picking out a window from its contents

Package *package = LoadPackage("http://xxx/package.xul");
InstantiateWindow(package, GetNodeWithID("main");

This happy scheme doesn't work today, because the code expects the result of parsing an XML document to be a window. So currently, a single XUL file must contain a single window.

<?xml version="1.0"?>
<?xml-stylesheet href="xul.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  ...
</window>

We would like to head more toward the "package" implementation in the future.

Internationalization

For practical reasons, the locale-specific attributes of a UI description would be most happily developed (and possibly distributed) in separate files, where localization can be performed by altering only a subset of the UI description devoted expressly to localization issues. That is, a separate file of localized strings.

Internationalization is discussed more completely in the XUL Coding Style Guidelines document. In brief, Mozilla has settled on XML entities as the mechanism. Entities are a feature of the language and therefore outside the scope of this paper. A XUL file can be made localizeable very easily by substituting entities for any content which may change as the locale changes. The localized text must be defined in a separate DTD or DTD fragment. The whole system is then configured with different locale-specific DTDs, and the correct DTD will be chosen for a given XML file at runtime, depending on the current locale settings. Mozilla will make that decision automatically if the localized XML file specifies its DTD using a chrome URL, as outlined in XUL Localizability Issues.

Original Document Information