XUL Overlays

  • Revision slug: XUL_Overlays
  • Revision title: XUL Overlays
  • Revision id: 50691
  • Created:
  • Creator: Sevenspade
  • Is current revision? No
  • Comment fix deki conversion mangling; no wording changes

Revision Content

XUL Files and XUL Overlays

Overlays are XUL files used to describe extra content in the UI. Though overlays often define UI elements that have been added as a result of an update or enhancement of some kind, they can be used in many different ways. Overlays provide a general mechanism for:

  • adding UI for additional components, as described in the example above
  • overriding small pieces of a XUL file without having to resupply the whole UI
  • reusing particular pieces of the UI

XUL files and overlays work together to describe a single master document. Though there is no formal restriction on what kind of XUL content is located in "base" XUL files and what kind should be put in overlays, XUL overlays generally define items that are not present in the basic versions of the UI, such as additional components. When plug-ins, browser extensions, or other applications provide new UI elements to the browser, these elements should be defined in overlay files. The installation of a media plug-in, for example, may add new icons and menu items to the interface:

Image of SSP UI in browser

In the navigatorOverlay.xul file or in a separate navigatorSSPOverlay.xul file (where navigator.xul defines the basic UI for the navigator package), these new plug-in elements would be defined as a collection of elements or subtrees:

<menuitem name="Super Stream Player"/>

<menupopup name="SS Favorites">
 <menuitem name="Wave" src="mavericks.ssp"/>
 <menuitem name="Soccer" src="brazil_soccer.ssp"/>
</menupopup>

<titledbutton id="SSP" crop="right" flex="1"
              value="&SSButton.label;" onclick="FireSSP()"/>

Overlays and ID Attributes

The layout engine uses the ID attribute to determine where the elements in the overlay file will be merged. Use the same IDs in the base XUL file and the XUL overlay; otherwise, the new elements will not appear at all. In the base file, the parent nodes for the overlay elements must be ID'd if they have not been already. For example, the <{{ XULElem("menu") }}> element in the following XUL subtree should be the parent of the Super Stream Player menu item, so it has been given the ID "file_menu":

<menu id="file_menu">
 <menuitem name="New"/>
 <menuitem name="Open"/>
 <menuitem name="Save"/>
 <menuitem name="Close"/>
</menu>

In the overlay file, you can "sync up" the new item by making it the child of a tag with the same ID in the overlay file. The layout engine takes the elements directly under the {{ XULElem("overlay") }} tag with IDs and merges them with the corresponding nodes in the base file. The complete XUL overlay file for adding the single Super Stream Player menu item from the example above is as follows:

<?xml version="1.0"?>
<overlay id="singleItemEx"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <menu id="file_menu">
  <menuitem name="Super Stream Player"/>
 </menu>
</overlay>

Note that below {{ XULElem("menu") }} in the base file and {{ XULElem("overlay") }} in the overlay file, the subtrees are equivalent. Merged items can be arbitrarily nested subtrees: new popup menus may contain other popup submenus, extra toolbars can overlay existing toolbars or appear beneath them, as the Personal Toolbar does below the Location Bar in Netscape's Communicator, etc. As long as the IDs of the elements appearing below the {{ XULElem("overlay") }} tag in the overlay file and tag with the same ID in the base file, overlays support the merging of any valid subtree.

At the moment you can't overlay an element without an ID, so you need to use DOM methods to tweak the element you need in a load handler.

Loading Overlays

Overlays can be loaded explicitly or dynamically. When you load an overlay explicitly, it means that you intend to make it available every time the base file is loaded. Since one of the main purposes of overlays is to provide UI for additions or components to the basic package, explicit loading can be somewhat problematic when the overlay defines optional UI elements.

Loading Overlays Explicitly

A processing instruction is used to load overlay files explicitly into the master document. Inserting the following processing instruction before the DOCTYPE declaration in a base file tells the layout engine to load the named overlay file:

<?xul-overlay href="chrome://component/content/componentOverlay.xul"?>

where component is the name of the package being overlayed (e.g. chrome://navigator/content/navigatorOverlay.xul).

The layout engine loads any overlay files and then flows the resulting XUL document, so problems associated with incremental insertion in menus, boxes, tables, and forms are avoided. Any number of overlays can be loaded into a master document, and an overlay can also load other overlays. Because an overlay is superimposed on the master document, there are no ambiguities relating to scoping of style sheets or scripts. Style sheets and scripts loaded by the overlay simply apply to the entire master document.

Loading Overlays Dynamically

The chrome registry makes it possible to load XUL overlays dynamically -- or only when necessary. The chrome registry, which is a special RDF datasource into which user-specific information is persisted, or stored, contains information about the components or additional packages that have been installed with the browser. When a component such as the "Super Stream Player" from the examples above is registered there, overlays associated with that component are loaded automatically. When the component is not present, only the base files are loaded.

Loading Overlays at Run-time

Firefox 1.5 and other Gecko 1.8-based applications also support loading overlays on-the-fly via document.loadOverlay function. TODO: elaborate

Overlays and Skins

Always load master skins from base files. Never load master skins from overlays.

Unlike base files, overlays should never load the master skin file for a package. The navigatorOverlay.xul file, for example, does not and should never load the navigator.css file that defines the master skin for the navigator package. Since the purpose of an overlay is to define new UI elements for a package within the context of that package's skin, the overlay should add structure but not new style. Any skins that are loaded by an overlay destructively replace the master skin for the base file, and can change the basic appearance of the package's skin in unfortunate ways.

The master skin is not the same as the global skin. For any package, the master skin file is that CSS file named after the package itself. The master skin file for the bookmarks package, for example, is called bookmarks.css, and is located in the skin/default subdirectory.

Overlaying Attributes

In addition to new elements and subtrees, you can also overlay attributes into existing elements. In XUL, attributes control important features of the skin like image sources, as in the following example, where an overlay destructively overwrites the image source in the base file with a replacement. In the base file, the HTML image element points to a Netscape GIF icon:

<html:img id="foo" src="netscapeImage.gif"/>

In the overlay, an element with the same ID attribute specifies a different image, and that image is superimposed on top of the original Netscape image as part of the merge process:

<html:img id="foo" src="mozillaImage.gif"/>

When the base file references an overlay file which contains the html image element above, the new src attribute is superimposed over original, and the Mozilla icon replaces the Netscape icon.

Overlay Positioning

XUL overlays also support positioning of nodes. You can specify a {{ XULAttr("position") }} attribute on a node in the overlay to provide a hint for insertion into the master document. In the following example, the last menu item, Example Four, will be placed just after the "New" menu item instead of being appended to the end of the menu like the other kids.

<overlay id="main-overlay" xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <menu id="file_menu">
  <menuitem name="Example One"/>
  <menuitem name="Example Two"/>
  <menuitem name="Example Three"/>
  <menuitem name="Example Four" position="1"/>
 </menu>
</overlay>

The node with the {{ XULAttr("position") }} attribute orders itself to the top of the menu. The {{ XULAttr("position") }} can also be given for nodes in overlay files that will be ordered in a group of similar items in the base file. For example, if only the last menuitem above had been in an overlay and the other items were defined in the base file, the overlayed menuitem would still appear at the top of the parent menu.

Attaching a Script to an Overlay

To execute a script when an overlay is applied, use a <script> element:

<script src="overlay.js"/>

If you need to set the version of JavaScript, you can set the type, and append ";version=x.y" to the end of the src attribute:

<script type="application/x-javascript" src="overlay.js;version=1.8"/>

UI Reuse with Overlays

One of the biggest benefits of using overlays is that it allows you to reuse groups of elements that appear frequently in the UI. The overlay mechanism allows you to merge elements into existing subtrees, but it also allows you to store common UI elements in overlay files and merge them into any base files that use them. Using the ID attribute on an otherwise empty node in the base file, you can essentially reference a subtree defined in an overlay file and merge it in wherever it's needed.

For example, the buttons that appear at the bottom of common dialogs, the OK and Cancel buttons, may be used in dozens of places in the UI. Rather than redefining this set of buttons each time they are necessary in a particular dialog, base XUL files can overlay the XUL file in which these buttons are defined, dialogOverlay.xul. (Actually, the implementation is one step more complicated than this: base files overlay dialogOverlay.xul from the global component directory, which in turn overlays a platform-specific XUL file such as platformDialogOverlay.xul. The mechanism is the same, however.)

Any dialog that wants to overlay these buttons just declares the overlay at the top:

<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>

And includes an empty {{ XULElem("box") }} with an ID of okCancelButtons in the UI. The following snippet shows a dialog with custom UI elements at the top and a reference to the overlay's OK and Cancel buttons at the bottom:

<box align="horizontal" id="bx1" flex="100%" style="margin-bottom: 1em; width: 100%;">
 <html:input type="checkbox" id="dialog.newWindow"/>
 <html:label for="dialog.newWindow">&openWin.label;</html:label>
 <spring flex="100%"/>
</box>

<box id="okCancelButtons"/>

For more detail, see the OK and Cancel button definitions being referenced here in the global component file platformDialogOverlay.xul. Toolbars, submenus, boxes, and any other subtrees that appear in multiple places can be defined in overlays files in this way and referenced for reuse wherever necessary.

Further Reading

{{ languages( { "fr": "fr/Overlays_XUL", "ja": "ja/XUL_Overlays", "pl": "pl/Nak\u0142adki_XUL" } ) }}

Revision Source

<h2 name="XUL_Files_and_XUL_Overlays">XUL Files and XUL Overlays</h2>
<p>Overlays are XUL files used to describe extra content in the UI. Though overlays often define UI elements that have been added as a result of an update or enhancement of some kind, they can be used in many different ways. Overlays provide a general mechanism for:</p>
<ul> <li>adding UI for additional components, as described in the example above</li> <li>overriding small pieces of a XUL file without having to resupply the whole UI</li> <li>reusing particular pieces of the UI</li>
</ul>
<p>XUL files and overlays work together to describe a single master document. Though there is no formal restriction on what kind of XUL content is located in "base" XUL files and what kind should be put in overlays, XUL overlays generally define items that are not present in the basic versions of the UI, such as additional components. When plug-ins, <a href="/en/Extensions" title="en/Extensions">browser extensions</a>, or other applications provide new UI elements to the browser, these elements should be defined in overlay files. The installation of a media plug-in, for example, may add new icons and menu items to the interface:</p>
<p><img alt="Image of SSP UI in browser" class=" internal" src="/@api/deki/files/428/=XUL_Overlay.gif"></p>
<p>In the <code>navigatorOverlay.xul</code> file or in a separate <code>navigatorSSPOverlay.xul</code> file (where <code>navigator.xul</code> defines the basic UI for the navigator package), these new plug-in elements would be defined as a collection of elements or subtrees:</p>
<pre>&lt;menuitem name="Super Stream Player"/&gt;

&lt;menupopup name="SS Favorites"&gt;
 &lt;menuitem name="Wave" src="mavericks.ssp"/&gt;
 &lt;menuitem name="Soccer" src="brazil_soccer.ssp"/&gt;
&lt;/menupopup&gt;

&lt;titledbutton id="SSP" crop="right" flex="1"
              value="&amp;SSButton.label;" onclick="FireSSP()"/&gt;
</pre>
<h2 name="Overlays_and_ID_Attributes">Overlays and ID Attributes</h2>
<p>The layout engine uses the <a href="/en/XUL/Attribute/id" title="en/XUL/Attribute/id">ID attribute</a> to determine where the elements in the overlay file will be merged. Use the same IDs in the base XUL file <em>and</em> the XUL overlay; otherwise, the new elements will not appear at all. In the base file, the parent nodes for the overlay elements must be ID'd if they have not been already. For example, the &lt;{{ XULElem("menu") }}&gt; element in the following XUL subtree should be the parent of the Super Stream Player menu item, so it has been given the ID "file_menu":</p>
<pre>&lt;menu id="file_menu"&gt;
 &lt;menuitem name="New"/&gt;
 &lt;menuitem name="Open"/&gt;
 &lt;menuitem name="Save"/&gt;
 &lt;menuitem name="Close"/&gt;
&lt;/menu&gt;
</pre>
<p>In the overlay file, you can "sync up" the new item by making it the child of a tag <em>with the same ID in the overlay file</em>. The layout engine takes the elements directly under the <code>{{ XULElem("overlay") }}</code> tag with IDs and merges them with the corresponding nodes in the base file. The complete XUL overlay file for adding the single Super Stream Player menu item from the example above is as follows:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;overlay id="singleItemEx"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&gt;
 &lt;menu id="file_menu"&gt;
  &lt;menuitem name="Super Stream Player"/&gt;
 &lt;/menu&gt;
&lt;/overlay&gt;
</pre>
<p>Note that below <code>{{ XULElem("menu") }}</code> in the base file and <code>{{ XULElem("overlay") }}</code> in the overlay file, the subtrees are equivalent. Merged items can be arbitrarily nested subtrees: new <a href="/en/XUL_Tutorial/Popup_Menus" title="en/XUL_Tutorial/Popup_Menus">popup menus</a> may contain other popup submenus, extra <a href="/en/XUL_Tutorial/Toolbars" title="en/XUL_Tutorial/Toolbars">toolbars</a> can overlay existing toolbars or appear beneath them, as the Personal Toolbar does below the Location Bar in Netscape's Communicator, etc. As long as the IDs of the elements appearing below the <code>{{ XULElem("overlay") }}</code> tag in the overlay file and tag with the same ID in the base file, overlays support the merging of any valid subtree.</p>
<p>At the moment you can't overlay an element without an ID, so you need to <a href="/en/Dynamically_modifying_XUL-based_user_interface" title="en/Dynamically_modifying_XUL-based_user_interface"> use DOM methods</a> to tweak the element you need in a <code>load</code> handler.</p>
<h2 name="Loading_Overlays">Loading Overlays</h2>
<p>Overlays can be loaded <em>explicitly</em> or <em>dynamically</em>. When you load an overlay explicitly, it means that you intend to make it available every time the base file is loaded. Since one of the main purposes of overlays is to provide UI for additions or components to the basic package, explicit loading can be somewhat problematic when the overlay defines optional UI elements.</p>
<h4 name="Loading_Overlays_Explicitly">Loading Overlays Explicitly</h4>
<p>A processing instruction is used to load overlay files explicitly into the master document. Inserting the following processing instruction before the DOCTYPE declaration in a base file tells the layout engine to load the named overlay file:</p>
<pre>&lt;?xul-overlay href="chrome://component/content/componentOverlay.xul"?&gt;
</pre>
<p>where <em>component</em> is the name of the package being overlayed (e.g. <code><a class=" external" href="chrome://navigator/content/navigatorOverlay.xul" rel="freelink">chrome://navigator/content/navigatorOverlay.xul</a></code>).</p>
<p>The layout engine loads any overlay files and then flows the resulting XUL document, so problems associated with incremental insertion in menus, boxes, tables, and forms are avoided. Any number of overlays can be loaded into a master document, and an overlay can also load other overlays. Because an overlay is superimposed on the master document, there are no ambiguities relating to scoping of style sheets or scripts. Style sheets and scripts loaded by the overlay simply apply to the entire master document.</p>
<h4 name="Loading_Overlays_Dynamically">Loading Overlays Dynamically</h4>
<p><a href="/en/Chrome_Registration#The_Chrome_Registry" title="en/Chrome_Registration#The_Chrome_Registry">The chrome registry</a> makes it possible to <a href="/en/Chrome_Registration#overlay" title="en/Chrome_Registration#overlay">load XUL overlays dynamically</a> -- or only when necessary. The chrome registry, which is a special <a href="/en/RDF" title="en/RDF">RDF</a> datasource into which user-specific information is <em>persisted</em>, or stored, contains information about the components or additional packages that have been installed with the browser. When a component such as the "Super Stream Player" from the examples above is registered there, overlays associated with that component are loaded automatically. When the component is not present, only the base files are loaded.</p>
<h4 name="Loading_Overlays_at_Run-time">Loading Overlays at Run-time</h4>
<p><a href="/en/Firefox_1.5_for_developers" title="en/Firefox_1.5_for_developers">Firefox 1.5</a> and other Gecko 1.8-based applications also support loading overlays on-the-fly via <a href="/en/DOM/document.loadOverlay" title="en/DOM/document.loadOverlay">document.loadOverlay</a> function. <span class="comment">TODO: elaborate</span></p>
<h2 name="Overlays_and_Skins">Overlays and Skins</h2>
<div class="warning">Always load master skins from base files. Never load master skins from overlays.</div>
<p>Unlike base files, overlays should never load the master skin file for a package. The <code>navigatorOverlay.xul</code> file, for example, does not and should never load the <code>navigator.css</code> file that defines the master skin for the navigator package. Since the purpose of an overlay is to define new UI elements for a package within the context of that package's skin, the overlay should add structure but not new style. Any skins that are loaded by an overlay destructively replace the master skin for the base file, and can change the basic appearance of the package's skin in unfortunate ways.</p>
<div class="note">The master skin is not the same as the global skin. For any package, the master skin file is that CSS file named after the package itself. The master skin file for the bookmarks package, for example, is called <code>bookmarks.css</code>, and is located in the skin/default subdirectory.</div>
<h2 name="Overlaying_Attributes">Overlaying Attributes</h2>
<p>In addition to new elements and subtrees, you can also overlay <em>attributes</em> into existing elements. In XUL, attributes control important features of the skin like image sources, as in the following example, where an overlay destructively overwrites the image source in the base file with a replacement. In the base file, the HTML image element points to a Netscape GIF icon:</p>
<pre>&lt;html:img id="foo" src="netscapeImage.gif"/&gt;
</pre>
<p>In the overlay, an element with the same ID attribute specifies a different image, and that image is superimposed on top of the original Netscape image as part of the merge process:</p>
<pre>&lt;html:img id="foo" src="mozillaImage.gif"/&gt;
</pre>
<p>When the base file references an overlay file which contains the html image element above, the new src attribute is superimposed over original, and the Mozilla icon replaces the Netscape icon.</p>
<h2 name="Overlay_Positioning">Overlay Positioning</h2>
<p>XUL overlays also support positioning of nodes. You can specify a {{ XULAttr("position") }} attribute on a node in the overlay to provide a hint for insertion into the master document. In the following example, the last menu item, Example Four, will be placed just after the "New" menu item instead of being appended to the end of the menu like the other kids.</p>
<pre>&lt;overlay id="main-overlay" xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&gt;
 &lt;menu id="file_menu"&gt;
  &lt;menuitem name="Example One"/&gt;
  &lt;menuitem name="Example Two"/&gt;
  &lt;menuitem name="Example Three"/&gt;
  &lt;menuitem name="Example Four" position="1"/&gt;
 &lt;/menu&gt;
&lt;/overlay&gt;
</pre>
<p>The node with the {{ XULAttr("position") }} attribute orders itself to the top of the menu. The {{ XULAttr("position") }} can also be given for nodes in overlay files that will be ordered in a group of similar items in the base file. For example, if only the last menuitem above had been in an overlay and the other items were defined in the base file, the overlayed menuitem would still appear at the top of the parent menu.</p>
<h2 name="Attaching_a_Script">Attaching a Script to an Overlay</h2>
<p>To execute a script when an overlay is applied, use a &lt;script&gt; element:</p>
<pre>&lt;script src="overlay.js"/&gt;
</pre>
<p>If you need to set the version of JavaScript, you can set the type, and append ";version=x.y" to the end of the src attribute:</p>
<pre>&lt;script type="application/x-javascript" src="overlay.js;version=1.8"/&gt;
</pre>
<h2 name="UI_Reuse_with_Overlays">UI Reuse with Overlays</h2>
<p>One of the biggest benefits of using overlays is that it allows you to reuse groups of elements that appear frequently in the UI. The overlay mechanism allows you to merge elements into existing subtrees, but it also allows you to store common UI elements in overlay files and merge them into any base files that use them. Using the ID attribute on an otherwise empty node in the base file, you can essentially reference a subtree defined in an overlay file and merge it in wherever it's needed.</p>
<p>For example, the buttons that appear at the bottom of common dialogs, the OK and Cancel buttons, may be used in dozens of places in the UI. Rather than redefining this set of buttons each time they are necessary in a particular dialog, base XUL files can overlay the XUL file in which these buttons are defined, <code>dialogOverlay.xul</code>. (Actually, the implementation is one step more complicated than this: base files overlay <code>dialogOverlay.xul</code> from the global component directory, which in turn overlays a platform-specific XUL file such as <code>platformDialogOverlay.xul</code>. The mechanism is the same, however.)</p>
<p>Any dialog that wants to overlay these buttons just declares the overlay at the top:</p>
<pre>&lt;?xul-overlay href="chrome://global/content/dialogOverlay.xul"?&gt;
</pre>
<p>And includes an empty {{ XULElem("box") }} with an ID of <code>okCancelButtons</code> in the UI. The following snippet shows a dialog with custom UI elements at the top and a reference to the overlay's OK and Cancel buttons at the bottom:</p>
<pre>&lt;box align="horizontal" id="bx1" flex="100%" style="margin-bottom: 1em; width: 100%;"&gt;
 &lt;html:input type="checkbox" id="dialog.newWindow"/&gt;
 &lt;html:label for="dialog.newWindow"&gt;&amp;openWin.label;&lt;/html:label&gt;
 &lt;spring flex="100%"/&gt;
&lt;/box&gt;

&lt;box id="okCancelButtons"/&gt;
</pre>
<p>For more detail, see the OK and Cancel button definitions being referenced here in the global component file <code>platformDialogOverlay.xul</code>. Toolbars, submenus, boxes, and any other subtrees that appear in multiple places can be defined in overlays files in this way and referenced for reuse wherever necessary.</p>
<h2 name="Further_Reading">Further Reading</h2>
<ul> <li><a class="external" href="http://mb.eschew.org/12.php">Chapter 12 "Overlays and Chrome"</a> of <a class="external" href="http://mb.eschew.org/">"Rapid Application Development with Mozilla"</a></li> <li><a href="/en/XUL_Tutorial/Overlays" title="en/XUL_Tutorial/Overlays">"Overlays"</a>, <a href="/en/XUL_Tutorial/Cross_Package_Overlays" title="en/XUL_Tutorial/Cross_Package_Overlays">"Cross Package Overlays"</a> of <a href="/en/XUL_Tutorial" title="en/XUL_Tutorial">"XUL Tutorial"</a></li>
</ul>
<p>{{ languages( { "fr": "fr/Overlays_XUL", "ja": "ja/XUL_Overlays", "pl": "pl/Nak\u0142adki_XUL" } ) }}</p>
Revert to this revision