
When I first started getting involved in Mozilla development, I was excited. Finally, I would be able to create applications leveraging my knowledge of HTML, JavaScript, and style sheets. I had been frustrated in college with the difficulty of grasping C++ and the tedium of coding, compiling, running, debugging, etc. etc. I was pretty confident I had a good grasp of what XUL was and how to wire things up with JavaScript and make it look pretty with CSS. Then along came something new about Mozilla that took me almost a week to finally grasp what it meant, and over a month to fully realize its implications. What is it? It's something new called XBL (Extensible Bindings Language). OK, this isn't something very new, but I believe that many folks still taking delight in playing with all the other fun features of Mozilla may have yet to encounter this.
Now before I go on, I must say that what I am about to talk about is not some tacked on feature that just "seemed cool." It's a fundamental component of Mozilla, and it can be the basis of a radical new way for you to think about web applications.
Ready? Let's get started. First off, let me tell you what XBL is. I need to explain this carefully because if you don't get this right off, you may have trouble understanding some of the concepts I'll be going through. But give it some time and it'll sink in. XBL allows you to "bind" a set of content and behavior to some other element. This content is "anonymous," meaning that the document only sees the original element, not the composite of elements inside it. Huh? Let's go with an analogy which I used myself to explain it to a friend. Do you remember those Transformer toys? You could put five or six of them together, and build a single larger Transformer that was more than just the sum of the smaller toys. This is somewhat how XBL works. You can take elements -- like, say, buttons, images, scrollbars, and other elements - and put them together to build a "composite" element. The interesting thing is that the inner workings of this composite element are hidden from your document.
|
Also Featured This Week Mozilla is Not Netscape (and Other True Facts) |
For instance, I might create a chess game in XUL and fashion a tag called <chesspiece>. I may in my XBL tell this <chesspiece> tag to be built up out of perhaps an <image> tag and a <text> tag, and have behaviors like oncheckmate or oncapturepiece -- just like a image tag might have an onload and onmouseover. In my XUL document, I just have the <chesspiece> tag. But when it appears on the screen, the browser will "build" that chesspiece tag out of the elements I specified in the XBL. This allows you to build new composite elements out of simpler ones. And it allows you to add a layer of abstraction to your code that you may not have been able to do up until now. So now, instead of begging some programmer somewhere to add that new "tag" you've always wanted, you can do it yourself with much less trouble. This is one of the things I think XML was totally created to do -- allow you to build your own language. XBL gives you the power to give shape to that language using basic components.
XBL expresses itself through the CSS style system. For instance: Perhaps I have some spreadsheet tag with a CSS class of bigtable. I would have a CSS style rule which applies some XBL binding through the bigtable class. Any element having a class of bigtable would show on the screen as a big HTML table with borders and every other column shaded. I could get even more interesting and have another class of type piechart which might display the content of the tag as an SVG (scalable vector graphic) pie chart. I could get even more interesting by putting a button underneath this tag, which changes its class via JavaScript from bigtable to piechart. If I did this, I could magically transform my data from a table view to a pie view -- all by just swapping out a class attribute on a single tag. This is just the beginning ...
XBL doesn't just allow you to create a special view of some element, it can also effect JavaScript as well. You can trigger JavaScript code from within a binding, you can create your own special properties on some tag and run some js code whenever that property is get or set, and you can create your own event handlers -- to send and receive new kinds of events you design. You could do wild things like say tell a <pieceofwood> tag to burstIntoFlames() -- and the underlying XBL might be an image of a log that is swapped with an animated gif of a burning log.
Does it make any sense yet? I'm betting you are reading this and scratching your head, wondering "what's the big deal" and "what is he talking about?" Instead of trying to convince you of anything, I'm going to walk through the construction of a fictional "tag" using XBL and describe the process as I go. Perhaps after you follow this toy example, you might begin to see the real power behind this component of Mozilla.
|
Setting up the browser
For these examples I recommend you download the latest milestone release of Mozilla, which at this time is M17. Set up a profile and try it out a little before continuing on. There's no special setup of the browser this time, as we will be opening the XUL files directly from File | Open File.
Authoring tools
All you will need for this exercise is a simple text editor. I recommend BBEdit on Mac and HomeSite on Windows. Perhaps someday in the future we'll have a XUL-specific authoring tool, but for now we must work in the prehistoric era.
Simple XBL syntax
Before I go into the creation of our own special XBL widget -- I call it a "jack" -- let me give you a few examples of what an XBL binding looks like:
<binding id="thumb" extends="xul:box">
<content>
<xul:spring flex="1"/>
<xul:image inherits="src"/>
<xul:spring flex="1"/>
</content>
</binding>
This is the binding for the little slider thumb on all Mozilla scrollbars. XBL has its own syntax which is completely independent of XUL.
Simple XBL examples
Here are some other examples:
This is a binding for the simple tab element in a tab widget:
<binding id="tab">
<content>
<xul:image inherits="src" class="tab-left"/>
<xul:text flex="1" inherits="value,crop,accesskey"
crop="right" class="tab-text"/>
</content>
</binding>
This is the binding for a <text> widget in XUL:
<binding id="text">
<handlers>
<handler type="click" value="var
forElementID = this.getAttribute('for');
if(forElementID) var forElement =
document.getElementById(forElementID);
if(forElement) forElement.focus();"/>
</handlers>
</binding>
And now a much more complicated binding. It's the binding that controls how a popup menu works. Don't worry about making sense of the tags right now...view this binding here.
The need
When I decided to learn how XBL worked, I came to it with a problem. I wanted to create a way to have elements on the screen "slide" around in XUL, much as they do in HTML via absolute positioning. Instead of going to ask the Mozilla developers to try to support some new tags with new syntax, I can now just build it myself. So first I specified my need: I needed a way for an element on the screen to move from one location to another. I knew about the <spring> tag, which allows you to create a buffer zone between elements -- say between two buttons on the screen. And I also knew that I could "expand" and "contract" this spring tag by changing a property on it called flex. So if I could come up with something that simplified this expansion and contraction, I could go a long way towards what I wanted. So I came up with a new tag that will serve my needs and also serve as an example for you to try out as well.
|
The tag: <jack>
I came up with a name for this tag: the <jack> tag. I imagined something I could "jack" up and down like a car jack -- where you have this piece of equipment that expands or contracts when you apply force on it. I could have come up with some special attributes for this tag, like maxflex or something like that, but I wanted something simple. So here's an example of a <jack> tag:
<jack flex="1" id="somename" />
Very similar to a <spring> tag -- so far.
Creating a test XUL file
To illustrate how a <jack> might work, I created a simple XUL file that places <jack>s around a set of buttons. One on the left, right, top and bottom:
<box flex="1">
<jack flex="4" id="jack1"/>
<box flex="1" orient="vertical" style="border:2px solid">
<jack flex="4" id="jack2"/>
<button value="go up" oncommand="slider('up')" flex="1"/>
<button value="go down" oncommand="slider('down')"
flex="1"/>
<button value="go left" oncommand="slider('left')"
flex="1"/>
<button value="go right" oncommand="slider('right')"
flex="1"/>
<jack flex="4" id="jack3"/>
</box>
<jack flex="4" id="jack4"/>
</box>
Now wait a minute! Aren't I doing this backward? Wouldn't I first create the binding and then build the code? Perhaps, but I'm doing it in this order to show you that you can build a syntax in XML (XUL, specifically) before you get the implementation down. This way you can create your abstraction free from the ideas and limitations that the actual implementation might unconsciously impose on you.
The behavior: css expression
XBL bindings are attached to tags in XUL via the style mechanism. What I mean is that just like you might set some text to be bold or left-justified, you can tell the browser to make it render as a blinking table with an animated gif in the background (not recommended, mind you). You do this by the expression in CSS of:
behavior: url("someURL.XML#idname")
Where someURL.XML is the name of the file that contains the bindings, and the #idname is the ID of the binding element you wish to use.
For example, here is the CSS style rule for our <jack> tag:
jack {
behavior: url("testxbl.xml#jack");
}
Note that you can use CSS to bind to the tagname itself, as is the case above, or you can bind it via ID or CLASS, or any other way that CSS can select an element.
The bindings tag
An XBL document looks something like this:
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl">
<binding> ... </binding>
<binding> ... </binding>
...
</bindings>
It is a "true" XML document, in that you need to declare all of the namespaces you wish to use, and you can interleave other kinds of XML documents in this file by adding other namespaces. For instance, you might create an XBL binding that mixes XUL elements with SVG elements.
The binding syntax
Here is the actual binding for our <jack> tag:
<binding id="jack" extends="xul:box">
<content>
<spring inherits="flex" />
</content>
<interface>
<method name="flexto" >
<argument name="start" />
<argument name="finish" />
<argument name="step" />
<argument name="interval" />
<argument name="theid" />
<body>
<![CDATA[
if(start!=finish){
this.setAttribute("flex",start+step);
var theString="document.getElementById('"+theid+"')
.flexto("+(start+step)+","+finish+","+step+","+interval+",
\""+theid+"\")"
//alert(theString)
setTimeout(theString,interval)
}
]]>
</body>
</method>
</interface>
</binding>
There's a lot of information here, so I'll go through it step by step. First you see the <binding> tag, which tells XBL we are starting a new binding. Inside this you see an attribute called extends. Extends is an attribute that can tell a binding to inherit the properties of another tag, or even the properties of another binding! This allows you to do something like "take all the properties of some basic element and now build upon it."
The next thing you see is the <content> tag. Everything inside the content tag will be displayed in place of the tag you are binding to. In a future article I will discuss how a binding can handle any tags that may be "inside" the tag you are binding to (called children). Right now, it is sufficient to just assume that whatever you place inside the content tag will show up in the XUL. I'm using a spring in this case. You see an attribute called inherits. This is the method XBL uses to transfer attributes from the bound tag to the anonymous content.
The next tag you see is the <interface> tag. Everything inside the interface defines this binding's properties and methods, which will be used in JavaScript. I have created a method called flexto, which needs the properties start, finish, step, interval, and theid. If the terminology of property and method are foreign to you, I'd recommend getting a good programming book, or reading the documentation on JavaScript. I'm making the assumption here that you have some knowledge of JavaScript and programming. You can create an unlimited number of properties and methods.
|
Inside the <body> tag within the <interface> tag, I have created a JavaScript function that will take in the values I pass into it and either increase or decrease the flex attribute until it matches the final value I request. I'm doing a basic DOM call of getElementById() to get the element I want to effect. Basically this JavaScript code is now very reusable. If I want to reuse this <jack> widget elsewhere, I no longer need to worry about bringing along other .js files or trying to remember how I implemented it. It'll just "work." This opens many doors for developers to create whole libraries of widgets and code that could be distributed to others -- or for you to build up your own specialized behaviors.
![]() |
Figure 1. Imagine that you had a box suspended in air by some springs on all sides. If you change the tension on those strings, you could move the box around. |
The other component of the XUL file, which I failed to mention up until now, takes advantage of this new method I have added to my tag. The code is listed here.
All this code does is add some glue to the buttons in my XUL. I have created four buttons, one for each direction I'd like the box to go. So for instance, if the direction is "up," I would get the top jack's flex (jack2), decrease it from whatever it is to 0, and also get the bottom jack's flex (jack3), and increase it from whatever it is (currentFlex) to that number plus 20. To get a better idea of this, see Figure 1.
A XUL slider.
Figure 2 shows a screenshot of what you would see in Mozilla.
![]() |
Figure 2. The results in Mozilla (click for full-size view). |
Try this out for yourself and watch how the group of buttons move around on the screen. This is just a toy example, and even the uses for the <jack> tag are quite open. You might create sliding drawers that contain pressing news, or you could make some simple animations where elements drop down from the top of the screen.
The point here though is not so much this new tag we created, but the fact that I could create whole new functionality in the browser without a stitch of C++ code! XUL gives you a lot of power in creating user interfaces for your web applications but only contains a limited set of UI widgets for you to build on. XBL gives you a whole new toolset to build up your own widgets -- with their own specialized behavior -- that can allow you to create interfaces of whatever complexity you desire! I've seen others create new classes of widgets, like a small calendar that pops up, allowing you to select a date, or a calculator widget that you could call up by just pressing some hotkey.
Another fascinating direction you might take is to combine XBL bindings to user stylesheets. You could create bindings via CSS in your user stylesheet which could, for instance, override the "back" button such that web pages fade in and out (via setting the CSS opacity setting), or you could add a new behavior to links so that whenever you roll over them, you see a popup window of all their properties. The combinations are quite mind boggling!
If you would like to try this out for yourself, I've included a ZIP file containing the three files you need for this exercise here.
|
Useful Links: XBL - The Extensible Binding Language - from mozilla.org's XPToolkit Project. |
Where do you go from here? I would recommend getting a good solid background in XUL and beginning to read up on the XBL documentation in the links below. Note that XBL is still a very new technology. For instance, there's a good chance that the CSS behavior:url() expression may be changed to -moz-behavior: url(), so that it more fully delineates this technology as coming from Mozilla and allows other implementations access to that name, if there eventually comes a standard for developing anonymous content.
I've only scratched the surface here. XBL has many more aspects that can lead you to do even more interesting things. If you come up with something cool, please send me an email: andrew@andrewwooldridge.com.
Andrew Wooldridge is a XUL and JS developer at Netscape Communications Corp.
Also Featured This Week
Mozilla is Not Netscape (and Other True Facts)
Discuss this article in the O'Reilly Network Browsers Forum.
Return to the Mozilla DevCenter.
Copyright © 2007 O'Reilly Media, Inc.