This working draft describes the ability to map elements to
script, event handlers, CSS, and more complex content models. This
can be used, for instance, to define custom XML vocabularies (tag
sets) in terms of SVG elements, or to re-order and wrap content so
that, for instance, simple HTML or XHTML markup can have complex CSS
styles applied without requiring that the markup be polluted with
multiple semantically neutral div
elements.
It can also be used to implement new DOM interfaces, and, in conjunction with other specifications, enables arbitrary tag sets to be implemented as widgets. For example, XBL could in theory be used to implement XForms.
This is not yet a W3C Working Draft. It is just a draft proposal.
@@XXX this section to be filled in before official publication
This specification defines the XML Binding Language and some supporting DOM interfaces and CSS features. XBL is a mechanism for overriding the standard presentation and interactive behavior of particular elements with a "binding". Bindings can be attached to elements using either cascading stylesheets, the document object model, or by declaring, in XBL, that a particular element in a particular namespace is 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, properties and fields that become accessible from the bound element, shadow content that is inserted underneath the bound element, and associated resources such as scoped stylesheets and precached images, sounds, or videos.
XBL cannot be used to give a document new semantics (except if script invoked by XBL explicitly changes the original DOM). The meaning of a document is not changed by any bindings that are associated with it, only its presentation and interactive behavior.
The following is a simple SVG example where a custom element
(<myNS:HelloWorld/>
) acquires the alternate
presentation behavior defined by the <xbl:definition> element
at the top of the file. The <myNS:HelloWorld/>
element will be rendered by using the contents of the shadow tree
which is attached by the binding. The shadow tree consists of an
<svg:text>
element which has the string "Hello,
world, using sXBL" inside:
<?xml version="1.0"?> <svg width="10cm" height="3cm" viewBox="0 0 200 60" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl" xmsns:myNS="http://www.example.com"> <title>Example xbl01.svg - "hello world" sample file</title> <desc>A simple "Hello, world" sXBL example where the rendering behavior of a custom element 'myNS:HelloWorld' consists of an 'svg:text' element which has the string "Hello, world, using sXBL" inside.</desc> <defs> <xbl:xbl> <!-- The following 'xbl:definition' element defines the presentation and interactive behavior that must be used for all 'myNS:HelloWorld' elements in this document. --> <xbl:definition element="myNS:HelloWorld> <xbl:template> <text>Hello, world, using sXBL</text> </xbl:template> </xbl:definition> </xbl:xbl> </defs> <rect x="1" y="1" width="198" height="58" fill="none" stroke="blue"/> <g font-size="14" font-family="Verdana" transform="translate(10,35)"> <!-- Here is an instance of an 'myNS:HelloWorld' element. The above binding definition attaches a shadow tree which defines alternative rendering and interactive behavior for this element. Instead of the standard SVG behavior where unknown elements are not rendered, the binding definition causes an 'svg:text' element to be rendered. --> <myNS:HelloWorld/> </g> </svg>
The above example results in equivalent rendering to the
following SVG. The highlighted sections below (i.e., the <g>
and <text>
elements) represent the shadow tree
which the binding definition (i.e., the <xbl:definition>
element defined above)
attaches to the custom element. The SVG user agent renders the
shadow tree in place of the custom element.
<svg width="10cm" height="3cm" viewBox="0 0 200 60" xmlns="http://www.w3.org/2000/svg" version="1.2"> <title>Example xbl01-equivalent.svg - equivalent rendering for "hello world" sample file</title> <rect x="1" y="1" width="198" height="58" fill="none" stroke="blue"/> <g font-size="14" font-family="Verdana" transform="translate(10,35)"> <!-- The document is rendered as if the 'myNS:HelloWorld' element were replaced by an SVG 'g' element with a 'text' element inside. --> <g> <text>Hello, world, using sXBL</text> </g> </g> </svg>
Other examples can be found in the Examples section.
This specification is the culmination of several years of work by several groups.
A binding is the definition of behavior that can be applied to an element so as to augment its presentation.
An XBL subtree is a subtree in an XML
document (an XML instance), the
subtree having as its root node
an xbl
element in the XBL namespace, which is used to
define bindings. XBL subtrees can stand alone in XBL documents, or can be included in
compound documents.
An XBL document is an XML document that has the
xbl
element at its root.
A compound document is an XML document that contains elements from multiple namespaces, with its root element being from a document language (not XBL), such as XHTML, SVG, or SMIL.
The term binding document is used to mean either an XBL document or a compound document containing XBL subtrees.
A bound element is an element in an arbitrary XML namespace, or in an HTML document, to which a binding has been applied.
A bound document is an XML or HTML document containing one or more bound elements.
The shadow tree for a bound element is the subtree of
nodes that are attached to a bound element as a result of XBL
processing. (See: shadow content.) The contents of the
shadow tree augment the bound element's standard presentation and
interactive behavior with alternate behavior. The shadow tree is
hidden from normal DOM processing (hence the name "shadow"). The
shadow tree is attached to the bound element. Once attached, the
shadow tree can be accessed only via XBL-specific DOM extensions and
therefore is not accessible via Core DOM navigation facilities such
as firstChild
or nextSibling
. (See: DOM
interfaces.)
The term shadow content refers to the various nodes in the shadow tree of a bound element. Shadow content is created by cloning a shadow content template during binding attachment. (See: shadow content.)
In this specification, the term in error, when used of an element or attribute, means that the element or attribute is not conformant according to the rules of this specification. Rules for exactly how an element or attribute 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. 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.
A correct element or attribute is one which is not in error.
The namespace of all the XBL elements and
XBL global attributes must be: http://www.w3.org/2004/xbl
XBL elements are frequently referred to by just their local name in this specification. In real documents, they must be associated with the XBL namespace as per the rules given in the Namespaces in XML specification [XMLNS].
For convenience, elements and attributes from specific namespaces
are sometimes referred to simply in the form
prefix:localname
, without explicitly stating which
namespace the prefix is bound to. When this occurs, readers should
assume the following prefix declarations are in scope:
xmlns:xbl="http://www.w3.org/2004/xbl" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/1999/xhtml"
All element names, attribute names, and attribute values in XBL are case sensitive.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. For readability, these words are not capitalised in this specification.
All sections of this specification including the introduction and the schema snippets are normative unless they explicitly state otherwise. Errata are also normative but override conflicting parts of the specification.
XBL subtrees must satisfy the constraints described in this specification.
XBL user agent implementations must behave as described by this specification, even when faced with non-conformant XBL subtrees.
JF has a pending action item to propose text for this section (minutes, member only) to point to 17.1 Externally referenced documents.
Several features in XBL allow external resources to be loaded.
When the specification says that the resource must be loaded unless it has already been loaded, then references to the same resource (even if they are somewhat indirect, for example via HTTP redirects) must result in the same instance being reused, or shared. To determine if two resources are the same, their final base URIs (after all redirects) are compared.
Assume RX is a resource that redirects to resource X using the
HTTP 301 redirection mechanism. A document contains an
import
element that refers to binding document X. A
new DOM Document
instance is created to represent that
instance and the relevant bindings are used. The binding document
(X) itself then refers to resource RX. While that resource was
being loaded, the redirect to X would be discovered, and therefore
instead of creating a new Document
, the existing one
would be reused.
Such resource sharing is limited to resources loaded by a document, and the resources loaded by already-loaded-shared-resources for that document. Can we phrase that better? The idea is that two IFRAMEs whose documents use the same resource should NOT share that resource. We may also want to be explicit than resources that are currently loading count as resources that are already loaded...
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 stylesheet 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.
The start of any XBL subtree is an xbl
element,
which is described below.
When an XBL element is found inside an element other than that listed as its "Expected context", it is in error. When an XBL element has a child node that does not satisfy the "Expected children" list in its definition (for instance because it is the wrong node type, wrong element type, or because too many elements of its type preceded it), the child is in error. In both cases, being in error means that the UA must, for the purposes of XBL evaluation, treat the XBL subtree as it would if the erroneous node and all its descendants were absent.
However, non-XBL elements retain their semantics, even when considered to be in error for the purposes of XBL.
For cases where unexpected attributes are found on XBL elements, or XBL attributes are found on elements other than those listed as the "Expected context", 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 unexpected attributes in no way affects the XBL processing.
Further error handling rules for more specific cases are given where appropriate.
<element name='xbl'> <zeroOrMore><ref name='definition'/></zeroOrMore> <zeroOrMore><ref name='import'/></zeroOrMore> <zeroOrMore><ref name='script'/></zeroOrMore> <ref name='id.attrib'/> </element>
xbl
element as a child.definition
: zero or more.import
: zero or more.script
: zero or more.The xbl
element is the root element
of all XBL subtrees.
The following example shows an SVG example with an xbl
element which contains two binding
definitions. It also shows an example of an svg:defs
element.
<svg:svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2"> <xbl xmlns="http://www.w3.org/2004/xbl"> <svg:defs> <!-- possible definitions of SVG gradients, filters, etc. that might be referenced from the binding definitions. -- > </svg:defs> <definition id="binding1" element="example"> ... </definition> <definition id="binding2"> ... </definition> <script> ... </script> </xbl> </svg:svg>
id
attribute.script-type
attribute specifies the
MIME type of the scripting language used by all bindings and XBL script
blocks in the XBL subtree. If the attribute is not specified, the
default language is ECMAScript. [ECMA262]style-type
attribute specifies
the MIME type of the styling language used by all bindings and XBL
style blocks in the XBL subtree. If the attribute is not specified,
the default language is CSS (text/css
).XBL user agents should act as if they had the following rules in their UA stylesheet:
@namespace xbl url(http://www.w3.org/2004/xbl); xbl|xbl:not(:root) { display: none; }
That is to say, they should hide XBL subtrees in compound documents.
UAs must consider any xbl
elements that
have another xbl
element as an ancestor as
being in error and must then ignore them,
meaning those elements must never be considered to declare any
bindings. For example, UAs must never bind elements to bindings
defined by definition
elements that have
two xbl
ancestors.
Similarly, XBL elements (other than import
and
xbl
) that do not have a correct
xbl
element as an ancestor are in error
too, and UAs must ignore them, treating them as they
would any arbitrary semantic-free XML element. For example, UAs must
never bind elements to bindings defined by definition
elements that have no xbl
ancestors at all.
<element name='definition'> <choice> <attribute name='ref'><data type='anyURI'/></attribute> <group> <optional><ref name='implementation'/></optional> <optional><ref name='template'/></optional> <optional><ref name='handlerGroup'/></optional> <optional><ref name='resources'/></optional> <attribute name='element'><data type='QName'/></attribute> </group> </choice> <ref name='id.attrib'/> </element>
xbl
ref
attribute is not
specified:implementation
: zero or one.template
: zero or one.handlerGroup
: zero or one.resources
: zero or one.ref
attribute is
specified:The definition
element describes a
single XBL binding that adds presentation and interactive behavior
to XML or HTML elements. Each binding has these optional
components:
Methods, Properties, and Fields: A binding can specify additional methods that can be invoked on the element. It can also specify additional properties and fields that can be retrieved or set on the element. In this way the functionality of the bound element becomes extensible. (See: binding implementations.)
Template: The optional template
defines the initial shadow content for the bound element.
Behavior: A binding can define
event listeners for various types of events. Some examples are: UI
events (e.g., key and mouse events) on the bound element or on
elements within the shadow content; mutation events on the bound
element and its descendants; and events having to do with XBL's
binding operations (e.g., the prebind
and
bound
events). (See: event
handlers.)
Resources: A binding can list stylesheets that are scoped to the bound element, and images, sounds, videos, or other files that a user agent can pre-cache in order to improve performance. (See: binding stylesheets, prefetching resources.)
Alternatively, a binding may reference an existing binding, with
the ref
attribute. In this
case, the ref
attribute
must reference a definition
element which in turn
supplies the binding definition.
Bindings may also act as an attachment mechanism, specifying a
namespace and local name of elements to associate with the given
binding when the binding is imported,
using the element
attribute.
In addition to the above, the definition
element may contain any element outside the XBL namespace, for
example svg:defs
. These are handled as they
would be in any other context, and are ignored by the XBL processing
model.
id
attribute.This attribute specifies a URI to use to find the binding
instead of looking inside the definition
element
itself. (See: interpretation of URIs to XBL
bindings.)
When a definition
element has a ref
attribute, the UA must
fetch the specified resource (unless it has already been loaded).
If the URI references a definition
element, and
that element does not have a ref
attribute, then for the
purposes of the rest of the XBL processing model, the element with
the ref
attribute is
treated as if it had the children nodes and the extends
attribute of the
element to which it refers.
If the URI does not reference a definition
element, it is in error and must be
ignored..
The referenced definition
element cannot have a
ref
attribute (i.e., only
one level of indirection is allowed); otherwise, the original
definition
element is in error
and must also be ignored..
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. If
the element has a ref
attribute, then the extends
attribute is
in error and must be ignored.If an element
attribute does not
resolve to a valid qualified name (QName) using the attribute
QName resolving semantics and the namespace prefix declarations
in scope on the element, 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. [XMLNS]
If a definition
element contains both a ref
attribute and has child nodes
other than comment nodes or whitespace text nodes, then it is
in error, and the contents of the element must
all be ignored for the purposes of XBL processing.
The definition
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.
definition
The implementation
element describes a set of
methods, properties, and fields that are attached to the bound
element. Once the binding is attached, these methods, properties,
and fields can be invoked directly from the bound element.
The implementation
element, if present, must either
contain code in the language specified by the XBL subtree's script-type
attribute, or have a
src
attribute that
points to a resource containing code in the language specified by
the script-type
attribute.
The syntax and semantics of this code depend on the specific
language. This specification defines the semantics for ECMAScript
implementations. (See: binding
implementations.)
id
attribute.name
attribute can be used to provide a specific name for an
implementation. This name can then be used to reference the
implementation. For example, in ECMAScript the value of this
attribute represents the name of the corresponding class that is
constructed for the implementation. If no name attribute is
specified, or if it is specified but empty, then the binding's
document URI and ID (if any) are used to uniquely reference the
binding's implementation.implements
attribute
can be used to describe a set of interfaces that are implemented by
the binding. Its value is a space-separated list of named
interfaces. If supported, in strongly typed languages the bound
element can be referenced not only as any of the interfaces that
the element might already support (e.g., HTMLElement) but also as
any of the interfaces described by this attribute. Support of this
capability is optional. Generally, if the interfaces listed in this attribute are not well defined DOM interfaces, the expectation is that the application will have access to resources, such as external IDL files, defining them. How this is handled is outside the scope of this specification.
src
attribute
specifies the URI to a resource of the type given by the XBL
subtree's script-type
attribute. If specified, it overrides the contents of the element
(even if the resource could not be fetched or was of the wrong
type). (See: binding implementations.)If an implementation
element is marked (via the
script-type
attribute of
the xbl
element) as being in a language that the UA
does not support, or, if the implementation
element
points (using the src
attribute) to a resource that is either unavailable, or not of the
type specified by the script-type
attribute of the
xbl
element, then it is in error and the
UA must ignore it, meaning it must not be used as an
implementation definition for any binding.
How UAs must handle nodes inside implementation
elements depends on the language used. (See: loading and
running scripts, binding implementations.)
implementation
blocks must be evaluated when their
binding is attached. Once a binding is attached, changes to the
implementation
element have no effect on that binding.
If an implementation
element is changed, however, it
shall affect bindings that are attached after the change.
<element name='template'> <ref name='id.attrib'/> </element>
definition
content
and inherited
elements
may occur as descendants, and non-XBL descendant elements may host
xbl:inherits
and
xbl:pseudo
attributes.The template
element contains child nodes that can
be in any namespace. The subtree specified by the
template
element is referred to as the shadow
content template. When a binding is attached, the
template
element's child nodes are cloned and attached
to the bound document under the bound element (where they are
accessible via the xblShadowTree
DOM
property). Because these cloned nodes are hidden from their parent
and exist outside the normal document tree, they are referred to as
shadow content.
When the template
element is cloned, it is renamed
to shadowTree
. (See: rules for shadow content
generation.)
id
attribute.applyGlobalSheets
attribute indicates whether or not rules in stylesheets associated
with the binding 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 apply the binding document stylesheets (same
as true
). (See: binding
stylesheets.)applyAuthorSheets
attribute indicates whether or not rules in author stylesheets
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
stylesheets.)allowSelectorsThrough
attribute indicates whether or not rules in in stylesheets from
outer scopes can match through elements in the shadow content
generated by the binding. 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 rules from outer scope match through
the shadow content (same as false
). (See:
binding stylesheetsThe 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.)
<element name='content'> <optional><attribute name='includes'><text/></attribute></optional> <ref name='id.attrib'/> </element>
template
element somewhere in the ancestor chain,
and there must not be any correct content
elements anywhere in the ancestor
chain.The content
element is used inside shadow
content to specify insertion points for explicit content that
might already exist underneath the bound element. As far as the
presentation model is concerned, any shadow content the binding
places between the bound element and the content
elements is interleaved between the bound element and its explicit
children without affecting the document model. (See:
processing content
elements.)
If the includes
attribute successfully matches
against children of the bound element, then those children are
inserted into the final flattened tree in place of the
content
element. If the includes
attribute
does not match against any children, then the child elements of the
content
element are inserted into the final flattened
tree in place of the content
element instead.
id
attribute.includes
attribute can be used to indicate that only certain content should
be placed at the content
element. Its value is a CSS
selector.
(See: processing content
elements.)applyBindingSheets
attribute indicates whether or not scoped stylesheets 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
stylesheets.)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.)<element name='inherited'> <ref name='id.attrib'/> </element>
template
element somewhere in the ancestor chain.The inherited
element is replaced by the shadow
content of the base binding. If the base binding has no shadow
content, or if this is not the first inherited
element,
then the contents of the inherited
element (if any) are
used instead. (See: processing inherited
elements.)
id
attribute.While it is legal to nest inherited
elements, it is pointless, since if one
inherited
element used its fallback
content, any subsequent such elements will too.
template
element somewhere in the ancestor
chain.The xbl:inherits
attribute is a global attribute in the XBL namespace that specifies
which attributes on the bound element should be forwarded to the
element on which the attribute is found when the shadow content
template is cloned. It is a space separated list of QNames or QName
pairs separated by equal signs. (See: attribute
forwarding.)
template
element somewhere in the ancestor
chain.The xbl:pseudo
attribute is a global attribute in the XBL namespace that specifies
the pseudo-element that, when used on the bound element, must be
mapped to the element on which the attribute is found. (See:
matching pseudo-elements.)
<element name='handlerGroup'> <zeroOrMore><ref name='handler'/></zeroOrMore> <ref name='id.attrib'/> </element>
definition
handler
: zero or more.The handlerGroup
element's event handlers can be
called for events that flow through the bound element. During
capture, target and bubbling phases, when a given event is received
by a bound element, if a corresponding event listener has been
attached to the handlerGroup
element, then the event
will be forwarded to that
event listener. (See: event forwarding, binding
attachment and detachment.)
id
attribute.handlerGroup
The handler
element describes a single event
handler. This handler is attached to its parent
handlerGroup
element, which is used as an event
forwarding target when handling events on the bound element. (See:
event handlers.) It wraps a script that is executed
when the event handler is matched.
id
attribute.event
attribute describes the specific event that this handler is
listening for. (See: criteria for event handlers.)handler
attribute specifies the
URI reference of a resource that defines the action that should be
performed if the event handler is fired. (See: event
handlers.)propagate
attribute specifies
whether after processing all listeners at the current node, the
event is allowed to continue on its path (either in the capture or
the bubble phase). (See: event handlers.)defaultAction
attribute
specifies whether after processing of all listeners for the event,
the default action for the event (if any) should be performed or
not. (See: event handlers.)capture
and default
. If
capture
is specified, then the event
handler must only be fired during the capturing phase of event
propagation. Otherwise, the handler must only be fired during the
target and bubbling phases. (See: criteria for event
handlers.)target
attribute specifies an ID that the event target must have for the
event to fire. (See: criteria for event handlers.)button
attribute imposes a filter on the handler. It is used with
mouse handlers to specify a particular button. (See: mouse
event handler filters.)clickcount
attribute imposes
a filter on the handler. It is used with mouse handlers to
specify how many clicks must have occured. (See: mouse event
handler filters.)modifiers
attribute imposes a
filter on key and mouse handlers. It is used with mouse and key
handlers to specify particular modifier keys. (See: mouse
event handler filters, key event handler
filters.)key
attribute imposes a filter on key handlers. It is used with key
handlers to specify which keys to listen for. (See: key event
handler filters.)keylocation
attribute
imposes a filter on key handlers. It is used with key handlers to
specify which keys to listen for. (See: key event handler
filters.)text
attribute imposes a filter on text input handlers. It is used with
text input handlers to specify which characters to listen for.
(See: text input event handler filters.)prevvalue
attribute imposes a
filter on mutation handlers. It is used with mutation handlers to
specify what prevValue
to listen for.
(See: mutation event handler filters.)newvalue
attribute imposes a
filter on mutation handlers. It is used with mutation handlers to
specify what newValue
to listen for. (See:
mutation event handler filters)attrname
attribute imposes a
filter on mutation handlers. It is used with attribute mutation
handlers to specify what attribute to listen for changes for. (See:
mutation event handler filters)attrchange
attribute imposes
a filter on mutation handlers. It is used with attribute mutation
handlers to specify what type of change to listen for changes for.
(See: mutation event handler filters.)If a handler
element is marked (via the
script-type
attribute of the xbl
element) as being in a
language that the UA does not support, or, if the handler
element points (using the handler
attribute)
to a resource that is either unavailable, or not of the type
specified by the script-type
attribute of the
xbl
element, then the UA must
ignore it, meaning it must not be used for the event
handler definitions of any binding.
How UAs must handle nodes inside handler
elements
depends on the language used. (See: loading and running
scripts, event handlers.)
handler
blocks must be evaluated each time they are
fired. Changes to the handler
elements therefore take
effect the next time the an event is fired.
<element name='resources'> <zeroOrMore><ref name='style'/></zeroOrMore> <zeroOrMore><ref name='prefetch'/></zeroOrMore> <ref name='id.attrib'/> </element>
definition
style
prefetch
The resources
element contains
a list of stylesheets to apply when using this binding, as
well as a list of files (images, videos, sound
files, etc) to optionally preload.
id
attribute.resources
The style
element is used to specify a
stylesheet that is to be applied to the bound element and to the
shadow content generated by the binding, and to explicit children of
insert nodes whose applyBindingSheets
attribute is set, in documents that use the binding.
id
attribute.media
attribute specifies the intended destination medium for style
information. How the value of this attribute is interpreted is
defined by Media Queries [MQ]. If this
attribute is not specified, then there is no restriction on which
media the stylesheet should be applied to (same as specifying media="all"
).src
attribute specifies the URI to a resource of the type given by the
XBL subtree's style-type
attribute. If specified,
it overrides the contents of the element (even if the resource
could not be fetched or was of the wrong type). (See: binding
stylesheets.)If a style
element is marked (via the
style-type
attribute
of the xbl
element) as being in a
language that the UA does not support, or, if the style
element points (using the src
attribute) to a resource that is
either unavailable, or not of the type specified by the style-type
attribute
of the xbl
element, then it is in
error and the UA must ignore it, meaning it must
not be used to style anything.
How UAs must handle nodes inside style
elements depends on the language used. (See: binding
stylesheets.)
resources
The prefetch
element can be used to list
resources that may be pre-loaded for performance reasons. Support
for this element is optional. UAs may ignore it.
id
attribute.xbl
The script
element contains code that is executed
when the XBL subtree is loaded. It can therefore be used to define
helper functions used by the bindings.
The script
element, when present, must either
contain code in the language specified by the XBL subtree's script-type
attribute, or have a
src
attribute that points to a
resource containing code in the language specified by the script-type
attribute. The
syntax and semantics of this code depend on the specific language.
(See: loading and running scripts.)
id
attribute.src
attribute specifies the URI to a resource of the type given by the
XBL subtree's script-type
attribute. If specified,
it overrides the contents of the element (even if the resource
could not be fetched or was of the wrong type). (See: script
blocks.)If an script
element is marked (via the script-type
attribute of the
xbl
element) as being in a language that the UA does
not support, or, if the script
element points (using
the src
attribute) to a
resource that is either unavailable, or not of the type specified by
the script-type
attribute
of the xbl
element, then it is in error
and the UA must ignore it, meaning it must not be
executed.
How UAs must handle nodes inside script
elements
depends on the language used. (See: loading and running
scripts.)
script
blocks must be evaluated when their end-tag
is parsed, or, for dynamically created elements, when they are
inserted into a document. Once evaluated, a script
block is dead and changes to its contents have no effect.
<element name='import'> <optional><attribute name='bindings'><data type='anyURI'/></attribute></optional> <ref name='id.attrib'/> </element>
The import
element specifies a group of bindings to
use. Unless explicitly imported using an import
element, binding definitions that declare attachments using the
element
attribute are
only used in the document that defines them.
The import
element may occur anywhere, within and
without XBL subtrees, but must be considered in error and
ignored (i.e. must not cause anything to be imported) if any of its
ancestors are in error.
id
attribute.The bindings
attribute specifies the URI of the bindings to import. If it has a
fragment identifier it specifies the subpart of the specified
resource to examine for binding attachment declarations. This
attribute is required. If it is omitted, the element is in
error and must be ignored.
The URI must point to a binding
document. If the URI designated by an import
element
has a fragment identifier, it must point to an element in the specified document. If it
does not, the element is in error and must be
ignored.
If the URI designated by an import
element cannot
be resolved, or returns an HTTP 404 error (or equivalent), or does
not point to a resource with an XML MIME type, or
has any other problem that makes it unusable, then the element is
in error and must be ignored.
When an import
element is parsed or inserted into a
document, and whenever the bindings
attribute is
subseqently changed, the URI specified by its bindings
attribute must be
loaded (unless it has already been loaded).
If the URI designated by an import
element cannot be
resolved, or returns an HTTP 404 error, or does not point to a
resource with an XML MIME type, or has any other problem that makes
it unusable, then the element is in error and
must not cause anything to be imported.
While the import
element remains in the document,
all the correct bindings that it imports and that
specify an attachment must be attached to any matching elements that
have the same ownerDocument
as the import
element. (See: binding attachment.)
If there is a fragment identifier, it imports all the
definition
elements in the subtree designated by that
fragment identifier. Otherwise, it imports all the
definition
elements in the binding
document.
An import is live, if new definition
elements are added to a subtree that is being imported by a
document, then the new bindings are immediately applied to that
document. Similarly, if an import
element is removed,
if it stops matching the conditions described above (such
as having a bindings
attribute), or if the bindings
attribute is changed,
then the bindings it was importing are detached from any elements
they were affecting.
XBL bindings are always implicitly imported into the document in which they are defined.
An XBL subtree that defines some bindings is automatically imported in that document, so such mappings are always used. The following example demonstrates this.
example.svg <svg xmlns="http://www.w3.org/2000/svg" ...> <xbl xmlns="http://www.w3.org/2004/xbl" ...> <definition element="foo"> ... <definition> <definition element="bar"> ... <definition> </xbl ...> <foo xmlns=""/> <!-- this will have a binding applied --> <bar xmlns=""/> <!-- this will have a binding applied --> </svg>
If the binding definitions are in a separate file, then that file needs to be imported explicitly:
widgets.svg <svg xmlns="http://www.w3.org/2000/svg" ...> <xbl xmlns="http://www.w3.org/2004/xbl" ...> <definition element="foo"> ... <definition> <definition element="bar"> ... <definition> </xbl ...> </svg>
example.svg <svg:svg ... xmlns:svg="http://www.w3.org/2000/svg" xmlns:xbl="http://www.w3.org/2004/xbl"> <xbl:import bindings="widgets.svg"/> <foo/> <!-- bound --> <bar/> <!-- bound --> </svg:svg>
If a file imports a specific binding but the file containing
that binding has its own import
elements, the second
import only affects nodes in that document. For example:
foo.svg <svg xmlns="http://www.w3.org/2000/svg" ...> <xbl xmlns="http://www.w3.org/2004/xbl" ...> <definition element="foo" id="foo"> <content> <bar xmlns=""/> <!-- not bound, not even when in shadow content --> </content> <definition> </xbl> </svg>
bar.svg <svg xmlns="http://www.w3.org/2000/svg" ...> <xbl id="bindings" xmlns="http://www.w3.org/2004/xbl" ...> <definition element="bar" id="bar"> <content> <foo xmlns=""/> <!-- bound: this document imports foo.svg --> <bar xmlns=""/> <!-- bound: bar binding is defined locally --> </content> <definition> </xbl> <import bindings="foo.svg" xmlns="http://www.w3.org/2004/xbl"/> </svg>
example.svg <svg:svg ... xmlns:svg="http://www.w3.org/2000/svg" xmlns:xbl="http://www.w3.org/2004/xbl"> <xbl:import bindings="bar.svg#bindings"/> <foo/> <!-- not bound: foo.svg not imported here --> <bar/> <!-- bound --> </svg:svg>
<define name='id.attrib'> <optional> <attribute name='id'> <data type='ID'/> </attribute> </optional> </define>
The id
attribute assigns
a name to an element. This name must be unique in the binding document. The id
attribute is of type ID. Refer
to the "Extensible Markup Language (XML)" Recommendation [XML].
An id
attribute's value
must be valid, as defined by XML. UAs must consider ID
attributes that have invalid values as being in error,
not associating their element with the given ID. (See XML 1.0,
section 3.3.1.)
What does it mean to require that the ID attribute must be valid? Does it mean "must match XML's Name production"? What if it isn't? Does it put it in error? If it is in error, what happens; is that covered by our new "in error" handling text?
Scripts in XBL may be found in script
,
implementation
, and handler
elements,
or in resources that those elements point to.
In the case of script
and
implementation
elements, if a src
attribute is present, or,
in the case of a handler
element, if a handler
attribute is present,
then the attribute overrides the contents of the element (even if
fetching the specified URI failed).
In any case, wherever the script is found, the rules for parsing it are the same, but depend on the language specified by the author.
For non-XML languages, if the content is inline, UAs must concatenate all the textual contents of text and CDATA child nodes, and must ignore any other, non-text nodes (such as elements and comments) along with all their children. All child elements must be processed, though, according to their semantics, before the XBL script block itself is executed. A script element labelled as containing script in a non-XML language yet containing element nodes is in error.
For example, in an XHTML-aware and ECMAScript-capable user
agent, the following ridiculous code would cause the alerts to
appear in the order One, Two, Three, and would set the test
property in the binding document's global
script scope to the string "undefinedABC":
<xbl xmlns="http://www.w3.org/2004/xbl"> <script> alert('Two'); test += "B"; <script xmlns="http://www.w3.org/1999/xhtml"> alert('One'); test += "A"; </script> alert('Three'); test += "C"; </script> </xbl>
Authors must not ever consider doing this.
For XML-based scripting languages, handling of unknown elements and unexpected nodes must be defined by that language.
If the content was in another file, and that file's Content-Type
(or equivalent for non-HTTP protocols), if any, was of the type
specified on the
xbl
element, then the contents of that file are used
directly, as specified by the relevant language specification.
The src
and
handler
attributes are
examined after any children have been processed.
It is theoretically possible to use XForms Actions as the
scripting language in XBL [XForms]. The
MIME type that indicates this scripting language is tentatively
defined to be application/x-xforms-actions+xml
. XBL
elements have the following semantics when used with XForms
Actions:
script
elementsxforms:action
elements that trigger immediately upon being added to the
document.handler
elementsxforms:action
elements that trigger when the appropriate event on the bound
element is detected.implementation
elementsimplementation
elements when the script language is
set to application/x-xforms-actions
are in error and the UA must ignore them,
by treating implementation
elements like
xforms:action
elements that are not bound to any
event.Stylesheets in XBL may only be found in style
elements. If a src
attribute is
present, it overrides the contents of the element (even if fetching
the specified URI failed).
Wherever the style is found, the rules for parsing it are the same, but depend on the language specified by the author.
For non-XML styling languages, if the content is inline, UAs must concatenate all the textual contents of text and CDATA child nodes, and the UA must ignore any other, non-text nodes (such as elements and comments) along with all their children. All child elements must be processed, though, according to their semantics, before the XBL style block itself is parsed. A style element labelled as containing a stylesheet in a non-XML language yet containing element nodes is in error.
For example, in an XHTML-aware and ECMAScript-capable user agent, the rather dubious code below would result in a binding that enclosed the bound element's children in a green box, not a red one:
<xbl xmlns="http://www.w3.org/2004/xbl"> <definition> <template> <div xmlns="http://www.w3.org/1999/xhtml"> <content/> </div> </template> <resources> <style id="test"> div { background: red; } <script xmlns="http://www.w3.org/1999/xhtml"> document.getElementById('test').firstChild.data = "div { background: green; }"; </script> <p xmlns="http://www.w3.org/1999/xhtml"> div { border: red solid; } This will either be ignored by the XBL processor, or will cause it to abort all processing altogether, as this text node is not a child of the style element. </p> </style> </resources> </definition> </xbl>
For XML-based styling languages, handling of unknown elements and unexpected nodes must be defined by that language.
If the content was in another file, and that file's Content-Type
(or equivalent for non-HTTP protocols), if any, was of the type
specified on the xbl
element, then the
contents of that file are used directly, as specified by the
relevant language specification. The src
attribute is examined after any
children have been processed.
Bindings can be attached and detached dynamically, using several mechanisms.
Bindings shall be attached as soon as the following conditions have been met: (a) it is known that the element is bound to the given binding (b) the element has been created and (c) the binding has loaded.
XBL attachment mechanisms use a URI to specify which binding to attach to the designated element. For example:
<definition element="my:foo" ref="http://www.example.org/bindings.xml#fooBinding"/>
This section defines how URIs in the definition
element's ref
attribute, in the argument to the addBinding()
method, and in the value of the 'binding' property, are to be
interpreted.
The URI specifies a particular binding document (an XBL document or compound document containing one or more XBL subtrees).
If the URI contains a fragment identifier, it must point to a
specific definition
element (by id
) within an XBL subtree in the
specified document, and that element must be a direct child of an
xbl
element that does not itself have an
xbl
element as an ancestor.
If there is no fragment identifier and the URI points to
an XBL document (not a compound document) then the first
definition
element in the binding document that is a
child of the root xbl
element is selected.
Otherwise, the URI does not point to a correct binding and is
in error.
definition
The simplest binding mechanism is the
definition
element. It declares which bindings should
be attached to which elements.
While an element matches the element
attribute of one of
the definition
elements that is imported into, or defined in, the element's
document, the binding defined by the first such
definition
element must be bound to the element.
A ref
attribute may be
used to defer the definition of the binding to another
definition
element. (See: the
definition element.)
Bindings can be attached to elements through CSS using the 'binding' property.
In the following example, a binding is referenced that will be attached to all XHTML checkbox elements.
input[type="checkbox"] { binding: url("http://www.example.org/xbl/htmlBindings.xml#checkbox"); }
Bindings attached through CSS must only remain on the bound element as long as the element continues to match the style rule. If at any time a resolution of style on the element determines that a different binding should be attached, the old binding (and all bindings that it explicitly extends in its inheritance chain) must be detached.
Whenever an element is removed from a document, any bindings attached to that element via CSS must be detached.
A property to bind an XBL binding to a particular element.
Value: | none | [ <uri> ',' ]* <uri> |
Initial: | none |
Applies To: | all elements (but not pseudo-elements) |
Inherited: | no |
Percentages: | n/a |
Media: | all |
Computed Value: | specified value, with URIs resolved to absolute URIs |
User agents may perform the CSS cascade, inheritance, and computation stages either across the entire tree, or per element, or per property per element, and either before applying bindings, or simultaneously, while applying bindings. In either 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.
Bindings can be attached to elements through the DOM using the NodeXBL
interface. The method addBinding
takes a
binding URI and attaches the binding to the element (in all
views).
var checkbox = document.getElementById("mycheckbox"); checkbox.addBinding("http://www.example.org/xbl/htmlBindings.xml#checkbox");
This attachment is not necessarily synchronous. Scripts that invoke this method should not assume that the binding is installed immediately after this method returns.
When a binding is attached using the DOM, it inherits from the current most derived binding that is already be attached to the element, if any. (See: implied 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.
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.
handlerGroup
element, when there is one. (See:
event forwarding.)prebind
event is fired before it is attached.
(See: rules for shadow content
destruction, rules for shadow content
generation.)prebind
event in the XBL namespace that bubbles
but is not cancelable is fired on the bound element.bound
event in the XBL
namespace that bubbles but is not cancelable is fired on the bound
element.We need to decide how to handle the case where a
binding's definition
is removed while it is being
attached.
Before a binding is detached, an unbinding
event in the XBL namespace that bubbles
but is not cancelable is fired on the bound element.
The shadow content nodes, the shadow tree, the implementation, any forwarding of events to the binding, etc, are then removed from the element.
The following events are fired during attachment and detachment:
implementation
, if any, has been installed and
after the contents of the template
element, if any,
have been cloned but before attachment to the bound element's
xblShadowTree
and recursive XBL processing on shadow
tree contents. (See: binding attachment model.)bound
event
fired on them.xblShadowTree
are removed, before any implementation
is
uninstalled, and before the value of xblShadowTree
is set to null.All of these events bubble and cannot be canceled.
The prebind
event must use the following interface:
interface ShadowTreeEvent : Event {
readonly attribute XBLTemplateElement
xblShadowTree;
void initShadowTreeEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in XBLTemplateElement xblShadowTreeArg);
void initShadowTreeEventNS(in DOMString namespaceURIArg,
in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in XBLTemplateElement xblShadowTreeArg);
};
The two methods initialise the event in a manner analogous to other events in DOM3 Events. [DOM3EVENTS]
The xblShadowTree
member must contain a
pointer to the shadow tree being constructed, if any, and must be
null otherwise.
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.
The results of inheritance are described in the sections on binding implementations and shadow content.
When two bindings are both attached (using the mechanisms described above), to the same element, the base binding at the end of the inheritance chain of the second binding implicitly inherits from the most derived binding of the inheritance chain of the first.
If one of the binding chains is removed, then the remaining binding chains are reconnected so that the base binding of the 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
definition
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).
The implicit inheritance link can be pictured as having several explicit chains adjacent to each other, with the implicit inheritance chain going down each explicit inheritance chain sequentially.
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 this element 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, s3. The resulting binding chain following the addition of the binding is therefore:
d1 → d2 → s1 → s2 → s3
The inheritance between d3 and
s1 is implicit, meaning that there is
no connection in the XBL subtrees between the two bindings. The
inheritance link has been forged dynamically through the invocation
of the addBinding
method.
Only one set of bindings is attached to the document, and they must affect all views in a multi-view UA. Bindings attached via stylesheets must be attached based on the stylesheets that apply to the default view.
Binding loads are asynchronous. That is to say, when a binding is
added (either via stylesheet, script, or some other method), and the
relevant binding document is not yet loaded, the load
is started in the background and the binding is only attached once
the 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.
Script must always be executed in the script context of the
document specified by the script's element's ownerDocument
DOM attribute. This implies that
scripts from different bindings in the same binding doucment 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.
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 directly from the bound element.
When two bindings in an inheritance chain both supply implementations, the derived binding's implementation inherits from the base binding's implementation. Method and property lookups are dynamic. Without disambiguating, if two bindings define the same method or property, then the most derived binding's method or property must be used.
Because bindings extend DOM elements, they can override any
built-in methods or properties on the DOM element. For example, a
binding could override the setAttribute
method on Element
or the retrieval of the
value
property for an HTMLInputElement
.
Implementations can be named using a name
attribute specified on the implementation
element. When an implementation
has a name, that name can be used to disambiguate the desired method
or property. How this works depends on the language used.
If the content is inline in the implementation
element, 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 child elements must be processed, though, according to their
semantics, before the XBL implementation is evaluated, as for script
blocks. (See: loading and running scripts)
If the content is in an external file, and that file is available and of the right type, then the contents are used literally.
Regardless of the source, the processing is the same. The
implementation script has ({
placed at the
start, })
placed at the end, and the result
is then parsed as ECMAScript. If the result is a single expression
evaluating to a single Object prototype is that
the right terminology? then that is used as the prototype for
the implementation for this binding. Otherwise, it is in
error, there is no implementation for this binding, and the
UA must ignore the implementation
.
In an implementation definition, the names of base bindings can be used to identify specific methods using dot-notation.
For example, given a binding with an implementation ColorPickerGrid
that derives from an
implementation ColorPicker
where the two
implementations both specify the setColor
method, a caller could invoke ColorPicker
's method with the following
syntax:
... // myElement is a ColorPickerGrid myElement.ColorPicker.setColor(); // Calls the ColorPicker method. myElement.setColor(); // Calls the ColorPickerGrid method. ...
In addition to being able to specifically name a base class, the
name baseBinding
can be used to specify the
method or property on the base binding without necessarily knowing
what the base class is. This situation can occur when bindings
implicitly inherit, e.g., through the use of addBinding
.
myElement.baseBinding.setColor(); // Calls the ColorPicker method.
A binding can specify a shadow content template
using the template
element. 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.
When the shadow content template is cloned (as described in this section), the clone is called a shadow tree.
For example, the HTML file upload control appears in most browsers as a composite widget consisting of a text field and a button. A sample XBL binding for the file widget might look as follows:
<binding id="fileupload"> <template> <html:input type="text"/> <html:input type="button"/> </template> </binding>
Because this content is not visible to its parent element, it is said to be shadow content.
The file control is actually a special case. Due to security considerations, untrusted bindings will typically not be able to extend the file upload control in UAs intended for use with untrusted content.
Whenever bindings are attached to an element, shadow content will potentially be generated or destroyed.
When a template
element is mutated in any way, any
bindings whose shadow tree was constructed from that element must be
reconstructed as described in this section.
If a definition
element that had no
template
element has a template
element
added, then a shadow tree is generated. If the template
element is removed, then the shadow tree is destroyed.
The template
element used to generate a binding is
always the first such element in a definition
element.
If the definition
element is mutated in a way which
changes which template
element is the first, then the
shadow tree is also reconstructed.
Everything described in this section up to the firing of the event, and everything described in this section after the firing of the event, must be completed atomically — that is, the UA must not execute author scripts during those two parts of the process. User agents may optimise this algorithm so long as the end result is the same.
The bindings in the binding's explicit chain are first checked to see if any have shadow content templates. If any do, then the most derived such template is the primary generating binding. Otherwise, there isn't one.
If there is no primary generating binding, then no shadow content
will be generated for the bound element, its xblShadowTree
attribute will be null
, and its xblChildNodes
attribute will equal its childNodes
attribute (except in certain
cases involving attribute forwarding).
If there is a primary generating binding, then its first
template
element is deeply cloned.
If the cloned content contains any inherited
elements and there is a base binding with a shadow content template
of its own, then that most derived base binding with a template has
its template cloned and its first inherited
element, if
any, handled as for the primary generating binding, recursively
until either a template is reached that has no
inherited
elements, or the last template is reached.
Then, the children of this most derived base binding's template are
used to replace the inherited
element. The
template
element itself is then discarded.
Any remaining occurrences of inherited
elements after the base bindings have all been folded in as
described above are replaced by their children nodes.
One way to implement the replacement of one element
by the child nodes of an element (possibly the same one) is to move
all the relevant child nodes into a DocumentFragment
and then replace the element by that fragment using the
replaceChild
method.
The xml:base
data of the cloned nodes 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 the binding document's Document
node.
The newly cloned template
element is then renamed to
be a shadowTree
element
in the XBL namespace.
No mutation events must be fired during the above steps.
A prebind
event in the XBL namespace
that bubbles but is not cancelable is fired on the bound element,
with the shadowTree
element as the event data.
The bound element's xblShadowTree
attribute is set to point to the root shadowTree
element
of this tree of clones.
The shadow tree is then applied to the bound element: the
xbl*
DOM attributes are updated and the CSS cascade and
inheritance should be computed.
Some implementations might optimize this algorithm, such as using "lazy evaluation" approaches and thereby postpone the cascade and inheritance operations.
Attributes on shadow content elements can be tied to attributes
on the bound element; then, whenever the attribute is set or removed
on the bound element, the corresponding attribute on the shadow
content is also set or removed. On any shadow content element, an
xbl:inherits
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.
Values must be resolved to a valid qualified name (QName) using
the attribute QName resolving semantics and the namespaces prefix
declarations in scope on the element on which the xbl:inherits
attribute is found. Any
value in the list that does not resolve to a valid QName is in error
and must be ignored. [XMLNS]
For example, returning to the HTML file upload control example
above, the shadow textfield can be set up to automatically
inherit the value
attribute from the bound
element.
<xbl:binding id="fileUploadControl"> <xbl:template> <html:input type="text" xbl:inherits="value"/> <html:input type="button" value="Browse..."/> </xbl:template> </xbl:binding>
Each entry in the xbl:inherits
list can either simply list an attribute (such as value
in the example above), or it can specify an =
-separated
pair consisting of the attribute on the shadow content that should
be tied to the attribute on the bound element. The new shadow
content attribute is listed first.
The special value xbl:text
can be used in an =-separated pair, where the prefix defined is the
XBL namespace. (The value is not a literal; it represents the
fictional "text" attribute in the XBL namespace.)
When specified on the left-hand side of the pair it indicates
that the attribute on the right-hand side should be stored as text
nodes underneath the shadow element in the xblChildNodes
list. If the element has other
nodes in its xblChildNodes
list then the
pair is in error and UAs must ignore it, meaning the
attribute value is not forwarded.
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.
Similarly, their xblParentNode
attribute
points to the element that generated them and their xblNextSibling
, xblPreviousSibling
, xblChildNodes
, xblFirstChild
, and xblLastChild
attributes are all null or
empty.
When used on the right-hand side, it indicates that any raw text nodes (including CDATA nodes) that are explicit children of the bound element should be coalesced and the resulting value should be stored as the attribute on the left-hand side.
The xbl:text
value cannot occur by
itself in the list. It may be used only in an = separated pair where
at least one value is not xbl:text
. If it
occurs by itself, it is in error and UAs must
ignore that value in the space-separated list that is
the xbl:inherits
attribute.
Any other values in the XBL namespace in the list are in
error and must be ignored. (In
particular, trying to change or set the value of xbl:pseudo
or, worse, xbl:inherits
, must not result in any
changes to any attributes.)
content
elementsThe shadow content template may contain content
elements that define where explicit children should be inserted in
the shadow content.
What about nested bindings, where the inner bound
element is the parent of a content
element and itself
has a template with content
elements? Do the inner
content elements match the repositioned explicit elements, or the
inner content
element? If the former, we need to define
this. The latter would mean encapsulation was broken.
Any inherited
elements are handled when the shadow
tree is cloned, and content
elements are handled when
the shadow tree is then attached to the bound element. This ensures
that all the content
elements, from the primary
generating binding's shadow content template, inherited shadow
content templates, and fallback content in inherited
elements that were not replaced by inherited shadow content
templates, are taken into account. (See: rules for generating
shadow content.)
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.
Expressions specified using the includes
attribute determine
which content
element a given child should be placed
under.
Request for public feedback
The XBL task force has not yet decided the syntax to use for
includes
attribute.
We have received a number of comments suggesting that XPath (or an XPath subset) is preferred.
It has been pointed out, however, that, on the long term, an approach based on XPath would suffer from a number of problems, including amongst others the following:
content
elements need to be very fast to resolve.One problem in deciding whether Selectors or XPath is the better solution is that XBL is targetted at several audiences, including a primarily HTML- and CSS-driven audience (Web authors), and a primarily XML-driven audience. The former are more familiar with Selectors, and the latter more familiar with XPath.
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.
The content
element used for a given piece of
content is the first encountered with an expression that matches the
element and that is not locked when doing
a pre-order, depth-first walk of the shadow content template.
The content
element itself is present in the shadow
content, but is not visible in the xblChildNodes
list. In that list, it is simply
replaced by the elements that matched it, or, if there were no
matches, by its contents.
If an explicit child of the bound element does not match any of
the content
element in the shadow tree (or if there are
no content
elements in the shadow tree), then that
child does not appear in the final flattened tree.
inherited
elements
The inherited
is used to place the shadow content
generated by the next binding in the chain that contributes shadow
content. That binding can use a inherited
element for
its base binding as well. This pattern continues all the way up the
binding chain.
If there is no base binding with a shadow content template or if
the base binding's content has already been placed into the shadown
tree by an earlier inherited
element, then the contents
of the inherited
element are cloned and inserted
instead, with any nested content
elements providing
insertion points for explicit content as appropriate.
The inherited
element never appears in the shadow
content, as it is replaced as described above before the shadow tree
is completed. (See: rules for shadow content
generation.)
All of the nodes in the shadow tree are live. Whenever an element
is inserted into, removed from, or appended to the DOM, all the
children 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.
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.
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 xblSetInsertionPoint()
method. However, children
already under a locked content
element must remain
there while the element's includes
attribute (or lack
thereof) matches them.
Whenever the subtree of a template
element is
dynamically modified, any shadow trees that were constructed by
cloning that element must be reconstructed. (As no events are fired
during this process, there is no way for such bindings to update
their shadow trees after it happens.)
Special care should be used when considering the interactions of CSS and XBL.
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.
Explicit content is said to be at the document-level scope, which is the highest, or outermost, shadow scope. Shadow content nodes are in their own binding-level shadow scopes. Binding scopes are determined by the bound element that contains the binding responsible for the generation of the shadow nodes. 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.
The resulting tree, after all children have been assigned to
content
elements and all attributes
forwarded, is called the final flattened tree, and is
the tree used by the rendering model. (See: 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 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 the XBL elements.
If "B.parentNode
" is an insertion point (a
content
element), let "X
" be
"B.parentNode.parentNode
", otherwise let "X
"
be "B.parentNode
".
Now if "X
" is the root of a shadow tree,
but "allowSelectorsThrough
" is false, it doesn't
match "B
". Otherwise, if "X
" is the
root of a shadow tree and "allowSelectorsThrough
" is
true, then let "X
" be "B.xblBoundElement
".
Then, it matches
"B
" if the "X
" element is the
"A
" element.
B
" if either "A>B
"
matches "B
", or "C>B
" matches
"B
" and "A C
" matches
"C
".
B.previousSibling
" is an insertion point (a
content
element), it doesn't match "B
",
otherwise, it matches if "B.previousSibling
" is
"A
".B
" if either "A+B
" matches
"B
", or if "C+B
" matches "B
" and
"A~C
" matches "C
".Pseudo-classes and pseudo-elements: Pseudo-classes and pseudo-elements are unchanged in the presence of XBL. They operate exclusively on the core DOM.
In particular, note that this means that the selector
:nth-child(odd)
would match both the A
and
B
nodes in the following example:
<xbl:template> <A/> <xbl:content> <B/> </xbl:template>
...regardless of the number of nodes that are inserted at the
insertion point given by the content
element (whether
that be 0, 1, 2, or more nodes).
Inheritance: The final modified content tree determines
how CSS properties (e.g., fonts and colors) are inherited. An
element either ends up underneath its explicit parent (just as in
the content model), or it ends up being nested through a series of
content
elements. When nested, it inherits from the
innermost shadow parent.
In DOM terms, this corresponds to inheritance using the xblParentNode
attribute.
:xbl-bound-element
pseudo-classThe :xbl-bound-element
pseudo-class
matches any bound element.
Shadow nodes may be associated with various pre-defined
pseudo-elements of the bound element. On any element in the shadow
content template, an xbl:pseudo
attribute (in the XBL namespace) can be used to specify the name of
the pseudo to associate with that element.
For example, once more returning to the HTML file upload control example above, the shadow textfield can be set up to be considered a match for the selector input[type=file]::value as follows.
<xbl:binding id="fileUploadControl"> <xbl:template> <html:input type="text" xbl:pseudo="value"/> <html:input type="button" value="Browse..."/> </xbl:template> </xbl:binding>
The pseudo must be given without its leading double colon.
If the pseudo-element name is not recognised, it is in error and the UA must ignore the attribute. User agents must not automatically recognise 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
applyAuthorSheets
attribute.
The allowed pseudo-elements are:
These pseudo-element descriptions are purely advisory, and while authors are encouraged to use them for their predefined roles, it is valid to use them for other purposes.
The following XBL is part of the definition of a button control.
<xbl:binding id="imageButton"> <xbl:template> <html:span xbl:pseudo="icon"/> <html:span xbl:inherits="xbl:text=title"/> </xbl:template> </xbl:binding>
This control could then be used like this:
<button title="Save" class="save-button"/>
...and styled like this:
button { binding: url(buttons.xml#imageButton); } button.save-button::icon { content: url(icons/save.png); }
In property descriptions, the term "all elements" in the "Applies To:" line includes these pseudo-elements, as they map directly to real elements in the binding.
This will eventually be moved to the SVG specification.
In XBL, the SVG rendering model is subtly altered to handle elements with shadow trees.
Painting: When painting groups, for child elements that
have xblShadowTree
s, instead of painting
the child element itself, the group should paint the nodes in that
element's xblChildNodes
list.
ID references and URIs: When a URI identifies an element
with an xblShadowTree
, the SVG processor
must use the first element node given by the element's xblChildNodes
list instead of the element itself.
If there are no elements, or if there is more than one element, then
the document is in error.
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
.
content
elements?),
etc.Since the processing rules of all non-XBL elements found while processing a binding document are not affected by their being part of an XBL subtree, there are certain elements that are unlikely to have the desired effect when included in shadow content templates. Some of these cases are described below.
While some of these effects may seem peculiar, it must be emphasised that they are merely the result of XBL not affecting the semantics of these elements at all. It would have been possible to define XBL in such a way that the semantics of various elements from the SVG, XHTML, XML Events, etc, namespaces were modified, but this would have required XBL knowing about special elements from a large number of namespaces, causing XBL implementations to have large interdependencies.
Shadow content is not considered part of an 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, not the
document-level scope of the document into which the
shadow content is inserted.
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., SVG or XHTML nodes)
refer to resources in the bindings document, not content in the
bound document or the shadow scope.
The semantics of svg:style
and
html:style
elements is that they introduce new
styles for their document. Since the document, in the case of
anything in an XBL subtree, is the bindings document (or the
compound document in which the XBL subtree is found), that
is the document that must be affected by such a stylesheet.
If one of these style elements is placed in a shadow content template, then the document into which the shadow content is later inserted during binding attachment must not be affected, and the bindings document itself must only be affected once (by the node in the binding document), not by any of the clones created.
Script elements, such as html:script
and its ilk, are typically evaluated
only during parsing, or during parsing and when inserted into a
document. In all cases, however, they are evaluated in the context
of their owner document. Therefore such elements must only be
evaluated during initial parsing, in the context of the XBL
subtree's document, and not during binding attachment.
XML Events elements in the binding document must result in event
handlers being registered as event listeners on the nodes in the
original bindings document (including possibly the template
node) as described in XML Events.
They may be included in shadow content templates, but when the
shadow content template is cloned, the newly cloned event handlers
must cause new event listeners to be added to their new DOM Core
parent nodes. Thus an event handler that is the child of an
template
element in the shadow content template will
never fire once it has been cloned, since the events do not bubble
into the shadowTree
element. [XMLEvents]
Shadow content nodes and bound elements are styled using stylesheets 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 stylesheets to apply; the stylesheets of the most derived binding being walked first. For each binding, the stylesheets that apply are as follows, in the order given:
Stylesheets of the binding document: While applyGlobalSheets
is
not set to false
on the shadowTree
element
found from the bound element's xblShadowTree
DOM attribute, the stylesheets of
the binding document, in the order specified in that document, must
be applied to the shadow content. They are never applied to the
bound element.
When using binding document stylesheets, if the binding document specifies alternate stylesheets, the stylesheets used must be those that are appropriate for the currently selected stylesheet set in that document. This may differ from the selected stylesheet set of the bound document.
Scoped stylesheets: A binding file can load stylesheets
using the style
element. (See: loading
stylesheets.) These stylesheets 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 stylesheets and
the stylesheets from the binding document have the same CSS origin
as the sheet with the rule responsible for the binding. Stylesheets
used by bindings that are attached using the DOM or using
import
are treated as author-level sheets.
When bindings from multiple levels are applied to the same bound element, the stylesheets that apply must cascade according to their own levels.
An element E attaches binding U from the user agent stylesheet, and binding A from the DOM, which places A in th author level. When the stylesheets that apply to E are sorted, U must be applied at the UA level and A at the author level.
Author sheets: While the applyAuthorSheets
attribute on the shadowTree
element found from the
bound element's xblShadowTree
DOM attribute
is set to true
, the rules specified in any author
sheets at outer shadow scopes 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, stylesheets 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 (in
some cases). A third attribute, applyBindingSheets
,
can be used to indicate that all children 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 stylesheets of the binding (those that apply to the
shadow content as described above) applied to them too.
Sheets 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 down to the most derived binding.
User agent sheets and user sheets are always applied to all shadow scopes.
Since styles from both author stylesheets and binding stylesheets
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.
Often, XBL developers will want to register the same event
listener on all bound elements corresponding to a given
definition
element. For example, suppose your XBL
contains the following definition
:
<xbl:definition element="myNS:button"> ... </xbl:definition>
And suppose you create three instances of "myNS:button" as follows:
<myNS:button id="b1">...</myNs:button> <myNS:button id="b2">...</myNs:button> <myNS:button id="b3">...</myNs:button>
And suppose you want to attach a "DOMActivate" event listener to
each of the three instances. You can certainly register three
separate event listeners using either three separate event listener
registration elements (e.g., in the case of SVG, you can use
svg:handler
) or using three separate DOM method calls
(e.g., three calls to EventTarget::addEventListener
). However,
sometimes it is more convenient to define the event listener once as
part of the definition
element and then have the given
event listener (in effect) automatically assigned to each bound
element instance that corresponds to the given
definition
.
In order to provide such convenience, XBL provides an automatic
event forwarding mechanism for all events listeners attached to a
handlerGroup
element.
Every time an event fires on a bound element (whether during the
capture, target, or bubbling phases), if any event listeners for the
given event exist on the corresponding handlerGroup
elements, then those listeners must be invoked.
To illustrate, if we update the above example to add
handlerGroup
and handler
elements as follows:
<xbl:definition element="myNS:button"> <xbl:template>...</xbl:template> <xbl:handlerGroup> <handler event="DOMActivate"...>...</handler> </xbl:handlerGroup> </xbl:definition> ... <myNS:button id="b1">...</myNs:button> <myNS:button id="b2">...</myNs:button> <myNS:button id="b3">...</myNs:button>
The result is that the user agent must automatically attach an
implicit "DOMActivate" event listener to each
myNS:button
element. If the DOMActivate event is fired
and dispatched to any of the myNS:button
elements,
then the user agent must invoke DOMActivate event handlers defined
by the handler
element.
Event listeners attached to the handlerGroup
elements must always be fired after all the appropriate
event listeners on the bound element itself, in both the capture and
bubbling phase.
Since XBL handlers usually constitute the default actions for a
widget, this allows authors in the bound document to write event
handlers that potentially suppress the default actions taken by the
XBL handlers (by using the stopImmediatePropagation()
method).
Within an XBL inheritance chain, event handlers always fire first
on the derived binding and then on the base binding in the chain. A
derived handler then has a way of preventing the event from flowing
to its base binding handlers (again by using the stopImmediatePropagation()
method).
handlerGroup
element, no
matter whether the event listeners are defined in markup or via the
DOM (i.e., using EventTarget::addEventListener
).currentTarget
field shall always be set to the
bound element.addEventListener
calls via the
DOM). These event ordering rules shall apply to all phases (i.e.,
capture, target and bubbling).handlerGroup
element in the
definition
element. It must not be applied to other
handlerGroup
elements.handler
elementEvent handlers are defined using handler
and
handlerGroup
elements. A handler specifies what event
it is listening for using the event
attribute. The
handler may contain script that is executed when an event flows to
the bound element if that event matches all of the criteria
specified by the handler. The handler may also use the handler
attribute to specify
another resource that is used when those criteria are met.
The most basic handler specifies the event to listen for and an
action to take when the handler fires. This action is specified by
giving a script as a child of the handler
element. (See: loading and running scripts.)
By default, events are registered as bubbling and target events. This means that:
<handlerGroup> <handler event="click"> foo() </handler> </handlerGroup>
...is analogous to onclick="foo()"
defined on the
bound element. (The main difference is that in the XBL version, the
script is run in the context of the binding document instead of the
bound document context.)
The propagate
attribute specifies
whether after processing all listeners at the current node, the
event is allowed to continue on its path (either in the capture or
the bubble phase). The possible values are stop
and continue
(the
default). If stop
is specified, then after
the event handler has been fired, the event's stopPropagation()
method is called.
The defaultAction
attribute
specifies whether after processing of all listeners for the event,
the default action for the event (if any) should be performed or
not. For instance, in XHTML the default action for a mouse click on
an html:a
element or one of its descendents is to
traverse the link. The possible values are cancel
and perform
(the
default). If cancel
is specified, then
after the event handler has been fired, the event's preventDefault()
method is called.
Event listeners registered with handler
elements are
registered in the default event group.
The event
attribute is required and specifies the event type (and possibly
namespace) for which to fire the handler. Its value can be any legal
DOM event QName (including custom events created using the
DocumentEvent interface of the DOM). For DOM3 Events support [DOM3EVENTS], the value should be a QName
with a prefix bound to the relevant namespace, and must be resolved
to a namespace and local name using the attribute QName resolving
semantics and the namespaces prefix declarations in scope on the
element. [XMLNS] If the value is a simple
Name (no prefix), then the namespace is assumed to be null
.
If the attribute is omitted, or if the attribute is present but the value cannot be resolved to a namespace and local name as described above, then the element in error. Such Event handlers do not have an event listener for the element added to the handler group.
The phase
attribute specifies the phase of event flow that the handler is
registered for. The possible values are default
, which means the handler will only fire
if event.target
is the bound element or if
the event is in the bubbling phase of event flow, and capturing
, which indicates the handler should
fire during the capturing phase of event flow.
If the attribute is omitted, the behavior described for default
is used. Unrecognised values are in
error and UAs must ignore them, causing the
event handler to be treated as if default
was specified.
The target
attribute specifies an ID that the event target must have for the
event to fire. The ID is never resolved, it is simply compared
case-sensitively to the ID of the event target (if any) each time
the event handler is considered. If the attribute is present but its
value is the empty string, then no events will ever cause the
handler to be fired (since IDs cannot be the empty string). If an
event target has no ID then it cannot be matched by an event handler
with a target
attribute.
If the attribute is omitted, then any event target is considered a match.
Mouse, key, and mutation event handlers have certain additional
attributes on their event objects that are supported by XBL.
Additional attributes on the handler
element can be used to impose a filter on the event
handler. When a filter is imposed, the event object [DOM3EVENTS] must meet additional
conditions before the event handler will fire.
For events that use or derive from the MouseEvent
interface, two filter attributes may
be used. (All other filter attributes, if specified, are in
error and UAs must ignore them.)
The filters are:
button
button
attribute on the
event object for the XBL event handler to fire. If the attribute is
not specified, then any value of the button
attribute on the event object must be
considered a match.clickcount
detail
attribute on the
event object for the XBL event handler to fire. If the attribute is
not specified, then any value of the detail
attribute on the event object must be
considered a match. Note that this is checked for any
event that uses the MouseEvent
interface,
not just those for which detail
is
defined. Authors should take care to not specify this attribute
with, for example, mouseover
events, since
in that context detail
is undefined.modifiers
For events that use or derive from the KeyboardEvent
interface, three filter attributes
may be used. (All other filter attributes, if specified, are in
error and UAs must ignore them.)
The filters are:
key
keyIdentifier
attribute of the event object. For example, Enter
. If this filter is specified, then the
modifiers
attribute, even if not explicitly specified, must be matched as
well.keylocation
standard
, left
, right
, numpad
, which map to the DOM values 0x00, 0x01,
0x02, or 0x03 respectively. If specified, the event object's keyLocation
attribute must have a value equal to
the numeric value of one of the specified keywords. Unknown and
duplicate values are in error and UAs must
ignore them (although without dropping any correct
values).modifiers
key
attribute is also specified, in
which case no modifiers must be pressed at all (same as if the
attribute was present but set to the empty string).For events that use or derive from the TextEvent
interface, one filter attribute may be
used. (All other filter attributes, if specified, are in
error and UAs must ignore them.)
The filter is:
text
data
attribute
of the event object.For events that use or derive from the MutationEvent
interface, four filter attributes
may be used. (All other filter attributes, if specified, are
in error and UAs must ignore them.)
The filters are:
prevvalue
prevValue
attribute of the event
object.newvalue
newValue
attribute of the event
object.attrname
attrName
attribute of the event
object.attrchange
modification
,
addition
, removal
, which map to the DOM values 0x00, 0x01,
or 0x02 respectively. If specified, the event object's attrChange
attribute must have a value equal to
the numeric value of one of the specified keywords. Unknown and
duplicate values are in error and the UA must
ignore them, although without causing correct values to
be dropped.There are currently no attributes specifically designed to be
used with events that use the MutationEventName
interface.
For mouse and
key handlers, the
modifiers
attribute may be specified (see above). Its value is a space
separated list of zero or more of the following literal
case-sensitive keywords:
ctrlKey
attribute on
the event object must be true, otherwise it must be false.shiftKey
attribute on
the event object must be true, otherwise it must be false.altKey
attribute on
the event object must be true, otherwise it must be false.metaKey
attribute on
the event object must be true, otherwise it must be false.Alternatively it can be the exact string literal none
, in which case all four attributes on the
event object given above must be false.
It is left up to the user agent to decide which modifier keys represent the primary accelerator and shortcut mnemonic keys, but they must be one of the four keys listed above.
This attribute is not defined in terms of the complete
modifiersList
parameter and getModifierState
method. Should this change?
DOM events can fire on shadow targets just as they can on explicit targets. 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.
Events must flow through the final transformed content model (the
final flattened tree) after all elements have been
repositioned through the usage of content
elements.
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 original event pointing at the shadow content
responsible for the event can be obtained from a new field of the
event object, originalEvent
, which is set
to the event that was cloned.
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 retargetting 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 semantics are exactly reversed. The first node to see the event is the node after which bubbling stops; and 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.
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 focussed.)
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.
This example illustrates what happens with focus if the shadow
tree contains focusable elements. The example shows a binding for
an element named FirstAndLastNames
. The shadow tree
for the binding contains two SVG editable text fields, one for the
first name and one for the last name.
<svg viewBox="0 0 200 60" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl" xmsns:myNS="http://www.example.com"> <defs> <xbl:xbl> <xbl:definition element="myNS:FirstAndLastNames"> <xbl:template> <g font-size="16"> <text x="10" y="10">First name:</text> <text x="110" y="10" id="C" editable="true" nav-index="1"/> <text x="10" y="30">Last name:</text> <text x="110" y="30" id="D" editable="true" nav-index="2"/> </g> </xbl:template> </xbl:definition> </xbl:xbl> </defs> <g transform="translate(20,30)"> <text x="10" y="10">Customer number:</text> <text x="110" y="10" id="A" editable="true" nav-index="10"/> </g> <g id="B" transform="translate(20,50)" nav-index="20"> <myNS:FirstAndLastNames/> </g> </svg>
Tabbing through the document will go from A to C to D, not C to D to A.
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 textfield and a button. Tab indices can be specified on the textfield 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 textfield 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 textfield 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 this in more detail.)
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 textfield. 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 textfield to the button, a mouseout is generated for the textfield, 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.
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.
interface DocumentXBL { readonly attribute NamedNodeMap bindingDocuments; Document loadBindingDocument(in DOMString documentURI); };
bindingDocuments
of
type NamedNodeMap
, readonlybindingDocuments
attribute
is a NamedNodeMap of all the binding documents loaded by the
document. Documents are referenced using their URIs.loadBindingDocument
loadBindingDocument
method
can be used to synchronously obtain the document of a
specified binding document for use within a particular
document (the one on which the loadBindingDocument
method was
invoked). The binding document can then be modified
programmatically using the DOM. (See: loading
bindings.) If the load succeeded, it is also added
to the bindingDocuments
attribute.
documentURI
of type DOMString
Document
loadBindingDocument
is the
document of the binding document used by the calling
document to attach bindings that are defined in the
binding document, or null
if
the load failed.The NodeXBL
interface contains methods
for accessing shadow content and for obtaining shadow parents in
the altered model. The interface is implemented by DOM nodes
(regardless of whether they are currently involved with any XBL
processing) and may be obtained using binding-specific casting
methods on a Node interface.
All nodes except Notation
and Attr
nodes must implement NodeXBL, not just element nodes.
interface NodeXBL { readonly attribute Node xblParentNode; readonly attribute NodeList xblParentNodes; readonly attribute NodeList xblChildNodes; readonly attribute Node xblFirstChild; readonly attribute Node xblLastChild; readonly attribute Node xblPreviousSibling; readonly attribute Node xblNextSibling; readonly attribute Element xblFirstElementChild; readonly attribute Element xblLastElementChild; readonly attribute Element xblPreviousElementSibling; readonly attribute Element xblNextElementSibling; readonly attribute Element xblBoundElement; readonly attribute Element xblShadowTree; readonly attribute NodeList xblDefinitions; void addBinding(in DOMString bindingURI); void removeBinding(in DOMString bindingURI); boolean hasBinding(in DOMString bindingURI); };
xblParentNode
of type Node
, readonlyxblParentNode
attribute's
value is the element's ancestor in the final flattened tree
after all shadow trees have been applied.
If the node was repositioned by a content
element, then this attribute has the same value as the
parentNode
attribute of the
content
element responsible for the
repositioning in the deepest shadow scope, except if that
is the shadowTree
element at the top of the
shadow tree, in which case the xblParentNode
attribute has the same
value as the xblBoundElement
attribute of that content
element.
If the node is a node in a shadow tree that is not
currently in the final flattened tree (for example, the
shadowTree
element at the top of the shadow
tree is never in the final flattened tree), then this
attribute returns null
.
If the node is in a shadow tree and has the
shadowTree
element at the top of the shadow
tree as its parentNode
, then this
attribute returns the same value as the xblBoundElement
attribute.
If the node is in a shadow tree and has a
content
element that is not in error as its
parentNode
, then this attribute
returns the same value as the parentNode
attribute on the
content
element, except if that would
be the shadowTree
element at the top of the
shadow tree, in which case it returns the same as value as
the xblBoundElement
attribute.
If the node is a text node generated by
xbl:text
in attribute forwarding,
then this attribute returns the element that generated the
text nodes.
Otherwise it returns the same as the parentNode
attribute.
xblParentNodes
of type NodeList
, readonlyxblParentNode
is null
, this attribute returns an empty
list. Otherwise, the first value of this attribute is the
same as the xblParentNode
attribute, and subsequent values are found by the same
algorithm as described for xblParentNode
, ignoring each binding that
repositioned the node in turn, from the deepest shadow scope to
the document-level shadow scope, ignoring duplicates.
In brief, this attribute contains all the elements that
contain content
elements to which the node has
been assigned, as well as the explicit parent node, if that
node is itself in the final flattened tree.
xblChildNodes
of type NodeList
, readonlyxblChildNodes
attribute is
a NodeList that represents the children of the node after
content
elements have been applied. This
attribute can be used to navigate the content model
according to XBL after bindings have moved explicit and
shadow children using content
elements. The
attribute's value is the same as childNodes
if the node is not bound.xblNextSibling
of type Node
, readonlyxblParentNode
's xblChildNodes
list, or null
if xblParentNode
is null
or if the current node is the
last node in that xblChildNodes
list.xblPreviousSibling
of type Node
, readonlyxblParentNode
's
xblChildNodes
list, or null
if xblParentNode
is null
or if the current node is the
first node in that xblChildNodes
list.xblFirstChild
of type Node
, readonlyxblChildNodes
list, or null
if the list is empty.xblLastChild
of type Node
, readonlyxblChildNodes
list, or null
if the list is empty.xblNextElementSibling
of type Element
, readonlyxblParentNode
's
xblChildNodes
list, or null
if xblParentNode
is null
or if there are no elements past the
current node in that xblChildNodes
list.xblPreviousElementSibling
of type Element
, readonlyxblParentNode
's
xblChildNodes
list, or null
if xblParentNode
is null
or if there are no elements before
the current node in that xblChildNodes
list.xblFirstElementChild
of type Element
, readonlyxblChildNodes
list, or null
if the list contains no
elements.xblLastElementChild
of type Element
, readonlyxblChildNodes
list, or null
if the list contains no
elements.xblBoundElement
of type Element
, readonlyxblBoundElement
attribute
is used to obtain the bound element with the binding
attached that is responsible for the generation of the
specified shadow node. This attribute enables an author to
determine the shadow scope of any content node. For content
at the document-level scope, the attribute's
value is null
.xblShadowTree
of type Element
, readonlyxblShadowTree
attribute returns the
cloned copy of the template
element that
represents the shadow content template of the element. (That
element is renamed to shadowTree
during shadow
content generation.) For bound elements whose binding have
no shadow content template, and for elements that are not
bound, it returns null
.xblDefinitions
of type NodeList
, readonlydefinition
element for the binding. If
the binding chain contains multiple bindings, all the
definition
elements are listed, with the most
derived binding first and the base binding last.addBinding
addBinding
method attaches
the specified binding (and any bindings that the binding
inherits from) to an element. This call is not necessarily
synchronous. The binding may not be attached yet when the
call completes.
bindingURI
of type DOMString
removeBinding
removeBinding
method detaches
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
does nothing.
bindingURI
of type DOMString
hasBinding
hasBinding
method walks up
the bindings applied to the element
and compares each binding's URI with the parameter passed.
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. For example
widgets may walk up their ancestors looking for an element
that has been bound to the form-container binding in order
to locate their scope (so that radio buttons may properly
be mutually exclusive, or so that a submit button can
properly submit a form).
bindingURI
of type DOMString
boolean
true
if any of the
bindings match the parameter, false
otherwise.In effect the shadow content exists in its own insulated pocket
within the document, its shadow scope. Explicit parents 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.
The shadow scope of an element can be determined using the xblBoundElement
property on the NodeXBL
interface. This returns the bound element
in the enclosing shadow scope that is responsible for the shadow
node. If invoked on an element at the document-level
scope, it returns null
.
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 at the
document-level scope.
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 (that is, cloned
shadowTree
elements that can be accessed by an
xblShadowTree
attribute) cannot be inserted into a
document. Any attempt to do so must raise a HIERARCHY_REQUEST_ERR
.
When the DOM is navigated using the normal DOM Core attributes, starting from the document, the UA must represent the original DOM, with no XBL nodes and shadow content, and with children of bound elements in their original order.
The xblShadowTree
attribute on bound
elements returns the element that was cloned from the XBL
template
element. (That element is renamed to
shadowTree
during shadow content generation.)
Manipulating the shadow content tree must directly affect the
content under the bound element. content
elements may
be moved about or even removed altogether,
xbl:inherits
attributes may be attached and
modified, etc, and all these changes must be immediately
reflected in the DOM.
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).
Imagine the following document fragment:
... <A> <B> <C/> <D/> </B> </A> ...
...is bound to the following XBL:
<xbl:xbl xmlns:xbl="http://www.w3.org/2004/xbl"> <xbl:definition element="B"> <xbl:template> <P> <Q> <xbl:content includes="C"> <R/> </xbl:content> </Q> <xbl:content includes="D"> <S/> </xbl:content> </P> </xbl:template> </xbl:definition> <xbl:definition element="Q"> <xbl:template> <X> <Y> <xbl:content> <Z1/> </xbl:content> <xbl:content> <Z2/> </xbl:content> </Y> </X> </xbl:template> </xbl:definition> </xbl:xbl>
The resulting DOM would look like the following. To read these diagrams, use the following key:
| Solid/dashed lines represent normal DOM traversal attribute ---+--- relationships using childNodes, parentNode, nextSibling, | previousSibling, firstChild, lastChild, etc. : Dotted lines represent XBL traversal attribute relationships ...:... using xblChildNodes, xblParentNode, xblNextSibling, : xblPreviousSibling, xblFirstChild, xblLastChild, etc. ) xblShadowTree
White-space nodes have, for sanity, been left out of these diagrams.
DOM view:
| +-- A | +-- B | +-- C | +-- D
Clone of the shadow tree for B elements (B.xblShadowTree):
template | +-- P | +-- Q | | | +-- content | | | +-- R | +-- content | +-- S
Clone of the shadow tree for Q elements (Q.xblShadowTree):
template | +-- X | +-- Y | +-- content | | | +-- Z1 | +-- content | +-- Z2
The xbl traversal for the whole thing:
: :.. A : :.. B : :.. P : :.. Q : : : :.. X : : : :.. Y : : : :.. C : : : :.. Z2 : :.. D
The combined view of the DOM and XBL traversals of the whole thing:
:|___ :....A template :|___ ) | :... B | :| | :|... P template | :|____ ) | | :|... Q | | :| :| | | :| :|.... X | :| | :\_______ | :| | :....... Y __ | :| | : \ | :| +-- content* : | | :| | : | | :| +-- R : +-- content* | :| : | | +---:|--------- C* ......: | `-- Z1 | :| : | | :| : `-- content | :| : |___ | :| :............ Z2 | :`-- content# | : | | : `-- S |___:____ :... D#
In the following tree, the dashed lines show the additional
relationships that are contained in xblParentNodes
(with their indices in brackets),
the dotted lines represent the relationships that are in both xblParentNode
and xblParentNodes
(at index 0):
: :.. A : (2) :.. B <-----------------. : | :.. P | ^ : | | :.. Q <---------+ (1) | : : | (1) \ : :.. X | \ : : | \: :.. Y | : : | :\ :.. C : \ : : \ :.. Z2 : | :.. D
The XBLContentElement
interface is
implemented by content
elements that are
inside shadow template trees. It can be obtained using
binding-specific casting methods on the Element
interface.
interface XBLContentElement { void xblSetInsertionPoint(in Node child); };
xblSetInsertionPoint
xblSetInsertionPoint
method
checks that the given element is a child of the same bound
element as the shadow tree is itself associated with, and,
if it is, checks that the element matches this
content
element, and, if it does, assigns the
element to this content
element instead of
whatever previous content
element it was
assigned to.
The order of elements assigned to a content
element is always the same as the relative order of those
elements in the explicit DOM.
child
of type Element
content
element.Event
InterfaceObjects that implement the Event
interface must also implement the OriginalEvent
interface:
interface OriginalEvent { readonly attribute Event originalEvent; };
The originalEvent
attribute
must point to the event that was cloned the last time the event
was retargetted, if any, and must be null if the event was never
retargetted. (See: event flow and targeting across shadow
scopes.)
If an event is retargetted several times, a chain is formed using this attribute, from which script can access each clone of the event, finding the original target at each step.
The XBLShadowTreeElement
interface is
implemented by shadowTree
elements that are in the XBL
namespace.
interface XBLTemplateElement : Element { Element getElementById(in DOMString elementId); };
getElementById
This method is modelled after the method
of the same name defined by [DOM3CORE] on the Document
interface.
Returns the Element
that has
an ID attribute with the given value. If no such element
exists, this returns null
. If
more than one element has an ID attribute with that value,
what is returned is undefined.
The method shall only search through the
shadowTree
element and its descendants.
The DOM implementation is expected to use the attribute
Attr.isId
to determine if an
attribute is of type ID.
Attributes with the name "ID" or "id" are not of type ID unless so defined. For example, elements with the name "id" on elements that are in the XHTML, SVG and XBL namespaces are defined to be of type ID by their respective specifications.
elementId
of type DOMString
id
value for an element.Element
This entire section is new and needs to be reviewed.
The flowchart example should be close to correct, but it still requires careful review.
The various other RCC examples (GML, XForms, UI) from the last SVG 1.2 public draft have been copied from the SVG 1.2 draft and placed into this document (after modifications to upgrade RCC to sXBL). The examples at the end are just as incomplete as they were when they were part of the writeup on SVG12/RCC.
This section contains some examples of using sXBL with SVG 1.2.
In the following example, bindings are used to make three new elements act like coloured text blocks.
<svg:svg xmlns:svg="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl"> <svg:defs> <xbl:xbl> <xbl:definition element="red"> <xbl:template> <svg:text fill="red"><xbl:content/></svg:text> </xbl:template> </xbl:definition> <xbl:definition element="green"> <xbl:template> <svg:text fill="green"><xbl:content/></svg:text> </xbl:template> </xbl:definition> <xbl:definition element="blue"> <xbl:template> <svg:text fill="blue"><xbl:content/></svg:text> </xbl:template> </xbl:definition> </xbl:xbl> </svg:defs> <red> Red text. </red> <green> Green text. </green> <blue> Blue text. </blue> </svg:svg>
In the following example, an SVG file references a set of custom
elements for flowcharting from an external file using the import
element, and then uses the
flowcharting custom elements to lay out and render a flowchart:
<svg width="12cm" height="3cm" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl"> <desc>Example xbl02 - simple flowchart example using sXBL</desc> <!-- XPointer reference to the location for the flowchart extensions --> <xbl:import bindings="xbl02-flowcharts.svg#flowcharts"/> <!-- Define elements that use the flowchart extensions. As a result of using the extensions, a shadow tree of low-level SVG (circle, rect, path elements) is attached to the 'flowchart' element. The user agent renders the shadow tree. --> <flowchart xmlns="http://example.org/flowcharts" x="0%" y="0%" width="100%" height="100%"> <terminalNode>Start</terminalNode> <processNode>Step 1</processNode> <processNode>Step 2</processNode> <terminalNode>End</terminalNode> </flowchart> </svg>
View this image as SVG (SVG/sXBL-enabled browsers only)
Here is the file which defines the simple flowcharting extensions used in the example above:
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:flow="http://example.org/flowcharts"> <desc>Supplemental file for example xbl02.svg - contains definition of simple flowchart extension elements.</desc> <xbl:xbl id="flowcharts"> <!-- Example needs to be upgraded to show handling of mutation events --> <defs> <symbol id="connectorline"> <path transform="translate(0 50)" stroke="black" stroke-width="3" fill="black" d="M 0,0 L 90,0 L 90,-10 L 100,0 L 90,10 L 90,0"/> </symbol> </defs> <xbl:definition element="flow:terminalNode"> <xbl:template> <g> <circle stroke="#008" stroke-width="5" fill="none" cx="50" cy="50" r="50"/> <text x="50" y="57" font-size="25" text-anchor="middle"><xbl:content/></text> </g> </xbl:template> </xbl:definition> <xbl:definition name="flow:processNode"> <xbl:template> <g> <rect stroke="#080" stroke-width="5" fill="none" width="150" height="100" rx="10"/> <text x="75" y="57" font-size="25" text-anchor="middle"><xbl:content/></text> </g> </xbl:template> </xbl:definition> <xbl:definition name="flow:flowchart"> <!-- For this example, set up template with no extra whitespace to simplify the sample ECMAScript. --> <xbl:template><svg><xbl:content/></svg></xbl:template> <xbl:handlerGroup> <!-- Note: using the 'svg:handler' element that is new with SVG 1.2 --> <handler ev:event="xbl:bound" type="text/ecmascript"><![CDATA[ var svgns = "http://www.w3.org/2000/svg"; var xlinkns = "http://www.w3.org/1999/xlink"; var flowchartns = "http://example.org/flowcharts"; var ELEMENT_NODE = 1; var SIDE_INDENT = 50; var PROCESSNODE_WIDTH = 150; var TERMINALNODE_WIDTH = 100; var CONNECTOR_WIDTH = 100; var YPOS = 50; var flowchartelement = evt.target; var templateElement = flowchartelement.xblShadowTree; var svgElm = templateElement.firstChild; svgElm.setAttributeNS(null, "x", flowchartelement.getAttributeNS(null, "x")); svgElm.setAttributeNS(null, "y", flowchartelement.getAttributeNS(null, "y")); svgElm.setAttributeNS(null, "width", flowchartelement.getAttributeNS(null, "width")); svgElm.setAttributeNS(null, "height", flowchartelement.getAttributeNS(null, "height")); // Determine total width needed and set viewBox attribute appropriately. var totalWidth = 0; var nodeCount = 0; for( var node = flowchartelement.firstChild ; node != null ; node = node.nextSibling ) { // only process elements in flowchart ns if( node.nodeType == ELEMENT_NODE && node.namespaceURI == flowchartns) { nodeCount++; if (node.localName == "processNode") totalWidth += PROCESSNODE_WIDTH; else if (node.localName == "terminalNode") totalWidth += TERMINALNODE_WIDTH; } } totalWidth += (nodeCount-1)*CONNECTOR_WIDTH + 2*SIDE_INDENT; svgElm.setAttributeNS(null, "viewBox", "0 0 "+totalWidth+" 200"); var xtrans = 50; // Position all of the nodes and draw the connectors. var xpos = SIDE_INDENT; var nodeNum = 0; for( var node = flowchartelement.firstChild ; node != null ; node = node.nextSibling ) { // only process elements in flowchart ns if( node.nodeType == ELEMENT_NODE && node.namespaceURI == flowchartns) { node.xblShadowTree.setAttributeNS(null, "transform", "translate("+xpos+" "+YPOS+")"); var nodeWidth; if (node.localName == "processNode") { nodeWidth = PROCESSNODE_WIDTH; } else if (node.localName == "terminalNode") { nodeWidth = TERMINALNODE_WIDTH; } xpos += nodeWidth; // Add connector line to end of flowchart node's shadowTree. if (nodeNum < (nodeCount-1)) { var useElement = document.createElementNS(svgns, "use"); useElement.setAttributeNS(xlinkns, "xlink:href", "#connectorline"); useElement.setAttributeNS(null, "transform", "translate("+nodeWidth+" 0)"); node.xblShadowTree.appendChild(useElement); xpos += CONNECTOR_WIDTH; } nodeNum++; } } ]]></handler> </xbl:handlerGroup> </xbl:definition> </xbl:xbl> </svg>
The next example takes sample code from section 4.6 from the Geography Markup Language (GML) specification, version 2.1.2. The 'extensionDefs' element would effect a client-side transformation from original XML/GML into final-form SVG rendering.
<svg width="12cm" height="3cm" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xbl="http://www.w3.org/2004/xbl"> <desc>Example xbl-gml-01 - GML and XBL</desc> <!-- XPointer reference to the location for the GML extensions --> <xbl:import bindings="xbl-gml-01-exts.svg#gml"/> <CityModel xmlns="http://www.opengis.net/examples" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/examples city.xsd"> <gml:name>Cambridge</gml:name> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord><gml:X>0.0</gml:X><gml:Y>0.0</gml:Y></gml:coord> <gml:coord><gml:X>100.0</gml:X><gml:Y>100.0</gml:Y></gml:coord> </gml:Box> </gml:boundedBy> <cityMember> <River> <gml:description>The river that runs through Cambridge.</gml:description> <gml:name>Cam</gml:name> <gml:centerLineOf> <gml:LineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord><gml:X>0</gml:X><gml:Y>50</gml:Y></gml:coord> <gml:coord><gml:X>70</gml:X><gml:Y>60</gml:Y></gml:coord> <gml:coord><gml:X>100</gml:X><gml:Y>50</gml:Y></gml:coord> </gml:LineString> </gml:centerLineOf> </River> </cityMember> <dateCreated>2000-11</dateCreated> </CityModel> </svg>
The next example takes sample code from [Appendix G of the XForms
specification | http://www.w3.org/TR/xforms/sliceG.html ] . The
extensionDefs
element would effect a
client-side transformation from original XForms elements into
final-form SVG rendering. In this example, the assumption is that
the extension would implement all or at least a large part of the
XForms specification via DOM/scripting.
<svg width="12cm" height="3cm" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:xforms="http://www.w3.org/2002/xforms/cr" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xbl="http://www.w3.org/2004/xbl" xmlns:my="http://commerce.example.com/payment"> <desc>Example xbl-xforms-01 - using sXBL within a combined XForms+SVG user agent</desc> <title xml:lang="fr">XForms en SVG</title> <!-- XPointer reference to the location for the XForms extensions to SVG. The extensions convert the XForms UI elements into low-level SVG interactive graphics and also provide high-level features, such as client-side validation and the XForms event model. --> <xbl:import bindings="xbl-xforms-01-exts.svg#xforms"/> <rx:renderXForms xmlns:rx="http://example.org/rcc-xforms" xmlns="http://www.w3.org/2002/xforms/cr"> <model schema="payschema.xsd"> <instance> <my:payment as="credit"> <my:cc /> <my:exp /> </my:payment> </instance> <submission action="http://www.example.com/buy.rb" method="post" id="s00" /> <bind nodeset="my:cc" relevant="../@as='credit'" required="true()" /> <bind nodeset="my:exp" relevant="../@as='credit'" required="true()" /> </model> <group xmlns="http://www.w3.org/2002/xforms/cr"> <trigger> <label>Français</label> <toggle case="fr" ev:event="xforms-activate" /> </trigger> <trigger> <label>English</label> <toggle case="en" ev:event="xforms-activate" /> </trigger> </group> <input ref="my:cc"> <label xml:lang="fr">Numéro de carte bancaire</label> <alert xml:lang="fr">Saisissez un numéro de carte bancaire valide en séparant chaque groupe de chiffres d'un espace ou d'un trait d'union.</alert> </input> <input ref="my:exp"> <label xml:lang="fr">Date d'échéance</label> </input> <submit submission="s00"> <label xml:lang="fr">Achetez</label> </submit> </svg>
The next example supplements the XForms example above with the following simple example
which shows a set of extension elements
ui:menubar
,
ui:menu
,
ui:menuitem
)
which present a menubar and a scrolling area for graphics.
<svg width="525" height="575" xmlns="http://www.w3.org/2000/svg" version="1.2" xmlns:ui="http://example.org/xbl-ui"> <desc>Example xbl-ui-01 - using XBL for UI elements</desc> <title>UI in SVG</title> <!-- XPointer reference to the location for the UI extensions to SVG. The extensions convert the UI elements into low-level SVG. --> <xbl:import bindings="xbl-ui-01-exts.svg#ui"/> <ui:menubar x="25" y="25" width="500" height="20" font-size="14"> <ui:menu title=File> <ui:menuitem title=New op="newdoc(evt)"> <ui:menuitem title=Open op="opendoc(evt)"> </ui:menu> <ui:menu title=Edit> <ui:menuitem title=Copy op="copy(evt)"> <ui:menuitem title=Past op="paste(evt)"> </ui:menu> </ui:menubar> <ui:scrollArea x="25" y="50" width="500" height="400"> <image xlink:href="..." ... /> <path d="..." ... /> <text transform="..." font-size="...">...</text> </ui:scrollArea> </svg>
The last example shows XBL being used for custom container elements that perform layout, in this case a magazine layout.
<svg> ... <!-- XPointer reference to the location for the widgets extensions to SVG. The extensions convert the widget elements into low-level SVG. --> <xbl:import bindings="xbl-dynlayout-01-exts.svg#dynlayout" /> <foo:DynamicPageLayout> <foo:articles> <foo:article> <foo:title>Major war erupts</foo:title> <foo:para>War broke out around the world today...</foo:para> </foo:article> <foo:article> <foo:title>Two headed-chicken born</foo:title> <foo:para>The sleepy town of Frostbite Falls is excited about...</foo:para> </foo:article> </foo:articles> </foo:DynamicPageLayout> ... </svg>
The following defines the grammar for sXBL using RelaxNG.
<!-- ============================================================== sXBL 1.0 ~ simplied schema Robin Berjon <robin.berjon@expway.fr> 31/05/2004 ============================================================== --> <grammar ns='http://www.w3.org/2004/xbl' xml:lang='en' xmlns='http://relaxng.org/ns/structure/1.0' xmlns:a='http://relaxng.org/ns/compatibility/annotations/1.0' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes' > <!-- NOTES: - this is a simplified schema in that it does not define classes and other such constructs that would make it easier to integrate into the rest of the SVG schema - I seem to remember there was a bug in my RNG namespace wildcards. If so, it has been copied here (I have no reference handy). - I have followed the descriptions in the spec, so that if it says "zero or more foo" and then "zero or more bar", then the foos must occur before the bars. This can be changed. - there are some spec issues embedded in the comments --> <!-- ... common definitions .............................................. --> <define name='id.attrib'> <optional> <attribute name='id'> <data type='ID'/> </attribute> </optional> </define> <!-- ... elements ........................................................ --> <element name='xbl'> <zeroOrMore><ref name='definition'/></zeroOrMore> <zeroOrMore><ref name='import'/></zeroOrMore> <ref name='id.attrib'/> </element> <element name='definition'> <choice> <attribute name='ref'><data type='anyURI'/></attribute> <group> <optional><ref name='template'/></optional> <optional><ref name='handlerGroup'/></optional> <attribute name='element'><data type='QName'/></attribute> </group> </choice> <ref name='id.attrib'/> </element> <element name='template'> <ref name='id.attrib'/> </element> <element name='content'> <optional><attribute name='includes'><text/></attribute></optional> <ref name='id.attrib'/> </element> <element name='handlerGroup'> <!-- the content model for this element mentions ev:listener and svg:handler but is rather unclear as to what should be included here --> <ref name='id.attrib'/> </element> <element name='import'> <!-- this should really be either of xlink:href or src --> <optional><attribute name='bindings'><data type='anyURI'/></attribute></optional> <ref name='id.attrib'/> </element> </grammar>
This section will be removed before the Last Call draft of the sXBL specification.
With this first public draft of sXBL, the SVG 1.2 feature formerly known as RCC (Rendering Custom Content: http://www.w3.org/TR/2004/WD-SVG12-20040510/#rcc) has been factored out into its own reusable namespace and reconciled to be forward-looking for use by other XBL grammars.
The following table provides a quick summary comparison of how sXBL compares with the RCC (Rendering Custom Content) feature found in earlier drafts of SVG 1.2:
RCC | sXBL |
In RCC, the svg:extensionDefs element could use an xpointer to reference the binding definitions. If so, the xpointer had to point to a different svg:extensionDefs element, typically in a separate file. |
To accomplish the same functionality in sXBL, use the xbl:import element. In sXBL, there is more flexibility. The xpointer can point to either an xbl:xbl element, typically in a separate file, or to an SVG file which can contain any number of xbl:xbl elements, all of which get processed. |
In RCC, the 'namespace' attribute applied to all svg:elementDef children of the svg:extensionDefs element. |
In sXBL, the 'namespace' attribute is no longer needed. The 'element' attribute on the xbl:definition element takes a QName. The namespace prefix on the QName identifies the namespace for the custom element. |
In RCC, the 'name' attribute provided the localname of the custom element. The namespace for the custom element came from the 'namespace' attribute on the svg:extensionDefs element. |
In sXBL, the 'element' attribute identifies the custom element by a QName. The namespace prefix on the QName identifies the namespace for the custom element. The localname part of the QName completes the identification of the custom element. |
N/A in RCC |
In sXBL, it is possible to have the bound document associate custom elements with per-element bindings using the xbl:definition element with a 'ref' attribute. This allows the bound document (i.e., the document which contains the custom elements) to dictate how to associate its custom elements with the binding definitions (i.e., xbl:definition elements) found in another document. |
In RCC, svg:defs, svg:script, and svg:handler could appear in various locations within RCC definitions. |
In general, sXBL has the same rules. One addition with sXBL is the xbl:handlerGroup element, described below. |
In RCC, the svg:prototype contained an initial template for the elements which were cloned into the shadow tree for the custom element. The svg:prototype element was the root node of the set of elements which were rendered and received events. Because svg:prototype was part of the rendering and event pipelines, you were able to attach styling properties, transforms, and event attributes (the various attributes listed above) to the svg:prototype element. |
sXBL is nearly the same. Just like svg:prototype, xbl:template contained an initial template for the elements which are cloned into the shadow tree for the custom element. xbl:template is the root node of the xblShadowTree, in much the same way that svg:prototype element was the root node of the shadow tree. However, one distinction is that for rendering the xbl:template is flattened out of the rendering pipeline. Therefore, it is not possible to attach styling properties, transforms, and event attributes to an xbl:template; instead, you need to include a container element such as an <svg:g> element in the shadow tree if you need to attach styling properties, transforms, and event attributes. |
The latest public draft of RCC described these two elements (http://www.w3.org/TR/2004/WD-SVG12-20040510/#transformer-element), but warned the community that there features are "...likely to be removed from the next draft of SVG 1.2, due to the high burden on implementation and the difficulty in optimization." |
Not available In the transition from RCC to sXBL, <svg:transformer>, <svg:param> have been removed. |
In RCC, the svg:refContent allowed the shadow content to include-by-reference child elements of the custom element. The svg:refContent element was a container node for the referenced elements and was part of the rendering and event pipelines. Because svg:refContent was part of the rendering and event pipelines, you were able to attach styling properties, transforms, and event attributes (the various attributes listed above) to the svg:refContent element. |
The most important aspects of sXBL are the same. Just like svg:prototype, xbl:content does an include-by-reference to the child elements of the custom element. The exact name of the attribute (e.g., 'select' versus 'includes' is still under debate and the syntax of this attribute (xpath? tagnames? CSS selector syntax?) is also still under debate. The rules for what happens if there is a mismatch between the bound element's content and the set of xbl:content elements is also under debate. Finally, sXBL might include a backup content feature that was not available in RCC. One distinction with sXBL is that the xbl:content is flattened out of the rendering pipeline. Therefore, it is not possible to attach styling properties, transforms, and event attributes to an xbl:content; instead, you need to include a parent container element such as an <svg:g> element in the shadow tree if you need to attach styling properties, transforms, and event attributes. |
In RCC, told the user agent about custom attributes to enable animation of custom attributes and attachment of mutation event listeners. |
Moved out of RCC into SVG 1.2. These features will be defined within the SVG 1.2 specification and will not be part of the sXBL specification. |
In RCC, the SVGBindBegin event was raised just after cloning the svg:prototype but before recursively applying RCC bindings to the contents of the shadow tree. The SVGBindEnd event is raised after recursively applying RCC bindings to the elements which were cloned onto the shadow tree. |
In sXBL, the binding events are in the XBL namespace (http://www.w3.org/2004/xbl). xbl:prebind matches SVGBindBegin, and xbl:bound matches SVGBindEnd. sXBL adds an xbl:unbinding event so that script can be told when a binding is about to be unattached from a custom element. |
RCC detailed processing model The SVG 1.2 drafts were incomplete in various ways in describing the complete details of the RCC processing model. Some aspects were well-specified. Other aspects were designed but had not been committed to the public specifications yet. Some aspects of the processing model were not yet resolved. |
sXBL detailed processing model The sXBL specification is still under development. In general, the detailed processing model for sXBL is highly consistent with the detailed processing model for the parts of RCC that were described in early SVG 1.2 drafts. Some aspects of the sXBL processing model are still under discussion. |
Nigel McFarlane has kindly offered to write an appendix describing the differences between Mozilla's XBL and the sXBL language defined by this specification.
The membership of the XBL task force was drawn from the SVG and CSS working groups, and consisted of L. David Baron, Robin Berjon, Alex Danilo, Jon Ferraiolo, Darryl Fuller, Ian Hickson, David Hyatt, Dean Jackson, Christophe Jolif, Chris Lilley, Antoine Quint, Peter Sorotokin.