XBL XBL XBL!
I thought I should provide some sort of introduction to XBL so that when you're sick of me saying it, at least you'll know what I'm talking about.
This is an intentionally simplified introduction, but it also reflects my perspective on how XBL can be used. There is no guarantee that this reflects the official priorities of XBL. For more information refer to the XML Binding Language (XBL) 2.0 specification and XBL 2.0 Primer.
Descriptions of XBL inevitably end up sounding like binding blah, blah bound document blah, blah bound element blah, blah binding document. There's some definitions near the end of this article.
Overview: CSS on Steroids
XBL - the XML Binding Language - provides a mechanism for associating enhanced presentation or behavior with selected elements in a web-page.
It's like CSS on steroids.
CSS allows styling information to be simply and unobtrusively associated with an element. XBL enhancements (or bindings) are associated with an element in a similar manner, but with XBL you can re-order the children of the bound-element, or insert new content with scoped styling, add new scripting methods and handle all events that propagate through the element.
Even when content is re-arranged or inserted by XBL, the DOM of the bound-document is unaffected. For example, a web-site could serve pages with no banner or site navigation in the body,
<body> <p>I am the unique content of this page.</p> </body>
then XBL could be used to insert the banner, navigation, footer, etc.
<body> <div id="banner"> <h1><img class="logo" src="/logo.png" style="vertical-align: middle;" /> meekostuff.net</h1> </div> <div id="navigation"> <ul> <li><a href="/">Home</a></li> <li><a href="/about.html">About</a></li> <li><a href="/projects/">Projects</a></li> <li><a href="/blog/">Blog</a></li> <li><a href="/contact.html">Contact</a></li> </ul> </div> <div id="main"> <p>I am the unique content of this page.</p> </div> <div id="footer"> <p>Perhaps a site-specific footer would be useful.</p> </div> </body>
Although the banner, etc is now displayed to the user, the page author doesn't have to worry that IDs and classes in the inserted markup clash with those already present because XBL keeps the inserted markup invisible to the bound-document.
Rationale: Semantics and Scalability
The complex enhancements that facilitated by XBL allow the page author to concentrate on writing succinct and semantically appropriate markup and then delegate presentation and behavior as required. This will generally result in improved maintainability, accessibility and SEO of web-pages.
Web-pages are becoming more dynamic, both in the widgets and effects that enhance the user experience, and in the insertion and removal of content. Web-applications, as the extreme example, are becoming common-place. As more features are introduced and content is inserted or removed (including the presentational content of widgets) several problems can arise:
- a script component responsible for one feature could step on the presentational content of another
- content insertion needs to be monitored for possible enhancement, and content removal for cleaning-up
- name-clashes (for IDs and classes) are more likely as the presentational content of widgets is in the same namespace as the page
- features that re-arrange content could cause style settings to be mis-applied
XBL mitigates all these problems resulting in a more scalable solution for enhancing web-pages.
Demo
XBL bindings can enhance or override the default presentation and behavior of a bound-element with one or more of the following:
- Templates
- Rearrange the child elements of the bound-element, allowing you to add content or change the structure of the tree rooted at the element.
- Styles
- Declare styles for content added in the template.
- Handlers
- Declare event listeners for events that propagate through the bound-element.
- Implementations
- Declare methods and properties that can be called from handlers. They are also conditionally available on the bound-element.
The following example provides simple illustrations of these main aspects of XBL bindings. It is an XBL document containing a single binding definition which implements a numeric-input field similar to that proposed in HTML5 (but with much less functionality).
<?xml version="1.0" encoding="UTF-8"?> <xbl xmlns="http://www.w3.org/ns/xbl"> <binding element="input[type=number]"> <template> <div id="bindingBox" xmlns="http://www.w3.org/1999/xhtml"> <div id="textBox"> <input type="text" id="text" /> </div> <div id="buttonBox"> <div id="stepUp"></div> <div id="stepDown"></div> </div> </div> </template> <implementation> ({ stepUp: function() { var input = this.shadowTree.getElementById("text"); input.value++; }, stepDown: function() { var input = this.shadowTree.getElementById("text"); input.value--; } }) </implementation> <handlers> <handler event="click"> var stepUp = this.shadowTree.getElementById("stepUp"); var stepDown = this.shadowTree.getElementById("stepDown"); if (event.target == stepUp) this.stepUp(); if (event.target == stepDown) this.stepDown(); </handler> </handlers> <resources> <style> #bindingBox { display: block; margin: 0; padding: 0; } #textBox, #buttonBox { float: left; margin: 0; padding: 0; } #text { height: 14px; margin: 0; } #stepUp, #stepDown { display: block; width: 15px; height: 8px; margin: 0; padding: 0; border: 1px solid ButtonShadow; border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; overflow: hidden; } #stepUp { background: ButtonFace url(arrow-up.gif) center -2px no-repeat; } #stepDown { background: ButtonFace url(arrow-dn.gif) center -2px no-repeat; } </style> </resources> </binding> </xbl>
And here is a demo of how that would work in a browser if this XBL document were associated
with a web-page whose only content was <input type="number" />
.
You should be able to use the up/down arrow buttons to increment/decrement the value of the input.
Let's step through the example code:
<?xml version="1.0" encoding="UTF-8"?> <xbl xmlns="http://www.w3.org/ns/xbl">
The XBL document is an XML document with a xbl
element in the XBL namespace as the root.
<binding element="input[type=number]">
Binding definitions (only one in this example) are contained by the binding
element.
The element
attribute contains a CSS Selector specifying which elements in the target document
will be bound to this binding - in this case on input
elements
where the type
property is "number".
<template> <div id="bindingBox" xmlns="http://www.w3.org/1999/xhtml"> <div id="textBox"> <input type="text" id="text" /> </div> <div id="buttonBox"> <div id="stepUp"></div> <div id="stepDown"></div> </div> </div> </template>
Templates can be used to add content to the bound-element and even change the layout.
For empty bound-elements - like input
s -
the template
element is like an iframe that overlays and hides the bound-element.
The person viewing the page sees the contents of the template,
but scripts on the page still interact only with the bound-element.
<implementation> ({ stepUp: function() { var input = this.shadowTree.getElementById("text"); input.value++; }, stepDown: function() { var input = this.shadowTree.getElementById("text"); input.value--; } }) </implementation>
Implementations add new methods (or properties) to bound-elements.
Inside these methods the binding is referenced with this
,
the bound-element with this.boundElement
and the content of the template element (which appears inside the bound-element) with this.shadowTree
.
The shadow-tree has a getElementById()
method,
which, in terms of our iframe-analogy would make the shadow-tree the document-node of the iframe.
<handlers> <handler event="click"> var stepUp = this.shadowTree.getElementById("stepUp"); var stepDown = this.shadowTree.getElementById("stepDown"); if (event.target == stepUp) this.stepUp(); if (event.target == stepDown) this.stepDown(); </handler> </handlers>
Handlers in the XBL-document map to event-listeners on the bound-element. They are called in the context of the binding-implementation.
<resources> <style> ... </style> </resources>
Style information for XBL-bindings must be nested within a resources
element.
The styles are applied to the elements in the shadow-tree and don't effect elements in the bound-document.
Use-cases
XBL is especially suitable for features that add presentational content to the page as part of their implementation, such as:
- specialized form elements - date-time, range, number
- page decor - adding banner, navigation, etc to unadorned pages
- popups - full-size image overlays, dialogs and help
- SVG styling - this would rely on inserting SVG elements around the HTML of the page
Some of these enhancements could still function with scripting disabled.
Alternatively, because XBL is automatically applied to targeted elements (even during document load) it can be used purely as a built-in event-delegation system. This simplifies the implementation of widgets with event driven functionality:
- tabboxes, accordions
- collapsible trees and cascading menus
- sortable tables
Definitions
XBL
When I refer to XBL, I'm usually talking about the W3C's XML Binding Language (XBL) 2.0 specification. This is also commonly known as XBL2.
I have a project that provides a subset of XBL, XBLUI - XBL User Interface enhancements. I won't make any distinction between XBL - the specification, and XBL - this implementation, except to point out where I extend the spec.
There are other technologies and standards (see History) that offer features similar to XBL, including Mozilla's earlier (and non-compatible) eXtensible Binding Language - also known as XBL1, and Microsoft's even earlier DHTML Behaviors. Sometimes I will group these into a vague XBL category. In those cases I won't point out the differences between them unless it is to be explicit about how something is done in XBL2.
Bindings
In XBL, enhancements to elements in a web-page are called element bindings, or just bindings. Other technologies use the term behaviors instead of bindings.
Bound Element
When a binding definition is associated with an element, a binding-object is created from the definition, and the element becomes the bound-element of the binding object.
XBL Document
A XBL document is an XML document that contains binding definitions.
Binding Document
When a XBL document is associated with a web-page then it becomes the binding-document for the page.
Bound Document
When a XBL document is associated with a web-page then the page becomes the bound-document for the XBL document.
History
IE5 was the first browser with the ability to declaratively associate behaviors to elements. It provided DHTML Behaviors which are defined in HTC files and associated with elements using CSS or scripting methods. DHTML Behaviors support many of the goals of XBL, although perhaps not in a robust, performant and cross-browser manner. For whatever reason, they have not seen much uptake.
Mozilla then implemented the Extensible Binding Language (also referred to as XBL1 or Mozilla XBL) which, along with XUL, Javascript and CSS, is used to implement the Firefox user interface. Like DHTML Behaviors, Mozilla XBL has not had much uptake outside of its parent organization.
The XBL2 specification attempts to build on the successes and resolve some of the failures of these earlier element binding solutions. Mozilla and Webkit projects have expressed the intention to provide native implementations in the near future, and other browser vendors have apparently expressed an interest.
Notes
Event Delegation
Event handling behavior can be associated with elements in two ways:
- Find elements that match a certain requirement (perhaps a CSS selector) and attach appropriate event listeners.
- Add event listeners to the root-node and for each event determine if the event propagates through a targeted element.
The second approach is referred to as event-delegation and has the following advantages:
- Less processing during configuration (though more during event handling)
- No processing of elements that the user doesn't interact with
- Can work during document-load
- Don't need to keep track of which elements have event handlers
The first approach is better if you have to dress up the element anyway.
There are many event-delegation systems implemented in Javascript libraries, including:
- JSB by Dean Edwards
- reglib by Greg Reimer
- Live events in jQuery
- XBLUI available here