Crowley Code! 
 (Take 12)

XUL overlays demystified 2007/08/03

This assumes just a little knowledge of how to get a basic Hello World XULRunner app going. If you need help, I swear by Mark Finkle.

Every would-be Firefox extension developer (myself certainly included) has at some point sparred with overlays and been vanquished. They are not the friendliest things, as they are actually quite powerful and can handle a wide range of tasks. When building a Firefox extension, you build overlays to hook into the menus, create sidebars and toolbars, add status icons and do most anything else you can dream up.

To understand overlays, it helps to first get a look at the main application <window>. Here is a simple application window:

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://foo/skin/main.css" type="text/css"?>
<?xul-overlay href="chrome://foo/content/overlay_asdf.xul"?>
<?xul-overlay href="chrome://foo/content/overlay_qwerty.xul"?>
<!DOCTYPE window SYSTEM "chrome://uploadr/locale/foo.dtd">
<window id="main" title="&title;" width="750" height="500"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
	<script src="chrome://uploadr/content/main.js" />
	<toolbox>
		<menubar id="menu">
			<menu id="menu_file" label="&menu.file;">
				<menupopup>
					<menuitem id="menu_go" label="&menu.file.go;"
					oncommand="go();" />
					<menuitem id="menu_FileQuitItem" label="&menu.file.exit;"
					oncommand="exit();" />
				</menupopup>
			</menu>
		</menubar>
	</toolbox>
	<vbox flex="1">
		<hbox id="view_asdf" flex="1" />
		<vbox id="view_qwerty" flex="1" />
	</vbox>
</window>

This application does a couple of things of note. First, it sets up a XULRunner application window with a menu and a couple of boxes, but more importantly, at the top, it includes the two overlays we're about to write.

Before we write the overlays, though, let's add to the main.css file we're including to make this interesting. The two overlays are going to be two different views in our application so we won't want to see them both at the same time. For starters we'll just hide #view_qwerty.

#view_qwerty {
	display: none;
}

Now come the overlays. An <overlay> is contructed very much like a <window> and can include all of the same types of content. The trick is in how they are inserted into the DOM. When an overlay is being processed, elements whose ID is shared by a similarly typed element in the main window, the contents of the overlay element are appended to the contents of the same element in the main window.

Knowing that, let's write our two overlays. First overlay_asdf.xul and then overlay_qwerty.xul.

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://foo/skin/main.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://foo/locale/main.dtd">
<overlay id="overlay_asdf"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
	<hbox id="view_asdf" flex="1">
		<html:p>This is view asdf.</html:p>
	</hbox>
</overlay>
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://foo/skin/main.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://foo/locale/main.dtd">
<overlay id="overlay_qwerty"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
	<vbox id="view_qwerty" flex="1">
		<html:p>This is view qwerty.</html:p>
	</vbox>
</overlay>

The structure of the overlays is very similar to the structure of the window, so we'll just take that as is and move on. The important thing to notice here is the way that #view_asdf is a <hbox> just as it is in the main window, while #view_qwerty is a <vbox>, again as it is in the main window. This is not strictly required, as the elements must only be similar, but because boxes want to be horizontal, you can introduce weirdness into your app if you're careless about matching these tags up. So the moral of the story is to match your overlay tags with the tag being overlaid in the main window.

So now we have an app that, when run, will show us a window with a menu and a paragraph proclaiming "This is view asdf." Too exciting. One little bit of Javascript in main.js will bring it all together.

var go = function() {
	var asdf = document.getElementById('view_asdf');
	var qwerty = document.getElementById('view_qwerty');
	if ('none' == asdf.style.display) {
		asdf.style.display = '-moz-box';
		qwerty.style.display = 'none';
	} else {
		asdf.style.display = 'none';
		qwerty.style.display = '-moz-box';
	}
};

With any luck, running your app will be able to toggle between its two views by selecting the "Go" option from the "File" menu. Here's a peek under the hood. When XULRunner brings in your overlays, it's updating the main DOM. The end result is a DOM that looks like this:

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://foo/skin/main.css" type="text/css"?>
<?xul-overlay href="chrome://foo/content/overlay_asdf.xul"?>
<?xul-overlay href="chrome://foo/content/overlay_qwerty.xul"?>
<!DOCTYPE window SYSTEM "chrome://uploadr/locale/foo.dtd">
<window id="main" title="&title;" width="750" height="500"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
	<script src="chrome://uploadr/content/main.js" />
	<toolbox>
		<menubar id="menu">
			<menu id="menu_file" label="&menu.file;">
				<menupopup>
					<menuitem id="menu_go" label="&menu.file.go;"
					oncommand="go();" />
					<menuitem id="menu_FileQuitItem" label="&menu.file.exit;"
					oncommand="exit();" />
				</menupopup>
			</menu>
		</menubar>
	</toolbox>
	<vbox flex="1">
		<hbox id="view_asdf" flex="1">
			<html:p>This is view asdf.</html:p>
		</hbox>
		<vbox id="view_qwerty" flex="1">
			<html:p>This is view qwerty.</html:p>
		</vbox>
	</vbox>
</window>

The overlays buy us code separation, shorter files, and more sanity. Three cheers for overlays!

Comments (5)

  1. Nice post, only thing missing is how to include same overlay twice in single xul file,and keep element id unique, as far as I know it is not possible to do this at this time.

    Greg Bugaj — 2007/09/13 8:31 am

  2. hi, iam have built 2 toolbar with very little difference. they work seperately fine.the problem is when i install both of them together one gets overlayed upon other. can u guide me on how to position the toolbar properly..is there anyway to do it. thanks for the gud post

    — dhanalakshmi kannan — 2008/02/28 4:34 am

  3. hMZYIN mhbzvjrwvwbr, [url=http://zxcpefwcwunz.com/]zxcpefwcwunz[/url], [link=http://zfcqrbtjctfh.com/]zfcqrbtjctfh[/link], http://tsknxhgrwhnt.com/

    cuzowblx — 2008/09/15 3:57 pm

  4. hMZYIN mhbzvjrwvwbr, [url=http://zxcpefwcwunz.com/]zxcpefwcwunz[/url], [link=http://zfcqrbtjctfh.com/]zfcqrbtjctfh[/link], http://tsknxhgrwhnt.com/

    cuzowblx — 2008/09/15 3:57 pm

  5. gOvGwE gsjntuiqtpev, [url=http://xfomniwgsydm.com/]xfomniwgsydm[/url], [link=http://utmogmqckemp.com/]utmogmqckemp[/link], http://ahvgqfnbffro.com/

    kduurx — 2008/09/15 5:29 pm

Richard Crowley?  Kentuckian engineer who cooks and eats in between bicycling and beering.

I blog mostly about programming and databases.  Browse by month or tag.

To blame for...


© 2009 Richard Crowley.  Managed by Bashpress.