A Closer Look At XUL
What does XUL look like? Look at any Mozilla window except the browser
window (such as the e-mailer or the Address Book). In this article I
illustrate XUL with a simple trouble-ticketing system, such as any
support center might provide to its users. Those users can then supply
feedback on documentation lodged on an intranet or extranet. Depending
on your viewpoint, this is an applet, a dialog box, or an embedded
application -- you'll see as I continue.
Listing 1 shows the XUL code behind this system.
Listing 1. The XUL code example for a trouble-ticket system
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="ticket.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="init.js"/>
<script src="commands.js"/>
<script src="server.js"/>
<toolbox>
<menubar id="menubar" grippyhidden="true">
<menu id="menu_login" accesskey="L" label="Login">
<menupopup>
<menuitem id="m10" label="Login" accesskey="L"
oncommand="cmd_login()"/>
<menuitem id="m11" label="Logoff" accesskey="O"
oncommand="cmd_logoff()"/>
<menuitem id="m12" label="Exit" accesskey="X"
oncommand="cmd_exit()"/>
</menupopup>
</menu>
<menu id="menu_ticket" accesskey="N" label="New Ticket">
<menupopup>
<menuitem id="m20" label="User Ticket" accesskey="U"
oncommand="cmd_user()"/>
<menuitem id="m21" label="Technical Ticket" accesskey="T"
oncommand="cmd_tech()"/>
<menuitem id="m22" label="Reviewer's Ticket" accesskey="R"
oncommand="cmd_rev()"/>
</menupopup>
</menu>
<menu id="menu_action" accesskey="A" label="Action">
<menupopup>
<menuitem id="m30" label="Clear" accesskey="C"
oncommand="cmd_clear()"/>
<menuitem id="m31" label="Submit" accesskey="S"
oncommand="cmd_submit()"/>
</menupopup>
</menu>
<spacer flex="1"/>
<menu id="Help" accesskey="H" label="Help">
<menupopup>
<menuitem id="m40" label="Help Contents" accesskey="H"
oncommand="cmd_help()"/>
<menuitem id="m41" label="Contact Details" accesskey="D"
oncommand="cmd_contact()"/>
<menuitem id="m42" label="About" accesskey="A"
oncommand="cmd_about()"/>
</menupopup>
</menu>
</menubar>
</toolbox>
<hbox class="title">
<deck id="title">
<label value=""/>
<label value="User Problem"/>
<label value="Technical Problem"/>
<label value="Review Status"/>
</deck>
<spacer flex="1"/>
<label value="Ticket #"/>
<textbox id="f00" readonly="true" size="10"/>
</hbox>
<deck id="forms" flex="1">
<vbox/>
<vbox>
<checkbox id="f10" label="Information Missing"/>
<checkbox id="f11" label="Errors Discovered"/>
<checkbox id="f12" label="Please Send Author's E-mail"/>
</vbox>
<vbox>
<label>Please describe the nature of the problem.
Your client's version will be automatically reported</label>
<textbox id="f20" multiline="true" rows="6"/>
</vbox>
<vbox>
<radiogroup>
<radio id="f30" label="draft approval"/>
<radio id="f31" label="final draft"/>
<radio id="f32" label="publication approval"/>
</radiogroup>
</vbox>
</deck>
<statusbar id="sbar">
<description>Current Status:</description>
<deck id="stext" selectedIndex="0">
<description id="sb0" class="warn">Disconnected</description>
<description id="sb1" class="ok">Logged On</description>
<description id="sb2" class="ok">Delivered</description>
<description id="sb3" class="warn">Delivery Failed</description>
</deck>
<spacer flex="1"/>
</statusbar>
</window>
|
This listing is hardly larger than a single Java class, and yet it
is an application's entire GUI. XUL provides convenient brevity. The
tags, like toolbar
, menu
, textbox
, and radiogroup
are refreshingly simple -- no 3GL calls are required to XCreatePixmapFromBitmapData()
or other low-level agony.
Many of the tags provide invisible structure: toolbox
, hbox
, and vbox
are container tags that affect layout of their collected elements (for
example, "vbox" is short for "vertical box"). This containership
appears frequently in XUL: a toolbox
contains a menubar
which contains several menu
s, each of which provides a menupopup
drop-down menu, and that menupopup
holds a number of menuitem
menu items. Of the other tags, the spacer
tag is used to create extra gaps between screen elements. The label
and description
tags are specialized equivalents to HTML's <p>. Unfortunately, I don't have room to cover every possible XUL tag here.
Some of the attributes used in XUL tags are shared with HTML, such as id
, class
, value
, accesskey
, readonly
, and selectedIndex
. Others are special to XUL, like grippyhidden
(which stops a menu bar from being hidden by the user) and oncommand
(which is an event handler that fires when a menu option is chosen).
Mozilla's registered name for the XML application is given by the URL in the window
tag at the top; this is a product identifier and is not loaded from
anywhere. Some of the content of this XUL document can be seen in
Figure 1:
Figure 1. The opening XUL page
This plain XHTML document deploys the applet in three ways:
- A hyperlink.
- A button.
- An XHTML
iframe
The embedded applet appears in the bottom half of the shot. You can
see that its menu bar looks similar to the menu bar of the entire
browser window. In fact, they are implemented as different instances of
the menubar
tag. Just as for the main browser menu bar, the applet menu bar is
responsive to the mouse, tab-key-style navigation, and hot-key
combinations. This integration comes for free, something that doesn't
happen with a Java applet. A Java applet doesn't have a URL of its own
either; it must always be initialized by an applet
or an object
tag.
The XHTML that hosts this applet is shown in Listing 2 and is just a trivial use of HTML event handlers and iframe
.
Listing 2. The XHTML that hosts the applet
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
var flags = "toolbar=no,locationbar=no,menubar=no,width=275,height=275";
function show()
{
window.open('ticket.xul', '_blank', flags);
}
</script>
</head>
<body>
<h2>Test Page</h2>
<p>
A hyperlink that starts the example
in a separate window:
<a href="about:blank"
onclick="show(); return false">Lodge Ticket</a>.
</p>
<p>
A button that starts the example
in a separate window:
<button onclick="show()">Lodge Ticket</button>.
</p>
<p>
Here is the ticket entry system displayed in
an <iframe>:
</p>
<iframe width="275" height="275" src="ticket.xul"/>
</body>
</html>
|