XBL 2.0 is part of Mozilla's XBL Project. For a list of other Mozilla projects, see the project page.
Please send comments to the dev-tech-xbl@mozilla.org mailing list (subscribe, archives).
This document is stored in CVS. View document history. Edit.
Portions of this content are © 1998–2006 by individual mozilla.org contributors; content available under a Creative Commons license. (Details)
The XML Binding Language (XBL) describes the ability to associate
elements in one document with script, event handlers, CSS, and more
complex content models in another document. This can be used to re-order
and wrap content so that, for instance, simple HTML or XHTML markup can
have complex CSS styles applied without requiring that the markup be
polluted with multiple semantically neutral div
elements.
It can also be used to implement new DOM interfaces, and, in conjunction with other specifications, enables arbitrary tag sets to be implemented as widgets. For example, XBL could in theory be used to implement XForms.
This specification is a (non-backwards-compatible) revision of Mozilla's XBL 1.0 language, originally developed at Netscape in 2000, and originally implemented in the Gecko rendering engine. [XBL10]
This specification was developed by the Mozilla Foundation and its contributors, in conjunction with individuals from Opera Software ASA, Google, Inc, and Apple Computer, Inc, to address problems found in the original language and to allow for implementations in a broader range of Web browsers.
This document is also based, in part, on work done in the W3C's Bindings Task Force. However, no text from that collaboration, other than that written by the aforementioned contributors, remains in this specification. Inspiration was similarly taken from other efforts, such as HTML Components. [HTC]
Although they have had related histories, this specification is separate from the W3C's "sXBL" drafts, and is not compatible with them. (The two efforts use different namespaces, for one.)
This is the working copy of XBL 2.0. If you wish to make comments regarding this document, please send them to dev-tech-xbl@mozilla.org. All feedback is welcome.
xbl
Element
binding
Element
implementation
Element
template
Element
content
Element
inherited
Element
xbl:attr
Attribute
xbl:pseudo
Attribute
div
Element
handlers
Element
handler
Element
resources
Element
style
Element
prefetch
Element
script
Element
id
Attribute of XBL Elements
<binding element="">
content
Elements
xml:base
handler
Element
focus
, DOMFocusIn
, blur
, and
DOMFocusOut
Events
mouseover
and mouseout
Events
This specification defines the XML Binding Language and some supporting DOM interfaces and CSS features. XBL is a mechanism for overriding the standard presentation and interactive behavior of particular elements by attaching those elements to appropriate definitions, called bindings. Bindings can be attached to elements using either CSS, the DOM, or by declaring, in XBL, that elements matching a specific selector are implemented by a particular binding. The element that the binding is attached to, called the bound element, acquires the new behavior and presentation specified by the binding.
Bindings can contain event handlers that watch for events on the bound element, an implementation of new methods and properties that become accessible from the bound element, shadow content that is inserted underneath the bound element, and associated resources such as scoped style sheets and precached images, sounds, or videos.
XBL cannot be used to give a document new semantics. The meaning of a document is not changed by any bindings that are associated with it, only its presentation and interactive behavior.
To help readers understand how certain features can be used, this specification includes some examples.
In these examples, a long ellipsis ("...") is used to indicate elided content that would be present in a full example but has been removed for clarity.
Here we see a simple binding being used to reorder content in an HTML
page, so that the element with class="nav"
is positioned
before the element with class="main"
. CSS associated with
the binding is then used to position the two elements.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="nav-then-main"> <template> <div id="wrapper"> <div id="col2"><content includes=".nav"/></div> <div id="col1"><content includes=".main"/></div> </div> </template> <resources> <style> #wrapper { display: table-row; } #col1, #col2 { display: table-cell; } </style> </resources> </binding> </xbl>
The HTML page associated with such a binding might look like:
<!DOCTYPE HTML> <html> <head> <title>Demo</title> <link rel="stylesheet" href="example.css"> </head> <body> <div class="main"> <h1>Demo</h1> ... </div> <div class="nav"> <p><a href="http://example.com/">Home</a></p> ... </div> </body> </html>
The CSS stylesheet referred to from that document would include
various stylistic rules, and would in particular contain a link to the
XBL file, making it apply to the body
element so as to
reorder the two child elements:
/* Colors and Fonts */ h1 { font: 2em sans-serif; color: green; background: white; } ... /* Reorder content */ body { binding: url(example.xml#nav-then-main); }
The result of all the above is equivalent to the result one would get
if one simply placed the div
element with
class="nav"
before the div
element
with class="main"
. However, the effect is achieved without
needing any changes to the markup. This allows the same markup to be
given different presentations dynamically. It also allows changes to be
applied across entire sites by merely changing global stylesheet and
binding files, much as CSS can be used to change the layout and
presentation of a site even without XBL.
Here is another example, this time of an inaccessible implementation
of the proposed HTML5 details
disclosure element:
it opens and closes when clicked, and reflects its current state in the
element's "open
" attribute.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding element="details"> <template> <div> <div><content includes="legend:first-child">Details...</content></div> <div state="hidden" id="container"><content/></div> </div> </template> <handlers> <handler event="click" phase="default-action"> this.open = !this.open; </handler> <handler event="DOMAttrModified" attr-name="open" attr-change="addition" phase="target"> this.shadowTree.getElementById('container').setAttribute('state', 'visible'); </handler> <handler event="DOMAttrModified" attr-name="open" attr-change="removal" phase="target"> this.shadowTree.getElementById('container').setAttribute('state', 'hidden'); </handler> </handlers> <implementation> ({ get open() { return this.boundElement.hasAttribute('open'); }, set open(val) { if (val) this.boundElement.setAttribute('open', 'open'); else this.boundElement.removeAttribute('open'); return this.open; }, }) </implementation> <resources> <style> #container[state=hidden] { display: none; } </style> </resources> </binding> </xbl>
Since the examples are all untested (there are no XBL2 implementations at the time of writing), it is quite possible that they have errors. Please report any errors you think you see, so that we can correct the examples.
This specification is not backwards compatible with XBL1.
There are numerous changes. However, of particular importance to
readers familiar with XBL1, there have been some changes to the element
names. In particular, the XBL1 element content
is
now called template
, and the XBL1
element children
is now called content
.
This specification has a similar scope to XSLT. The main differences are:
XSLT operates on a static DOM, permanently replacing that DOM for rendering. XBL, on the other hand, transparently transforms the DOM for rendering while leaving the underlying structure intact, and dynamically reflects changes to the underlying DOM in the transformed rendering.
XSLT allows any arbitrary transformation to be performed. XBL shadow trees, on the other hand, only support reordering of the bound element's child nodes and interleaving of those explicit children with shadow content. Arbitrary transformations are not possible in XBL while retaining the transparent nature of XBL's shadow tree processing.
In addition, XBL can be used for component creation, which is not covered by XSLT.
An XBL user agent is an implementation that attempts to support this specification.
A binding is the definition of behavior that can be applied to an element so as to augment its presentation.
The namespace of all the XBL elements and
XBL global attributes must be: http://www.w3.org/ns/xbl
An XBL document is an XML document that has
the xbl
element at its root.
A non-XBL document is an XML document whose root element is from a namespace other than XBL (e.g. XHTML). A non-XBL document can include XBL, if the other languages involved allow it.
An XBL subtree is a
subtree in an XML document, the subtree having as its root
node an xbl
element in the XBL namespace, which is used
to define bindings. XBL subtrees can stand alone in XBL documents, or can be
included in non-XBL
documents.
The term binding document is used to mean either an XBL document or a non-XBL document containing one or more XBL subtrees.
In the following XHTML example, the XBL subtree is the portion of the markup that is emphasized. It is in a non-XBL document, since the root element is an XHTML element.
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Demo</title> <xbl xmlns="http://www.w3.org/ns/xbl"> <script><![CDATA[ function fmt(n) { if (n < 10) return "0" + n; else return n; } ]]></script> <binding element=".date"> <implementation> ({ xblBindingAttached: function() { var tm = /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d) UTC$/.exec(this.boundElement.textContent); var date = new Date(); date.setUTCFullYear(parseInt(tm[1], 10)); date.setUTCMonth(parseInt(tm[2], 10) - 1); date.setUTCDate(parseInt(tm[3], 10)); date.setUTCHours(parseInt(tm[4], 10)); date.setUTCMinutes(parseInt(tm[5], 10)); date.setUTCSeconds(0); this.boundElement.textContent = date.getFullYear() + "-" + fmt(date.getMonth() + 1) + "-" + fmt(date.getDate()) + " " + fmt(date.getHours()) + ":" + fmt(date.getMinutes()) + " LT"; this.boundElement.title = "Adjusted to local time zone" }, }) </implementation> </binding> </xbl> </head> <body> <h1>Demo</h1> <p class="date">2006-08-10 18:40 UTC</p> <p>...</p> </body> </html>
(As an aside, the binding defined in this example causes elements with
class="date"
to have their content parsed into a UTC date
and converted into a local time. The binding mutates the original DOM to
do this, and it doesn't reflect any dynamic changes made to the
element's content; there are better, albeit slightly more involved, ways
of achieving the same effect that don't have these problems.)
A bound element is an XML or HTML element to which a binding has been applied.
In the example above, the
first p
element is the bound
element.
A bound document is an XML or HTML document containing one or more bound elements.
In the example at the top of this section, the document is both the binding document (because it contains the definition of the binding), and the bound document (because it contains the affected bound element). In the example in the introduction section, the HTML file is the bound document, and the XBL file is the binding document.
In this specification, the term in error, typically used of an element or attribute, means that the element, attribute, or other construct is not conformant according to the rules of this specification. Rules for exactly how the construct must be treated when it is in error are always given when the term is used. Typically this will involve ignoring the erroneous nodes, meaning the UA must, for the purposes of XBL processing, act as if those nodes were absent. UAs must not, however, remove such nodes from the DOM in order to ignore them, nor should it change what DOM interfaces those nodes implement. The nodes retain all their non-XBL semantics.
UAs should report all errors to users, although they may do this in an unobtrusive way, for example in an error console.
In addition to the error handling rules given in this specification, UAs may abort all processing when encountering an error.
Aborting is only likely to be a viable error handling mechanism in controlled environments, e.g. in conformance checkers. Web browsers are expected to use the error recovery mechanisms described in this specification, not abort.
A correct element, attribute, value, or binding is one which is not in error.
The following sample XBL document is in error
because the script
element in XBL is
only allowed as a child of the xbl
element:
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="demo"> <script> // This example is in error. // You are not allowed to put ascript
element inside // abinding
element, only inside anxbl
element. // This is because scripts evaluate in the scope of the // entire XBL document, and are therefore not associated // with a particular binding. function life() { return 42; } </script> </binding> </xbl>
The correct way of doing this would be:
<xbl xmlns="http://www.w3.org/ns/xbl"> <script> // This example is correct. function life() { return 42; } </script> <binding id="demo"> <!-- Now you can see that this binding actually does nothing. --> </binding> </xbl>
The term "semantics" is used to refer to the intrinsic meaning or processing model of elements, attributes, events, and DOM interface members. Semantics are defined by specifications; for example, this specification defines the semantics of XBL elements.
XBL elements are frequently referred to by just their local name in this specification. In real documents, they must be associated with the XBL namespace as per the rules given in the Namespaces in XML specification [XMLNS].
For convenience, elements and attributes from specific namespaces are
sometimes referred to simply in the form prefix:localname
,
without explicitly stating which namespace the prefix is bound to. When
this occurs, readers should assume the following prefix declarations are
in scope:
xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/1999/xhtml"
When this specification refers to elements in a namespace, it does not exclude elements in no namespace; the null namespace is considered a namespace like any other for the purposes of XBL processing.
All element names, attribute names, and attribute values in XBL are case sensitive, with the exception of attribute values defined by other specifications (those have the sensitivity defined by those other specifications).
An XML MIME type is text/xml
,
application/xml
, or any MIME type ending with the string
+xml
(ignoring any MIME parameters).
The terms "author style sheets", "user style sheets", "user agent style sheets", and "pseudo-element" are used as defined by the CSS specifications. [CSS21]
The term "QName" is used as defined by the Namespaces in XML specification. [XMLNS]
The term "view" is used as defined by the DOM2 Views specification. [DOM2VIEWS]
As well as sections marked as non-normative, all diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]
There are two classes of products that can claim conformance to this implementation: XBL subtrees, and XBL user agents.
XBL subtrees must satisfy the constraints described in this specification in order to be considered conformant.
Products that generate XBL subtrees cannot claim conformance to this specification, though they can claim to only produce XBL subtrees that themselves are conformant to this specification.
XBL user agents must behave as described by this specification in order to be considered conformant, even when faced with non-conformant XBL subtrees.
User agents may optimize any algorithm given in this specification, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms. (The algorithms in this specification are generally written with more concern for clarity than over efficiency.)
This specification is defined in terms of the DOM. The language in this specification assumes that the user agent expands all entity references, and therefore does not include entity reference nodes in the DOM. If user agents do include entity reference nodes in the DOM, then user agents must handle them as if they were replaced by their DOM replacement values when implementing this specification.
For example, if a requirement talks about an element's child text nodes, then any text nodes that are children of an entity reference that is a child of that element would be used as well.
This specification describes the rules for processing of XBL elements and related features, whether they are used in a conformant manner or not. Conformant implementations, therefore, will interoperably handle any content, whether valid or not.
The element
attribute of the binding
element and the includes
attribute of the content
element, if
specified, must have their values parsed according to the rules in the
Selectors specification. [SELECTORS]
This specification does not specify what level of Selectors support is required.
Namespace prefixes can be used with selectors. In XBL attributes that
take selectors, the namespace prefixes that may be used are the prefixes
that are in scope using the xmlns:*
syntax. User agents must
use the XML namespace prefixes in scope on the attribute's element when
parsing selectors with namespace prefixes. The default namespace in
selectors in XBL attributes is always unbound. [XMLNS]
The "xml" prefix is defined to always be declared (and bound
to the http://www.w3.org/XML/1998/namespace
namespace), as
is the "xmlns" prefix (which is bound to
http://www.w3.org/2000/xmlns/
).
Selectors are case-insensitive, but namespace prefixes are case-sensitive. Thus, there could be multiple namespace prefixes declared that match a particular namespace prefix as used in a selector. User agents must act as if all namespace prefixes in scope were lexically sorted by Unicode codepoint, with the first namespace prefix of each group of namespace prefixes differing only by case (using case folding as defined by Unicode) being the one assumed to be in scope for the purposes of selector matching. [UNICODE]
The following excerpt from an XBL document defines a binding that is
bound to elements declaring links (e.g. the a
element in HTML).
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding element=":link, :visited"> ... </binding> </xbl>
The following excerpt defines a binding bound to any element in the
http://example.com/
namespace that is the child of an
element in the http://www.example.net/
namespace with the
name parent
. (Note that the >
character
does not have to be escaped.)
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:eg1="http://www.example.net/" xmlns:eg2="http://example.com/"> <binding element="eg1|parent > eg2|*"> ... </binding> </xbl>
Finally this third example defines a binding that matches elements
with the name blockquote
, regardless of what namespace they
are in. If it is known that the binding document is only ever going to
be used from documents that use one namespace, for example if the
bindings are always to be imported into HTML documents, then it is
easier to just specify the local name (as in this example) and ignore
the namespaces.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding element="blockquote"> ... </binding> </xbl>
Some attributes are defined as taking space-separated values. The list of values for such attributes must be obtained by taking the attribute's value, replacing any sequences of U+0009, U+000A, U+000D, and U+0020 characters (in any order) with a single U+0020 SPACE character, dropping any leading or trailing U+0020 SPACE character, and then chopping the resulting string at each occurrence of a U+0020 character, dropping that character in the process.
A space-separated attribute whose value is the empty string, or which consists of only U+0009, U+000A, U+000D, and U+0020 characters, has no values.
In the attribute button="1 2"
, the values are "1" and
"2".
In the attribute
class=" key - note - rocks"
,
there are five keywords: "key", "note", "rocks", and two occurrences of
the single-character keyword "-".
Some attributes are defined as containing MIME types. A valid MIME type
is one that matches the production for valid-MIME-type
in the following EBNF:
valid-MIME-type := type "/" subtype *(";" parameter)
...where the type
, subtype
,
and parameter
tokens are those defined in RFC 2045.
[RFC2045]
Some attributes, pseudo-attributes, and method arguments are defined as
specifying URIs. Such attributes must have values that match the URI
token of RFC 3986 or the IRI
token of RFC 3987. If they do not, they are in
error (though the processing of erroneous URIs varies depending on
the context). [RFC3986] [RFC3987]
Certain attributes are defined as requiring certain values, e.g. true
or false
. For such attributes,
the values must be specified exactly, in the case given in this
specification, and with no leading or trailing whitespace.
Implementations must only perform literal comparisons, and must not use
case-insensitive comparisons nor trim attribute values before comparison.
XBL2 does not have an extension mechanism; implementations that recognize elements in the XBL namespace that aren't part of this specification, or who recognise attributes that have no namespace, that are on elements in the XBL namespace, and that aren't part of this specification, are non-conforming. If UAs support features in other namespaces that affect the XBL processing model in a way that contradicts this specification, then they are not conforming either.
XBL2 user agents must recognize the string "XBL" as being a DOM feature
corresponding to support of XBL2 and its corresponding DOM APIs. Support
for this specification must be treated as support for versions "1.0" and
"2.0" of the "XBL" feature in terms of versions for the hasFeature()
DOM Core method.
XBL2 user agents that also implement SVG must recognize the following
string as being a language extension URI for the purposes of SVG requiredExtensions
evaluation:
http://www.w3.org/ns/xbl#v2
This section is non-normative.
XBL raises a number of security concerns.
Data theft: A naïve implementation of XBL would allow any document to bind to bindings defined in any other document, and (since referencing a binding allows full access to that binding document's DOM) thereby allow access to any remote file, including those on intranet sites or on authenticated extranet sites.
XBL itself does not do anything to prevent this. However, it is strongly suggested that an access control mechanism (such as that described in [ACCESSCONTROL]) be used to prevent such cross-domain accesses unless the remote site has allowed accesses.
Privilege escalation: In conjunction with data theft, there is the concern that a page could bind to a binding document on a remote site, and then use the privileges of that site to obtain further information. XBL prevents this by requiring that the bindings all run in the security context of the bound document, so that accessing a remote binding document does not provide the bound document with any extra privileges on the remote domain.
Cookie theft: Related to privilege escalation is the
risk that once an access-controlled binding document hosted on a remote
site has been loaded, authentication information stored in cookies for
that domain would become accessible to the bound document. XBL prevents
this by requiring that the cookie
attribute on the
DocumentWindow
interface be set to null.
Secure bindings: Using XBL for bindings that need access to the local filesystem, e.g. for implementing File Upload form controls, is not yet handled by this specification. However, a future version will provide a secure way to define an XBL binding that can be used to implement privileged mechanisms that can then be used by other bindings to provide such controls.
The start of any XBL subtree is an xbl
element, which is described below.
When an XBL element is found inside an element other than those listed under the "Expected contexts" list in the definitions below, it is in error. When an XBL element has a child node that does not satisfy the "Expected children" list in its definition (for instance because it is the wrong node type, wrong element type, or because too many elements of its type preceded it), the child is in error. In both cases, being in error means that the UA must, for the purposes of XBL evaluation, treat the XBL subtree as it would if the erroneous node and all its descendants were not present in the DOM.
However, non-XBL elements retain their semantics, even when considered to be in error for the purposes of XBL.
Regardless of the requirements of the last few paragraphs and of the "expected children" lines, comment nodes, and text and CDATA nodes containing only whitespace characters, may always be given as children of XBL elements.
For cases where attributes on XBL elements do not conform to this specification or (for namespaced attributes) to another specification, and for cases where attributes in the XBL namespace are found on elements other than those listed as their "Expected element" in the definitions below, the error handling is similar: the attributes must be considered to be in error and the UA must ignore them, meaning that the presence of these non-conforming attributes in no way affects the XBL processing.
Further error handling rules for more specific cases are given where appropriate.
XBL user agents that support CSS should act as if they had the following rules in their UA style sheet:
@namespace xbl url(http://www.w3.org/ns/xbl); xbl|* { display: none; } xbl|div { display: block; }
XBL user agents that do not support CSS should not render the XBL
elements other than the div
element,
which they should render as a paragraph-like element.
The following sections describe the content model of XBL elements, but not their actual processing model. The processing model for XBL is described in later sections.
xbl
Elementxbl
element as a child.
binding
: zero or more.
script
: zero or more.
The xbl
element is the root
element of all XBL subtrees.
id
attribute.
script-type
attribute specifies the MIME
type of the scripting language used by all bindings and XBL script
blocks in the XBL subtree. The value must be a valid MIME type. If the attribute is not
specified, the default language is ECMAScript.
[ECMA262]
style-type
attribute specifies the MIME
type of the styling language used by all bindings and XBL style blocks
in the XBL subtree. The value must be a valid
MIME type. If the attribute is not specified, the default language
is CSS (text/css
).
UAs must consider any xbl
elements
that have another xbl
element as an
ancestor as being in error and must then ignore them, meaning those elements must never be
considered to declare any bindings.
For example, conforming UAs will never bind elements to
bindings defined by binding
elements that have two xbl
ancestors.
Similarly, XBL elements (other than the xbl
element itself) that do not have a correct xbl
element
as an ancestor are in error too, and UAs must ignore them.
For example, conformant UAs will never bind elements to
bindings defined by binding
elements that have no xbl
ancestors at
all.
The same does not apply to the style-type
and script-type
attributes. If the UA does not support the specified styling language (or
has styling disabled), it must still apply bindings as appropriate; only
style
blocks must be ignored.
Similarly, if the UA does not support the specified scripting language
(or has scripting disabled), it must still apply bindings as appropriate;
only script
, handler
and implementation
sections must be
ignored.
The empty string is not a special value for these
attributes. Setting the style-type
attribute to the empty string,
e.g., will result in all style
blocks
being ignored, since the empty string is not a valid MIME type that the
UA supports.
The following document defines two bindings, one using Perl as the
scripting language and the other using JavaScript. The second one
extends the first one. (This example assumes that
text/x-perl
refers to Perl. Note that this specification
doesn't actually define how Perl-based bindings are to be supported by
the UA; the code below assumes that an implementation
element takes an
anonymous Perl package and blesses a hash to that package for each
binding, but this is nothing but conjecture.)
<root> <xbl xmlns="http://www.w3.org/ns/xbl" script-type="text/x-perl"> <binding id="validityImplementor"> <implementation> use strict; use vars qw(@ISA); @ISA = qw(XBLImplementation); sub validate { my $self = shift; my $data = $self->{boundElement}->getAttribute('value'); my $pattern = $self->{boundElement}->getAttribute('pattern'); return $data =~ m/^(?:$pattern)$/s; } </implementation> </binding> </xbl> <xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="validityClassifier" extends="#validityImplementor"> <handlers> <handler event="change"> if (this.baseBinding.validate()) this.boundElement.className = 'valid'; else this.boundElement.className = 'invalid'; </handler> </handlers> </binding> </xbl> </root>
(What these bindings do is somewhat boring. The first does nothing
except expose a "validate()" method that returns true if the contents of
the element's value
attribute matches the regular
expression in the element's pattern
attribute. The
second makes the binding call this method every time the change
event bubbles through the element, and changes
the element's class
attribute based on the return
value.)
binding
Elementxbl
implementation
: zero or
one.
template
: zero or one.
handlers
: zero or one.
resources
: zero or one.
The binding
element describes a
single XBL binding that adds presentation and interactive behavior to
XML or HTML elements. Each binding has these optional components:
Methods, Properties, and Fields: A binding can specify additional methods that can be invoked on the element. It can also specify additional properties and fields that can be retrieved or set on the element. In this way the functionality of the bound element becomes extensible. (See: binding implementations.)
Template: The optional template
defines the initial shadow content for the bound element.
Behavior: A binding can define event listeners for various types of events. Some examples are: UI events (e.g., key and mouse events) on the bound element or on elements within the shadow content, and mutation events on the bound element and its descendants. (See: event handlers.)
Resources: A binding can list style sheets that are scoped to the bound element, and images, sounds, videos, or other files that a user agent can pre-cache in order to improve performance. (See: binding style sheets, prefetching resources.)
Bindings can act as an attachment mechanism, specifying a namespace
and local name of elements to associate with the given binding when the
binding is imported, using the element
attribute.
In addition to the above, the binding
element's child nodes may include
any element outside the XBL namespace. These are handled as they would be
in any other context, and are ignored by the XBL processing model.
id
attribute.
extends
attribute is used to specify the URI of a binding that this binding inherits
from. (See: interpretation of URIs to XBL
bindings.) If the URI is in error or does
not refer to another binding, the UA must ignore
it, meaning that this binding does not explicitly inherit from another
binding. (See: explicit inheritance.) Only one
URI can be specified.
This attribute, if specified, must contain a selector. All elements in the binding
document, and in any documents that import
the binding document, that match the given selector, must be bound to the
binding defined by this binding
element. (The element's own shadow tree, if any, must not be taken into
account when determining if it matches a selector for the purposes of
this attribute.)
If an element
attribute contains an invalid
selector, it is in error and must be ignored, meaning that while the
binding is still parsed and may be referenced using other attachment
mechanisms, the binding is not attached to any element by its element
attribute, as if the attribute had simply been omitted.
The binding
element defines a
presentation and behavior binding. It does not define an element's
semantics. If an element has no semantics when processed alone, then it
has no semantics when processed with XBL.
Sending markup that does not have well-defined semantics over the network is bad practice. XBL is intended to be used to augment the user experience, for instance by providing better quality widgets or enhancing aesthetics. If the document being sent is unusable without XBL, then XBL is being abused.
This binding extends a binding defined in an external file. The
binding in the other file defines a value
property, and fires events when that property is changed. This
binding just implements a check box that all checkbox
elements in the http://ui.example.com/
namespace will be
bound to.
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:ui="http://ui.example.com/"> <binding element="ui|checkbox" id="checkbox" extends="http://www.example.org/resources/ui-core.xml#valuedControl"> <template> <div id="wrapper"> <div id="control"/> <div id="label"><content/></div> </div> </template> <resources> <style> #wrapper > div { display: inline-block; } </style> </resources> <handlers> <handler event="click" phase="default-action"> if (this.baseBinding.value == 'on') this.baseBinding.value = 'off'; else this.baseBinding.value = 'on'; </handler> <handler event="change" phase="target"> if (this.baseBinding.value == 'on') this.shadowTree.getElementById('control').textContent = '☑'; else this.shadowTree.getElementById('control').textContent = '☐'; </handler> </handlers> </binding> </xbl>
implementation
Elementbinding
src
attribute: depends on the scripting language.
src
attribute: none.
The implementation
element describes a set
of methods, properties, and fields that are attached to the bound
element. Once the binding is attached, these methods, properties, and
fields can be invoked directly from the bound element.
The implementation
element,
if present, must either contain code in the language specified by the XBL
subtree's script-type
attribute, or have a src
attribute
that points to a resource containing code in the language specified by
the script-type
attribute. The syntax and
semantics of this code depend on the specific language. This
specification defines the semantics for ECMAScript implementations. (See: binding implementations.)
id
attribute.
src
attribute specifies the URI to a resource of
the type given by the XBL subtree's script-type
attribute. If the attribute
is specified, the contents of the element must be ignored (even if the
resource could not be fetched or was of the wrong type). (See: binding implementations.)
If an implementation
element is marked (via the script-type
attribute of the xbl
element) as being in a language that the UA
does not support, then the UA must ignore it.
Similarly, if the implementation
element points (using
the src
attribute) to a resource that is either unavailable, or not of the type
specified by the script-type
attribute of the xbl
element (or implied by its absence), then it
is in error and the UA must ignore it. In both cases, "ignoring it" means it
must not be used as an implementation definition for any binding.
How UAs must handle nodes inside implementation
elements depends on the
language used. (See: loading and running scripts,
binding implementations.)
implementation
blocks are
evaluated once, on first use. Changes to an implementation
element or its contents
have no effect once the element has been evaluated. (See: binding implementations.)
The following example shows a binding that defines a new method, two new properties (one with a custom getter and setter, one without), an internal field (used to back the property), and some hooks to initialize the binding and to handle the bound element being inserted and removed from the document. The binding applies to any element with the class "demo" (in the files into which it is imported, that is).
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding element=".demo"> <implementation> ({ add: function (op1, op2) { return op1+op2; }, get memory() { return this._memory.toString(); }, set memory(value) { this._memory = parseInt(value, 10); }, xblBindingAttached: function() { this._memory = 0; // internal property to back "memory" external property this.external.state = 'initialized'; // external property }, xblEnteredDocument: function() { this.external.state = 'in document'; }, xblLeftDocument: function() { this.external.state = 'out of document'; }, }) </implementation> </binding> </xbl>
The get field() {}
and
set field(syntax) {}
features are part
of JavaScript 1.5 and will probably be in ECMAScript 4. The examples
in this specification assume an implementation that supports ECMAScript
4, but any language could be supported in real implementations.
The following example shows how to refer to an external file for the implementation of a binding. In this example, the handlers simply defer to methods defined in that implementation, so that all the code is in that file.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="demo"> <implementation src="demo.js"/> <handlers> <handler event="click"> this.clicked(event); </handler> <handler event="focus"> this.focused(event); </handler> <handler event="blur"> this.blurred(event); </handler> </handlers> </binding> </xbl>
The demo.js
file for this might look like this, to ensure
that the methods defined are in fact internal methods, not exposed on
the external object:
({ xblBindingAttached: function () { this.clicked = function (event) { ... }; this.focused = function (event) { ... }; this.blurred = function (event) { ... }; }, // ... other methods and fields ... })
template
Elementbinding
content
and inherited
elements may occur as
descendants, and non-XBL descendant elements may host xbl:attr
and xbl:pseudo
attributes.
The template
element
contains child nodes that can be in any namespace. When a binding is
attached, the template
element's
child nodes are cloned and attached to the bound document under the bound
element. Dynamic changes to the descendants of template
elements are reflected in bindings.
(See: shadow content.)
id
attribute.
apply-author-sheets
attribute
indicates whether or not rules in author style
sheets associated with the bound element's document apply to the
shadow content generated by the binding. Its value must be either
true
(indicating that they do) or false
(indicating that they do not). The default behavior, which is used when
the attribute is omitted or has a value other than the two allowed
values, is to not apply the bound document's author
style sheets (same as false
). (See: binding style sheets.)
allow-selectors-through
attribute indicates whether or not rules in CSS can cross scopes.
Its value must be either true
(indicating that they can) or
false
(indicating that they cannot). The default behavior,
which is used when the attribute is omitted or has a value other than
the two allowed values, is to not let selectors cross scopes (same as
false
). (See: selectors and shadow
scopes.)
The semantics of non-XBL elements inside this element are untouched, which can lead to unintuitive results. (See: semantics of non-XBL elements in XBL contexts.)
The following binding defines a shadow tree that wraps the contents of
the bound element in four blocks. It uses the apply-author-sheets
attribute to
allow the bound document to style the nodes directly, and uses the allow-selectors-through
attribute to allow the bound document to pretend (for the purposes of
selector matching) that the shadow tree actually is descended from the
bound element.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="wrapBy4"> <template apply-author-sheets="true" allow-selectors-through="true"> <div class="wrap1"> <div class="wrap2"> <div class="wrap3"> <div class="wrap4"> <content/> </div> </div> </div> </div> </template> </binding> </xbl>
Using this binding could take the following document:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Pretty Title</title> <style> h1 span { display: block; } h1 { border: solid red; } h1 .wrap1 { border: solid orange; } h1 .wrap2 { border: solid yellow; } h1 .wrap3 { border: solid green; } h1 .wrap4 { border: solid blue; } </style> </head> <body> <h1> <span class="wrap1"> <span class="wrap2"> <span class="wrap3"> <span class="wrap4"> Pretty Title </span> </span> </span> </span> </h1> ... </body> </html>
...and shrink it to this:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Pretty Title</title> <style> h1 { binding: url(cool.xml#wrapBy4); } h1 { border: solid red; } h1 .wrap1 { border: solid orange; } h1 .wrap2 { border: solid yellow; } h1 .wrap3 { border: solid green; } h1 .wrap4 { border: solid blue; } </style> </head> <body> <h1>Pretty Title</h1> ... </body> </html>
...which removes the semantic-free elements used as presentation hooks from the content markup layer, and places them in the presentation layer where they belong.
content
Elementtemplate
element somewhere in the ancestor
chain, and there must not be any content
elements anywhere in the ancestor
chain.
The content
element is used
inside shadow content to specify where explicit children that might already exist
underneath the bound element are inserted into the shadow tree. As far as the presentation model is
concerned, any shadow content the binding places between the bound
element and the content
elements is
interleaved between the bound element and its explicit children without affecting the document
model.
If the includes
attribute has children of the bound
element assigned to it, then those children are inserted into the final flattened tree in place of the content
element. Otherwise, the child
elements of the content
element are
inserted into the final flattened tree in place of
the content
element instead. (See:
processing content
elements.)
id
attribute.
includes
attribute can be used to indicate
that only certain content should be placed at the content
element. Its value must be a valid
selector. (See: processing content
elements.)
apply-binding-sheets
attribute
indicates whether or not scoped style sheets loaded for an XBL binding
are applied to a bound element's explicit
children (in addition to the bound element itself) that are inserted
below this content
element when it
is processed. Its value must be either true
(indicating
that they are) or false
(indicating that they are not). The
default behavior, which is used when the attribute is omitted or has a
value other than the two allowed values, is that they are not applied
(same as false
). (See: binding style
sheets.)
locked
attribute indicates whether or not new
children may be inserted below this content
element when it is processed. Its
value must be either true
(indicating that they may not) or
false
(indicating that they may). The default behavior,
which is used when the attribute is omitted or has a value other than
the two allowed values, is that they may be inserted (same as
false
). Elements already assigned to a content
element whose locked
attribute
is dynamically changed are not removed from that element. (See: processing content
elements.)
This sample extract from a binding document shows how to use the includes
attribute to distribute children to different parts of a shadow content
template.
<xbl:xbl xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:data="http://example.com/data-language"> <xbl:binding element="data|grid"> <xbl:template> <xbl:div class="caption" xbl:attr="xbl:text=title"/> <xbl:div class="outer-table"> <xbl:div class="columns"> <xbl:content includes="data|column"> <!-- default to have just one column if none are declared --> <data:column/> </xbl:content> </xbl:div> <xbl:div class="rows"> <xbl:content includes="data|heading"/> <xbl:div class="body"> <xbl:content includes="data|row:not([hidden])"/> </xbl:div> </xbl:div> </xbl:div> </xbl:template> ... </xbl:binding> ... </xbl:xbl>
The above template would be used with markup such as the following:
<data xmlns="http://example.com/data-language"> ... <grid title="The Lesser of Two Evils"> <column id="product" sort="alphabetic primary"/> <column id="catchphrase" sort="alphabetic secondary"/> <heading> <item>Product</item> <item>Catchphrase</item> </heading> <row> <item>Arachno Spores</item> <item>The fatal spore with the funny name</item> </row> <row> <item>Pastorama</item> <item>Located on the former site of Brooklyn</item> </row> </grid> ... </data>
The following illustrates how the above markup would get redistributed.
In this example, the binding uses the apply-binding-sheets
attribute
to let its stylesheet affect the explicit
children of the bound element.
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:ui="http://example.org/ui-language/"> <binding element="ui|listbox"> <template allow-selectors-through="true"> <div id="listbox-focus"> <content includes="ui|listitem" apply-binding-sheets="true"/> </div> </template> <resources> <style> @namespace xbl url(http://www.w3.org/ns/xbl); @namespace uil url(http://example.org/ui-language/); uil|listbox { display: block; background: white; color: black; } uil|listbox > xbl|div#listbox-focus { border: ridge silver; } uil|listbox:focus > xbl|div#listbox-focus { border: inset silver; } uil|listitem { display: block; background: white; color: black; } uil|listitem[selected] { display: block; background: navy; color: white;} </style> </resources> ... </binding></xbl>
In the following example, the locked
attribute is used to keep the children
of the bound element in the location that the user has selected. By
default, the listitem
elements would be placed in
the first content
element, but
because it is locked, they will instead go into the second one.
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:ui="http://example.org/ui-language/"> <binding element="ui|duallist"> <template> <div> <ui:listbox id="left" title="Selected Items"> <content includes="ui|listitem" locked="true" id="leftList"/> </ui:listbox> </div> <div id="buttons"> <ui:button id="move-right"> Move Right </ui:button> <ui:button id="move-left"> Move Left </ui:button> </div> <div> <ui:listbox id="right" title="Available Items"> <content includes="ui|listitem" id="rightList"/> </ui:listbox> </div> </template> <implementation> ({ xblBindingAttached: function() { this.shadowTree.getElementById('move-right').addEventListener( 'click', this.moveRight, false ); this.shadowTree.getElementById('move-left').addEventListener( 'click', this.moveLeft, false ); }, moveRight: function(event) { this.shadowTree.getElementById('rightList').setInsertionPoint( this.shadowTree.getElementById('left').selectedElement ); }, moveLeft: function(event) { this.shadowTree.getElementById('leftList').setInsertionPoint( this.shadowTree.getElementById('right').selectedElement ); }, }) </implementation> </binding> </xbl>
inherited
Elementtemplate
element somewhere in the ancestor
chain.
The inherited
element
represents where the next inherited shadow tree is to be inserted. If the
binding is the base binding (and thus has no inherited bindings) or if
none of the bindings it inherits from have shadow trees, or if this is
not the first inherited
element in
the binding's shadow tree, then the contents of the inherited
element (if any) will be used
instead. (See: the final
flattened tree.)
id
attribute.
While it is legal to nest inherited
elements, it is pointless, since
if one inherited
element used its
fallback content, any subsequent such elements will too.
The following binding wraps the bound element's children in a set of
div
s for extra styling. By using the
inherited
element, it has been
designed such that it must be used in conjunction with other bindings:
it will (if applied after the others) wrap the shadow trees of those
templates. Contrast this with the
example in the template
section, which would not
interact with other bindings. However, if this binding is not applied in
conjunction with a binding that has a content
element giving a place for the
element's explicit children, then those children will not be in the
final flattened tree.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="wrapBy4"> <template apply-author-sheets="true" allow-selectors-through="true"> <div class="wrap1"> <div class="wrap2"> <div class="wrap3"> <div class="wrap4"> <inherited/> </div> </div> </div> </div> </template> </binding> </xbl>
xbl:attr
Attributetemplate
element somewhere in the ancestor
chain.
The xbl:attr
attribute is a global attribute in
the XBL namespace that specifies which attributes on the bound element
should be forwarded to the element on which the attribute is found when
the shadow content template is cloned. It is a space-separated list of QNames or QName pairs separated by
equal signs, each possibly suffixed by a hash character ("#") and a type
designation. (See: attribute forwarding.)
The value of the xbl:attr
attribute must be a space-separated value of items that match the
pattern given in the attribute forwarding
section.
One of the major uses of the xbl:attr
attribute is to implement one
element in terms of another element which already has special behavior
in user agents. This example shows how a ui:text
element
can be implemented in terms of an html:input
element, with
certain attributes being forwarded to that element directly.
<xbl:xbl xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:ui="http://example.com/ui-language/" xmlns:html="http://www.w3.org/1999/xhtml"> <xbl:binding element="ui|text"> <xbl:template> <html:label> <html:span xbl:attr="xbl:text=label"/> <html:input xbl:attr="value=default disabled readonly" id="input"/> </html:label> </xbl:template> <xbl:implementation> ({ get value () { return this.shadowTree.getElementById('input').value; }, set value (val) { this.shadowTree.getElementById('input').value = val; }, }) </xbl:implementation> </xbl:binding> </xbl:xbl>
xbl:pseudo
Attributetemplate
element somewhere in the ancestor
chain.
The xbl:pseudo
attribute is a global attribute
in the XBL namespace that specifies the pseudo-element that, when used on the bound
element, must be mapped to the element on which the attribute is found.
The value of the xbl:pseudo
attribute must be a valid pseudo-element name, in lowercase, without the
leading "::". The valid pseudo-elements are defined by the CSS
specifications, and are "value", "choices", "label", "repeat-item", and
"icon". Future versions of CSS might introduce new values. (See: matching pseudo-elements.)
The xbl:pseudo
attribute is useful as a way to
let author styles
affect the insides of a shadow tree without exposing the exact
construction of the tree. Here, the binding represents a composite
widget with an icon, a label, a text field, and some buttons.
Pseudo-elements are used for each part allowing the author to style each
part separately.
<xbl:xbl xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:html="http://www.w3.org/1999/xhtml"> <xbl:binding id="input-dialog"> <xbl:template> <xbl:div class="root"> <xbl:div class="icon-block"> <html:img xbl:pseudo="icon" xbl:attr="src=icon alt=alt"/> </xbl:div> <xbl:div xbl:pseudo="label" xbl:attr="xbl:text=label"/> <xbl:div class="field-block"> <html:input xbl:pseudo="value" xbl:attr="value" id="field"/> </xbl:div> <xbl:div class="buttons-block"> <html:button xbl:pseudo="choices" id="ok"> OK </html:button> <html:button xbl:pseudo="choices" id="cancel"> Cancel </html:button> </xbl:div> </xbl:div> </xbl:template> ... </xbl:binding> </xbl:xbl>
An author-level stylesheet for a document using the binding might look like:
textDialog { binding: url(dialogs.xml#input-dialog); } textDialog::value { background: white; color: black; } textDialog::choices { border: outset; }
div
Elementtemplate
content
inherited
div
content
and inherited
elements may occur as
descendants, and non-XBL descendant elements may host xbl:attr
and xbl:pseudo
attributes.
The div
element has no
intrinsic meaning. It is intended to be used as a styling hook for
presentational bindings.
id
attribute.
div
elements based on their class
attribute). The class
attribute doesn't apply to other XBL
elements, only to div
.
title
attribute doesn't
apply to other XBL elements, only to div
.
The div
element in XBL is not
the same element type as the div
element
in HTML, but it is intended to be used in similar ways (and shares the
name for that reason).
Many of the examples in this specification use the div
element.
The following example uses the state
attribute so that the CSS style sheet can
render the shadow tree differently based on whether the switch that the
binding represents is turned on or off.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="switch"> <template> <div class="wrapper"> <div id="main" state="off"/> </div> </template> <handlers> <handler event="click"> this.shadowTree.getElementById('main').setAttribute('state', this.shadowTree.getElementById('main').getAttribute('state') == 'on' ? 'off' : 'on'); </handler> </handlers> <resources> <style> #main[state=off] { ... } #main[state=on] { ... } </style> </resources> </binding> </xbl>
handlers
ElementThe handlers
element's event
handlers can be called for events that flow through the bound element.
During capture, target, bubbling, and default phases, when a given event is received
by a bound element, if a corresponding event listener has been attached
to the handlers
element, then the
event will be forwarded
to that event listener. (See: event forwarding,
binding attachment and detachment.)
Typically, event handlers are defined using handler
elements.
id
attribute.
The following example shows how handlers
can be used with any event
listener mechanism.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="test"> <handlers id="test-handlers"/> ... </binding> <script> document.getElementById('test-handlers').addEventListener('click', function (event) { // this will get called for every click event that bubbles through // any element that is bound to the "test" binding above. ... }, false); </script> </xbl>
handler
Elementhandlers
The handler
element
describes a single event handler. This handler is attached to its parent
handlers
element, which is used as
an event forwarding target when handling events on the bound element.
(See: event handlers.) It wraps a script that is
executed when the event handler is matched.
id
attribute.
event
attribute describes the specific event that this handler is listening
for. (See: registering event handlers with the
handler
element.)
capture
, target
, bubble
, or
default-action
. If capture
is specified, then
the event handler must only be fired during the capturing phase of event
propagation. If target
is specified, then the event handler
must only be fired during the target phase. If
default-action
is specified, then the event handler must
only be fired during the default phase (if
it occurs). Otherwise, the handler must only be fired during the
bubbling phase. (See: registering event handlers
with the handler
element.)
true
or the value
false
. If true
is specified, then the event
handler must only be fired if the event's trusted
attribute is true. Otherwise, the
value of the trusted
flag does not affect the event
handler. (See: registering event handlers with
the handler
element.)
propagate
attribute specifies whether after
processing all listeners at the current node, the event is allowed to
continue on its path (either in the capture or the bubble phase). When
specified, it must have the value stop
or the
value continue
. If the value is stop
, then propagation will be stopped, otherwise it
won't. It has no effect if the phase
attribute has the value
default-action
. (See: registering
event handlers with the handler
element.)
default-action
attribute specifies
whether after processing of all listeners for the event, the default
action for the event (if any) should be performed or not. (See: registering event handlers with the
handler
element.)button
attribute imposes a filter on
the handler. It is used with mouse handlers to specify a particular
button. (See: mouse event handler filters.)
click-count
attribute imposes a
filter on the handler. It is used with mouse handlers to
specify how many clicks must have occurred. (See: mouse event handler filters.)
modifiers
attribute imposes a filter on
key and mouse handlers. It is used with mouse and key handlers to
specify particular modifier keys. (See: mouse event
handler filters, key event handler
filters, modifiers.)
key
attribute imposes a filter on key handlers. It is used with key handlers
to specify which keys to listen for. (See: key
event handler filters.)
key-location
attribute imposes a filter
on key handlers. It is used with key handlers to specify which keys to
listen for. (See: key event handler filters.)
text
attribute imposes a filter on text input handlers. It is used with text
input handlers to specify which characters to listen for. (See: text input event handler filters.)
prev-value
attribute imposes a filter on
mutation handlers. It is used with mutation handlers to specify what
prev-value
to listen for. (See: mutation event handler filters.)
new-value
attribute imposes a filter on
mutation handlers. It is used with mutation handlers to specify what
new-value
to listen for. (See: mutation event handler filters)
attr-name
attribute imposes a filter on
mutation handlers. It is used with attribute mutation handlers to
specify which attribute to listen to for changes. (See: mutation event handler filters)
attr-change
attribute imposes a filter on
mutation handlers. It is used with attribute mutation handlers to
specify the type of change to listen for. (See: mutation event handler filters.)
If a handler
element is marked
(via the script-type
attribute of the xbl
element) as being in a language that the UA
does not support then the UA must ignore it,
meaning it must not be used for the event handler definitions of any
binding.
How UAs must handle nodes inside handler
elements depends on the language
used. (See: loading and running scripts, event handlers.)
handler
blocks are evaluated each
time they are fired. Changes to the handler
elements therefore take effect the
next time the event is fired.
The following binding implements a link which, when clicked once with the primary button and with no key modifiers, or, when focused and sent a keypress of the Enter key with no modifiers, will cause the link to be followed.
It will only do this if the click or the keypress is a real event triggered by the user; it won't do it for events faked by script. However, if the event faked by script is a DOMActivate event, then it will follow the link, because the handler for the DOMActivate event doesn't check that the event is trusted. (If it did, it would never fire, because the event is dispatched by the binding, and therefore is not trusted.)
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="events"> <handlers> <handler event="click" phase="default-action" button="1" click-count="1" modifiers="none" trusted="true"> this.activate(); </handler> <handler event="keypress" phase="default-action" key="Enter" modifiers="none" trusted="true"> this.activate(); </handler> <handler event="DOMActivate" phase="default-action"> if (event.target == this.boundElement) this.boundElement.ownerDocument.location.href = this.href; </handler> </handlers> ... <!-- it is assumed that the implementation for this binding implements a .activate() method that fires the DOMActivate event on itself. --> </binding> </xbl>
resources
Elementbinding
style
: zero or more.
prefetch
: zero or more.
The resources
element
contains a list of style sheets to apply when using this binding, as well
as a list of files (images, videos, sound files, etc) to optionally
preload.
id
attribute.
style
Elementresources
src
attribute: depends on the styling language.
src
attribute: none.
The style
element is used to
specify a style sheet that is to be applied to the bound element and to
the shadow content generated by the binding, as well as to any explicit children (and their descendants) assigned
to content
elements in the shadow
content whose apply-binding-sheets
attribute
is set.
The style
element in XBL never
applies styles to elements in the bound document other than the bound
element (and possibly its children). It
never affects any ancestors of the bound element, or any nodes in any
other bindings or binding templates.
id
attribute.
media
attribute specifies the intended destination medium for style
information. If specified, the value of the attribute must be a valid
Media Query (media_query
token). How the value of
this attribute is interpreted is defined by Media Queries. If this
attribute is not specified, then there is no restriction on which media
the style sheet should be applied to (same as specifying
media="all"
). [MQ]
src
attribute specifies the URI to a resource of
the type given by the XBL subtree's style-type
attribute. If the attribute is
specified, the contents of the element must be ignored (even if the
resource could not be fetched or was of the wrong type). (See: binding style sheets.)
If a style
element is marked (via
the style-type
attribute of the xbl
element) as being in a language that the UA
does not support, the UA must ignore it.
Similarly, if the style
element points
(using the src
attribute) to a resource that is either unavailable, or not of the type
specified by the style-type
attribute of the xbl
element (or implied by its absence), then it
is in error and the UA must ignore it. In both cases, "ignoring it" means it
must not be used to style anything.
How UAs must handle nodes inside style
elements depends on the language used.
(See: binding style sheets.)
For a summary of the various ways that content can be styled in the presence of XBL, see the styling summary section.
prefetch
Elementresources
The prefetch
element
can be used to list resources that may be pre-loaded for performance
reasons.
Support for this element is optional. UAs may ignore it.
id
attribute.
The following binding uses two images; it sets the source of an HTML
img
element programmatically to refer to those images. To
increase the chance that the "green.png" image is available straight
away when it is used, it uses a prefetch
element and specifies that that
image will be needed.
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:html="http://www.w3.org/1999/xhtml"> <binding id="light"> <template> <html:img id="l" src="red.png" alt=""/> </template> <resources> <prefetch src="red.png"/> <!-- this one isn't necessary, since the UA will fetch this one as soon as it sees the <html:img> element --> <prefetch src="green.png"/> </resources> <implementation> ({ red: function() { this.shadowTree.getElementById('l').src = 'red.png'; }, green: function() { this.shadowTree.getElementById('l').src = 'green.png'; }, }) </implementation> </binding> </xbl>
This binding might be used as follows:
<!DOCTYPE HTML> <html> <head> <title>Light Demo</title> <style> #light { binding: url(demo.xml#light); } </style> </head> <body> <p id="light">Red</p> <p> <input type="button" onclick="doRed()" value="red"> <input type="button" onclick="doGreen()" value="green"> </p> <script> var light = document.getElementById('light'); function doRed() { light.textContent = "Red"; if (light.red) // binding might not be applied, so only call the method if it is defined light.red(); } function doGreen() { light.textContent = "Green"; if (light.green) // same light.green(); } </script> </body> </html>
Ok, so this example is a little far fetched. So are most of the examples in this spec. They're just examples!
script
Elementxbl
src
attribute: depends on the scripting
language.
src
attribute: none.
The script
element
contains code that is executed when the XBL subtree is loaded. It can
therefore be used to define helper functions used by the bindings.
The script
element, when present,
must either contain code in the language specified by the XBL subtree's
script-type
attribute, or have a src
attribute that
points to a resource containing code in the language specified by the
script-type
attribute. The syntax and
semantics of this code depend on the specific language. (See: loading and running scripts.)
id
attribute.
src
attribute specifies the URI to a resource of
the type given by the XBL subtree's script-type
attribute. If the attribute
is specified, the contents of the element must be ignored (even if the
resource could not be fetched or was of the wrong type). (See: loading and running scripts.)
If an script
element is marked (via
the script-type
attribute of the xbl
element) as being in a language that the UA
does not support, the UA must ignore it.
Similarly, if the script
element
points (using the src
attribute) to a resource that is either
unavailable, or not of the type specified by the script-type
attribute of the xbl
element (or implied
by its absence), then it is in error and the UA
must ignore it. In both cases, "ignoring it"
means that the script must not be executed.
How UAs must handle nodes inside script
elements depends on the language used.
(See: loading and running scripts.)
script
blocks must be evaluated
when their end-tag is parsed, or, for dynamically created elements, when
they are first inserted into a document. This is the case whether or not
the elements are in
error.
Once evaluation has started, a script
block is dead and changes to its contents or attributes have no effect.
id
Attribute of XBL ElementsThe id
attribute assigns an identifier to an element.
The given identifier must be unique in the binding
document. The id
attribute is of type ID. [XML].
If the attribute's value is the empty string, the attribute must not set an ID. Otherwise, the attribute's value must be treated as (one of) the element's ID(s).
Bindings can be attached and detached dynamically, using several mechanisms.
Bindings must be attached as soon as the following conditions have all been met:
Element
object for the element has been created,
and
In particular, binding can happen before the element is inserted into its document.
If the binding document was already loaded when the element was
created, or when it became known that the element matched the binding
(e.g. because the binding's element
attribute is mutated in a script),
then the binding must be applied such that to any running scripts,
notwithstanding those implementing xblBindingAttached()
notification
methods, it appears that the binding was applied immediately. When
mutation events are to fire, they must fire after the binding
being applied.
If the binding document has yet to be (fully) loaded when it becomes known that the binding applies, then the user agent must wait until all running scripts have completed before attaching the binding.
If the binding attachment mechanism is the 'binding'
property, then it does not become known to the user agent that the
binding applies (or does not apply) until the next time style resolution
is performed. This specification does not define when style resolution
happens.
Assume that foo.xml
defines a binding that
applies to all "foo
" elements. The following
script uses loadBindingDocument()
to ensure
that foo.xml
is loaded, then creates a foo
element and uses it.
// load the binding document document.loadBindingDocument('foo.xml'); // this is synchronous // create an element <foo> var foo = document.createElement('foo'); // binds synchronously too foo.myCustomMethod(); // calls the binding's implementation
Without the call to loadBindingDocument()
, if the
binding document wasn't loaded yet the element wouldn't be bound
straight away, and the last line would fail.
Bindings must be detached as soon as it is known that the binding no
longer applies to the element. In the case of attachment using the 'binding
'
property, this won't be until the next time style resolution is
performed.
When it becomes known that a binding is to be detached, it must happen such that to any running scripts it appears that the binding was removed immediately, except if the script in question is running as part of the last step of the binding attachment process, in which case the detachment happens after all the bindings being attached have had their methods called. (See: binding attachment model.)
XBL implementations must have a bindings-are-ready counter (for each
Document
) that keeps track of when there are outstanding
bindings to bind. This counter is set at the times given in the following
sections. (It is not set for all kinds of attachments.)
If the bound document is being parsed by the user agent, then, as soon
as all the following conditions have been met, the user agent must fire
an xbl-bindings-are-ready
event
on the document's root element. The conditions are:
The event must use the Event
interface, must bubble, must
not be cancelable, and must not have a default action. [DOM3EVENTS]
Initially, the bindings-are-ready counter must be set to zero.
The bound document's load
event must not fire until after
the xbl-bindings-are-ready
event
has fired. The xbl-bindings-are-ready
event
must fire even in the complete absence of any use of XBL in the document.
The xbl-bindings-are-ready
event
must only fire once per document load.
<binding element="">
The simplest binding mechanism is the binding
element's element
attribute. It declares which bindings should be attached to which
elements. (See: attributes
containing selectors, the binding
element.)
While an element matches the element
attribute of one or more of the
binding
elements that is imported into, or defined in, the
element's document, the bindings defined by each such binding
element must be bound to the
element. This applies to all elements that are associated with a
document, even when they have not yet been inserted into the document, or
are not in the final flattened tree.
There are two ways to import binding documents (and thus have their
<binding
element="">
bindings apply): the <?xbl?>
processing instruction,
and the loadBindingDocument()
method. The
latter is defined in the section on the DocumentXBL
interface.
The <?xbl?>
processing instruction specifies a binding document to load. Any
bindings defined
in that document must be applied to matching elements in the document
with the processing instruction.
<?xbl?>
processing instructions that occur after the
root element's start tag in the markup are in
error. <?xbl?>
PIs that are dynamically inserted
through the DOM after the root element's start tag has been parsed or the
root element has been attached to the document are in
error too.
A <?xbl?>
processing instruction that is not in error according to the above must be parsed using
the same syntax as the XML Stylesheet PI. [XMLSSPI] If there are any parse errors, then the
entire processing instruction is in error.
Otherwise, if it has an href
pseudo-attribute then it
specifies the URI of the binding document to
import. If the URI cannot be resolved, or returns an error, or does not
point to a resource with an XML MIME type,
or has any other problem that makes it unusable, then the processing
instruction is in error.
If a processing instruction is in error (as described in the previous few paragraphs) then it must be ignored.
Otherwise, the referenced document must be loaded (unless it has already been
loaded), and any bindings defined by that document must be applied to
matching elements in the document that contained the PI. Once loaded, the
binding document is added to the bindingDocuments
list of the document
with the PI.
Dynamic changes to <?xbl?>
processing instructions
must be ignored from an XBL standpoint.
An imported binding document is live.
For example, if new binding
elements are added to an imported
binding document (via the DOM), then the new bindings are immediately
applied to the document that had the PI importing that binding document.
XBL bindings are always implicitly imported into the document in which they are defined.
Whenever an <?xbl?>
PI causes a binding document to be
loaded, the document's bindings-are-ready counter must be
increased by one. Once the binding document is loaded, the counter must
be decreased by one.
An XBL subtree that defines some bindings is automatically imported in that document, so such mappings are always used. The following example demonstrates this.
example.xml <...> <xbl xmlns="http://www.w3.org/ns/xbl" ...> <binding element="foo"> ... </binding> <binding element="bar"> ... </binding> </xbl ...> <foo xmlns=""/> <!-- this will have a binding applied --> <bar xmlns=""/> <!-- this will have a binding applied --> </...>
If the binding definitions are in a separate file, then that file needs to be imported explicitly:
widgets.xml <...> <xbl xmlns="http://www.w3.org/ns/xbl" ...> <binding element="foo"> ... </binding> <binding element="bar"> ... </binding> </xbl ...> </...>
example.xml <?xbl href="widgets.xml"?> <...> <foo/> <!-- bound --> <bar/> <!-- bound --> </...>
If a file imports some bindings and the file containing those bindings
has its own <?xbl?>
processing instructions, that
second PI only affects nodes in the binding document, not the original
document. For example:
foo.xml <...> <xbl xmlns="http://www.w3.org/ns/xbl" ...> <binding element="foo"> <content> <bar xmlns=""/> <!-- not bound, not even when in shadow content --> </content> </binding> </xbl> </...>
bar.xml <?xbl href="foo.xml"?> <...> <xbl xmlns="http://www.w3.org/ns/xbl" ...> <binding element="bar"> <content> <foo xmlns=""/> <!-- bound: this document imports foo.xml --> <bar xmlns=""/> <!-- bound: bar binding is defined locally --> </content> </binding> </xbl> </...>
example.xml <?xbl href="bar.xml"?> <...> <foo/> <!-- not bound: foo.xml not imported here --> <bar/> <!-- bound --> </...>
Bindings can be attached to elements through CSS using the 'binding
'
property.
In the following example, a binding is referenced that will be attached to all XHTML checkbox elements.
input[type="checkbox"] { binding: url("http://www.example.org/xbl/htmlBindings.xml#checkbox"); }
Bindings attached through CSS must only remain on the bound element as long as the element continues to match the style rule. If at any time a resolution of style on the element determines that a different binding should be attached, the old binding (and all bindings that it explicitly extends in its explicit inheritance chain) must be detached.
Whenever an element is removed from a document, any bindings attached to that element via CSS must be detached.
Attaching a binding using CSS does not import the binding document. The element
attributes of binding
elements in
the binding document do not take effect unless the binding document is
imported. (See: importing binding
documents.)
Attaching using CSS does not affect the bindings-are-ready counter.
binding
'
PropertyA property to attach a binding to a particular element.
Value: | none | [ <uri> ]* <uri> |
Initial: | none |
Applies To: | all elements (but not pseudo-elements) |
Inherited: | no |
Percentages: | n/a |
Media: | all |
Computed Value: | specified value, with URIs resolved to absolute URIs |
User agents may perform the CSS cascade, inheritance, and computation
stages either across the entire tree, or per element, or per property per
element, and either before applying bindings, or simultaneously, while
applying bindings. In any case, for each element the computed value of
'binding
'
must be found and then used to apply the bindings to the element (when
the element is first styled, and each subsequent time the styles that
match the element change).
Since each time a binding is applied it can change the computed values
of properties of elements that are descendants of the bound element, this
may require several passes. This may be avoided by computing the value of
the 'binding
' property for the element, and then
applying any bindings, before any of its descendants.
The following XBL document defines two bindings for use in SVG. The first renders an isosceles triangle in place of bound elements that use it, the other renders a right-angled triangle in place of bound elements that use it.
<xbl xmlns="http://www.w3.org/ns/xbl" xmlns:xbl="http://www.w3.org/ns/xbl"> <binding id="isosceles"> <template> <polygon xbl:attr="transform" points="0 -1, 1 0, -1 0" xmlns="http://www.w3.org/2000/svg"/> </template> </binding> <binding id="rightangle"> <template> <polygon xbl:attr="transform" points="0 0, 1 0, 0 -1" xmlns="http://www.w3.org/2000/svg"/> </template> </binding> </xbl>
Assuming the above file was called triangles.xml
, these
bindings could be bound to elements using CSS like so:
@namespace triangles url(http://triangles.example.com/); triangles|isosceles { binding: url(triangles.xml#isosceles); } triangles|rightangle { binding: url(triangles.xml#rightangle); }
If the stylesheet was called triangles.css
, an SVG file
using these elements might look like:
<?xml-stylesheet href="triangles.css"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:t="http://triangles.example.com/"> <circle cx="10" cy="10" r="5"/> <rect x="20" y="20" height="5" width="10"/> <t:isosceles transform="translate(10 20) scale(10)"/> <t:rightangle transform="translate(20 20) scale(10)"/> </svg>
The same example could also be done all in one file like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:t="http://triangles.example.com/"> <defs> <xbl xmlns="http://www.w3.org/ns/xbl" xmlns:xbl="http://www.w3.org/ns/xbl"> <binding id="isosceles"> <template> <polygon xbl:attr="transform" points="0 -1, 1 0, -1 0" xmlns="http://www.w3.org/2000/svg"/> </template> </binding> <binding id="rightangle"> <template> <polygon xbl:attr="transform" points="0 0, 1 0, 0 -1" xmlns="http://www.w3.org/2000/svg"/> </template> </binding> </xbl> <style type="text/css"> @namespace triangles url(http://triangles.example.com/); triangles|isosceles { binding: url(#isosceles); } triangles|rightangle { binding: url(#rightangle); } </style> </defs> <circle cx="10" cy="10" r="5"/> <rect x="20" y="20" height="5" width="10"/> <t:isosceles transform="translate(10 20) scale(10)"/> <t:rightangle transform="translate(20 20) scale(10)"/> </svg>
Bindings can be attached to elements through the DOM using the ElementXBL
interface. The method
addBinding
takes a binding URI and
attaches the binding to the element (in all views).
var checkbox = document.getElementById("mycheckbox"); checkbox.addBinding("http://www.example.org/xbl/htmlBindings.xml#checkbox");
This attachment is not necessarily synchronous. Scripts that invoke
this method should not assume that the binding is installed immediately
after this method returns. (An xbl-bound
event is fired when the binding is
installed.)
When a binding is attached using the DOM, it inherits from the current most derived binding that is already attached to the element, if any. (See: binding inheritance.)
Any bindings attached to an element using the addBinding()
method will remain on the
element until the element is destroyed or a corresponding removeBinding()
call is made.
Attaching a binding using the addBinding()
DOM APIs does not import the binding document. The element
attributes of binding
elements in
the binding document do not take effect unless the binding document is
imported. (See: importing binding
documents.)
Attaching using the addBinding()
API does not affect the bindings-are-ready counter.
When a new binding is attached, the UA must perform the following steps in order (or act as if it did). Implementations may choose to suspend redraw during this process.
extends
attribute, then the user agent must
immediately consider the binding that the attributes references (if any)
to apply to the bound element as well, and must attach that binding
first, recursively applying these steps to that binding. If this causes
a loop — that is, if a binding directly or indirectly derives from
itself through a chain of one or more extends
attributes — then the user agent must only apply each binding in
the chain once. (See: explicit inheritance, interpretation of URIs to XBL bindings.)
handlers
element, when there is one. (See:
event forwarding.)
content
elements.)
The attachment process for the binding must then wait for the above
steps to have been completed for all bindings that are known to apply to
elements. When all the new bindings have reached this point, then, for
each newly attached binding, the xblBindingAttached()
method must be
invoked on the binding's implementation,
immediately followed, if that bound element is in a
document, by the invocation of the xblEnteredDocument()
method.
The order that bindings on different bound elements have these methods
called must be the relative tree order of all their bound elements, as
returned by the compareDocumentPosition()
function. In
certain cases (e.g. bound elements in disconnected fragments), this order
is implementation-specific; however, it must always be consistent with
the return values of that function. [DOM3CORE]
The order that bindings on the same bound element have these methods called must be the derivation order, with less derived bindings being initialized before more derived bindings.
After all the appropriate methods have been called, an xbl-bound
event that
bubbles, is not cancelable, has no default action, and uses the
Event
interface, must be fired on every bound element that
just got bound, in the same order as their xblBindingAttached()
methods were
invoked. (See: binding inheritance.) [DOM3EVENTS]
If a binding stops applying to a document while the above steps are being applied, the binding is not removed until after the steps above have all been completed. Once they have been completed, any bindings that no longer apply must be detached. (See: binding detachment model.)
A bound element is in a document if it has a
Document
node as an ancestor, or it is in a shadow tree and
that shadow tree's bound element is itself in a document.
When a bound element that is not in a document is affected in such a way that it
subsequently is in a document, then the
xblEnteredDocument()
method must be invoked on the binding's implementation.
Similarly in reverse: when a bound element that is in a document is affected in such a way
that it subsequently is not in a document, then the xblLeftDocument()
method must be
invoked on the binding's implementation.
These methods must be invoked as soon as the DOM is in a stable state, after any mutation events have fired, and after all running scripts have finished executing. If a bound element is removed and then reinserted into a document (or vice versa) during script execution, or while mutation events are being fired, the user agent must coalesce all the notifications into zero or one method calls (i.e. matching pairs of insertions and removals must not cause bindings to be notified).
Bindings can inherit from each other explicitly using the extends
attribute. They can also inherit from each other implicitly if
multiple bindings are attached to an element.
An explicit inheritance chain is a chain of
bindings connected using the extends
attribute.
An implicit inheritance chain is a chain of explicit inheritance chains. There can be at most one implicit inheritance chain per bound element.
A base binding is a binding that does not inherit from any other binding, either explicitly or implicitly. The base binding of a bound element is at one end of the bound element's implicit inheritance chain.
A base binding of the explicit chain is any binding that does not inherit explicitly from another, but may inherit implicitly from other bindings.
A most derived binding is a binding that no other binding inherits from. The most derived binding of a bound element is the binding at the other end of the bound element's implicit inheritance chain from the base binding.
If Bi is the ith binding in a group of N chains, where B1 is the base binding and BN is the most derived binding, then Bi-1 is the next most derived binding of Bi.
In this specification, inheritance is represented as an arrow pointing to the binding that is being inherited. Thus, in the chain A→B, the A binding is the most derived binding, and the B binding is the next most derived binding, in this case also the base binding.
In the example above, the base binding is the first "c", the four base bindings of the explicit chains are "c", "c", "d", and "g", and the most derived binding is "e".
The results of inheritance are described in the sections on binding implementations and shadow content.
The binding
element's extends
attribute gives an explicit inheritance chain for a binding, ensuring
that whenever the binding is bound to an element, the named binding also
gets bound. (See: binding attachment model, binding detachment model.)
The extends
attribute thus creates an explicit inheritance chain.
If a binding
element's extends
attribute is changed, then, for each time the binding is bound to an
element, the user agent must follow these steps:
Let binding be the instance of the binding that is attached to the bound element.
If binding is not directly attached to
the bound element, but is instead attached to the bound element because
another binding is inheriting from it using the extends
attribute, then let binding be that
binding instead, and repeat this step.
Otherwise, binding was attached to the bound
element directly, and is not being inherited by another binding using
the extends
attribute.
Detach binding. (See: binding detachment model.)
Attach a new instance of binding so that it is in the same place in the binding chain as the old instance was. (See: binding attachment model, implicit inheritance.)
It is possible to form a loop with the extends
attribute. For example, a binding A can inherit from B which inherits
from C which inherits from B again. The attachment algorithm is defined
in a way that makes the loop stop as soon as a duplicate binding would be
bound. In this case, the user agent will form a chain starting with A
(the most derived binding), derived from B,
derived from C, with C as the base binding
(chain A→B→C). If, given the same definitions, the element was
bound directly to C, then the chain would be C→B.
When two bindings are both attached to the same element, the base binding at the end of the explicit inheritance chain of the second binding implicitly inherits from the most derived binding of the explicit inheritance chain of the first.
If one of the explicit inheritance chains is removed, then the remaining binding chains are reconnected so that the base binding of the explicit chain after the break now inherits from the most derived binding before the break.
The order of bindings is always such that bindings added via the
binding
element are first (in the
order the bindings are specified in the file, with the files, if there
are more than one, ordered in the same order that they are referred to,
traversed pre-order, depth-first), the bindings attached via CSS are
second (in the order specified on the 'binding
' property), and the bindings added
via addBinding
are third (in the
order they were attached, most recently attached being the most derived binding).
For example, take a binding d1, which specifies a
base binding d2 using the extends
attribute such that its explicit inheritance chain is:
d1 → d2
If binding d1 is attached to an element using
addBinding
that already has a
binding chain of:
s1 → s2 → s3
...then the base binding at the end of the inheritance chain, d2, is the one that will inherit from the most derived binding that is already attached to the element, s1. The resulting binding chain following the addition of the binding is therefore:
d1 → d2 → s1 → s2 → s3
The inheritance between d2 and
s1 is implicit, meaning that there is no
connection in the XBL subtrees between the two bindings. The inheritance
link has been forged dynamically through the invocation of the addBinding
method.
An element can be bound to the same binding multiple times, in which case a binding can end up inheriting from itself. (This can only happen via implicit inheritance, though.)
Consider the following completely useless but short bindings:
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="a"> <template> l <inherited> l <content> o </content> - </inherited> W </template> </binding> <binding id="b" element="[X]" extends="#a"> <template> e <inherited> error </inherited> o <content> r </content> </template> </binding> <binding id="c" element="[Y]"> <template> H <inherited> error </inherited> l <content> error </content> ! </template> </binding> </xbl>
When imported by the following equally silly but simple document:
<?xbl href="test.xml"?> <root X="" Y=""> d </root>
The resulting flattened tree would spell "H e l l o - W o r l d !".
The binding "c" that attaches because of the Y attribute implicitly
inherits from the binding "b" that is bound because of the X attribute,
and that latter binding explicitly inherits from the "a" binding. Since
the "Y" binding has a content
element, the "d" explicit child node of the bound element ends up
assigned to the content
element in
the "Y" binding.
The following table shows the source of each character:
Output: | H | e | l | l | o | - | W | o | r | l | d | ! |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Source: | c | b | a | a | a | a | a | b | b | c | R | c |
...where R represents the bound document.
The inheritance chain of the bindings attached to the root
element in this example is:
c → b → a
...where the first arrow is an implicit inheritance, and the second is an explicit inheritance.
Only one set of bindings is attached to the document, and they must affect all views in a multi-view UA. Bindings attached via style sheets must be attached based on the style sheets that apply to the default view.
Binding loads are asynchronous. That is to say, when a binding is added
(either via style sheet, script, or some other method), and the relevant
binding document is not yet loaded, the load
must be started in the background and the binding only attached once the
binding document is available. An author can ensure that all bindings are
synchronously attached by calling loadBindingDocument
to pre-fetch
any binding documents that are required.
The bound document must wait until all XBL dependencies have loaded
before firing its load
event.
When a binding is detached, the xblLeftDocument()
method must be
invoked on the binding's implementation.
Then, the shadow tree must be removed, the implementation must be removed
from the bound element's list of binding implementations, and any
forwarding of events to the binding must be stopped for this bound
element.
If the binding had an extends
attribute when it was bound to the
element (it may have changed since then, in which case the binding is
being detached precisely for that reason), then the user agent must then
detach the binding that was attached because of that attribute (if any).
(See: explicit inheritance, interpretation of URIs to XBL bindings.)
If the binding had a shadow tree, the explicit children must then be
redistributed. (See: processing content
elements.)
The subtree specified by the template
element is referred to as the shadow content template. This template describes a
content tree that will be generated under the bound element during
binding attachment. An element declared in a bound document using a
single element can then be constructed out of multiple child elements,
and this implementation is hidden from the bound document.
A shadow tree is a tree of nodes created by
cloning a binding's shadow content template. A
bound element can have zero, one, or more shadow trees. If a bound
element has any, they are combined by the user agent, along with the
element's explicit children, to form the final flattened tree. Shadow trees are hidden from
normal DOM processing (hence the name "shadow"); they are not accessible
via Core DOM navigation facilities such as firstChild
or
nextSibling
. (See: shadow content.)
The term shadow content refers to the various nodes in the shadow tree(s) of a bound element. Shadow content is created by cloning shadow content templates during binding attachment.
For example, the HTML file upload control appears in most browsers as a composite widget consisting of a text field and a button. A sample XBL binding for the file widget might look as follows:
<binding id="fileupload"> <template> <html:input type="text"/> <html:input type="button"/> </template> </binding>
Because this content is not visible to its parent element, it is said to be shadow content.
The file control is actually a special case. Due to security considerations, untrusted bindings will typically not be able to extend the file upload control in UAs intended for use with untrusted content.
Whenever bindings are attached to an element, shadow content will potentially be generated. Similarly, when a binding is removed from an element, its shadow content, if any, is destroyed.
A shadow tree must be generated if a template
element is added to a binding
element that had no template
element. If the template
element is removed, then the shadow
tree must be destroyed.
The template
element used to
generate a binding is always the first such element in a binding
element. If the binding
element is mutated in a way which
changes which template
element is
the first, then the corresponding shadow tree must be regenerated.
Similarly, when a template
element or any of its descendants is mutated in any way, any bindings
whose shadow tree was constructed from that element must be regenerated.
Regenerating a shadow tree consists of first destroying the existing shadow tree and then generating a new one.
When a shadow tree is generated, user agents must act as follows:
If the binding element has no template
element, then no shadow content
will be generated for this binding.
Otherwise, its first template
element must be deeply cloned.
The xml:base
data of the cloned template
element must be set so that the
baseURI
of nodes in the resulting shadow tree is the same as
their pre-cloning counterparts. All shadow nodes'
ownerDocument
pointers are left pointing at their binding
documents' Document
node(s).
No mutation events must be fired during the above steps.
Any bindings that apply to elements in the shadow tree must be applied.
For bindings with ECMAScript implementations: the shadowTree
member of the internal object must be set to be a reference to the
template
element clone (the root of
the shadow tree).
The shadow tree is then applied to the bound
element: the binding's shadow tree is placed in the appropriate place in
the final flattened tree, explicit children are
(re)distributed to the appropriate content
elements, and the CSS cascade and
inheritance is be computed along the new tree. (See: processing content
elements.)
After this point, further bindings may need to be applied, or certain bindings may need to be removed (because of CSS inheritance or because the selectors that decide which elements match which bindings can be affected by the shadow tree being associated with the bound element).
Everything described in this section must be completed atomically — that is, the UA must not execute author scripts during this process.
Some implementations might optimize this algorithm, such as using "lazy evaluation" approaches and thereby postpone the cascade and inheritance operations.
The destruction of a shadow tree consists of recreating the final flattened tree without the influence of that
binding's shadow tree by redistributing the explicit
children to the remaining shadow trees' content
elements (or, if there are none,
putting the nodes back directly under the bound element).
For bindings with ECMAScript implementations: the shadowTree
member of the internal object must be set to null.
Attributes on shadow content elements can be tied to attributes on the
bound element; then, whenever the attribute is set or removed on the
bound element, the corresponding attribute on the shadow content is also
set or removed. On any shadow content element, an xbl:attr
attribute can be
used to specify a space-separated list of
attributes that should be inherited. Attributes with namespaces can be
defined using a namespace prefix and the attribute name separate by a
colon.
For example, returning to the HTML file upload control example above,
the shadow text field can be set up to automatically inherit the
value
attribute from the bound element.
<xbl:binding id="fileUploadControl"> <xbl:template> <html:input type="text" xbl:attr="value"/> <html:input type="button" value="Browse..."/> </xbl:template> </xbl:binding>
Each entry in the xbl:attr
list can either simply list an
attribute (a QName, such as value
in
the example above), or it can specify an =
-separated pair of
QNames consisting of the attribute on
the shadow content that should be tied to the attribute on the bound
element. When two names are specified, the attribute to be added on the
shadow content node is listed first, and the attribute of the bound
element is second.
Each entry may also be suffixed by a single hash mark (#) followed by a type designation.
The xbl:attr
attribute's value must be parsed as follows. First, it must be split on
spaces (treated as a space-separated value).
Next, each resulting item must be matched against the following pattern
(given here in pseudo-BNF, where square brackets indicate optional
terms):
xbl inherits item := [s1 ':'] s2 ['=' [s3 ':'] s4] ['#' s5]
...where s1..s5 are strings of characters not containing any of ":". "=", or "#".
If any item does not match this pattern, then the item is in error and must be ignored. Other items in the list, if any, are not affected by this.
The values s1:s2 and s3:s4
(if present) must be resolved to fully qualified names using the
attribute QName resolving semantics and the
namespaces prefix declarations in scope on the element on which the xbl:attr
attribute is
found, at the time that the attribute is parsed. Any value in the list
that does not resolve to a fully qualified name is in
error and must be ignored. [XMLNS]
Changes to namespace prefix definitions in the shadow tree that affect
QNames used in xbl:attr
attributes take effect the next time
the attribute is parsed (which must be the next time the attribute is
changed, but may be earlier).
The special value xbl:text
can be
used in an =
-separated pair, where the prefix is
associated with the XBL namespace. (The value is not a literal; it
represents the fictional "text" attribute in the XBL namespace.)
When specified on the left-hand side of the pair it indicates that the value of the attribute on the right-hand side are to be represented as text nodes underneath the shadow element in the final flattened tree. If the element has any child nodes in the DOM (any nodes, including comment nodes, whitespace text nodes, or even empty CDATA nodes) then the pair is in error and UAs must ignore it, meaning the attribute value is not forwarded. Otherwise, a text node must be created, and that text node will be placed under the element in the final flattened tree.
Text nodes created in this way are orphans; their
parentNode
, nextSibling
,
previousSibling
, childNodes
,
firstChild
, and lastChild
attributes are all
null or empty. Their ownerDocument
attribute is set to the
same as the shadow content node that generated them. (The only way one of
these text nodes can be accessed is if the element is itself bound: the
text node might then appear in a content
element's xblChildNodes
list.)
When used on the right-hand side, it indicates that any text nodes (including CDATA nodes and whitespace text nodes) that are explicit children of the bound element must have their data concatenated and the resulting value stored as the attribute on the left-hand side.
The xbl:text
value cannot occur by
itself in the list. If it occurs by itself, it is in
error and UAs must ignore that value in the
space-separated list that is the xbl:attr
attribute.
The special value xbl:lang
can also
be used in an =
-separated pair. (Again, this is
just the fictional "lang" attribute in the XBL namespace, not the literal
string "xbl:lang", so the "xbl" prefix, or whatever prefix is used, must
be declared as the XBL namespace.)
When used on the right-hand side, it indicates that the value to be
copied is the natural language of the bound element, typically given by
the attribute xml:lang
of that element or an ancestor, or by
HTTP headers, or similar. If no language is defined, then the value to be
copied must be the empty string.
The xbl:lang
value cannot occur by
itself or on the left-hand side. If it does, it is in
error and UAs must ignore that value in the
element's xbl:attr
attribute.
Any other values in the XBL namespace in the list are in error and must be ignored. (In particular, trying to change or set the
value of xbl:pseudo
or, worse, xbl:attr
, must not result
in any changes to any attributes.)
If an attribute is listed multiple times on the left hand side (or on its own), then the last designation wins (as if the attributes were each forwarded in turn, an earlier forwarding being overwritten by a later one).
If the attribute or attribute pair is followed by a type designation, in the form of a hash mark character ("#") and by a type name, then the value must be processed as described for its type below before being forwarded.
url
text
(default)
xbl:attr
attribute.
In the following shadow template, the "src" attribute on the bound
element is forwarded to the "src" attribute on the image
element in the shadow tree, and the link will work even if the original
attribute had a relative URI and the base URIs of the various nodes are
different:
<xbl:template> <xul:image xbl:attr="src#url title alt=xbl:text xml:lang=xbl:lang"/> </xbl:template>
This example also shows how to turn the value of an attribute on the
bound element, in this case the "alt" attribute, into child nodes of the
element in the shadow tree, using xbl:text
. For accessibility reasons, the
language of the element is also explicitly forwarded.
The xbl:attr
attribute must be parsed when the binding is first applied and whenever
the attribute's value changes. It must be applied (causing the relevant
attributes and text nodes to be updated) when the shadow tree is
generated, when the attribute is changed, and whenever any of the bound
element's attributes or text nodes referred to by the xbl:attr
attribute change.
The element to which the attributes are forwarded (that is, the element
with the xbl:attr
attribute specified) has its attributes mutated. Whenever attribute
forwarding happens: existing attributes to which values are being
forwarded must have their values changed, attributes that are being
forwarded that do not yet exist on the shadow tree element must be added
to the shadow tree element, attributes to which values would be forwarded
but whose source attributes are not present on the bound element must be
removed from the shadow tree element.
The shadow tree element's attributes can be changed dynamically, and
this doesn't affect the attribute forwarding, until dynamic changes cause
attribute forwarding to be performed again. When attribute forwarding is
performed, all attributes are forwarded, even those that haven't changed
on the bound element, thus blowing away any dynamic changes to the shadow
tree element's attributes that are referenced by the xbl:attr
attribute.
content
ElementsA node is said to match a content
element when the content
element has
no includes
attribute, or when the element in
question matches the selector given by that includes
attribute.
If an element stops matching a content
element that it is assigned to, then
the bound element's explicit chlidren must be redistributed.
XBL bindings can
interleave shadow content between bound elements and their explicit children. They do so using XBL's content
element. Any number of content
nodes may be used in a binding's
shadow content template.
In addition, the shadow trees of inherited bindings get inserted into
the first inherited
element in the
binding.
The explicit children of an element are the
nodes that are listed in the element's childNodes
array,
with the exception that any content
elements in that array are instead replaced by whatever nodes they
currently have assigned to them, or, if no nodes are assigned to that
content
element, by the child nodes
of that content
element. If an
element's childNodes
list is empty but the element has an
xbl:attr
attribute
that uses the xbl:text
value on the
left hand side in a way that is not in error then
its "explicit children" is the text node generated during attribute forwarding.
Consider the following simple document:
<X><A/></X>
Now, if the element X in that document is bound to a binding with the following shadow tree template:
<template> <my:T> <my:P/> <content/> <my:Q/> </my:T> </template>
The explicit children of the T
element, ignoring
whitespace nodes, are, in order, P
, A
, and
Q
. This is because the children of T
are
P
, a content
element,
and Q
, and the content
element has just one node associated with it, namely the A
element.
When the explicit children are distributed and
assigned to the content
elements in
the bound element's shadow trees, the includes
attribute determines which content
element a given child is to be placed under.
If no includes
attribute is specified, a content
element is considered generic and
will match on all content, including text nodes, CDATA nodes, comments,
and so on.
If the includes
attribute is specified, it must be
interpreted as a selector, and only elements
that match the
selector apply to that content
element. If the selector is invalid, the content
element is in
error and does not match any nodes. Matching of the elements to the
selector is done without taking into account the shadow tree in which the
content
element itself is found. [SELECTORS]
Each node that is to be distributed (each explicit child node) must be assigned to a
content
element as follows:
content
element for this binding, and the
content
element is locked, then that is the
content
element to which the node
must be assigned, stop here.
content
element for this binding, unassign
it.
content
element that is not locked and to which the
node in question applies, then the first such element in a depth-first,
pre-order traversal of the shadow tree T is the content
element to which the node must be
assigned, stop here.
inherited
element in its shadow
tree, then the node is not assigned to a content
element, and does not appear in the
final flattened tree; stop here.
inherited
element in its shadow
tree but it is the least derived binding with a shadow tree, then the
node is not assigned to a content
element, and does not appear in the final flattened
tree; stop here.
The explicit children must be processed in
order, so if two nodes are assigned to a content
element, their order in the xblChildNodes
list is the same as their
relative order in the explicit children list.
Consider the following simple document:
<X><A/><B/><C/></X>
Imagine that the element X in that document is bound to a binding with the following shadow tree template:
<template> <my:T> <my:M/> <content/> <my:N/> </my:T> </template>
Imagine further that the element T is itself bound to a binding with the following template:
<template> <my:R> <content includes="N"/> <content includes="B"/> </my:R> </template>
The resulting final flattened tree would be:
X | `-- T | `-- R | +-- N | `-- B
In this example, there are two selectors, "N" and "B", both of which match just elements with the given local name.
The algorithm described in the previous section is applied when:
content
elements or their includes
attributes.
includes
attribute in the shadow tree
is mutated.
content
element in a shadow
tree no longer match the element's includes
attribute.Consider the following binding shadow tree:
<template> <div>As: <content includes="A, AA"/></div> <div>Other: <content/></div> </template>
If an element is bound to this binding while it has three child
elements A, AA, and B, then the A and AA elements would end up under the
first content
element, and the B
element would end up under the second content
element. But if the includes
attribute of the first content
element in the shadow tree was then dynamically modified to just have
the value "A
", then the AA element would be
reassigned to the second content
element.
The final flattened tree is the view of the document and shadow trees after XBL has been fully applied. It is only used for two things:
All other processing continues to use the DOM Core tree. (See: shadow content and other things.)
The final flattened tree must be constructed by taking the bound document's core DOM tree and performing the equivalent of the following steps on each bound element, until there are no more bound elements in the tree that have not been processed:
template
element.
xbl:attr
attribute that
uses the xbl:text
value on the left
hand side in a way that is not in error, let the
element's only child node be the attribute-forwarding text node. (If the
element in question has any child nodes, then the xbl:text
value will be in
error.)
content
elements in
the shadow tree with the nodes that were assigned to them in the previous
section, unless there are no such nodes, in which case replace them
with their child nodes.
inherited
elements in the shadow tree with
their child nodes.
inherited
element in the shadow tree, if any, with the child nodes of the next most derived binding's shadow tree's root
template
element, or, if there is
no less-derived binding with a shadow tree, with the child nodes of the
inherited
element itself.
Imagine the following document fragment:
... <A> <B> <C/> <D/> </B> </A> ...
...is bound to the following XBL:
<xbl:xbl xmlns:xbl="http://www.w3.org/ns/xbl"> <xbl:binding element="B"> <xbl:template> <P> <Q> <xbl:content includes="C"> <R/> </xbl:content> </Q> <xbl:content includes="D"> <S/> </xbl:content> </P> </xbl:template> </xbl:binding> <xbl:binding element="Q"> <xbl:template> <X> <Y> <xbl:content> <Z1/> </xbl:content> <xbl:content> <Z2/> </xbl:content> </Y> </X> </xbl:template> </xbl:binding> </xbl:xbl>
The resulting DOM would look like the following. To read these diagrams, use the following key:
| Solid/dashed lines represent normal DOM traversal attribute ---+--- relationships using childNodes, parentNode, nextSibling, | previousSibling, firstChild, lastChild, etc. : ...:... Dotted lines represent the final flattened tree. :
White-space nodes have, for sanity, been left out of these diagrams.
DOM view:
| +-- A | +-- B | +-- C | +-- D
The shadow trees of B elements:
template | +-- P | +-- Q | | | +-- content | | | +-- R | +-- content | +-- S
The shadow trees of Q elements:
template | +-- X | +-- Y | +-- content | | | +-- Z1 | +-- content | +-- Z2
The final flattened tree:
: :.. A : :.. B : :.. P : :.. Q : : : :.. X : : : :.. Y : : : :.. C : : : :.. Z2 : :.. D
The final flattened tree overlayed with the core DOM (the "*" and "#"
characters here identify which content
elements the two explicit children
are assigned to):
:|___ :....A template :|___ | :... B | :| | :|... P template | :|____ | | :|... Q | | :| :| | | :| :|.... X | :| | :\_______ | :| | :....... Y __ | :| | : \ | :| +-- content* : | | :| | : | | :| +-- R : +-- content* | :| : | | +---:|--------- C* ......: | `-- Z1 | :| : | | :| : `-- content | :| : |___ | :| :............ Z2 | :`-- content# | : | | : `-- S |___:____ :... D#
Shadow content introduces the concept of shadow scope to nodes within a document. Because shadow content elements can also have bindings attached that generate their own shadow content, this scoping can be taken to an arbitrary level of nesting.
Shadow content nodes are in binding-level shadow scopes. Binding scopes are determined by the bound element to which the binding responsible for the generation of the shadow nodes is attached. The bound element itself is in the shadow scope of the content around it, and its binding's shadow content is in a deeper shadow scope. Shadow content that contains no elements that are themselves bound is said to be in the deepest, or innermost, shadow scope.
All of the nodes in the shadow tree are live. Whenever an element is
inserted into, removed from, or appended to the DOM, and whenever its
attributes or pseudo-class states are changed, all the children of bound
elements must check that their assigned content
element is still appropriate,
following all the same rules that applied when first placing explicit children during shadow content generation.
If one or more nodes stop fitting into any of the content
elements then they no longer appear
in the final flattened tree. Similarly, nodes that
previously did not appear in the final flattened tree may start matching
a content
element and thus be
inserted into the flattened tree.
It is possible to manipulate the shadow content contained underneath a
bound element using standard DOM APIs. If shadow content that contains a
content
element is removed, then any
explicit children assigned to that element are
relocated to the first unlocked content
elements that match them. If a
content
element's includes
attribute is changed, then the explicit children
of the binding's bound element must be redistributed appropriately.
content
elements may be
dynamically locked by manipulating their locked
attribute.
A locked content
element cannot
accept new children unless they are explicitly assigned to it using the
setInsertionPoint()
method.
However, children already under a locked content
element remain there while the
element's includes
attribute (or lack thereof) matches
them.
Whenever the subtree of a template
element in a binding document is
dynamically modified, any shadow trees that were constructed by cloning
that element must be regenerated.
Bindings can interleave shadow elements between the bound element and
its explicit children. (See: processing content
elements.) In this situation, a new tree emerges that is different
from the explicit content node tree. In addition to having a single
explicit parent (the bound element) and a single set of children (the
explicit children in the DOM tree), elements also have a set of shadow
parents and shadow children (introduced by bindings when content
elements were used). This necessarily
affects the CSS model.
Combinators: CSS combinators, in the presence of XBL, must act as follows. This is intended to match the definitions of CSS in all cases other than when a selector would involve one or more XBL elements.
If "B
" is in a shadow tree and
"B.parentNode
" is a content
element or an inherited
element, let "X
"
be "B.parentNode.parentNode
", otherwise let
"X
" be "B.parentNode
".
Now if "X
" is the root of a shadow tree, but the
binding's "allow-selectors-through
" is
not true
, the selector doesn't match "B
".
Otherwise, if "X
" is the root of a shadow tree and the
binding's "allow-selectors-through
" is
true
and the binding is the bound element's most derived
binding with a shadow tree, then let "X
" be the bound
element for which the shadow tree was generated. Otherwise, if
"X
" is the root of a shadow tree and the binding's "allow-selectors-through
" is
true
but the binding is not the bound element's most
derived binding with a shadow tree, then let "X
" be the
parent node of the inherited
element into which the shadow tree was placed during the construction
of the final flattened tree; if this is itself
the root of a shadow tree, then repeat the steps described in this
paragraph using that element as "X
".
Then, the selector matches "B
" if the "X
"
element is the "A
" element.
B
" if either "A>B
" matches
"B
", or "C>B
" matches "B
" and
"A C
" matches "C
".
B
" is in a shadow tree and
"B.previousSibling
" is a content
element or an inherited
element, the selector doesn't
match "B
", otherwise, it matches if
"B.previousSibling
" is "A
".
B
" if either "A+B
" matches
"B
", or if "C+B
" matches "B
" and
"A~C
" matches "C
".
The selector p ~ p
never matches any elements in the
following example, even if the content
element has a p
element
assigned to it:
<template> <html:p>...</html:p> <content includes="p"><html:p>...</html:p></content> <html:p>...</html:p> </template>
Pseudo-classes and pseudo-elements: Pseudo-classes and pseudo-elements are unchanged in the presence of XBL. They operate exclusively on the core DOM.
In particular, note that this means that the selector
:nth-child(odd)
would match both the A
and
B
nodes in the following example:
<xbl:template> <A/> <xbl:content/> <B/> </xbl:template>
...regardless of the number of nodes that are inserted at the point
given by the content
element
(whether that be 0, 1, 2, or more nodes).
The final flattened tree determines how CSS properties (e.g., fonts and colors) are inherited. Elements must inherit from their parent node in the final flattened tree, regardless of what their DOM Core parent node is.
Similarly, the rendering is performed using the final flattened tree. Nodes that do not appear in the final flattened tree have no computed style (as if they were orphan nodes) and are not rendered.
:bound-element
Pseudo-ClassThe :bound-element
pseudo-class, when used from a binding, must match the bound element of
that binding. If the selector is used somewhere other than in a binding's
style sheet (i.e. with a style
element
in XBL) or in a content
element's
includes
attribute, then it must match any bound element. [SELECTORS]
In the following example, the binding uses this pseudo-class to to draw a border around each of the children of the bound element, but no other elements:
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding> <template><content allow-selectors-through="true"/></template> <style> :bound-element > * { border: solid; } </style> </binding> </xbl>
Shadow nodes may be associated with various pre-defined pseudo-elements of the
bound element. On any element in the shadow content template, an xbl:pseudo
attribute
(in the XBL namespace) can be used to specify the name of the pseudo to
associate with that element.
For example, once more returning to the HTML file upload control example above, the shadow text field can be set up to be considered a match for the selector input[type=file]::value as follows.
<xbl:binding id="fileUploadControl"> <xbl:template> <html:input type="text" xbl:pseudo="value"/> <html:input type="button" value="Browse..."/> </xbl:template> </xbl:binding>
The pseudo must be given without its leading double colon.
If the pseudo-element name is not recognized, it is in error and the UA must ignore the attribute. User agents must not automatically recognize any pseudo-element (as this will break forwards-compatibility).
If an element has multiple nodes with the same pseudo-element, then
they all match the relevant selector. Matching of nodes based on their
pseudo-element is unaffected by the apply-author-sheets
attribute.
The allowed pseudo-elements are:
These pseudo-element descriptions are purely advisory, and while authors are encouraged to use them for their predefined roles, it is valid to use them for other purposes.
The following XBL is part of the definition of a button control.
<xbl:binding id="imageButton"> <xbl:template> <html:span xbl:pseudo="icon"/> <html:span xbl:attr="xbl:text=title"/> </xbl:template> </xbl:binding>
This control could then be used like this:
<button title="Save" class="save-button"/>
...and styled like this:
button { binding: url(buttons.xml#imageButton); } button.save-button::icon { content: url(icons/save.png); }
In property descriptions, the term "all elements" in the "Applies To:" line includes these pseudo-elements, as they map directly to real elements in the binding.
User agents are required to support the above pseudo-element identifiers, in so far as they interact with XBL2. User agents may also support these same pseudo-elements for other purposes, e.g. as described in the CSS3 UI specification. [CSS3UI]
xml:base
This section is intended to re-iterate what the
xml:base
specification already states, in case there is any
question about how xml:base
processing should work in shadow
trees.
Relative xml:base
s on nodes in shadow trees are resolved
relative to their parentNode
, or the
ownerDocument
if there is no parentNode
.
Since the processing rules of all non-XBL elements found while processing a binding document are not affected by their being part of an XBL subtree, there are certain elements that are unlikely to have the desired effect when included in shadow content templates. Some of these cases are described below.
While some of these effects may seem peculiar, it must be emphasized that they are merely the result of XBL not affecting the semantics of these elements at all. It would have been possible to define XBL in such a way that the semantics of various elements from the XHTML, XML Events, etc, namespaces were modified, but this would have required XBL knowing about special elements from a large number of namespaces, causing XBL implementations to have large interdependencies.
Shadow content is not considered part of a document, so elements that are defined to trigger when they are "inserted into the document" do not trigger during binding attachment.
IDs used in shadow content, as seen on XML Events nodes, in XHTML on
the html:label
element's for
attribute, and in
many other places, must be resolved in the context of the shadow scope and (failing that) the binding document,
not the scope of the document into which the shadow content is inserted.
If a shadow template has an html:img
element that has its
usemap
attribute set:
<template ...> <html:img src="..." usemap="#test" alt="..."/> </template>
If the binding is applied to an element in a document containing an
html:map
element with ID "test", that image map will not be
associated with this image. If the binding document itself contains an
html:map
element with ID "test", however, that
would be associated with the element (even if it was, say, in
another binding's template).
If the template looked like this:
<template ...> <html:img src="..." usemap="#test" alt="..."/> <html:map id="test"> ... </html:map> </template>
...then the html:img
element would always be attached to
that html:map
element, regardless of the existence of other
html:map
elements in the binding document.
When an element's processing model is defined in terms of the element's
child nodes or descendants, shadow trees do not affect the processing
model (unless this is called out explicitly below). For instance, an HTML
title
element's behavior in determining the document title
is unaffected by XBL, even if the title
element is bound or
has bound elements in its descendants.
When the nodes are cloned, their xml:base
data remains as
it was in the bindings document (see rules for content
generation). Therefore URIs consisting of just fragment
identifiers (such as those in url()
notation in style
attributes of, e.g., XHTML nodes) refer to
resources in the bindings document, not content in the bound document or
the shadow tree.
This would cause trouble with attribute forwarding, so the attribute forwarding syntax allows attributes to be marked as being of type "url".
The semantics of html:style
elements is that they
introduce new styles for their document. Since the document, in the case
of anything in an XBL subtree, is the bindings document (or the non-XBL document in which the XBL subtree is found),
that is the document that must be affected by such a style
sheet.
Since the style sheets of such resource documents generally have no
effect, placing html:style
blocks in XBL binding documents
is usually redundant. Such an element placed in a shadow content template
does not affect the documents into which the shadow content is later
inserted during binding attachment.
Script elements, such as html:script
and its ilk, are
typically evaluated only during parsing, or during parsing and when
inserted into a document. In all cases, however, they are evaluated in
the context of their owner document. Therefore such elements must only be
evaluated during initial parsing, in the context of the XBL subtree's
document, and not during binding attachment.
XML Events elements in the binding document must result in event
handlers being registered as event listeners on the nodes in the original
bindings document (including possibly the template
node) as described in XML Events.
They may be included in shadow content templates, but when the shadow
content template is cloned, the newly cloned event handlers must cause
new event listeners to be added to their new DOM Core parent nodes. Thus
an event handler that is the child of an template
element in the shadow content
template will never fire once it has been cloned, since the events do
not bubble into the template
elements. [XMLEVENTS]
Event handler blocks that are children of handlers
elements (in particular XML Events
handler blocks) cause event listeners to be fired when event forwarding happens, just like with XBL handler
elements.
Forms and form controls in shadow trees don't interact with form
controls and form
elements in the bound document. Each
document and shadow tree creates a new scope for forms and form controls.
Here's an extract from an HTML document with a form:
... <form action="register" method="post"> <h2>Customer Registration</h2> <p>Please enter your details.</p> <fieldset> <legend>Contact Information</legend> <p>Name: <input name="name" title="Enter your full name (first name first)."></p> <p>Job Title: <input name="title" title="Enter your job title, e.g. 'Software Engineer'."></p> <p>E-mail: <input name="email" title="Enter your e-mail address, in the form 'user@example.com'."></p> </fieldset> <fieldset> <legend>Company Information</legend> <p>Name: <input name="company" title="Enter the name of your employer."></p> <p>Address: <textarea name="address" title="Enter the full street address of your employer, including postal code."></p> </fieldset> <fieldset> <legend>Additional Information</legend> <p>Birthday: <input name="dob" title="Enter your birthdate in the form YYYY-MM-DD, e.g. 1975-03-29."></p> <p>Favorite animal: <input name="animal" title="Enter the word 'Cat'."></p> </fieldset> <fieldset> <legend>Submission</legend> <p><button title="Only submit the form when you are sure it is complete.">Submit</button></p> </fieldset> </form> ...
The first binding, shown below as an extract from an XBL document,
could be attached to the form
above, through CSS, to
provide a help box that shows the help text associated with the
currently focused control:
... <binding id="form-with-help"> <template> <div> <div class="header">Form:</div> <div class="form"><content/></div> </div> <div> <div class="header">Help:</div> <div id="help"/> </div> </template> <resources> <style> .header { font-size: larger; } .form { height: 15em; overflow: scroll; } </style> </resources> <handlers> <handler event="focus"> this.shadowTree.getElementById('help').textContent = event.target.getAttribute('title'); </handler> </handlers> </binding> ...
The help could be positioned more usefully by a slightly more advanced
binding that positioned the div
when
setting the help.
The last binding isn't particularly interesting. However, the important thing to note is that if it was extended to include form controls of its own, as in the following example, the form controls in the binding would not interact with the form in the markup:
... <binding id="form-with-help"> <template> <div class="header"> <div class="title"><content includes=":bound-element > h2:first-of-type"/></div> <div class="tagline"><content includes=":bound-element > h2:first-of-type ~ p:first-of-type"/></div> </div> <div> <div class="panel"><content locked="true" id="current"/></div> </div> <div> <div class="buttons"> <button id="back">Back</button> <button id="next">Next</button> </div> </div> <div class="hidden"><content includes=":bound-element > fieldset" id="not-current"/></div> </template> <implementation> ({ set current(fieldset) { if (this._current) this.shadowTree.getElementById('not-current').setInsertionPoint(this._current); this._current = fieldset; if (this._current) this.shadowTree.getElementById('current').setInsertionPoint(this._current); }, back: function() { if (!this._current) return; var notCurrent = this.shadowTree.getElementById('not-current'); notCurrent.setInsertionPoint(this._current); var last = this._current; var index = 0; while (index < notCurrent.xblChildNodes.length && notCurrent.xblChildNodes[index] != this._current) last = notCurrent.xblChildNodes[index++]; this._current = last; this.shadowTree.getElementById('current').setInsertionPoint(this._current); } next: function() { if (!this._current) return; var notCurrent = this.shadowTree.getElementById('not-current'); notCurrent.setInsertionPoint(this._current); var last = this._current; var index = notCurrent.xblChildNodes.length-1; while (index > 0 && notCurrent.xblChildNodes[index] != this._current) last = notCurrent.xblChildNodes[index++]; this._current = last; this.shadowTree.getElementById('current').setInsertionPoint(this._current); } get current() { return this._current; }, xblBindingAttached: function() { this.current = this.getElementById('not-current').xblChildNodes[0]; this.shadowTree.getElementById('back').addEventListener('click', this.back, false); this.shadowTree.getElementById('next').addEventListener('click', this.next, false); }, }) </implementation> <resources> <style> ... </style> </resources> </binding> ...
Again, the binding could be made cleaner, e.g. by disabling the "back" button when on the first page, and by hiding the last fieldset and instead having a "finish" button, but these improvements are left as exercises for the reader.
Painting: When painting groups, for child elements that have
shadow trees, instead of painting the child element itself, the group
must paint the child nodes of the element's shadow tree's root template
element.
Text: When rendering text, for descendant elements that have
shadow trees, instead of using the element or its children directly, the
user agent must use the child nodes of the element's shadow tree's root
template
element. (All other
processing, e.g. handling of combining characters, must then be done as
defined for SVG.)
ID references and URIs: When a URI identifies an element with
a shadow tree, the SVG processor must use the first element node in the
element's shadow tree's root template
element's childNodes
list instead of the element itself. If there are no elements, then the
SVG document is in error. The SVG specification defines how to handle
documents that are in error.
When a URI reference with a fragment identifier in a shadow tree references the binding document, then, if an elemnt in the shadow tree is identified by the fragment identifier, that is the element that must be used; otherwise, the fragment identifier must be matched against the actual binding document instead.
Animation elements: When an animation element would be
implicitly associated with its parent element (e.g. when it has no xlink:href
attribute), but that parent element is a
template
element that is the root
of a shadow tree, then the animation element must instead be associated
with the element found using the following algorithm:
template
element that is the root of a
shadow tree, then let element be the bound element
for that shadow tree, and return to the second step.
Animation elements must be processed even when in shadow trees.
In the following example, the UA would render the string "Hello Cruel World", while animating the colour of the entire string over six seconds.
<svg xmlns="http://www.w3.org/2000/svg"> <defs> <b:xbl xmlns:b="http://www.w3.org/ns/xbl"> <b:binding element="|world"> <b:template> <tspan b:attr="b:text=data"/> World <animateColor attributeName="fill" from="rgb(0,0,255)" to="rgb(128,0,0)" begin="0s" dur="6s" fill="freeze" /> </b:template> </b:binding> </b:xbl> </defs> <text y="50" font-size="12"> Hello <world xmlns="" data="Cruel"/> </text> </svg>
Shadow content nodes and bound elements are styled using style sheets from a number of sources, depending on the values of certain attributes. When multiple bindings are applied to the same bound element, the sheets from each binding all contribute to the final set of style sheets to apply, the style sheets of the most derived binding being walked first. For each binding, the style sheets that apply are as follows, in the order given:
Scoped style sheets: A binding file can load style sheets
using the style
element. (See: loading style sheets.) These style sheets must be
applied to the bound element and to all shadow content attached to the
bound element.
If the binding was attached using CSS, the scoped style sheets have the
same CSS origin as the sheet with the rule responsible for the binding.
Style sheets used by bindings that are attached using the DOM or using
<?xbl?>
are
treated as author-level sheets.
When bindings from multiple levels are applied to the same bound element, the style sheets that apply must cascade according to their own levels.
An element E is attached to binding U from the user agent style sheet, and binding A from the DOM, which places A in the author level. When the style sheets that apply to E are sorted, U must be applied at the UA level and A at the author level.
Author style sheets: While the apply-author-sheets
attribute on
the template
element found at the
root of the element's shadow tree is set to true
, the rules
specified in any author style sheets at outer shadow scopes (including
those promoted to outer scopes using apply-binding-sheets
, as defined
below) must be applied to the shadow content. Otherwise, only those
matched through predefined pseudo-elements are
used, and other author-level sheets in higher shadow scopes must not be
applied to the shadow content. (The bound element is always styled using
the sheets of higher shadow scopes.)
By default, style sheets specified in bindings (as described above) are
applied only to shadow content generated by bindings attached to the
bound element and to the bound element itself. A second attribute, apply-binding-sheets
, can be used
to indicate that all descendants of the bound element, both shadow and
explicit, can be styled by the sheets in the binding's document. This can
be controlled on a per-insertion-point basis. While this attribute is set
to true
on a content
node in the shadow tree DOM, any nodes that are assigned to that element,
and any descendants of those nodes, must have the scoped style sheets of
the binding (those that apply to the shadow content as described above)
applied to them too, as if they had been promoted to the higher scope.
Sheets within each origin are always walked from the innermost shadow scope to the outermost shadow scope (with rules in the outermost shadow scope therefore overriding rules of equal specificity in the innermost shadow scope). With this ordering a binding that defines a widget can define a default look for the widget that can then be easily overridden by a client of the widget. For multiple bindings attached to the same element, the sheets are walked from the base binding to the most derived binding.
User agent style sheets and user style sheets: These are always applied to all shadow scopes.
Since styles from both author style sheets and binding style sheets are
applied to the bound element, it is possible for an infinite loop to form
where an author sets the 'binding
' property to a particular binding
that then explicitly sets the 'binding
' property to 'none' (or another
binding). This specification does not take any precautions to avoid this,
any more than it takes precautions to avoid loops caused by binding
constructors explicitly calling removeBinding()
to remove the binding
itself and binding detachment event handlers reattaching the bindings.
Similar potential loops exist also in underlying technologies, for
example :hover
rules that cause elements to no longer be
hovered, or focus event handlers that move focus to an element and blur
event handlers that move focus back to the element.
In so far as XBL is concerned, authors must avoid constructing such loops, and implementers must ensure that such loops do not prevent users from interacting with the user agent.
This section is non-normative.
The <style>
is applied only to the bound element and
the shadow content that was generated by the binding. The
<style>
is also applied to explicit children (and
their descendants) assigned to <content>
elements
whose apply-binding-sheets
is set to
true
.
Continuing from the above, author sheets (styles from the bound
document) are applied to the shadow content only if apply-author-sheets
is set to true
for the <template>
.
Last, but not least, one can use author sheets to change the style of
elements in the shadow content that use the xbl:pseudo
attribute, as long as it matches
them with pseudo-elements (irrespective of the apply-author-sheets
setting).
Bindings can define methods and properties on a bound element using the
implementation
element. A
binding implementation provides a new set of methods and properties that
can be invoked from the bound element.
How the binding implementation is defined depends on the scripting language used; the details for ECMAScript are defined below.
In general, however, each binding has an object that implements the
XBLImplementation
interface, along with any other interfaces that the implementation might
implement. This is the implementation object for that instance
of the binding. All elements implement the ElementXBL
interface, whose xblImplementations
member returns
an object implementing XBLImplementationList
. This
object lists all the implementation objects for that bound element. (If
the element is not a bound element, the list is empty.)
XBLImplementation
InterfaceAll implementation objects support the XBLImplementation
interface (in
addition to any other interfaces specific to the binding). By
implementing the methods defined in this interface, bindings can be
notified of the binding's state with respect to its environment.
interface XBLImplementation { void xblBindingAttached(); void xblEnteredDocument(); void xblLeftDocument(); };
The xblBindingAttached()
method is called by the user agent after the binding has been attached.
(See: binding attachment model.)
The xblEnteredDocument()
method is called by the user agent in two cases:
Thus, it can be used to perform initialization steps that depend upon being in a document. (See: binding attachment model, handling insertion and removal from the document.)
The xblLeftDocument()
method
is called by the user agent when the bound element, or one of its
ancestors, or one of the elements in a higher shadow scope, is removed
from the document. (See: handling insertion and
removal from the document.)
If the implementation
does
not define one of these methods, then when that method is invoked,
nothing must happen (as if all bindings had default implementations of
those methods that were no-ops).
Authors should not start their own methods with the three letters "xbl". Future versions of this specification might add new callbacks to this interface, and if they do, those methods will start with the prefix "xbl".
This binding implements a clock. However, to save resources, the clock is only active when it is actually included in a document.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding id="clock"> <implementation> ({ xblEnteredDocument: function () { this.timer = setInterval(update, 1000); }, xblLeftDocument: function () { clearInterval(this.timer); }, update: function () { this.shadowTree.getElementById('clock-value').textContent = new Date(); }, }) </implementation> <template><div id="clock-value"></div></template> </binding> </xbl>
XBLImplementationList
InterfaceThe xblImplementations
attribute on all elements must return an instance of an XBLImplementationList
object
(the same object for the lifetime of the element), which is a live list
of the implementation objects provided by the bindings for that bound
element at any particular point in time.
interface XBLImplementationList { XBLImplementation item(in unsigned long index); readonly attribute unsigned long length; };
The length
attribute
must return the number of implementation objects associated with the
bound element, or zero if the element is not a bound element or has none
of its bindings have implementations.
The item(n)
method must return the nth implementation object associated
with the bound element. If the index is not a number between zero and
length
-1 (inclusive), then the method must
raise an INDEX_SIZE_ERR
DOM exception. [DOM3CORE]
The list must be ordered such that the most derived binding is last, and the base binding has index zero.
In ECMAScript implementations, objects that implement the XBLImplementationList
interface
must also have a [[Get]] method that, when invoked with a property name
that is a number, acts like the item()
method would when invoked with that
argument.
Script can access binding implementations directly using the xblImplementations
member. In
addition, in languages that support dynamic dispatch (such as
ECMAScript), any attempts to access members of ElementXBL
objects that do not correspond
to methods or properties on the object itself but do correspond to
members of one of the objects in the xblImplementations
list must be
forwarded to the last object in the xblImplementations
list that is so
matched.
When a binding is attached, the user agent must follow the following steps to make the binding implementation available to scripts:
If this is the first time the binding defined by that binding
element is used since that binding
document was loaded, and if that element contains an implementation
element, then:
implementation
element child of the
binding
element must have its
code compiled and run (see below).
binding
element as that binding's
implementation prototype object.
Otherwise, if the binding
element doesn't contain an implementation
element, or if it
does but it does not evaluate to an object, then an empty object must
be created (by invoking the Object
constructor in the
global scope of the binding document), and the binding
element's implementation prototype
object must be forever set to that object.
Any further changes to implementation
elements will have no
effect on the implementation prototype object of this particular
binding.
Next, the UA must create two new ECMAScript objects by invoking the
Object
constructor in the global scope of the binding
document. These objects are the internal object
and the external object.
The [[Prototype]] property of the internal object must be set to the external object, and the [[Prototype]] property of the external object must be set to the binding's implementation prototype object.
The internal object must then have the following fields defined:
external
boundElement
shadowTree
baseBinding
extends
attribute caused another binding to
be attached to the bound element, then the baseBinding
field's value must be set
to a reference of that binding's implementation object, if it has one
(if that is an ECMAScript implementation as well, then that is that
binding's external object). Otherwise, it must be set to the value
null.
Conceptually, the internal and external objects together make the
implementation object, but as far as the xblImplementations
property's list
is concerned, the external object is the one that is returned as the
implementation object.
When the user agent has to compile and run an XBL binding ECMAScript implementation, it must first obtain the script itself in the manner described in the section on loading and running scripts, and must then compile and execute the script using the binding document's global scope.
If the script evaluates to an object, then that is the implementation prototype object. Otherwise, there isn't one.
When function code of an implementation object implemented in
ECMAScript is called, the user agent must set the this
value
to the internal object associated with the external object on which the function was invoked.
Whenever an event passes through a bound element, whether during the
capture, target, bubble, or default phases, the user agent must also invoke any
appropriate event listeners attached to the binding's first handlers
element.
When events are forwarded in this manner, the event handlers attached
to the handlers
element must fire
after any event handlers on the bound element itself in the capture
phase, after the event has been retargeted to shadow nodes, if
appropriate; and before any event handlers on the bound element itself in
the target and bubble phases, before the event has been retargeted to the
bound element, if appropriate. (See: event flow and
targeting across shadow scopes.)
Event handlers must fire first on the most
derived binding and then on its inherited binding, continuing all the
way up the chains to the base binding. A
derived handler then has a way of preventing the event from flowing to
the handlers of the bindings it inherits from, by using the
stopImmediatePropagation()
method.
Event handlers may be attached to the handlers
element using any method, including
DOM3 Events' addEventListener()
method and the handler
XBL element. All event handlers
registered on the first handlers
element of the binding are considered, not just those attached using the
handler
element.
In the following example, the bound element is the
hotspot
element. When either it is clicked or the element
inside it is clicked, an alert is generated containing the text "Hello
World".
The bound document is:
<hotspot message="Hello World"> <instruction> Activate this text. </instruction> </hotspot>
The binding is:
<binding> <handlers> <handler event="click"> alert(event.currentTarget.getAttribute('message')); </handler> </handlers> </binding>
Note that the event object passed to the handlers
's handlers is the same as would
have been passed to event handlers registered directly on the bound
element. This is why currentTarget
in this example points
to the bound element.
handler
ElementWhenever the event
or phase
attributes of an
XBL handler
element change, or
whenever a handler
element's parent
changes, an event listener must be registered on the element's parent
element, if it has one; and if an event listener had previously been
registered for that handler
element,
it must be removed.
In terms of the DOM3 Events addEventListenerNS()
method,
the arguments used when registering the new event listener must be set as
follows:
namespaceURI
null
in this version of XBL.
type
event
attribute, or the empty string if the
attribute is missing.
listener
EventListener
interface that
invokes the handler
element as
described below.
useCapture
phase
attribute is present and has the literal
value capture
, otherwise false.
evtGroup
null
in this version of XBL. (Event listeners
registered with handler
elements
are registered in the default event group.)
Thus, the event
attribute specifies the event type, and
the phase
attribute the listener type. If the event
attribute is missing or its value is the
empty string, it is in error. If the phase
attribute is
present but has a value other than the literal strings
capture
, target
, bubble
, or
default-action
, it is in error.
(However, their being in error does not affect
the processing model described above.)
When a handler
element is invoked
by the object passed to the addEventListenerNS()
method, the
user agent must check that the event in question was forwarded to a
handlers
element from a bound
element, and that that handlers
element is the parent node of the handler
element.
If that isn't the case, then the invocation must do nothing.
Otherwise, if that condition is met, then the UA must check
any relevant filters specified on the handler
element. If any of them fail to match
the event, then the invocation must not do anything else. (The filter
attributes are defined in the next few sections.)
Otherwise, if all the filters match, then the user agent must execute
the contents of the handler
element,
treating it as being in the language specified by the script-type
attribute. (See: loading and running scripts, event handlers implemented in ECMAScript.) The script
must be run in the context of the binding document (and not, e.g., in the
bound document's context).
The propagate
attribute specifies whether, after
processing all listeners at the current node, the event is allowed to
continue on its path (either in the capture or the bubble phase). The
possible values are stop
and continue
(the
default). If stop
is specified, then after the event handler
has been fired, the event's stopPropagation()
method must be
called.
The default-action
attribute specifies
whether, after processing of all listeners for the event, the default
action for the event (if any) should be performed or not. For instance,
in XHTML the default action for a mouse click on an html:a
element or one of its descendants is to traverse the link. The possible
values are cancel
and perform
(the default). If
cancel
is specified, then after the event handler has been
fired, the event's preventDefault()
method must be called.
The trusted
attribute is a filter that, if set to
the value true
, matches only events whose trusted
attribute is
true. Otherwise, if it has another value or if it is not specified, any
event matches this filter. This filter can be used regardless of the type
of the event.
The phase
attribute is a filter that matches only events that are in the phase it
specifies. If the attribute has the value capture
, it must
only match events whose eventPhase
attribute has the value
CAPTURING_PHASE
(1). If the attribute has the value
target
, it must only match events whose
eventPhase
attribute has the value AT_TARGET
(2). If the attribute has the value default-action
, it must
only match events whose eventPhase
attribute has the value
0x78626C44 (2019716164). This is the value
used in the default phase. If it is specified
and has another value, it must only match events whose
eventPhase
attribute has the value BUBBLE_PHASE
(3). If it is not specified, it must only match events whose
eventPhase
attribute has the value AT_TARGET
(2) or BUBBLE_PHASE
(3). (If it isn't specified, then it
isn't registered as a capture event listener, so the handler would never
see the value CAPTURING_PHASE
(1).) This filter can be used
regardless of the type of the event.
In addition to the trusted
and phase
filters, event-specific filters may be
used, as described in the following sections. Only filters appropriate to
the given event type may be used; all other filter attributes, if
specified, are in error and UAs must ignore them.
For events that use or derive from the MouseEvent
interface, three event-specific filter attributes may be used. [DOM3EVENTS]
The filters are:
button
button
attribute on the event object for the XBL event
handler to fire. If the attribute is not specified, then any value of
the button
attribute on the event object must be considered
a match. If the value is specified, it must be a space-separated list of values, each of which
must be one or more digits in the range U+0030 DIGIT ZERO (0) to U+0039
DIGIT NINE (9). Each string must be interpreted as a base ten integer
and then compared to the value of the button
attribute on
the event object. If none of the values match the button
attribute, then the event handler must not be executed.
click-count
detail
attribute on the event object for the XBL event
handler to fire. If the attribute is not specified, then any value of
the detail
attribute on the event object must be considered
a match. If the value is specified, it must be a space-separated list of values, each of which
must be one or more digits in the range U+0030 DIGIT ZERO (0) to U+0039
DIGIT NINE (9). Each string must be interpreted as a base ten integer
and then compared to the value of the detail
attribute on
the event object. If none of the values match the detail
attribute, then the event handler must not be executed. Note that this
is checked for any event that uses the MouseEvent
interface, not just those for which detail
is defined.
Authors should take care to not specify this attribute with, for
example, mouseover
events, since in that context
detail
is undefined.
modifiers
For events that use or derive from the KeyboardEvent
interface, three event-specific filter attributes may be used. [DOM3EVENTS]
The filters are:
key
keyIdentifier
attribute of the event object.
For example, Enter
. If this filter is specified but the
modifiers
attribute is not, the user agent
must act as if the modifiers
attribute had been set with the
value "none
". If specified, the value of this attribute
must be a valid value of the keyIdentifier
attribute.
key-location
standard
,
left
, right
, and numpad
(with no
duplicates), which map to the DOM values 0x00, 0x01, 0x02, or 0x03
respectively. If specified, the event object's keyLocation
attribute must have a value equal to the numeric value of one of the
specified keywords. Unknown and duplicate values are in error and UAs must ignore them (although without dropping any correct values).
modifiers
For events that use or derive from the TextEvent
interface, one event-specific filter attribute may be used. [DOM3EVENTS]
The filter is:
text
data
attribute of the event object.
The value of the attribute may be any string.
For events that use or derive from the MutationEvent
interface, four event-specific filter attributes may be used. [DOM3EVENTS]
The filters are:
prev-value
prevValue
attribute of the event object. The value of the
attribute may be any string.
new-value
newValue
attribute of the event object. The value of the
attribute may be any string.
attr-name
attrName
attribute of the event object. The value of the
attribute may be any string.
attr-change
modification
,
addition
, removal
(with no duplicates), which
map to the DOM values 0x00, 0x01, or 0x02 respectively. If specified,
the event object's attrChange
attribute must have a value
equal to the numeric value of one of the specified keywords. Unknown and
duplicate values are in error and the UA must ignore them, although without causing correct values to be dropped.
There are currently no attributes specifically designed to be used with
events that use the MutationEventName
interface.
The modifiers
attribute specifies a filter
dependent on which keyboard accelerator keys ("modifiers") are set.
The attribute is a space-separated list of values.
To process this filter, the user agent must first invoke the
getModifierState()
method of the event for all the modifiers
the UA supports, noting the return value for each modifier. The user
agent must then walk through all the values in the modifiers
attribute, as described in the list below. The filter matches if all the
modifiers that returned true are accounted for, and none of the values
made the filter fail.
The getModifierState()
method, and the
modifiers that go with it, are defined in DOM3 Events. [DOM3EVENTS]
By default, only the CapsLock
, NumLock
, and
Scroll
modifiers are accounted for. Values on the attribute
cause other modifiers to be accounted for.
Before comparing the modifiers to the attribute values, the user agent must convert all the modifiers to lowercase.
User agents must recognize the accel
keyword as a synonym
for the modifier that is the primary accelerator key on the platform (on
Windows, this would typically be control
, on Mac it would
typically be meta
).
User agents must also recognize the access
keyword as a
synonym for the primary shortcut mnemonic key on the platform (on
Windows, this would typically be alt
).
The attribute values must be handled as follows:
any
any
is specified, then all the modifiers
are accounted for.
none
none
makes the filter fail if any modifiers
returned true, except for the CapsLock
,
NumLock
, and Scroll
modifiers, which are
ignored for the purposes of this keyword.
+modifier
getModifierState()
method did not actually return true for the corresponding modifier, then
it makes the filter fail.
-modifier
getModifierState()
method returned true for the
modifier corresponding to modifier, then it makes the filter
fail.
modifier?
getModifierState()
method did not actually return true for
the modifier corresponding to modifier, the value is ignored.
modifier
")
+modifier
.
A modifier can be listed multiple times, though this is not particularly useful.
Here are some examples of what this means:
modifiers
not specified
key
attribute is
specified, in which case the event handler is only invoked if no
modifiers are pressed.
modifiers=""
modifiers="none"
modifiers="any"
modifiers="alt control"
modifiers="alt control?"
modifiers="any -control"
modifiers="Alt"
modifiers="accel -capslock"
modifiers="alt alt alt"
modifiers="+alt -accel"
DOM events can fire on shadow targets just as they can on explicit targets. Events must flow through the final flattened tree. As long as the event flows within the same shadow tree scope, it is no different from the behavior outlined in the DOM Events specification.
Whenever events originating from a shadow tree flow from a shadow
element in that shadow tree to the bound element, one of two actions
occurs. Either the event is retargeted so that the bound element becomes
the target, or the event is stopped and flow proceeds to the next phase.
Whenever an event is retargeted, the event is cloned, with the clone's
target
field set to the bound element.
The action taken (retarget vs. stop) is specific to the event type. In general, UI events must be retargeted and mutation events must be stopped. Exceptions to the rule are noted below. The goal of this retargeting or stopping is to stop outer shadow scopes from being exposed to nodes from inner shadow scopes, and to stop outer shadow scopes from getting apparently meaningless events that only make sense in the context of inner shadow scopes.
During the capture phase, the rules are exactly reversed. The first node to see the event is the node after which bubbling stops. The target node, when the event is passing through a node at a higher shadow scope than the event target, is always the bound element in whose shadow content the event target lies.
When an event is retargetted at a bound element, the bound element's event handlers must see the event only in the target phase. The capture phase listeners must not be triggered for the bound element.
The timing of event retargeting is such that when the event is
forwarded to the handlers
element,
the binding's handlers see the relevant shadow tree node as the target,
rather than the bound element as the target. (See: event forwarding.)
Events bubble into deeper scopes; for example, an event fired on a
bound element's explicit
child bubbles into the element containing the content
element the element was assigned to.
This does not cause any event retargeting to take place, either when
entering the deeper scope or when leaving it, since such an event does
not actually originate in that shadow tree.
Any method invocations on any clones of the event object must also be forwarded to the original event and all the clones, so that attempts to stop propagation and cancel the default action affect the event regardless of how many scopes it has crossed.
Bound document:
<root xmlns=""> <bound/> </root>
Binding template applied to the bound
element:
... <xbl:template> <shadow xmlns=""> <target/> </shadow> </xbl:template> ...
If someone clicks the "target" element, the click event is dispatched as follows:
root
. Capture phase, target is
bound
.
handlers
. Capture phase, target is
target
.
shadow
. Capture phase, target
is target
.
target
. Target phase, target
is target
.
shadow
. Bubbling phase,
target is target
.
handlers
. Bubbling phase, target is
target
.
bound
. Target phase, target
is bound
.
root
. Bubbling phase, target
is bound
.
handlers
. Default phase, target is
target
.
target
. Default
phase, target is target
.
If an event bubbles through or is targeted at one or more bound
elements, and the event is not canceled (after the capture, target, and
bubble phases have all completed, its defaultPrevented
attribute is still false), then the event's eventPhase
attribute must be set to the value 0x78626C44
(2019716164), and then the event must be forwarded to the relevant handlers
elements of all the bound elements
the event bubbled through or was targeted at in those bubble and target
phases, in reverse tree order (starting from the target node and walking
the tree towards the Document
node), with
currentTarget
set to the relevant bound element each time.
If the event is canceled (that is, if the defaultPrevented
attribute becomes true) while being forwarded to one of these bound
elements, subsequent bound elements must not receive the event.
If the event has a UA default action, it must only perform it if the
defaultPrevented
attribute is still false after it has been
so forwarded.
The stopPropagation()
and
stopImmediatePropagation()
methods must have no effect
during this "default" phase.
focus
,
DOMFocusIn
, blur
, and DOMFocusOut
EventsIf shadow content underneath a focusable bound element loses focus and shadow content also underneath the bound element takes focus, then both focus change events must be stopped. As far as the bound element is concerned, it retains focus throughout the two events. (Other specifications may go into more detail as to how to determine if an element can be focused.)
If the focus moves from the bound element's shadow content to a node completely outside the bound element, or vice versa, then the respective events must be retargetted instead.
The 'nav-index' property defined in the CSS UI module [CSS3UI] can be used to specify the tab order for focusable elements. This property can be specified on shadow content. Each shadow scope has a unique tab order. The 'nav-index' values used in one shadow scope are ignored by other shadow scopes. The tab order is resolved in the shadow tree first to produce a list of elements in the tab order. This list is substituted in place of the bound element in the bound element's tree tab order.
As an example, consider the HTML file upload control. It is a focusable element that in turn is made up of two focusable shadow elements: a text field and a button. Tab indices can be specified on the text field and the button to indicate the order in which the components of the file control should be accessed when tabbing.
When the user tabs such that the file control should become focused, the user agent determines if any shadow content should also become focused, using the tab order specified by the shadow content elements. It then generates a focus event on the text field inside the file control. As this event flows across shadow scopes, it is retargeted to be a focus event on the file control itself.
Focus events should also be stopped if the bound element is already focused. For example, if the user has already focused the text field within an HTML file upload control, then the file upload control is now also focused. If the user then focuses the button inside the file upload control, the focus event generated for the button is stopped before it reaches the file control, since the file control is already focused.
Because content in multiple shadow scopes can be focused, the CSS
:focus
pseudo-element is hierarchical in the presence of
XBL, with up to one element in each shadow scope matching the
pseudo-class. Style rules can be written with the assumption that they
will match (in the above example) both the file control and the element
focused inside the file control. In other words, an arbitrary chain of
elements can be in the :focus
state at the same time.
Further specifications may describe in more detail the
interaction of arbitrary chains of elements that can be in the
:focus
state at the same time.
mouseover
and mouseout
EventsMouseover and mouseout events must be retargeted if the pointing device genuinely moves onto (enters) or is moved away (exits) the bound element (in addition to entering or exiting some shadow content). If, however, the user has simply moved the pointing device from one element in the shadow tree to another element in the same shadow tree, without entering or exiting the bound element itself, then the event must be stopped.
For example, if the user enters the HTML file upload control from the left, a mouseover event is generated for the shadow text field. Because this event also constitutes a mouseover of the file control itself, the event is retargeted when it flows across shadow scopes. If the user then moves the mouse from the text field to the button, a mouseout is generated for the text field, followed by a mouseover of the button.
Since neither of these events constitutes a mouseover or mouseout of the file control itself, the events are not allowed to flow to the file control. If the user continues moving to the right and leaves the button, then the mouseout generated will be retargeted, since the file control will also have been exited.
When a script of a handler
element
implemented in ECMAScript is executed the user agent must set the
this
value to the internal object
part of the implementation object of the binding with which the handler
element is associated. The script
must be executed as a function body with one argument, called
event
, which is a reference to the Event
object
representing the event. The script must be compiled and executed each
time it is accessed, so that any dynamic changes to the event handler
code in the binding document take effect.
XBL introduces a few XBL-specific interfaces.
DocumentXBL
InterfaceThe DocumentXBL
interface
contains methods for loading and obtaining binding documents. The
interface is implemented by DOM documents that support having their
elements bound by XBL.
interface DocumentXBL { readonly attribute NamedNodeMap bindingDocuments; Document loadBindingDocument(in DOMString documentURI); };
bindingDocuments
of type NamedNodeMap
, readonly
bindingDocuments
attribute must return a NamedNodeMap
of all the binding
documents loaded by the document. Documents are referenced using their
URIs as the node names, with null namespaces. The
NamedNodeMap
must be live, and must raise
NO_MODIFICATION_ALLOWED_ERR
on any attempts at
modification or deletion.
loadBindingDocument
The loadBindingDocument
method
must synchronously load the specified binding document (unless it has
already been
loaded), as well as any binding documents that are required by
that binding document due to explicit inheritance, and any bindings
defined by that document must be applied to matching elements in the
document that corresponds to this DocumentXBL
object. The method must
then return the binding document's Document
object.
(See: binding attachment and detachment.) If
the load succeeded, it is also added to the bindingDocuments
attribute. If
the load fails, this method must return null.
documentURI
of type DOMString
Document
loadBindingDocument()
is
the Document
object of the binding document that was
loaded, or null
if the load failed.
ElementXBL
InterfaceThe ElementXBL
interface
contains methods for adding or removing bindings from an element. The
interface is implemented by all Element
nodes (regardless of
whether they are currently involved with any XBL processing) and may be
obtained using binding-specific casting methods on an
Element
interface.
interface ElementXBL { readonly attribute XBLImplementationList xblImplementations; void addBinding(in DOMString bindingURI); void removeBinding(in DOMString bindingURI); boolean hasBinding(in DOMString bindingURI); };
xblImplementations
of type XBLImplementationList
,
readonly
addBinding
addBinding
method must
attach the specified binding (and any bindings that the binding
inherits from) to the element. This call is not necessarily
synchronous. The binding may not be attached yet when the call
completes.
bindingURI
of type
DOMString
HIERARCHY_REQUEST_ERR
removeBinding
removeBinding
method
must detach the specified binding (and any bindings that the binding
inherits from explicitly using the extends
attribute)
from the element. This method can only detach bindings that were
attached using addBinding
. If
the binding in question is not attached to this element (or was
attached through another attachment mechanism) then the method must do
nothing.
bindingURI
of type
DOMString
hasBinding
The hasBinding
method must
check the bindings applied to the element and compares each binding's
URI with the parameter passed. If any of the bindings matches the
specified URI, then the method must return true, otherwise it must
return false. This can be used to check if an element has been bound
to a particular binding in in order to ensure that the expected
methods and attributes are available.
Any bindings attached to the element (including, e.g., those attached using CSS) are examined by this method.
For example widgets may walk up their ancestors looking for an element that has been bound to a form-container binding in order to locate their scope (so that radio buttons may properly be mutually exclusive, or so that a submit button can properly submit a form).
bindingURI
of type
DOMString
boolean
true
if any of the bindings match the parameter,
false
otherwise.
In effect the shadow content exists in its own insulated pocket within
the document, its shadow scope. Bound elements
have no knowledge of their shadow children in terms of DOM Core [DOM3CORE]. The shadow content is not accessible
via the childNodes
list for the bound element, nor is it
accessible using firstChild
/nextSibling
to
iterate over the children of the bound element.
DOM methods that can be invoked on elements (e.g.,
getElementsByTagName()
) will only see nodes that are in the
same shadow scope. Methods invoked on the document (e.g., getElementById
) only see nodes that are not in shadow
trees.
On shadow content nodes, ownerDocument
always points to
the document from which the nodes were cloned.
Elements in different shadow scopes may have clashing IDs. IDs need only be unique within each shadow scope.
Elements that are the root of a shadow tree (the cloned template
elements) cannot be inserted into a
document. Any attempt to do so must raise a
HIERARCHY_REQUEST_ERR
.
Manipulating the DOM of a shadow tree (content
elements being moved about or even
removed altogether, xbl:attr
attributes being attached and
modified, etc) must immediately cause the final
flattened tree to be updated.
Changes to namespace prefix definitions in the shadow tree that affect
QNames used in xbl:attr
attributes may have their effects
applied immediately but this is not required.
Because each bound element gets its own copy of the cloned template, changes to a bound element's shadow content only affect that bound element. Other bindings are unaffected.
If an element is added to the DOM dynamically, its shadow scope is that
of its parent element. Adding an element as a child of a bound element
causes that element to be assigned to an appropriate content
element (if there is one — if
there is not, the element does not appear anywhere in the final flattened tree).
XBLContentElement
InterfaceThe XBLContentElement
interface is implemented by content
elements in the XBL namespace (regardless of whether they are in error or not).
interface XBLContentElement : Element { readonly attribute NodeList xblChildNodes; void setInsertionPoint(in Node child); };
xblChildNodes
of type
NodeList
, readonly
The xblChildNodes
attribute must return a NodeList
containing a live list
of all the nodes that are currently assigned to the content
element.
A node can be assigned to multiple content
elements simultaneously, in the
case of bound elements inside shadow trees.
Exception: if the content
element is not in a shadow tree, then this
attribute must return null.
setInsertionPoint
The setInsertionPoint
method perform the following steps.
content
element finds itself. If there
is no such bound element (e.g. the content
element has been removed from
its shadow tree), then the method must raise an
INVALID_STATE_ERR
exception.
HIERARCHY_REQUEST_ERR
exception.
content
element has no includes
attribute, or that child matches the selector
given in the content
element's
includes
attribute. If the attribute is
present but the element does not match the selector it specifies (or
if the selector is not syntactically correct), then the method must
raise an TYPE_MISMATCH_ERR
exception.content
element, instead of
whatever previous content
element it was assigned to, if any.
If a node is assigned, using the setInsertionPoint
method, to a
content
element that is not
locked, then the element will only remain there until such time as
the user agent redistributes the bound element's explicit children.
See processing content
elements.
The order of nodes assigned to a content
element is always be the same as
the relative order of those nodes in the original core DOM.
child
of type
Node
content
element.
The following example implements a tabbed interface as a binding.
It creates a list of buttons to enable the user to access each of
the sections that the tab box contains, and then uses setInsertionPoint()
to make the
selected tab panel appear.
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding> <template> <div id="tabs"/> <div class="panel"><content id="current" locked="true"/></div> <div class="hidden"><content id="not-current"/></div> </template> <implementation> ({ set current(section) { if (this._current) this.shadowTree.getElementById('not-current').setInsertionPoint(this._current); this._current = section; if (this._current) this.shadowTree.getElementById('current').setInsertionPoint(this._current); }, get current() { return this._current; }, xblBindingAttached: function() { this.updateTabs(); this.current = this.boundElement.getElementsByTagName('section')[0]; }, clearTabs: function() { with (this.shadowTree.getElementById('tabs')) while (hasChildNodes()) removeChild(firstChild); }, addTabFor: function(section) { var tab = document.createElementNS('http://www.w3.org/ns/xbl', 'div'); tab.appendChild(document.createTextNode(section.getAttribute('title'));); tab.addEventListener('click', function (_this) { return function (event) { var tabs = this.shadowTree.getElementByID('tabs').getElementsByTagName('div'); for (var i = 0; i < tabs.length; ++i) tabs[i].setAttribute('class', ''); _this.current = section; event.target.setAttribute('class', 'selected'); event.preventDefault(); } }(this), false); this.shadowTree.getElementById('tabs').appendChild(tab); }, updateTabs: function() { this.clearTabs(); var sections = this.boundElement.getElementsByTagName('section'); for (var i = 0; i < sections.length; ++i) this.addTabFor(sections[i]); }, }) </implementation> <resources> <style> #tabs > div { /* style for tabs */ } #tabs > div.selected { /* style for selected tab */ } .panel { /* style for panel */ } .hidden { display: none; } </style> </resources> </binding> </xbl>
This binding could be applied to any element that has
section
elements as children, each section
element having its title given in its title
attribute.
The binding implemented above doesn't dynamically update when the DOM is changed, a full implementation would probably want to listen to mutation events to catch attribute changes and insertions and removals of the panels.
XBLTemplateElement
InterfaceThe XBLTemplateElement
interface is implemented by template
elements that are in the XBL
namespace (regardless of whether they are in
error or not).
interface XBLTemplateElement : Element { Element getElementById(in DOMString elementId); };
getElementById
This method is modeled after the method of the same name
defined by [DOM3CORE] on the
Document
interface.
This method must return an Element
that has an ID
attribute with the given value, and that is a descendant of the
template
element on which it is
invoked. If more than one such element exists, which one is returned
is undefined. If no such element exists, this returns
null
.
Attributes with the name "ID" or "id" are not of type ID unless so defined. For example, attributes with the name "id" on elements that are from the XHTML, MathML and XBL namespaces are defined to be of type ID by their respective specifications.
elementId
of type
DOMString
id
value for an element.
Element
EventXBL
InterfaceObjects that implement the Event
interface must also
implement the EventXBL
interface. [DOM3EVENTS]
interface EventXBL { readonly attribute boolean trusted; };
The trusted
attribute must return true if the user agent dispatched the event (e.g.
in response to user action), and false otherwise (e.g. if an author
script dispatched a synthetic event). Events fired by the user agent in
response to untrusted events must themselves be untrusted.
Several features in XBL allow binding documents to be loaded.
When the specification says that a binding document must be loaded
unless it has already been loaded, then references to the same
binding document (even if they are somewhat indirect, for example via
HTTP redirects) must result in the same Document
instance
being reused, or shared.
To determine if two binding documents are the same, their final base URIs (after all redirects) are compared.
A binding document A contains a binding
element that refers to a second
binding document X. A new DOM Document
instance is created
to represent that instance and the relevant bindings are used.
Now assume RX is a resource that redirects to resource X using the
HTTP 301 redirection mechanism. A second binding
element in the binding document A
refers to resource RX. When that resource is being loaded, the redirect
to X would be discovered, and therefore instead of creating a new
Document
, the existing one is reused.
Such sharing of binding documents must be limited to binding documents loaded by a document, its binding documents, its scripts, and its style sheets. Nested documents and images do not share binding documents with each other or with their container document.
For example, if a document uses a binding document, and its style
sheets use that binding document, the same binding document instance
will be used for both cases. However, if that document contains an
iframe
whose document uses the same binding document, a new
instance will be used: the binding document instance from the outer
document is not reused.
Binding documents that are currently loading count as binding documents that are already loaded for the purposes of this reuse mechanism.
When the specification simply says that the external resource must be loaded, without giving any caveats regarding multiple accesses of the same resource, then each reference must instantiate a new unique copy of the document.
For example, two style
elements whose src
attributes point to the same style sheet
must create two different Stylesheet
instances, such that
mutating one does not affect the other.
Several XBL attributes are defined to contain URIs. All URIs may be relative. For relative URIs, the rules given in [XMLBASE] must be used to resolve the value to an absolute URI.
Scripts in XBL may be found in script
, implementation
, and handler
elements, or in resources that those
elements point to.
In the case of script
and implementation
elements, if a src
attribute is present then the contents of the element
must be ignored (even if fetching the specified URI
fails).
The rules for parsing the scripts are the same for all three elements, but depend on the scripting language specified by the author.
For non-XML languages, if the content is inline, UAs must concatenate all the textual contents of text and CDATA child nodes, and must ignore any other, non-text nodes (such as elements and comments) along with all their children. All descendant elements must be processed, though, according to their semantics, before the XBL script block itself is executed.
For example, in an XHTML-aware and ECMAScript-capable user agent, the
following ridiculous code would cause the alerts to appear in the order
One, Two, Three, and would set the test
property
in the binding document's global script scope to the string
"undefinedABC":
<xbl xmlns="http://www.w3.org/ns/xbl"> <!-- WARNING: THIS EXAMPLE IS NON-CONFORMING --> <script> alert('Two'); test += "B"; <script xmlns="http://www.w3.org/1999/xhtml"> alert('One'); test += "A"; </script> alert('Three'); test += "C"; </script> </xbl>
Authors must not ever consider doing this. The above is invalid.
For XML-based scripting languages, handling of unknown elements and other unexpected nodes must be defined by that language.
If the content is not inline, then when the element is evaluated, the
resource specified by the src
attribute must be
fetched. For script
elements, while
an external script is being fetched, any pending binding attachments from the same
binding document must block, as must the evaluation of any further
script
blocks. For implementation
elements, while the
external script is being fetched, the attachment of that binding must block. If the
file's Content-Type (or equivalent for non-HTTP protocols), if any, is
not of the type specified on the xbl
element, then the script must be ignored.
Otherwise, the contents of that file must be used directly, as specified
by the relevant language specification.
This section is only normative for implementations that support XForms.
It is theoretically possible to use XForms Actions as the scripting
language in XBL [XFORMS]. The MIME type that
indicates this scripting language is tentatively defined to be application/x-xforms-actions+xml
. XBL elements have
the following semantics when used with XForms Actions:
script
elements
xforms:action
elements
that trigger immediately upon being added to the document.
handler
elements
xforms:action
elements
that trigger when the appropriate event on the bound element is
detected.
implementation
elements
implementation
elements when the
script language is set to application/x-xforms-actions+xml
are in error and the UA must ignore them, by treating implementation
elements like
xforms:action
elements that are not bound to any event.
Each document that runs script (including bound documents and binding
documents) has a DocumentWindow
object, a
Window
object, a global script scope, and a security
context. In ECMAScript, the global script scope and the
Window
object are one and the same.
This above paragraph is a vague description of the Web's de-facto scripting model. This specification depends on that model, but it hasn't yet been specified in detail. This specification will be updated when a suitable description is available.
Script must always be executed in the context of the global script
scope of the document specified by the script's element's
ownerDocument
DOM attribute. This implies that scripts from
different bindings in the same binding document bound to different
elements in the same bound document share the same scripting scope. If
the bindings were defined in the document itself, then the scope is the
same scope as for that document.
A binding document must inherit the security context of the document to which it is bound, not the security context of the domain from which it was fetched.
Scripting and security contexts are (or will be) described in the HTML5 specification. [HTML5]
In binding documents, the location
and
history
properties of the Window
object, and
the location
and cookie
properties of the
DocumentWindow
object, must return null, and any methods
that are defined in terms of the browsing context's session history must
do nothing. [HTML5]
User agents should implement a security mechanism such as the proposed
<?access-control?>
PI to prevent unauthorized
cross-domain access. [ACCESSCONTROL]
XBL style
elements describe the
style sheets that apply to bindings.
If a style
element's src
attribute is present,
the contents of the element must be ignored (even if fetching the specified URI failed).
Otherwise, it is the element's contents that give the style sheet.
Wherever the style is found, the rules for parsing it are the same, but depend on the language specified by the author.
For non-XML styling languages, if the content is inline, UAs must concatenate all the textual contents of text and CDATA child nodes, and the UA must ignore any other, non-text nodes (such as elements and comments) along with all their children. All descendant elements must be processed, though, according to their semantics, before the XBL style block itself is parsed. A style element labeled as containing a style sheet in a non-XML language yet containing element nodes is in error.
For example, in an XHTML-aware and ECMAScript-capable user agent, the rather dubious code below would result in a binding that enclosed the bound element's children in a green box, not a red one:
<xbl xmlns="http://www.w3.org/ns/xbl"> <binding> <template> <div> <content/> </div> </template> <resources> <style id="test"> div { background: red; } <script xmlns="http://www.w3.org/1999/xhtml"> document.getElementById('test').firstChild.data = "div { background: green; }"; </script> <p xmlns="http://www.w3.org/1999/xhtml"> div { border: red solid; } This will either be ignored by the XBL user agent, or will cause it to abort all processing altogether, as this text node is not a child of the style element. </p> </style> </resources> </binding> </xbl>
For XML-based styling languages, handling of unknown elements and other unexpected nodes must be defined by that language.
If the content was in another resource, and the Content-Type (or
equivalent for non-HTTP protocols), if any, was of the type specified on
the xbl
element (or implied by its
absence), then the contents of that file must be used directly, as
specified by the relevant language specification. Otherwise, the style
element doesn't provide any styling. The
src
attribute must
only be examined once all of the element's children have been processed
(if any).
XBL attachment mechanisms use a URI to specify which binding to attach to the designated element.
For example:
my|foo { binding: url("http://www.example.org/bindings.xml#fooBinding"); }
This section defines how these URIs, which are used in the argument to
the addBinding()
method, and in
the value of the 'binding
' property, are to be interpreted.
The URI specifies a particular binding document (an XBL document or non-XBL document containing one or more XBL subtrees). The user agent must fetch this resource (unless it has already been loaded).
If the URI contains a fragment identifier, then it must be processed as
described in the relevant MIME type definition. The element targeted by
the fragment identifier must be a binding
element within an XBL subtree in the
specified document, and that element must be a direct child of an
xbl
element that does not itself have an
xbl
element as an ancestor; if these
conditions are not met then the URI is in error.
For example, if the binding document is sent as
application/xhtml+xml
, and the fragment identifier matches a
binding
element's id
attribute, then that is the
binding that is attached.
If there is no fragment identifier and the URI points to an XBL
document (not a non-XBL document) then the first
binding
element in the binding
document that is a child of the root xbl
element is selected. Otherwise, the URI does not point to a correct binding and is in
error.
When an attachment mechanism uses a URI that is in error (as per the last two paragraphs), then the user agent must act as if the attachment mechanism had not specified that binding.
Otherwise, the specified binding is attached to the element, as described for the relevant attachment mechanism.
This section is non-normative.
Element | Attributes | Content Model |
---|---|---|
xbl
| ||
binding
|
| |
implementation
|
| |
template
|
| |
content
|
| |
inherited
|
| |
div
|
| |
handlers
| ||
handler
|
| |
resources
| ||
style
|
| |
prefetch
| ||
script
|
|
This section is non-normative.
Event Name | Interface | Target when fired by UA | Bubbles? | Cancelable? | Default Action |
---|---|---|---|---|---|
xbl-bound
| Event
| Bound element | ✓ Bubbles | — | None |
xbl-bindings-are-ready
| Event
| Bound document's root element | ✓ Bubbles | — | None |
This section is non-normative.
The properties of the internal object are:
The methods that binding implementations can support are:
David Hyatt developed XBL 1.0 and provided guidance for the development of XBL 2.0.
The editor would like to thank Alex Danilo, Alex Vincent, Anne van Kesteren, Axel Hecht, Antoine Quint, Benjamin Smedberg, Bjoern Hoehrmann, Boris Zbarsky, Brendan Eich, Cameron McCormack, Chris Lilley, Christophe Jolif, Cyril Concolato, Darryl Fuller, David Håsäther, Dean Jackson, Jon Ferraiolo, Jonas Sicking, Karl Dubost, L. David Baron, Lachlan Hunt, Liam Quin, Marcos Caceres, Mark Baker, Micah Dubinko, Mihai Sucan, Mikko Pohja, Mohamed Zergaoui, Norman Walsh, Peter Sorotokin, Robin Berjon, Ruud Steltenpool, Sean Hogan, Simon Pieters, Steve K. Speicher, Steve Zilles, Tim Rowley, and Tom Pike for their contributions to this specification.
All references are normative unless prefixed by the mark "(Informative)".