This XULNote presents some of the key concepts and terms in the XUL development environment. The purpose of this article is not to describe these items in any great detail but to define what they are in simple terms. I selected items for this group because they seemed to be either shrouded in mystery, misused as concepts or terms, or underestimated according to their role in XUL and cross-platform development. In contrast to the Mozilla Jargon File, this article describes items of specific interest to the web or content developer looking to establish a context for understanding Mozilla's new technologies -- and in particular Mozilla's XML-based User Interface Language, XUL.
Some of the most powerful and frequently misunderstood features of XUL and the Mozilla browser have to do with chrome. The term chrome is used in different contexts to mean different things. In general, chrome refers to a XUL interface and all of its supporting files; chrome means the XUL content and structure, plus the CSS skin, plus whatever localization and platform-specific files are part of that XUL interface. By contrast, the skin is just the CSS and referenced graphics for a XUL file, the localization strings are just a DTD, and the content is just the XUL.
The Chrome URL
This concept of a chrome as an integrated, dynamic thing in some way divorced from the "appcore" is realized in the use of the chrome url to point to chunks of XUL and their related files. The chrome url, which appears in place of the http url in pointers like the following global skin processing instruction:
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
specifies a chrome to be loaded by the Gecko rendering engine. In the example above, the chrome is simply a skin file to be loaded into the XUL file, but the chrome can also be used to load whole chromes, as when a menuitem in one window brings up a new chrome:
<menuitem value="Mozilla Help" oncommand="window.openDialog('chrome://help/content/help.xul', '_blank', 'chrome,all,dialog=no')" />
In this example, the chrome url is being used to point to a chrome within the package hierarchy of the Mozilla application. A Help chrome defined in mozilla/bin/chrome/help/ is being invoked from the Help menu. Note that when no file name is specified after the chrome directory path, a file name with the same name as the package is assumed. In other words, a chrome url like the global pointer above picks up a file called global.css, and the help pointer above could also be written as 'chrome://help/content', because the name of the package itself is "help."
Viewing Chromes Other Than Mozilla's
There is a special flag you can use to start Mozilla with some chrome other than the default. When you invoke Mozilla from the command line with the
-chrome flag, you can specify a chrome just as you would in the previous example:
mozilla -chrome chrome://help/content/help.xul
brings up the help package mentioned in the previous example as a "stand-alone" chrome. This special option allows you to create and access chromes independent of the Mozilla browser and begins to suggest some possibilities for XUL-as-platform beyond the simple restyling of the browser.
A package is in some ways like a chrome, but it is specific to the Mozilla architecture. A package is a chunk of interface code that sits in a particular place within Mozilla's package hierarchy. Like a chrome, that chunk usually contains XUL content, CSS and graphic skin information, localization strings, and maybe some platform-specific code. The navigator is a package defined in mozilla/bin/chrome/navigator, the mail/news component is a package in mozilla/bin/chrome/mailnews/, and so on. Each package directory typically has three subdirectories, content, skin, and locale, in which the XUL, CSS, and localization information are defined, respectively:
navigator/ content/ default/ navigator.xul ... skin/ default/ navigator.css nav-icon.gif ... locale/ US-en/ navigator.dtd
The default directory underneath each of these main package subdirectories is assumed in the chrome url (i.e., chrome://help/content/help.xul does not include a default directory as part of the url, though that directory exists in the actual structure). When you create different chrome for a package, you can create a subdirectory underneath content whose contents are loaded instead of default. For example, if you want to create a different skin for the navigator package, you can create a subdirectory underneath navigator/skin/ whose contents will be loaded instead of default's. So the following structure obtains:
navigator/ content/ default/ navigator.xul ... skin/ default/ navigator.css nav-icon.gif ... myNewSkin/ newskin.css newgifs.gif ... locale/ US-en/ navigator.dtd
To load chrome information stored in a new package directory like this, you can use the following chrome url,
which in turn loads the graphics in that subdirectory as needed.
The skin is the CSS and graphics that makes up the look or presentation of XUL. XUL itself contains very little provision for how widgets are to be presented in the interface. Even prior to the skinning that takes place with the global skin, which is loaded in almost every XUL file you see in Mozilla (and whose absence from your own XUL files can make your work look strange, senseless, or invisible altogether), a xul.css file is loaded which provides some very basic presentational information for the widgets in the toolkit. So CSS is a lot of what makes XUL XUL, especially with the advent of CSS2 and its new positioning capabilities.
Skinning is most often brought up in the context of dynamic changes to the overall look of an application. Though this is not yet in the browser, very soon it will be possible to change the look of a whole application dynamically, but only to the extent that the skin is actually defined in the main global.css, or global skin. When you create styles in <style> tags, as style attributes for individual elements, or in custom CSS files, you break the ability of Gecko to skin the application to which your XUL belongs.
Widgets are the pieces that you assemble to make an interface. Menus, toolbars, buttons, and scrollbars are widgets, and so are such general purpose pieces as boxes and springs. These widgets can be created and placed within a XUL file as simple elements:
<toolbar>, and so on. The syntax for these elements is based for the most part on XML. Collectively, these widgets are also known as the XPToolkit.
Object Models: DOM and AOM
With the dramatic improvements in the object model and the power of the W3C DOM2, the concept of the DOM is displacing that of the more abstract DHTML. Since any dynamic web development is dependent upon programmatic access to the web document (or XUL interface), and since the DOM is a standard and earlier notions of Dynamic HTML were not, the term "DOM" is used as a synonym for or instead of terms like "Dynamic HTML" or "DHTML."
The AOM stands for the Application Object Model, and is an extension of the DOM up into the interface defined in XUL. Just as HTML is reflected in the DOM as nodes like link, layer, and img, XUL is reflected in the Application Object Model in the hierarchy of XUL widgets: browser, menu, menuitem, and so on. The DOM and the AOM form a kind of continuum, the whole of which is manipulable from the standards upon which XUL is based.
Near Synonyms for XUL
There is much confusion about the words that begin with "X" in the Mozilla Open Source Project. The Mozilla XPArchitecture section below describes XPCOM, XPIDL, and XPConnect, three somewhat related technologies for getting access to application code from the interface. This section describes XUL, XPToolkit, and XPFE, which are in some respects synonymous and in others quite different.
In briefest terms, XUL is the XML-based language used for creating interfaces, XPToolkit is the set of XUL widgets (menus, toolbar, et cetera) actually assembed for this purpose -- the building blocks of the interface, as it were -- and XPFE, the Cross Platform Front End, is the front end that has been created from XPToolkit.
The differences here are significant: XUL is the universe of elements, attributes, syntax, rules, and relationships, while XPToolkit is really the finite set of interface-specific elements created in XUL. The XPFE is what's been created out of the XPToolkit. A loosely analogous relationship might be that XUL, XPToolkit, and XPFE are to one another what HTML, the actual HTML tags, and an HTML web page are to one another, respectively.
People sometimes get confused about the syntax for describing the parts of a widget. For a widget like the menu that appears in the following example, menu is the element and both value and the id are attributes.
<menu id="file" value="File" > <popup> <menuitem value="New" onclick="CreateNewDoc()" /> <menuitem value="Open" onclick="OpenDoc()" /> <menuitem value="Close" onclick="CloseDoc()" /> </popup> </menu>
Element names the item, the widget, while attributes describes features of that element, such as its name, its style, and so on. In object-oriented parlance, the element is analogous to the object itself while the attribute is like a property. The attribute has a value associated with it (such as the string "file" for the id attribute in the example above). Note that the menu element includes both the opening tag at the top and the closing tag at the bottom of the example. In a way, the menu element comprises the menu element itself and its children, the popup and menuitems.
Events are also a source of confusion for many less-hardened developers. In fact, I'm not sure I understand them adequately myself, but here goes a simple explanation of events and of how they are used, basically, in a event-based interface like those created in XUL. Events are messages that are sent from an object when that object performs some action. For example, A document fires, or raises, the "load" event when it is loaded into a browser. The "click" event is fired by a button when it is clicked.
If you don't do anything about these events, then you probably never know about them. Documents will load, buttons will be clicked, and links will be hovered over, and events will be raised for all these actions behind closed doors. If, however, you write event handlers inside event listeners, as we will describe shortly, you can use these events to set off other actions. This using of events to prompt other, more expicit actions is loosely what is meant by an event model.
Where, exactly, are these events fired? Fired at whom? Events that are fired by an object "bubble up" the hierarchical model that is the DOM (or the AOM) node by node. These events can be "handled" at any point in that hierarchy -- including in the same node in which they were raised. If no one at a particular level in the hierarchy is interested in the event, then the event bubbles up to the next highest level on out to the top of the hierarchy.
The term isn't used very often, but an "event listener" is a special attribute of an object that listens to its own events. The document, for example, has an "onload" event listener to listen for its "load" event. XUL buttons have "onclick" event listeners. The event listener is really a convenience; instead of using it, you could find out when an object fired an event, then go find out what that event was, and then write some event handling code as a response to that event, but the event listener provides an easy mechanism for writing event handlers for specific, common events.
An event handler is a snippet of code that you write in response to an event. An "onload" event handler says, in effect, when this document loads, I want to this to happen. And the event listener attribute provides a very convenient place in which to write event handlers -- so convenient, in fact, that the term "event handler" is often used to describe both the event listener attribute and the event handler code you write within it. To create an event handler, simple place the code you want executed within the appropriate event listener:
<menuitem value="Click Me" onclick="alert('Event Handled.')" />
It follows from the description above that event handlers can be written for events that are fired somewhere below them in the hierarchy. A menubar in XUL, for instance, can contain event handlers for events fired by its child menuitems.