Abstract
XBL (the Xenogamous Binding Language) describes the ability to
associate elements in a document with script, event handlers, CSS, and
more complex content models, which can be stored 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 be used to implement the
form controls in XForms or HTML.
Status of This
Document
Beware. This specification is no longer in active maintenance and the Web
Applications Working Group does not intend to maintain it further.
No browser vendor has plans to implement this specification at this
time. Unless you are interested in the history of the Web's component
model, this document is likely not of any use to you.
This section describes the status of this document at the time of
its publication. Other documents may supersede this document. A list of
current W3C publications and the latest revision of this technical report
can be found in the W3C technical reports
index at http://www.w3.org/TR/.
This document is the 24 May 2012 Working Group Note of XBL 2.0.
Publication as a Working Group Note does not imply endorsement by the W3C
Membership. This is a draft document and may be updated, replaced or
obsoleted by other documents at any time. It is inappropriate to cite this
document as other than work in progress.
The W3C Web Applications
Working Group is the W3C working group responsible for this document.
If you wish to make comments regarding this document, please send them
to dev-tech-xbl@mozilla.org
(subscribe,
archives)
or public-webapps@w3.org
(subscribe,
archives).
All feedback is welcome. The editor guarantees that all feedback sent to
the above lists will receive responses.
The editor's copy of this specification is available
in W3C CVS. A detailed
list of changes is available from the CVS server.
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 implementation 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.)
While the body of this specification was created outside the W3C, the
W3C Web Applications Working
Group is now guiding this specification along the W3C Recommendation
track.
This document was produced by a group operating under the 5 February
2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in
connection with the deliverables of the group; that page also includes
instructions for disclosing a patent. An individual who has actual
knowledge of a patent which the individual believes contains Essential
Claim(s) must disclose the information in accordance with section
6 of the W3C Patent Policy.
Table of Contents
1. Introduction
xe·nog·a·mous
adj. Of or relating to the fertilization of elements from
disparate trees.
This specification defines XBL (the Xenogamous 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.
<binding id="nav-then-main">
<template>
<style scoped>
#wrapper { display: table-row; }
#col1, #col2 { display: table-cell; }
</style>
<div id="wrapper">
<div id="col2"><content includes=".nav"></div>
<div id="col1"><content includes=".main"></div>
</div>
</template>
</binding>
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.xbl#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.
<binding element="details">
<template>
<style scoped>
#container[data-state=hidden] { display: none; }
</style>
<div>
<div><content includes="summary:first-child">Details...</content></div>
<div data-state="hidden" id="container"><content></content></div>
</div>
</template>
<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;
},
xblBindingAttached: function () {
this.addEventListener('click', function () { this.open = !this.open }, false);
this.addEventListener('DOMAttrModified', function (event) {
if (event.attrName = 'open') {
if (event.attrChange = MutationEvent.ADDITION) {
this.shadowTree.getElementById('container').dataset.state = 'visible';
} else if (event.attrChange = MutationEvent.REMOVAL) {
this.shadowTree.getElementById('container').dataset.state = 'hidden';
}
}
}, false);
},
})
</implementation>
</binding>
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.
1.1. Editor's note
This specification was updated (as of Septemebr 2010) to make the
following broad changes:
- Moving XBL to just be part of HTML, rather than having its own
namespace and requiring XML.
- Removing a number of features so as to reduce the initial
implementation burden:
handlers
(events forward to the internal object now, and that object
implements EventTarget
); style
and
script
are replaced by HTML equivalents;
prefetch
and handler
are removed altogether;
removed support for namespaces.
- Making
loadBindingDocument()
asynchronous.
- Adding an API to allow XBL to be manipulated from script.
This specification is not written in the strictest style; in many
places it is rather hand-wavy and fails to define things strictly (e.g.
in terms of event loops, WebIDL, and other such mechanisms that allow us
to define the Web platform strictly). If this update to XBL2 is more
successful than the previous draft, then it will likely be merged into
the HTML specification, and the processing models will be rewritten to be
much more well-defined. In particular, this will include making binding
get parsed in head
elements, and the syntax being updated to define that you can't use content
or inherited
in places that are handled
in an insertion mode other than "in body".
1.2. Relationship to
XBL1
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
.
1.3. Relationship to
XSLT
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.
1.4.
Terminology and Conventions
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 must
be the same as HTML: http://www.w3.org/1999/xhtml
The term binding document is used to
mean a Document
containing one or more binding
elements.
Here is a binding document. The
binding is highlighted.
<!DOCTYPE HTML>
<html>
<head>
<title>Demo</title>
<script>
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>
</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 fragment has a content
element that is in error because its includes
attribute has an invalid
selector:
<binding id="demo">
<template>
<content includes="@"></content>
</template>
</binding>
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.
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).
The HTML parser lowercases all elements and attribute names,
so it can appear like XBL is case-insensitive when used in HTML. However,
that's actually a feature of the HTML parser, not of XBL.
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]
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: binding documents, and XBL user agents.
Binding documents must satisfy the
constraints described in this specification in order to be considered
conformant.
Products that generate binding documents cannot claim conformance to
this specification, though they can claim to only produce binding
documents 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 content.
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.
1.5.1. Error Handling
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.
1.5.2.
Attributes
Containing Selectors
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 cannot be used with selectors in XBL, as there is no
way to declare the prefixes. The default namespace in selectors in XBL
attributes is always unbound.
The following fragment defines a binding that is bound to elements
declaring links (e.g. the a
element in HTML).
<binding element=":link, :visited">
...
</binding>
This example defines a binding that matches elements with the name
a
, regardless of what namespace they are in. This would
match both the HTML a
element and the SVG a
element.
<binding element="a">
...
</binding>
1.5.3.
Attributes Containing Space-Separated Values
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 attributes="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 "-".
1.5.4. Attributes Containing URIs
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]
1.5.5.
Attributes Containing Keywords
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.
1.6. Security Concerns
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 prevents this
by diallowing cross-origin bindings.
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
HTMLDocument
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.
2. XBL Elements
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 element and its descendants 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, 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 html url(http://www.w3.org/1999/xhtml);
html|binding, html|implementation, html|template, html|content, html|inherited { display: none; }
XBL user agents that do not support CSS should not render XBL elements.
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.
2.1. The binding
Element
- Expected context:
- Metadata content (e.g. an HTML
head
element)
- Expected children (in any order):
implementation
: zero or
one.
template
: 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.
Bindings can act as an attachment mechanism, specifying elements to
associate with the given binding when the binding is imported, using the element
attribute.
Attributes
- Global attributes
- Any of HTML's global attributes.
- extends
- The
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.
- element
-
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 div
elements
with the class "checkbox
" will be bound to.
<binding element="div.checkbox" id="checkbox"
extends="http://www.example.org/resources/ui-core.xml#valuedControl">
<template>
<style scoped>
#wrapper > div { display: inline-block; }
</style>
<div id="wrapper">
<div id="control"></div>
<div id="label"><content></content></div>
</div>
</template>
<implementation>
({ xblBindingAttached: function () {
this.addEventListener('click', function () {
if (this.baseBinding.value == 'on')
this.baseBinding.value = 'off';
else
this.baseBinding.value = 'on';
}, false);
this.addEventListener('change', function () {
if (this.baseBinding.value == 'on')
this.shadowTree.getElementById('control').textContent = '☑';
else
this.shadowTree.getElementById('control').textContent = '☐';
}, false);
} })
</implementation>
</binding>
2.2. The implementation
Element
- Expected context:
binding
- Expected children:
- If the element has no
src
attribute: JavaScript text.
- If the element does have a
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 JavaScript code, or have a src
attribute
that points to a JavaScript file. (See: binding implementations.)
Attributes
- Global attributes
- Any of HTML's global attributes.
- src
- The
src
attribute specifies the URI
to a JavaScript resource. 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 the implementation
element points (using the src
attribute) to a resource
that is unavailable, then it is in error and the
UA must ignore it, meaning it must not be used as
an implementation definition for any binding.
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: loading and running scripts, 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).
<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>
The following example shows how to refer to an external file for the
implementation of a binding. This is the same binding as the previous
example.
<binding element=".demo">
<implementation src="demo.js"></implementation>
</binding>
The demo.js
file would look like this:
({
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';
},
})
2.3. The template
Element
- Expected context:
binding
- Expected children:
- Anything. Of particular interest, the
content
and inherited
elements may occur as
descendants, and non-XBL descendant elements may host attributes
and pseudo
attributes.
The template
element
contains arbitrary element descendants. 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.)
Attributes
- Global attributes
- Any of HTML's global attributes.
- apply-author-sheets
- The
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
- The
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.
<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></content>
</div>
</div>
</div>
</div>
</template>
</binding>
Using this binding could take the following document:
<DOCTYPE HTML>
<html>
<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:
<DOCTYPE HTML>
<html>
<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.
2.4. The content
Element
- Expected context:
- Any, but there must be a correct
template
element somewhere in the
ancestor chain, and there must not be any content
elements anywhere in the
ancestor chain.
- Expected children:
- Anything.
Attributes
- Global attributes
- Any of HTML's global attributes.
- includes
- The
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
- The
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
- The
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.
<binding element=".grid">
<template>
<div class="caption" attributes="text=title"></div>
<div class="outer-table">
<div class="columns">
<content includes=".column">
<!-- default to have just one column if none are declared -->
<div class="column"></div>
</content>
</div>
<div class="rows">
<content includes=".heading"></content>
<div class="body">
<content includes=".row:not([hidden])"></content>
</div>
</div>
</div>
</template>
...
</binding>
The above template would be used with markup such as the following:
<div class=grid title="The Lesser of Two Evils">
<div class=column id="product" sort="alphabetic primary">
<div class=column id="catchphrase" sort="alphabetic secondary">
<div class=heading> <div class=item>Product<div> <div
class=item>Catchphrase<div> <div> <div class=row> <div
class=item>Arachno Spores<div> <div class=item>The fatal spore with
the funny name<div> <div> <div class=row> <div
class=item>Pastorama<div> <div class=item>Located on the former site
of Brooklyn<div> <div> <div>
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.
<binding element=".listbox">
<template allow-selectors-through="true">
<style scoped>
.listbox { display: block; background: white; color: black; }
.listbox > div#listbox-focus { border: ridge silver; }
.listbox:focus > div#listbox-focus { border: inset silver; }
.listitem { display: block; background: white; color: black; }
.listitem[data-selected] { display: block; background: navy; color: white;}
</style>
<div id="listbox-focus">
<content includes=".listitem" apply-binding-sheets="true"></content>
</div>
</template>
<implementation>
...
</implementation>
</binding>
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 li
elements would be placed in the
first content
element, but because it
is locked, they will instead go into the second one. (This example
assumes that there is also a binding for the "selectableList
" class that defines a .selectedElement
IDL attribute.)
<binding element="ul.split">
<template>
<div>
<ul id="left" title="Selected Items" class="selectableList">
<content includes="li" locked="true" id="leftList"></content>
</ul>
</div>
<div id="buttons">
<button id="move-right"> Move Right </button>
<button id="move-left"> Move Left </button>
</div>
<div>
<ul id="right" title="Available Items" class="selectableList">
<content includes="li" id="rightList"></content>
</ul>
</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>
2.5. The inherited
Element
- Expected context:
- Any, but there must be a correct
template
element somewhere in the
ancestor chain.
- Expected children:
- Anything.
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.)
Attributes
- Global attributes
- Any of HTML's global attributes.
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.
<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></inherited>
</div>
</div>
</div>
</div>
</template>
</binding>
2.6. The attributes
Attribute
- Expected element:
- Any, but there must be a correct
template
element somewhere in the
ancestor chain.
The attributes
attribute is a global
attribute 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 pairs of attribute names separated by equal signs, each possibly
suffixed by a hash character ("#") and a type designation. (See: attribute forwarding.)
The value of the attributes
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 attributes
attribute is to implement one
element in terms of another element which already has special behavior in
user agents. This example shows how an element can be implemented in
terms of an HTML input
element, with certain attributes
being forwarded to that element directly.
<binding element=".uitext">
<template>
<label>
<span attributes="*text=data-label"/>
<input attributes="value=data-default disabled=data-disabled readonly=data-readonly" id="input">
</label>
</template>
<implementation>
({
get value () { return this.shadowTree.getElementById('input').value; },
set value (val) { this.shadowTree.getElementById('input').value = val; },
})
</implementation>
</binding>
Here is how this binding could be used:
<div data-label="Location" data-default="County Down"></div>
Of course, it would be far more usable and accessible (not to mention
having better fallback when scripts are disabled) if the page just used
input
directly!
2.7. The pseudo
Attribute
- Expected element:
- Any, but there must be a correct
template
element somewhere in the
ancestor chain.
The pseudo
attribute is a global attribute 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 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 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.
<binding id="input-dialog">
<template>
<div class="root">
<div class="icon-block">
<img pseudo="icon" attributes="src=icon alt=alt">
</div>
<div pseudo="label" attributes="*text=label"></div
<div class="field-block">
<input pseudo="value" attributes="value" id="field">
</div>
<div class="buttons-block">
<button pseudo="choices" id="ok"> OK </button>
<button pseudo="choices" id="cancel"> Cancel </button>
</div>
</div>
</template>
...
</binding>
An author-level stylesheet for a document using the binding might look
like:
.textDialog { binding: url(dialogs.xbl#input-dialog); }
.textDialog::value { background: white; color: black; }
textDialog::choices { border: outset; }
3. Binding Attachment and
Detachment
Bindings can be attached and detached dynamically, using several
mechanisms.
Bindings must be attached as soon as the following conditions have all
been met:
- it is known that the binding applies to the element,
- the DOM
Element
object for the element has been created,
and
- the binding document defining the binding has loaded.
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.xbl
defines a binding that
applies to all "foo
" elements. The following script
uses loadBindingDocument()
to ensure that
foo.xbl
is loaded, then creates a foo
element and uses it.
// load the binding document
document.loadBindingDocument('foo.xbl').onload = function () {
// create an element <foo>
var foo = document.createElement('foo'); // binds synchronously
foo.myCustomMethod(); // calls the binding's implementation
};
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.)
3.1. The Bindings-Are-Ready State
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 document has finished parsing,
- the bindings-are-ready counter is
at zero,
- all bindings that are known to apply to elements have been completely
applied, and
- no scripts are running.
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.
3.2.
Attachment using <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.
3.2.1. Importing Binding
Documents
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.
A binding
element that defines a
binding is automatically imported in the element's owner document, so
such mappings are always used. The following example demonstrates this.
example.xml
<...>
<binding element="foo" xmlns="http://www.w3.org/1999/xhtml">
...
</binding>
<binding element="bar" xmlns="http://www.w3.org/1999/xhtml">
...
</binding>
<foo/> <!-- this will have a binding applied -->
<bar/> <!-- 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
<...>
<binding element="foo" xmlns="http://www.w3.org/1999/xhtml">
...
</binding>
<binding element="bar" xmlns="http://www.w3.org/1999/xhtml">
...
</binding>
</...>
example.xml
<?xbl href="widgets.xbl"?>
<...>
<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
<...>
<binding element="foo" xmlns="http://www.w3.org/1999/xhtml">
<content>
<bar xmlns=""/> <!-- not bound, not even when in shadow content -->
</content>
</binding>
</...>
bar.xml
<?xbl href="foo.xbl"?>
<...>
<binding element="bar" xmlns="http://www.w3.org/1999/xhtml">
<content>
<foo xmlns=""/> <!-- bound: this document imports foo.xml -->
<bar xmlns=""/> <!-- bound: bar binding is defined locally -->
</content>
</binding>
</...>
example.xml
<?xbl href="bar.xml"?>
<...>
<foo/> <!-- not bound: foo.xml not imported here -->
<bar/> <!-- bound -->
</...>
3.3. Attachment using
CSS
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 HTML checkbox elements.
input[type="checkbox"] {
binding: url("http://www.example.org/res/htmlBindings.xbl#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.
3.3.1. The 'binding
'
Property
A property to attach a binding to a particular element.
'binding
'
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
|
- none
- No bindings are to be attached through CSS.
- <uri>
- The specified binding is attached. More than one binding can be
specified, resulting in the bindings being attached in the specified
order, with the last binding implicitly inheriting from the previous one,
and so forth, up to the first binding. (See: binding inheritance.)
3.3.2. Processing Model
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.
3.3.3. Examples
The following fragment of XML 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.
<...>
<binding id="isosceles" xmlns="http://www.w3.org/1999/xhtml">
<template>
<polygon attributes="transform" points="0 -1, 1 0, -1 0" xmlns="http://www.w3.org/2000/svg"/>
</template>
</binding>
<binding id="rightangle" xmlns="http://www.w3.org/1999/xhtml">
<template>
<polygon attributes="transform" points="0 0, 1 0, 0 -1" xmlns="http://www.w3.org/2000/svg"/>
</template>
</binding>
</...>
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>
<binding id="isosceles" xmlns="http://www.w3.org/1999/xhtml">
<template>
<polygon attributes="transform" points="0 -1, 1 0, -1 0" xmlns="http://www.w3.org/2000/svg"/>
</template>
</binding xmlns="http://www.w3.org/1999/xhtml">
<binding id="rightangle">
<template>
<polygon attributes="transform" points="0 0, 1 0, 0 -1" xmlns="http://www.w3.org/2000/svg"/>
</template>
</binding>
<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>
3.4. Attachment
using the DOM
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.
var checkbox = document.getElementById("mycheckbox");
checkbox.addBinding("http://www.example.org/res/htmlBindings.xbl#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.
3.5. Binding Attachment Model
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.
- If the binding has an
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.)
- If the binding has a template, the binding's shadow tree must be
generated. This may cause other bindings to be applied synchronously, if
their binding documents are already loaded. (See: rules for shadow content
generation, binding
attachment and detachment.)
- If other bindings are already attached to the bound element, then the
newly added binding will add a new explicit inheritance chain to the
element's list of bindings (its implicit inheritance chain). (See:
implicit inheritance.)
- If the new binding has an implementation, it must be made available to
scripts. Language-specific constructors for the binding implementation
must run at this point. (See: binding
implementations.)
- Events must start being routed through the binding's internal object, when there is one. (See: event forwarding.)
- If the new binding changes which shadow trees contribute to the final flattened tree then the explicit children must be redistributed.
(See: processing
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.)
3.6.
Handling
Insertion and Removal from the Document
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).
3.7. Binding Inheritance
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.
3.7.1. Explicit Inheritance
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.
3.7.2. Implicit Inheritance
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 markup for the bindings 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.)
3.7.3.
Mixing Implicit and Explicit Inheritance
Consider the following completely useless but short bindings in in XML
file (called, for the sake of argument, "test.xml
"):
<html xmlns="http://www.w3.org/1999/xhtml">
<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>
</html>
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.
3.8.
Attachment During Document Load
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.
3.9. Binding Detachment Model
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.)
4. Shadow Content
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
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.
4.1.
Rules for Shadow
Content Generation
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 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.
4.2.
Rules for Shadow
Content Destruction
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).
The shadowTree
member of the internal object must be set to null.
4.3. Attribute Forwarding
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 attributes
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.
<binding id="fileUploadControl">
<template>
<input type="text" attributes="value"/>
<input type="button" value="Browse..."/>
</template>
</binding>
Each entry in the attributes
list can either simply list an
attribute name (a string, such as value
in the example above,
containing no spaces, colons, asterisks, or hash marks),
or it can specify an =
-separated pair of attribute names
(ditto), 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 attributes
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 attributes-item
production in the following ABNF:
attributes-item := attribute [ '=' attribute ] [ '#' type ]
attribute := *attribute-character / special-attribute
attribute-character := < any character but ':', '=', '#', or '*' >
special-attribute := '*text' / '*lang'
type := '#' ( 'url' / 'text' )
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 pseudo
and attributes
, if used such that they match
the attribute
production of the above ABNF, are in error and must be ignored.
4.3.1.
Forwarding to and from text nodes
The special value *text
can be used in
an =
-separated pair.
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 special value *lang
can also be used
in an =
-separated pair.
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 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 *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 attributes
attribute.
4.3.3. Error handling
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), and all the ones before the first are in
error.
4.3.4. Type specifiers
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.
- If the type is
url
- The value must be resolved to an absolute URI using the base URI of
the source element before being forwarded.
- If the type is
text
(default)
- The value is forwarded unchanged.
- If the type is any other value
- The attribute must not be forwarded. The value is in error and UAs must ignore
that value in the element's
attributes
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:
<template>
<>img attributes="src#url title alt=*text lang=*lang"/>
</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 *text
.
For accessibility reasons, the language of the element is also explicitly
forwarded.
4.3.5. Dynamic changes
The attributes
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 attributes
attribute change.
4.3.6.
How Attribute Forwarding Affects the Shadow Tree
The element to which the attributes are forwarded (that is, the element
with the attributes
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 attributes
attribute.
4.4. Processing content
Elements
A 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.
4.4.1. How Nodes
are Distributed
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 attributes
attribute that uses the *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 xmlns="http://example.com/"><A/></X>
Now, if the element X in that document is bound to a binding with the
following shadow tree template:
<template xmlns:T="http://example.com/">
<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:
- If the node is already assigned to a
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.
- Otherwise: if the node is already assigned to a
content
element for this binding,
unassign it.
- Let T be the shadow tree of the most derived
binding with a shadow tree for the bound element.
- If T contains a correct
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.
- Otherwise, if this binding has no correct
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.
- Otherwise, if the binding has a correct
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.
- Otherwise, let T be the shadow tree of the next most derived binding with a shadow
tree and return to step 4.
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 xmlns="http://example.com/"><A/><B/><C/></X>
Imagine that the element X in that document is bound to a binding with
the following shadow tree template:
<template xmlns:my="http://example.com/">
<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 xmlns:my="http://example.com/">
<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.
4.4.2. When
Nodes Are Redistributed
The algorithm described in the previous section is applied when:
Consider the following binding shadow tree:
<template>
<div>As: <content includes="A, AA"></content></div>
<div>Other: <content></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.
4.5. The Final Flattened Tree
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:
- Rendering
- Rendering must be performed using the final flattened tree. Nodes that
do not appear in the final flattened tree must not be rendered. (See: CSS property inheritance
and rendering.)
- Event dispatch
- Events flow along the final flattened tree. (See: event flow and
targeting across shadow scopes.)
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:
- If the bound element has no shadow trees, move on to the next bound
element.
- Otherwise, replace the child nodes of the bound element with the child
nodes of the most derived shadow tree's root
template
element.
- For any element in the shadow tree that has an
attributes
attribute that uses the *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 *text
value will be in
error.)
- Replace any
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.
- Replace the second and subsequent
inherited
elements in the shadow tree
with their child nodes.
- Replace the first
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.
- If the previous step added a shadow tree to the flattened tree, then
return to step 3 to deal with that newly added shadow tree. Otherwise,
move on to the next bound element.
Imagine the following document fragment:
...
<my:A xmlns:my="http://example.com/">
<my:B>
<my:C/>
<my:D/>
</my:B>
</my:A>
...
...is bound to the following XBL:
...
<binding element="B" xmlns="http://www.w3.org/1999/xhtml">
<template xmlns:my="http://example.com/">
<my:P>
<my:Q>
<content includes="C">
<my:R/>
</content>
<my:/Q>
<content includes="D">
<my:S/>
</content>
<my:/P>
</template>
</binding>
<binding element="Q">
<template>
<my:X>
<my:Y>
<content>
<my:Z1/>
</content>
<content>
<my:Z2/>
</content>
<my:/Y>
<my:/X>
</template>
</binding>
...
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#
4.5.1. Terminology
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.
4.6. Handling DOM Changes
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.
4.7. Shadow Content
and CSS
4.7.1. Selectors and Shadow Scopes
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.
- A>B
-
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.
- A B
- Matches "
B
" if either "A>B
" matches
"B
", or "C>B
" matches "B
" and
"A C
" matches "C
".
- A+B
- If "
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
".
- A~B
- Matches "
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>
<p>...</p>
<content includes="p"><p>...</p></content>
<p>...</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 div
elements
in the following example:
<template>
<div></div>
<content></content>
<div></div>
</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).
4.7.2.
CSS Property
Inheritance and Rendering
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.
The :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:
<binding>
<template>
<style scoped>
:bound-element > * { border: solid; }
</style>
<content allow-selectors-through="true"></content>
</template>
</binding>
4.7.4. Matching Pseudo-Elements
Shadow nodes may be associated with various pre-defined pseudo-elements of the
bound element. On any element in the shadow content template, an 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.
<binding id="fileUploadControl">
<template>
<input type="text" pseudo="value"/>
<input type="button" value="Browse..."/>
</template>
</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:
- ::value
- Intended to represent the entire rectangular 'interactive area' (or
the nearest equivalent in non-visual environments) of a text-entry form
control, specifically excluding the caption.
- ::choices
- Intended to represent the entire rectangular 'selection area' (or the
nearest equivalent in non-visual environments) of a list form control,
specifically excluding the caption.
- ::label
- Intended to represent the non-interactive area (or the nearest
equivalent in non-visual environments) of control, typically the caption.
- ::repeat-item
- Within a repeating sequence, each repeated item could be labeled as
matching a pseudo-element ::repeat-item.
- ::icon
- Intended to represent the icon part of a control, for example the
picture in a toolbar button or the icon next to a menu item.
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.
<binding id="imageButton">
<template>
<span pseudo="icon"></span>
<span attributes="*text=title"></span>
</template>
</binding>
This control could then be used like this:
<button title="Save" class="save-button"/>
...and styled like this:
button { binding: url(buttons.xbl#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]
4.8. Shadow
Content and 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
.
4.9. Shadow Content and
Other Things
4.9.1. General Rules
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 ...>
<img src="..." usemap="#test" alt="...">
</template>
If the binding is applied to an element in a document containing a
map
element with ID "test", that image map will not be
associated with this image. If the binding document itself contains a
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 ...>
<img src="..." usemap="#test" alt="...">
<map id="test"> ... </map>
</template>
...then the img
element would always be attached to that
map
element, regardless of the existence of other
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., HTML 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".
4.9.2. Style Blocks
The semantics of style
elements (absent their scope
attribute) is that they introduce new
styles for their document. Since the document, in the case of anything in
a shadow tree, is the binding document, 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 style
blocks in binding documents (without a
scope
attribute) 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.
The style
element is used with its scope
attribute as a child of a template
to provide styles for bindings,
leveraging HTML's intrinsic semantics.
4.9.3. Script Blocks
Script elements, such as the HTML script
element 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 binding
document, and not during binding attachment.
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 below 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>
<style scoped>
.header { font-size: larger; }
.form { height: 15em; overflow: scroll; }
</style>
<div>
<div class="header">Form:</div>
<div class="form"><content></content></div>
</div>
<div>
<div class="header">Help:</div>
<div id="help"></div>
</div>
</template>
<implementation>
({ xblBindingAttached: function () {
this.addEventListener('focus', function (event) {
this.shadowTree.getElementById('help').textContent = event.target.getAttribute('title');
}, false);
},
})
</implementation>
</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>
<style scoped> ... </style>
<div class="header">
<div class="title"><content includes=":bound-element > h2:first-of-type"></content></div>
<div class="tagline"><content includes=":bound-element > h2:first-of-type ~ p:first-of-type"></content></div>
</div>
<div>
<div class="panel"><content locked="true" id="current"></content></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"></content></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>
</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.
4.9.5. SVG
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:
- Let element be the animation element.
- If element has no parent element, then the
animation element is not associated with any element. Stop these steps.
- Let parent be the parent element of element.
- If parent is a
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.
- Otherwise, parent is the element to which the
animation element is assigned.
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>
<html:binding element="world" xmlns:b="http://www.w3.org/1999/xhtml">
<html:template>
<tspan attributes="*text=data"/> World
<animateColor attributeName="fill" from="rgb(0,0,255)" to="rgb(128,0,0)" begin="0s" dur="6s" fill="freeze" />
</html:template>
</html:binding>
</defs>
<text y="50" font-size="12">
Hello <world xmlns="" data="Cruel"/>
</text>
</svg>
4.10. Binding Style Sheets
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.
4.10.1. Summary of styling
rules
This section is non-normative.
The <style>
element, with its scope
attribute, is applied to the bound
element and the shadow content that was generated by the binding. Its
styles are 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 pseudo
attribute, as long as it matches them
with pseudo-elements (irrespective of the apply-author-sheets
setting).
5. Binding Implementations
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.
In general, 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.)
All 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:
- When the bound element, or one of its ancestors, or one of the
elements in a higher shadow scope, is inserted into the document.
- When the binding is originally attached, if the bound element is
already in the document.
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.
<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>
The 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.
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.
5.3.
Accessing Binding Implementations
Script can access binding implementations directly using the xblImplementations
member. In
addition, 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.
5.4. Creation
of Implementations
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, and if
the binding
element does not have
an implementation prototype object, then:
- The first
implementation
element child of the binding
element must have its code compiled and run (see below).
- The return value of that script, if it is an object, must be forever
associated with that
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
- This field's value must be set to a reference to the external
object.
boundElement
- This field's value must be set to a reference of the node object
that is the bound element.
shadowTree
- This field's value must be initially set to null. Its value is
changed during shadow content
generation and destruction.
baseBinding
- If the binding's
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.
It must also implement the EventTarget
interface.
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.
5.4.1. Compiling Bindings
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.
5.4.2.
Invoking Methods on an Implementation Object
When function code of an implementation object 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.
6. Event Handlers
6.1. Event Forwarding
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 internal object.
When events are forwarded in this manner, the event handlers attached to
the internal object 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.
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 (here an XML document) is:
<hotspot message="Hello World">
<instruction> Activate this text. </instruction>
</hotspot>
The binding is:
<binding element="hotspot">
<implementation>
({ xblBindingAttached: function () {
this.addEventListener('click', function (event) {
alert(event.currentTarget.getAttribute('message'));
}, false);
}})
</implementation>
</binding>
Note that the event object passed to the event handlers on the internal object 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.
6.2.
Event Flow and
Targeting Across Shadow Scopes
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 internal object, 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:
- The capture listeners on
root
. Capture phase, target is
bound
.
- The capture listeners on the binding's internal object. Capture phase, target is
target
.
- The capture listeners on
shadow
. Capture phase, target
is target
.
- The bubbling listeners on
target
. Target phase, target
is target
.
- The bubbling listeners on
shadow
. Bubbling phase, target
is target
.
- The bubbling listeners on the binding's internal object. Bubbling phase, target is
target
.
- The bubbling listeners on
bound
. Target phase, target is
bound
.
- The bubbling listeners on
root
. Bubbling phase, target
is bound
.
- The default action listeners on the binding's internal object. Default phase, target is
target
.
- The UA's default action listeners for
target
. Default
phase, target is target
.
6.3. The Default Phase
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 internal objects 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.
6.4.
The focus
, DOMFocusIn
, blur
,
and DOMFocusOut
Events
If 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.
6.5. The
mouseover
and mouseout
Events
Mouseover 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.
7. DOM Interfaces
XBL introduces a few XBL-specific interfaces.
The 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.
- IDL Definition
-
interface DocumentXBL {
readonly attribute NamedNodeMap bindingDocuments;
Document loadBindingDocument(in DOMString documentURI);
};
- Attributes
-
bindingDocuments
of type NamedNodeMap
, readonly
- The
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.
- Methods
-
loadBindingDocument
-
The loadBindingDocument
method must return the Document
object corresponding to
the binding document that has been created for the given URL (creating
the Document
object and kicking off the load if
necessary). (See: binding attachment and
detachment.) Any bindings defined by that document must be applied
to matching elements in the document that corresponds to this DocumentXBL
object once the
document and its subresources are loaded (just before the load
event is fired on the
Document
object).
- Parameters
-
documentURI
of type DOMString
- The URI of a binding
document.
- Return Value
-
Document
- The return value of
loadBindingDocument()
is the Document
object of the binding document that
was or will be loaded.
- No Exceptions
The 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.
- IDL Definition
-
interface ElementXBL {
readonly attribute XBLImplementationList xblImplementations;
void addBinding(in DOMString bindingURI);
void removeBinding(in DOMString bindingURI);
boolean hasBinding(in DOMString bindingURI);
};
- Attributes
-
xblImplementations
of
type XBLImplementationList
,
readonly
- See binding implementations.
- Methods
-
addBinding
- The
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.
- Parameters
-
bindingURI
of type
DOMString
- A URI that specifies
the location of a specific binding to attach.
- No Return Value
- No Exceptions
removeBinding
- The
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.
- Parameters
-
bindingURI
of type
DOMString
- A URI that specifies
the location of a specific binding to detach.
- No Return Value
- No Exceptions
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).
- Parameters
-
bindingURI
of type
DOMString
- A URI that specifies
the location of a specific binding for which to look.
- Returns
-
boolean
true
if any of the bindings match the parameter,
false
otherwise.
- No Exceptions
7.2.1.
Scoping and Access Using the DOM
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, attributes
attributes being attached and
modified, etc) must immediately cause the final flattened tree to be updated.
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).
The XBLContentElement
interface is implemented by content
elements in the XBL namespace (regardless of whether they are in error or not).
- IDL Definition
-
interface XBLContentElement : Element {
readonly attribute NodeList xblChildNodes;
void setInsertionPoint(in Node child);
};
- Attributes
-
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.
- Methods
-
setInsertionPoint
-
The setInsertionPoint
method perform the following steps.
- Let e be the bound element for which the user
agent generated the shadow tree in which the given
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.
- Let child be the node that was given as an
argument to the method.
- The user agent must then check that the parent of child is in fact e. If it is not,
then the method must raise an
HIERARCHY_REQUEST_ERR
exception.
- The user agent must then check that either the
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.
- Finally, the user agent must assign child to
the
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.
- Parameters
-
child
of type
Node
- The child of the bound element to assign to this
content
element.
- No Return Value
- No Exceptions
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.
<binding>
<template>
<style scoped>
#tabs > div { /* style for tabs */ }
#tabs > div.selected { /* style for selected tab */ }
.panel { /* style for panel */ }
.hidden { display: none; }
</style>
<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.createElement('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>
</binding>
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.
The HTMLTemplateElement
interface is implemented by template
elements that are in the XBL namespace (regardless of whether they are in error or not).
- IDL Definition
-
interface HTMLTemplateElement : HTMLElement {
Element getElementById(in DOMString elementId);
};
- Attributes
- No Attributes
- Methods
-
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.
- Parameters
-
elementId
of type
DOMString
- The unique
id
value for an element.
- Returns
-
Element
- The matching element or null if there is none.
- No Exceptions
XBL binding
elements must implement
the following interface:
[NamedConstructor=Binding(in optional DOMString selector)]
interface HTMLBindingElement : HTMLElement {
HTMLTemplateElement getTemplate();
void setImplementation(in Object implementationPrototypeObject);
void addToDocument();
};
The Binding(selector)
constructor must create a binding
element. If there is an
argument, then the element's element
attribute must be set to
that argument's value.
The getTemplate
method must
first check to see if the binding
element has a template
element child;
if it does not, then one must be created and appended as a child of the
element. Then, the method must return the first template
element child of the binding
element.
The setImplementation(implementationPrototypeObject)
method must
first check to see if the element has an implementation prototype
object set. If it does (even if it is null), then the method must
raise an INVALID_STATE_ERR
exception. Otherwise, it must set
the element's implementation prototype object's to implementationPrototypeObject.
The addToDocument()
method
must append the element to the first head
element in the
document, if any, or else the element's root element, if any, or else the
Document
object itself (as the root element).
This interface lets you implement a binding purely from script:
var fancyHeader = new Binding('h1');
fancyHeader.getTemplate().innerHTML = '☺ <content></content> ☺';
fancyHeader.setImplementation({
xblBindingAttached: function () {
this.addEventListener('click', this.clicked, false);
},
clicked: function(event) {
alert('Hello!');
},
});
fancyHeader.addToDocument();
This would be equivalent to the following markup:
<binding element="h1">
<template>☺ <content></content> ☺</template>
<implementation>
({
xblBindingAttached: function () {
this.addEventListener('click', this.clicked, false);
},
clicked: function(event) {
alert('Hello!');
},
})
</implementation>
</binding>
7.6. The EventXBL
Interface
Objects that implement the Event
interface must also
implement the EventXBL
interface. [DOM3EVENTS]
- IDL Definition
-
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.
8. Resources
8.1. Loading External Resources
8.1.1. Binding Documents
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.
References to binding documents that have another origin than the
aspiring bound document must be treated as being in
error, failing as if it was not available.
8.1.2. External
Resources
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.
8.2. Loading and Running Scripts
Scripts in XBL may be found in implementation
elements, or in
resources that such elements point to.
For implementation
elements, if a
src
attribute is present then the contents of the
element must be ignored (even if fetching the
specified URI fails).
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.
If the content is not inline, then when the element is evaluated, the
resource specified by the src
attribute must be
fetched. For implementation
elements, while the external script is being fetched, the attachment of that binding must
block. The contents of that file must be used directly, as specified by
the ECMAScript language specification.
8.2.1. Scripting Model
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.
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.
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]
8.3.
Interpretation of
URIs to XBL bindings
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 HTML or XML document. 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 in the specified
document, otherwise 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, 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.
9. Summaries of Elements,
Attributes, and Events
9.1. Elements and
Attributes
This section is non-normative.
9.2. Events
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
|
9.3. Implementations
This section is non-normative.
The properties of the internal object
are:
The methods that binding implementations can support are:
Acknowledgments
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 Russell, 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, Dimitri Glazkov, Jon Ferraiolo, Jonas
Sicking, Karl Dubost, L. David Baron, Lachlan Hunt, Liam Quin, Maciej
Stachowiak, Marcos Caceres, Mark Baker, Micah Dubinko, Mihai Sucan, Mikko
Pohja, Mohamed Zergaoui, Norman Walsh, Peter Sorotokin, Robin Berjon, Ruud
Steltenpool, Sam Weinig, Sean Hogan, Simon Pieters, Steve K. Speicher,
Steve Zilles, Tab Atkins, Tim Rowley, and Tom Pike for their contributions
to this specification.
References
All references are normative unless prefixed by the mark
"(Informative)".
- [CSS21]
- CSS 2.1
Specification, B. Bos, T. Çelik, I. Hickson, H. Lie.
W3C.
- [CSS3UI]
-
CSS Basic User Interface Module Level 3, T. Çelik. W3C.
- [DOM3CORE]
- Document
Object Model (DOM) Level 3 Core Specification, A. Le Hors, P.
Le Hégaret, L. Wood, G. Nicol, J. Robie, M. Champion, S. Byrne.
W3C, November 2003. The latest version of the DOM Level 3 Core
specification is available at http://www.w3.org/TR/DOM-Level-3-Core/
- [DOM3EVENTS]
- Document
Object Model (DOM) Level 3 Events Specification, P. Le
Hégaret, T. Pixley. W3C, November 2003. (Note: Despite its
non-normative status on the W3C Recommendation track, this specification
should be considered normative for the purposes of conformance.) The
latest version of the DOM Level 3 Events specification is available at http://www.w3.org/TR/DOM-Level-3-Events/
- [ECMA262]
- ECMAScript
Language Specification, Third Edition. ECMA, December 1999.
This version of the ECMAScript Language is available at
http://www.ecma-international.org/publications/standards/Ecma-262.htm
- (Informative) ECMAScript
Language Specification, Fourth Edition (Incomplete Draft
Proposal). ECMA, January 2006. This version of the ECMAScript Language is
available at http://developer.mozilla.org/es4/spec/spec.html
- [HTC]
- (Informative) HTML
Components, C. Wilson. Microsoft, September 1998. The HTML
Components submission is available at
http://www.w3.org/TR/1998/NOTE-HTMLComponents-19981023
- [HTML5]
- (Informative) HTML5, I. Hickson. W3C.
- [MQ]
- Media
Queries, F. Rivoal. W3C.
- [RFC2045]
- Multipurpose Internet
Mail Extensions (MIME) Part One: Format of Internet Message
Bodies, N. Freed, N. Borenstein. IETF, November 1996. RFC 2045
is available at http://www.ietf.org/rfc/rfc2045
- [RFC2119]
- Key words for use
in RFCs to Indicate Requirement Levels, S. Bradner. IETF,
March 1997. RFC 2119 is available at http://www.ietf.org/rfc/rfc2119.txt
- [RFC3986]
- Uniform Resource
Identifier (URI): Generic Syntax, T. Berners-Lee, R. Fielding,
L. Masinter. IETF, January 2005. RFC 3986 is available at
http://www.ietf.org/rfc/rfc3986
- [RFC3987]
- Internationalized
Resource Identifiers (IRIs), M. Dürst, M. Suignard. IETF,
January 2005. RFC 3987 is available at http://www.ietf.org/rfc/rfc3987
- [SELECTORS]
- Selectors Level 3,
T. Çelik, E. Etemad, D. Glazman, I. Hickson, P. Linss, J. Williams. W3C.
- [UNICODE]
- The
Unicode Standard, Version 5.0.0, The Unicode Consortium.
Boston, MA, Addison-Wesley, November 2006. ISBN
0-321-48091-0.
The latest version of the Unicode specification is available at http://www.unicode.org/versions/
- [XBL10]
- (Informative) XML Binding
Language, D. Hyatt. Mozilla, February 2001. The XBL submission
is available at http://www.w3.org/TR/2001/NOTE-xbl-20010223/
- (Informative) XML Binding
Language, D. Hyatt. Mozilla, November 2000 (and subsequently
edited by other contributors). The XBL 1.0 specification is available at
http://www.mozilla.org/projects/xbl/xbl.html
- [XML]
- Extensible
Markup Language (XML) 1.0 (Fourth Edition), T. Bray, J. Paoli,
C. Sperberg-McQueen, E. Maler, F. Yergeau. W3C, September 2006. The
latest version of the XML specification is available at http://www.w3.org/TR/REC-xml/
- [XMLBASE]
- XML
Base, J. Marsh. W3C, June 2001. The latest version of the XML
Base specification is available at http://www.w3.org/TR/xmlbase/
- [XMLNS]
- Namespaces in
XML (Second Edition), T. Bray, D. Hollander, A. Layman, R.
Tobin. W3C, August 2006. The latest version of the Namespaces in XML
specification is available at http://www.w3.org/TR/REC-xml-names/
- [XMLSSPI]
- Associating
Style Sheets with XML documents, J. Clark. W3C, June 1999. The
latest version of the Associating Style Sheets with XML documents
specification is available at http://www.w3.org/TR/xml-stylesheet/