Next, we'll find out how to add custom properties to XBL-defined elements.
JavaScript and the DOM provide access to get and set the properties of elements. With XBL, you can define your own properties for the elements you create. You can also add methods that can be called. That way, all you need is to get a reference to the element (using GetElementById or a similar function) and then get or set the additional properties and call the methods on it. You can also define default handling for events passed to the element such as mouse clicks and keypresses.
Properties and methods are defined with-in an implementation element, which should be a child of the binding element. With-in the implementation, you define individual property and method elements, one for each one that you want. The general syntax is as follows:
<binding id="element-name">
<content>
-- content goes here --
</content>
<implementation>
<property name="property-name-1"/>
<property name="property-name-2"/>
<property name="property-name-3"/>
.
.
.
<method name="method-name-1/>
-- method content goes here --
</method>
.
.
.
</implementation>
</binding>
|
Each property is defined using the property element. Often, properties would correspond to an attribute placed on the element such as value or disabled, but they do not have to.
The name attribute on the property element is used to indicate the name of the property. You can use the name from a script to get and set the value. The example below creates a button which generates and stores a random number. You can retrieve this same number multiple times by getting the number property from the button. Most of the work here is done in the onclick handlers. Later, we'll find out how to to move this to XBL.
XUL:
<box id="random-box" class="randomizer"/>
<button value="Generate">
onclick="document.getElementById('random-box').number=Math.random();"/>
<button value="Show"
onclick="alert(document.getElementById('test-id').number)"/>
XBL:
<binding id="randomizer">
<implementation>
<property name="number"/>
</implementation>
</binding>
|
A number property has been defined in the binding, which stores the random number. The two extra buttons set and get the value of this property. The syntax is very similar to getting and setting the properties of HTML elements. In this example, no content has been placed inside either the XUL box or its definition in XBL, which is perfectly valid.
This example isn't quite correct because the property is not assigned a default value. To do this, add the default value as the content of the property tag. For example:
<property name="number"> 25 </property> |
This will assign the value 25 as the default value of the number property. Actually, you can instead place a script inside the property tag that evaluates to the default value. That might be necessary if the value needs to be computed. For example, the following property is given a default value equal to the current time:
<property name="currentTime"> new Date().getTime(); </property> |
Sometimes you will want to validate the data that is assigned to a property. Or, you may want the value to be calculated dynamically as it's asked for. For example, if you want a property that holds the current time, you would want to have its value generated as needed.
You can use the onget and onset attributes to control this. Add each to the property element and set its value to a script which either gets or sets the value of the property.
For example, you could assign a script to the value of onget to calculate the current time. Whenever a script attempts to access the value of the property, the onget script will be called to retrieve the value. The script should return the value that should be treated as the value of that property.
The onset handler is similar but is called whenever a script attempts to assign a new value to the property. This script should store the value somewhere, or validate the value. For example, some properties might only be able to store numbers. Attempting to assign alphabetic text to such a property should fail.
The special variable val holds the value that the property should be assigned to. Use this to grab the value and validate it or store it. The onset property should also return the new value.
The following decribes what happens in a typical case:
There are two elements, one called 'banana' and the other 'orange'. They each have a custom property called 'size'. The following line of script is executed:
banana.size = orange.size; |
The onget and onset attributes are optional. You can set one or both or neither of them. If you don't set them, the value will be simply stored or retrieved as is with no special processing. This is what happened in the random number example earlier.
The property tag defines a property that is accessible by a script, with the syntax 'element.property'. It is common to have the properties match an attribute on the XBL-defined element. The following example maps a property to an attribute on an element.
<property name="value"
onget="return this.getAttribute('value');"
onset="return this.setAttribute('value',val);"
/>
|
Whenever a script attempts to get the value of the property, it is grabbed instead from the attribute on the element with the same name. Whenever a script attempts to set the value of a property, it is set as an attribute on the element. This is convenient because then you can modify the property or the attribute and both will have the same value.
You can use an alternate syntax for the onget and onset attributes that is useful if the scripts are longer. You can replace the onget attribute with a child element called getter. Similarly, you can replace the onset attribute with a setter element. The example below shows this:
<property name="number">
<getter>
return this.getAttribute('number');
</getter>
<setter>
var v=parseInt(val);
if (!isNaN(v)) return this.setAttribute('number',''+v);
else return this.getAttribute('number');"
</setter>
0
/>
|
This property will only be able to hold integer values. If other characters are entered, they are stripped off. If there are no digits, the value is not changed. This is done in the code inside the setter element. The real value of the property is stored in the number attribute.
You can use either syntax for creating get and set handlers.
You can make a property read-only by adding a readonly attribute to the property tag and setting it to true. Attempting to set the value of a read-only property will fail.
(Next) The next section shows how to add methods to XBL-defined elements.