
If you've worked with XUL at all, you know it's a great language for creating user interfaces for applications. But you may have noticed that things tend not to move around much in XUL -- except for maybe dropdown menus or when you drag and drop a bookmark. What if, though, you wanted to create a chess game, or even a "virtual desktop" application where you needed visual elements to move from place to place?
If you did what I did, which is look in the existing Mozilla XUL code for something that might help you, I'm sure you probably came up a bit short. The reason for this is that the tag set I'm about to describe currently has no representation in the existing code, as it is relatively new. I'm sure that as later versions are created, and the need arises, you will see this aspect of XUL used more often. So what the heck am I talking about? It's the <bulletinboard> tag.
The implications for <bulletinboard> are huge! I could barely contain my excitement when I discovered that this had been added to the Mozilla codebase. Here are a few of the potential applications for <bulletinboard>:
But ultimately, I keep pondering the implications <bulletinboard> has for gaming. Mozilla gives you the ability to play sounds, display images, connect to a network, fetch information remotely, etc., etc. All of which someone might tie together in novel ways to make some really interesting multiplayer games. Before <bulletinboard>, these applications would simply have been impossible or much more difficult to create.
|
Other examples of current XUL applications using <bulletinboard> can be found at DMOZ under XUL Applications, and especially in the subcategory, XUL Applications -- Games |
Before <bulletinboard>, if you wanted to create animation in Mozilla, you'd have to use HTML and absolute positioning since XUL didn't support that. The reason is that the box model on which XUL is based uses flexibility and relative positioning of elements. (This gives you things like "intrinsic sizing" where the window arranges itself based on the size needs of all the widgets it contains.)
You can find many examples of animation using this CSS absolute positioning methodology in any DHTML book. (This is a big aspect of the "D" in DHTML.) Resorting to this method had many drawbacks, as you had to interleave HTML tags in XUL. This sometimes has undesirable side effects (like slowing down the browser due to the extra rendering baggage HTML tags bring along). You might also have tried to "fake" animation with animated gifs or Flash files.
Now, with the bulletinboard tag, you can position elements on the screen (and thusly move them around with scripting) in virtually the same way you might position them with DHTML.
Here's what you might do in DHTML:
Listing 1: HTML positioning.
<html>
<head>
<style>
#firstone{ position:absolute; left:30px; top:30px; }
#secondone{ position:absolute; left:100px; top:100px;}
</style>
</head>
<body>
<div id="firstone" >
<img id="fooimage" src="foo.gif">
</div>
<div id="secondone" >
<img id="fooimage2" src="foo2.gif">
</div>
</body>
</html>
The equivalent of this in XUL might be:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="main" align="center" valign="middle" autostretch="never"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
<bulletinboard style="width:300px; height:300px;" >
<image id="firstone"
src="chrome://global/content/logo.gif" style="top:10px; left:100px;"/>
<image id="secondone" src="chrome://global/content/logo.gif"
style="top:100px; left:120px;"/>
</bulletinboard>
</window>
This example places two images inside a 300 by 300 pixel space and positions them according to the top and left style definitions.
Let's take a moment and step back from the code and think about what's going on. Imagine that you were standing in front of a standard bulletin board on a wall -- say in a school or an office building. There are some features of a "real world" bulletin board that I think help illustrate its virtual XUL equivalent.
The "real world" bulletin board contains little snips of paper that folks have posted, usually by stick pins, that contain information you'd like to share. You also see that some newer pieces of paper might overlap other older notes that have been around longer, and some of the notes might be obscured completely by newer ones. You also see that -- for the most part -- all the little notes are contained by the frame of the bulletin board. We all know how hard it is to stick notes on a hard concrete wall with only stick pins at your disposal.
These "real world" features map quite closely to our XUL <bulletinboard>. Imagine that instead of pieces of paper you have XUL boxes (or other tags). Imagine that you "stick" these pieces of paper on the board with a push pin which is placed at the top left hand side of the paper. In XUL, this would be equivalent to the "top" and "left" attributes you place in a contained XUL tag.
Much in the same way you can rearrange slips of paper on a real bulletin board, you can do the same for our XUL equivalent. All you need to do is change the top and left attributes (either by setAttribute for each or via stylesheets).
Imagine as well that "newer" pieces of paper overlap "older" ones. This occurs in the XUL <bulletinboard> as well. "Older" elements, which are listed first inside the tag, are covered up by "newer" ones that are listed after them. Imagine if you shot an arrow upward from the bottom of the XUL code, the tags you "hit" first are the ones which will be topmost in the z-ordering. This is an important aspect of the bulletinboard tag.
Currently, <bulletinboard> only operates within two dimensions. Z-order isn't explicitly defined. But there is an implied z-order as I mentioned earlier. Elements listed after a given element appear above them on screen.
|
The syntax for the <bulletinboard> tag is quite simple. All you need to do is wrap any existing tags you want to be positionable with the
<bulletinboard> tag. This is a common code pattern in XUL. For instance you see the same thing with the <stack> and <deck> tags (and many others). Here's another example:
<bulletinboard>
<box id="item1">
<iframe src=http://www.news.com />
</box>
<box id="item2">
<button id="button1" class="mybutton" value="clickme" oncommand="" />
</box>
</bulletinboard>
You can now position the element with the ID item1 or item2 anywhere you want to on the screen, either placing the "top" and "left" attributes in the tags themselves or setting them via stylesheets (top: and left:).
Our XUL bulletinboard has a few advantages to its corkboard counterpart (apart from never running out of thumbtacks). We can use JavaScript to dynamically change the position of any element in this board -- which is really why most people would be interested in using this. Again, we can revisit many DHTML sites and can practically lift the code right out of them with minor modifications to animate XUL-based elements.
Here's a simple example. Imagine if you wanted to move item2 in the listing above from its current location (which by default is 0,0) to say 200,300 (I'm assuming pixels here). In JavaScript you might write something like:
function moveIt(theNodeID, theTop, theLeft){
theNode=document.getElementById(theNodeID)
theNode.setAttribute("top",theTop) // change the y position
theNode.setAttribute("left",theLeft) // change the x position
}
And you would execute this code like this:
moveIt("item2",30,40)
There are a number of things that you need to take into consideration when developing XUL apps with <bulletinboard>:
<box top="30px" left="20px" /> instead of <box style="top:30px;left:20px" >), because you save time not having to have a stylesheet resolution cycle in the reflow.removeChild() and appendChild() on the parent <bulletinboard> tag.For users who want to roll up their shirtsleeves a little further, I've included an advanced example of using <bulletinboard> in conjunction with JavaScript, XBL, and stylesheets. This example is a simple puzzle that allows you to drag images around and arrange them into the Mozilla.org logo image. You can find this example here. Load the puzzle.xul file and drag the images around.
Here is a screenshot of Puzzle in action:
![]() |
Puzzle in action. |
How it works:
<bulletinboard> with several images that I had already cut up in Fireworks.draggable which I applied to all of the images. I added a -moz-bindingdraggable class.<image> tags, and put the JavaScript routines in another file.<window> tag.Play with this example and see how it works. Notice that the image you click on to start dragging it around doesn't come to the front. You might try to add code that does this (perhaps removing the target DOM node and reattaching it -- which would have the effect of putting that node at the bottom of the "list" and thusly on top).
I created this example also with the idea that you might take it and create your own XUL applications.
The <bulletinboard> tag is fairly simple and straightforward, but it's very useful as a way to indicate that you want its child elements to be positioned much as standard DHTML does. But instead of using CSS position:absolute, you merely need to indicate an element's top and left attribute.
You cannot currently control the z-index directly, but you can indirectly by changing the order of a <bulletinboard> element's children. The possibilities for XUL-based applications based on <bulletinboard> are very interesting, and if you begin to get really sophisticated and start mixing in <grid>, <stack>, <deck>, and other tags, you might even come up with something new and astonishing.
This is the real power of XUL. It makes creating user interfaces easy, fun, and simple. Have fun exploring the <bulletinboard> tag and let me know what you come up with!
Andrew Wooldridge is a XUL and JS developer at Netscape Communications Corp.
Discuss this article in the O'Reilly Network Browsers Forum.
Return to the Mozilla DevCenter.
Copyright © 2007 O'Reilly Media, Inc.