Next, we'll find out how to add custom methods to XBL-defined elements.
Methods
In addition to adding script properties to the XBL-defined element, you can also add methods. These methods can be called from a script. Methods are the functions of objects, such as 'window.open()'. You can define custom methods for your elements using the method
<implementation>
  <method name="method-name">
    <parameter name="parameter-name1"/>
    <parameter name="parameter-name2"/>
    .
    .
    .
    <body>
      -- method script goes here --
    </body>
  </method>
</implementation>
A method declaration goes inside the implementationmethodparameterbody
The value of the name attribute becomes the name of the method. Similarly, the name attributes on the parameterparameterparameter
The body
function getMaximum(num1,num2)
{
  if (num1<=num2) return num2;
  else return num1;
}
XBL:
<method name="getMaximum">
  <parameter name="num1"/>
  <parameter name="num2"/>
  <body>
    if (num1<=num2) return num2;
    else return num1;
  </body>
</method>
This function, getMaximum, returns the largest of the values, each passed as a parameter to the method. Note that the less-than symbol has to be escaped because otherwise it would look like the start of a tag. You can also use a CDATA section to escape the entire block of code. You can call the method by using code such as 'element.getMaximum(5,10)' where element is a reference to an element defined by the XBL containing the getMaximum method. (The bound element.)
The parameter
Methods are only available to call after the page is rendered, which may cause problems if using createElement. For example, the following code will probably fail:
var element = document.createElement("my_element");
element.getMaximum() // this will fail
By the way, it is safe to call methods from the constructor, other methods on the object and event handlers.
Accessing the Anonymous Content
There may be times when you want to modify some aspect of the elements defined in the content
Elements with an XBL behavior attached to them have a special property which holds an array of the anonymous child elements inside it. Each element of the array stores each direct child element of the XBL-defined element. This special property cannot be accessed directly. Instead, you must call the document's getAnonymousNodes()
var value=document.getAnonymousNodes(element);
Here, 'element' should be set to a reference to the element that you want to get the anonymous content of. The function returns an array of elements, which is the anonymous content. To get elements below that, you can use the regular DOM functions because they aren't hidden. Note that it is possible for an XBL-bound element to be placed inside another one, in which case you will have to use the getAnonymousNodes()
The following example creates a row of buttons:
<binding id="buttonrow">
  <content>
    <button label="Yes"/>
    <button label="No"/>
    <button label="Sort Of"/>
  </content>
</binding>
To refer to each button, you can use the getAnonymousNodes()getAnonymousNodes()
The next example can be used to create text with a label. The method 'showTitle' can be used to show or hide the label. It works by getting a reference to the title element using the anonymous array and changing the visibility of it.
XUL:
<box id="num" class="labeledbutton" title="Number of Things:" value="52"/>
<button label="Show" oncommand="document.getElementById('num').showTitle(true)"/>
<button label="Hide" oncommand="document.getElementById('num').showTitle(false)"/>
XBL:
<binding id="labeledbutton">
  <content>
    <xul:label xbl:inherits="value=title"/>
    <xul:label xbl:inherits="value"/>
  </content>
  <implementation>
    <method name="showTitle">
      <parameter name="state"/>
      <body>
        if (state) document.getAnonymousNodes(this)[0].
          setAttribute("style","visibility: visible");
        else document.getAnonymousNodes(this)[0].
          setAttribute("style","visibility: collapse");
      </body>
    </method>
  </implementation>
</binding>
Two buttons added to the XUL have oncommandcontent
Accessing from Inside the Anonymous Content
To go the other way, and get the bound element from inside the anonymous content, you can use the getBindingParent method of the document to get the element that the binding is bound to. You can also use the the parentNode property to go up by a single node, but the getBindingParent method is useful for a node that is nested several levels deep. For example, we could move the Show and Hide buttons into the XBL file and do the following:
var el = env.locale; Example 1 : Source
<binding id="labeledbutton">
  <content>
    <xul:label xbl:inherits="value=title"/>
    <xul:label xbl:inherits="value"/>
    <xul:button label="Show" oncommand="document.getBindingParent(this).showTitle(true);"/>
    <xul:button label="Hide" oncommand="document.getBindingParent(this).showTitle(false);"/>
  </content>
  <implementation>
    <method name="showTitle">
      <parameter name="state"/>
      <body>
        if (state) document.getAnonymousNodes(this)[0].setAttribute("style","visibility: visible");
        else document.getAnonymousNodes(this)[0].setAttribute("style","visibility: collapse");
      </body>
    </method>
  </implementation>
</binding>
The oncommandlabeledbutton class). Then, the 'showTitle' method is called, which functions as it did before.
Custom properties and methods are added only to the outer XUL element the XBL is bound to. None of the elements declared inside the content
The children of an element placed in the XUL file can be retrieved in the normal way and don't move even if you use the children
XUL:
<box id="outer" class="container">
  <button label="One"/>
  <button label="Two"/>
  <button label="Three"/>
  <button label="Four"/>
</box>
XBL:
<binding id="labeledbutton">
  <content>
    <description value="A stack:"/>
    <stack>
      <children/>
    </stack>
  </content>
</binding>
If you use the DOM functions such as childNodes to get the children of the the XUL box element with the id of outer, you willl find that it has has 4 children. These correspond to its four buttons, even though those buttons are drawn inside the stack. The stack has only one child, the childrendescriptionstack
Constructors and Destructors
XBL supports two special methods created with separate tags, constructordestructor
There are two points when a binding is attached to an element. The first occurs when a window is displayed. All elements that have XBL-bound content will have their constructors invoked. The order that they are called in should not be relied upon, as they are loaded from various files. The window's onload-moz-binding style property of an element. The existing binding will be removed, after its destructor is called. Then, the new binding will be added in its place and its constructor invoked.
The script for a constructor or destructor should be placed directly inside the appropriate tag. There should only be at most one of each per binding and they take no arguments. Here are some examples:
<constructor>
  if (this.childNodes[0].getAttribute("open") == "true"){
    this.loadChildren();
  }
</constructor>
<destructor action="saveMyself(this);"/>
The next section shows how to add event handlers to XBL-defined elements.