Binding Attachment and Detachment

Attachment using CSS

Bindings can be attached to elements through CSS using the -moz-binding property.

-moz-binding
Value: none | [,]* <uri> | inherit
Initial Value: none
Applies to: all elements (not generated content or pseudo-elements)
Inherited: no
Percentages: N/A

The value of the -moz-binding property is a set of URLs that identify specific bindings. An individual URL in the set consists of the binding document's URL and the binding's document-unique identifier.

In the following example, a binding is referenced that will be attached to all HTML checkbox elements.

input[type="checkbox"] {
  -moz-binding: url("http://www.mozilla.org/xbl/htmlBindings.xml#checkbox");
}

Bindings attached through CSS will 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) will be detached.

No bindings will be attached to elements that match the style rule, but are inside an element that has style display:none set. See bug 307098.

Whenever an element is removed from a document, any bindings attached via CSS loaded by the document will be detached.

Attachment using element.style property

None of the XBL inheritance properties of element.style.MozBinding described here are implemented (if ever).

Bindings can be attached to elements through the scripting by assigning the element.style.MozBinding property. Respectively bindings can be detached by setting element.style.MozBinding to empty string.

Note: Some older papers mentioned DOM methods document.addBinding and document.removeBinding; these were subsequently discarded as redundant and not implemented.
var checkbox = document.getElementById("mycheckbox");
checkbox.style.MozBinding =
 "url(http://www.mozilla.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. See Binding Documents for more information.

When a binding is attached using the DOM, it inherits from the current most derived binding that may already be attached to the element. Any bindings attached to an element will remain on the element until the element is destroyed or the corresponding style rule is removed.

If a binding is attached and it already specifies an inherited binding using the extends attribute, then the base binding at the end of the inheritance chain is the one that will inherit from the most derived binding that is already attached.

For example, given a binding d1, with an explicit inheritance chain of

d1 -> d2 -> d3

If this element is attached to an element using element.style.MozBinding that already has a binding chain of

s1 -> s2 -> s3

the resulting binding chain following the addition of the binding is

d1 -> d2 -> d3 -> s1 -> s2 -> s3

The inheritance between d3 and s1 is implicit, meaning that there is no connection in the XBL documents between the two bindings. The inheritance link has been forged dynamically through the invocation of the element.style.MozBinding.

<constructor> call

As a document is loaded and style rules are matched for elements, any binding documents that are encountered will load as needed. Binding document loads suppress the firing of the DOM load event for the bound document. When the load event fires, and if all binding documents loaded successfully, it can be assumed that all bindings are attached to all elements in the page. For elements that are created during or after the load event is fired, no assumptions can be made regarding order of binding attachment.

When a binding is attached, the following events occur:

  • If required, anonymous content is cloned from the binding's content template and inserted around the bound element.
  • The methods and properties of the binding are installed on the element and become available to scripts that reference the bound element.
  • Any specified event handlers are installed on their requested targets.

If the binding needs to execute any initialization code following its attachment to an element, it can do so using a <constructor> block inside <implementation> section. This block contains script that executes upon completion of the binding attachment. Within this block this refers to the bound element.

<destructor> call

Bindings attached through CSS are detached when any of the following conditions are met:

  • A bound element matches a style rule that specifies a different binding
  • The element is removed from the bound document
  • The element is destroyed (e.g., by closing the document)

Bindings attached through the DOM are detached when the following conditions are met:

  • MozBinding style rule is removed
  • The element is destroyed (e.g., by closing the document)

When a binding is detached, the following events occur:

  • Anonymous content generated by the binding is destroyed.
  • Methods and properties with getters/setters are no longer accessible from the binding, although properties with raw values remain.
  • Any specified event handlers are unhooked from their respective targets.

A binding can specify a <destructor> block within <implementation> section that executes prior to the binding detachment. Using a <destructor> block, a binding can perform any necessary cleanup before it is torn down.

Bindings in an inheritance chain are always detached from the most derived binding to the base. Therefore the <destructor> block of the derived binding will execute, and then the base binding's block will execute.

When bindings attached through style are detached because of a style change, they have no effect on any other bindings attached using the DOM. Those bindings will stay installed. If new bindings are attached through CSS, they are installed after the DOM bindings in the inheritance chain.

For example, given a bound element with a binding chain of

d1->d2 ->d3 ->s1 ->s2 ->s3

withs1 representing the binding attached via CSS. If a resolution of style on the bound element determines that a new bindingt should be attached, then the following binding chain is detached:

s1->s2 ->s3

and the new binding is attached. The final inheritance chain is:

d1->d2 ->d3 ->t

When bindings are detached using element.style.MozBinding, any base bindings that were attached through the extends attribute on the binding will also be removed. In other words, a removal of element.style.MozBinding will remove the same group of bindings that were installed via the original call to element.style.MozBinding = "url(...)".

The rule for detachment can be summarized as follows. Whenever a binding is detached, all bindings that it explicitly inherits from are also detached.

Binding Documents

Whenever a binding is attached to an element in another document, the binding document is only fetched if no binding from the binding document has been used before in the bound document. A given bound document has a unique copy of each separate binding document that it uses.

All bindings from the same binding document URL that are used in a bound document will share the same binding document. Therefore if all the bindings in a chain come from binding documents that have already been loaded by the bound document, then the attachment of a binding (either through CSS or through the DOM) is guaranteed to be synchronous.

An author can ensure that all bindings are synchronously attached by calling loadBindingDocument to pre-fetch any XBL documents that are required. If the binding document is loaded prior to the firing of the load event, then any binding attachments that are placed following the load will be synchronous if they come from one of these previously loaded binding documents.

The document obtained from loadBindingDocument is a copy of the binding document that is unique to the bound document. The bindings in the binding document can be modified using standard DOM APIs. Any subsequent binding attachments that occur on elements in the bound document for bindings in the binding document use the modified copy. Therefore new binding definitions can be generated dynamically or the anonymous content templates for bindings can be altered and used by the bound document.