Second Draft
6 Aug 99
contact
Change history
18 Aug 99 - This document is officially obsolete, and has been for months. See instead Introduction to XUL.
6 Aug 99 - Documented the "features" parameter in window.open and window.openDialog.
23 Jun 99 - Internationalization section mentions the means of locating locale-specific DTDs.
17 May 99 - Added JavaScript Extensions section.
2 Mar 99 - Updated namespace information and examples. Added section on XUL DOM extensions.
25 Feb 99 - Added section on case sensitivity. Embellished description of filetypes, namespaces and content models, and reworked the "XUL Preamble" section to match.
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 "zuul," as if that spelling helped any, and short for "XML-based 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.
Readers of the First Draft of this document will notice that a fundamental change has taken place in the way a UI is described. The first draft documented an intention to add springs and struts to the layout model, and spent a great deal of time worrying about keeping the content in separate files from specific (perhaps different on different platforms) layout instructions: the separation of content and form. The springs and struts layout model has been abandoned in favor of an HTML 4/CSS model, and the separation of content and form, beyond the not inconsiderable capabilities provided by those standards, has been recognized as overly ambitious.
"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.
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
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. Every widget built into Mozilla will need to have such a document. Check the XPFE index for the most recent list. At time of writing, authors of these widgets have been kind enough to document their designs:
Since XUL is a language for describing window layout, there is some overlap in the topics covered by this document and separate documents describing XUL windows.
As pointed out in the above documents, 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.
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. In general, a namespace need be specified only for element tags; not for attributes. A widget specified
<html:button xul:onclick="DoSomething()">
will almost certainly not work as expected; the onClick handler will probably be lost (regardless of its correct use of case). In the absence of specific instructions, expect a widget to expect its applicable attributes to require no explicit namespace.
<html:button onclick="DoSomething()">
and<xul:titledbutton onclick="DoSomething()">
That said, the HTML elements at time of writing tend not to care whether their attributes have an HTML namespace or none at all, though sometimes they do exhibit a preference and require a namespace to work as expected.
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". It is currently
built into the distribution at resource:/res/samples/xul.css
. Generally,
you will want to include this style sheet in your files with a stylesheet processing
instruction.
And finally, any namespaces used in the document must be declared. Generally, a XUL file will begin
<?xml version="1.0"?>
<?xml-stylesheet href="xul.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns:html="http://www.w3.org/TR/REC-html40"
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. For the moment, that exact namespace must be declared in any XUL file. 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.
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.
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>
tag in the HTML namespace.
<html:script>
// 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
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>
<![CDATA[
function lesser(a,b) {
return a < b ? a : b;
}
]]>
</html:script>
Mozilla has found it necessary to support a few extensions to standard JavaScript. These are, well, nonstandard. They are therefore subject to change, and will not work with other browser applications.
open(URL[, windowName [, windowFeatures]])
The standard syntax still applies. See a JavaScript reference for details.
Mozilla, however, understands a few extensions to windowFeatures
.
The treatment of these extensions is somewhat confused in the name of backward
compatibility and because of the sometimes uneasy interplay between standards-compliant
open
and the more freewheeling openDialog
.
titlebar
- The window can be created with or without a
titlebar.close
- The window can be created with or without a close
widget.chrome
- Normally, the URL given to window.open
is treated as a content URL. That is, Mozilla generates a browser window
and loads the given URL into its content area, as window.open
has always behaved. However, the presence of a chrome
flag
in the windowFeatures
parameter will cause the given URL
to be treated as the window chrome, itself. It will be treated as the
top-level window contents; it will not be wrapped in a browser window.
The window will also be sized to wrap its contents.dialog
- Use a dialog-style window border.modal
- The window will be run modally. The call to window.open
will not return until the user has dismissed the window. (Note this is
not working at time of writing.)chrome
,
dialog
and modal
. If any string at all, even a zero-length
string, is given in the features
parameter, any features not
explicitly mentioned are assumed off. titlebar
and close
are the two exceptions: they are not considered off unless explicitly mentioned
("titlebar=no
"), since anything else would break extant
script.openDialog(URL[, windowName [, windowFeatures [, args]]])
window.openDialog
is an extension to window.open
.
It behaves the same, except that it can optionally take one or more parameters
past windowFeatures
, and windowFeatures
itself is
treated a little differently.
The optional parameters, if present, will be bundled up in a JavaScript array
and added to the newly created window as a property named arguments
.
They may be referenced in the JavaScript of the window at any time, including
during the execution of an onload
handler. These parameters may
be used, then, to pass arguments to and from the dialog window.
A dialog summoned up
openDialog("http://zzz.xul", "dlg", "chrome",
"pizza", 6.98)
could reference the "pizza" string as window.arguments[0]
,
and the number as window.arguments[1]
.
openDialog
treats the features
parameter exactly
as does open
, with the following differences.
all
- Initially activates (or deactivates ("all=no
"))
all chrome (except the behaviour flags chrome
, dialog
and modal
). These can be overridden (so "menubar=no,all
"
turns on all chrome except the menubar.) This feature is explicitly ignored
by window.open
. window.openDialog
finds it useful
because of its different default assumptions.chrome=no
"). openDialog
treats the absence of the features parameter as does window.open, except as
always, chrome
and dialog
are on. If the features
parameter is a zero-length string, or contains only one or more of the behaviour
features (chrome
, dialog
and modal
)
the chrome features are assumed "OS' choice." That is, window creation
code is not given specific instructions, but is instead allowed to select
the chrome that best fits a dialog on that operating system.Note that this functionality may just be bundled up into window.open
,
since there is no real conflict. Alternatively, window.openDialog
could in the future assume certain settings, such as the chrome
flag.
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
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
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.
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 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>
tag).
XUL defines several new widget types, enumerated at Required Widgets. Not all of these widgets have been implemented at time of writing. Each widget will define a unique XML syntax for describing itself; see the widget documentation for details.
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:xul ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<xul:broadcaster id="canGoBack"/>
<xul:titledbutton src="resource:/res/toolbar/TB_Back.gif"
align="bottom" value="Back" onclick="BrowserBack()">
<xul:observes element="canGoBack" attribute="disabled"/>
</xul:titledbutton>
</xul: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.
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>
And the corresponding code is a little more slanted toward getting a window
InstantiateWindow("http://xxx/window.xul");
We would like to head more toward the "package" implementation in the future.
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.