They usually provide a binding object with a specific function like copying and saving some data or showing and hiding widget controls.. Like properties, they can be called from within t
Trang 1Chapter 7 Extending the UI with XBL- P2
The code you see here is not necessary in this binding, but it shows you the format for executing code in the destructor Destructors are great to use when you have loaded a component in the binding and want to set the
variable representing the component to null to avoid memory leaks If you have a lot of bindings that load and then unload components while a Mozilla session is still running, a significant amount of memory can be eaten up unless you take this kind of step
7.2.3.3 Properties
Like Java properties, an XBL <property> has getters and setters, so they can behave differently when you read or write data Here is a subset of properties used in this binding:
<property name="value" readonly="true">
<getter>
return this.input.value;
</getter>
</property>
<property name="uppercase" readonly="true"
onget="return this.value.toUpperCase( );"/>
<property name="backgroundColor">
<getter>
Trang 2return
this.input.inputField.style.backgroundColor;
</getter>
<setter>
this.input.inputField.style.backgroundColor=val; return val;
</setter>
</property>
At this point, the characteristics of properties to watch out for include the readonly attribute, the getter and setter elements, and the existence of a val keyword that is used internally for accessing a property's current value For your reference, this binding's property extracts are used for getting the value of the input field, returning an uppercase version of the inputted text, and getting or setting the input field's background color
7.2.3.4 Methods
Methods in XBL are self-contained functions represented by the <method> tag and encapsulated within the <implementation> element They usually provide a binding object with a specific function like copying and saving some data or showing and hiding widget controls Like properties, they can be called from within the binding, from another binding that
subclasses that binding, and directly from the bound element
<method name="clear">
<body>
Trang 3this.input.value='';
</body>
</method>
<method name="setValue">
<parameter name="newValue"/>
<body>
this.input.value=newValue;
</body>
</method>
The method code is contained in a <body> tag, and each method can have 0
or more parameters, which gather the values passed into the method when called
7.2.4 Handlers
Handlers in XBL mimic regular document events like onclick and
onmousedown, and provide a means for trapping them within your binding and carrying out tasks associated with them
<handlers>
<handler event="mouseover">
this.input.focus( );
</handler>
</handlers>
Trang 4Each handler is contained in a <handler> tag and the event name is
placed in the event attribute minus the "on" prefix The handler in the code shown above places the focus in the inputfield when the mouse goes over it See the section "Event Handling," later in this chapter, for more details
7.2.5 Style
The sample binding's last piece of the puzzle is style Any XUL elements used in the content inherit the default styles for those widgets, but if you want to add more, you can include your own stylesheet like this:
<resources>
<stylesheet src="inputfield.css"/>
</resources>
Notice the <resources> container element, which is a prerequisite for this feature The use of stylesheets in bindings is covered more thoroughly at the end of the chapter in the section Section 7.7
At this point, you should be familiar with the pieces that make up a binding, which, at the top level, are the content, implementation, event handlers, and extra resources The binding that you have constructed is small, yet it shows all the main concepts involved in structuring a binding With some
personalizing, it could be included in potentially any application
7.3 Adding Behavior to Bindings
Like XUL widgets, XBL uses JavaScript to provide functionality to bindings
by accessing XPCOM methods via XPConnect Like binding content,
behavior is optional in a binding Each can exist without the other At times,
Trang 5you might want only implementations, such as a base binding that contains certain properties that are inherited by other bindings
The <implementation> element is the container for all other elements that make up a binding's behavioral portion Example 7-1 shows an empty implementation shell that highlights the element's contained hierarchy
Example 7-1 XBL implementation element
<implementation>
<constructor />
<destructor />
<method name="">
<parameter name="" />
<body />
</method>
<property>
<getter />
<setter />
</property>
<field />
</implementation>
The code in Example 7-1 shows the <implementation> element having
a constructor, destructor, method, property, and field as possible children Each component can exist in quantities of zero or more, with the exception
of the constructor and destructor, of which there can be only zero or one
Trang 6The rest of this section describes each binding implementation component in more detail
7.3.1 Binding Methods
Bindings can exist solely as content generators, acting passively when they are drawn But you can also create bindings that provide new capabilities and more interactive functions or that execute routines in your application
In the spirit of self-containment, functions can be added to a binding that carry out functionality related to that binding These functions are the
behavior of a binding The ideal way to add behavior is to add methods to your binding with the <method> element Each parameter for a method defined in the <method> element is contained within its own
<parameter> tag
<method name="dumpString">
<parameter name="aString1"/>
<parameter name="aString2"/>
<body>
<![CDATA[
if (!aString1 && aString2)
return;
return dump(aString1+" "+aString2+"\n");
]]>
</body>
</method>
Trang 7To use the method to print text to the command shell, call the name that is specified in the name attribute All methods created in a binding are added
to the binding element object and called as members of that object, as shown here:
<mybinding id="myNewWidget">
<image
src="http://www.mozdev.org/sharedimages/header.gif" />
</mybinding>
<button label="test method"
oncommand="document.getElementById('myNewWidget')
.dumpString('hello', 'there!');"/>
Using the <![CDATA XML entity is also important The purpose of
<![CDATA is to escape JavaScript that may otherwise cause conflicts with the XML parser Having characters like quotes and slashes in XML is
problematic when they are not escaped Using <!CDATA with large portions
of JavaScript in a binding can improve performance and minimize bugs Methods were designed for language neutrality with the type attribute and getter and setter elements Currently, bindings support only JavaScript,
which is the default when no type is specified However, this may change as other scripting engines are plugged into Gecko
7.3.1.1 Attachment and detachment
Trang 8Two special methods exist in XBL that allow you to manipulate what
happens when a binding is added or removed from a document These
methods use the native <constructor> and <destructor> tags A constructor is valuable, for example, when you need to initialize a binding object or prefill the UI based on stored values Destructors can clean up when a binding is discarded
When bindings are attached, their content is inserted into the document at the point you specify After insertion or, more specifically, after the
attachment occurs the code in the <constructor> executes Similarly, you can use the <destructor> element to execute functions when a binding is destroyed
<implementation>
<constructor>
<![CDATA[
dump("\n********\nCreate\n********\n");]]>
</constructor>
<destructor>
<![CDATA[
dump("\n********\nDestroy\n********\n");]]>
</destructor>
</implementation>
This example prints some text to output, but you can include code that
carries out variable initialization or anything else you want to occur at these stages of the binding's life Bound elements constructed before the document
Trang 9load event execute this script before the document load event fires In the case of extended bindings, base handlers are fired first, followed by derived handlers
7.3.2 Binding Properties
Properties on a binding are included by using the <property> element Fundamentally, properties are used to hold and manipulate values that are used elsewhere in the binding, such as when a text widget has its displayed value changed periodically by the application Currently, there are two
classifications for properties, one of which gets a raw value directly on the element
<property name="someAttribute">
false;
</property>
This example always sets the attribute named someAttribute to false Though still supported, this use of the <property> element was replaced
by a new element called <field> Although it is not in the XBL 1.0
specification, the <field> element is implemented and used in the Mozilla code base It has the same syntax but a different name We recommend using the <field> element
<field name="someAttribute">
false;
</field>
Trang 10The second property usage defines functions that are carried out when
getting and setting a property's value Take this anonymous content with a label child:
<xul:box align="left" flex="1">
<xul:label xbl:inherits="value=title"/>
<xul:spacer flex="1"/>
</xul:box>
This content simply shows some text on the screen The bound element that uses this content looks like this:
<mybinding id="my-binding" title="For Those Who Love to Use XBL" />
The XUL label used in the binding inherits the title attribute value that
is set on the bound element Example 7-2 shows how to set this title and its retrieval Both access the bound element, and any changes filter down to the label
Example 7-2 An XBL property setting and getting a value
<property name="title">
<setter>
<![CDATA[
this.setAttribute('title',val); return val;
]]>
</setter>
<getter>
Trang 11<![CDATA[
return this.getAttribute('title');
]]>
</getter>
</property>
The script keyword val is used internally to represent the latest property value The request to change the property or retrieve its value can come from another property in the same binding (this.<propertyName>), from a binding method, or from a method in the bound document that accesses the binding object directly This JavaScript sets the value of a property named title on the binding object:
var titleElement =
document.getElementById("my-binding");
titleElement.title = "The Adventures of an XBL
hacker";
You can use the onget and onset attribute as an alternative to
<getter> and <setter> elements Properties are initialized after the content is generated but before the binding attached event is set off This ensures that all properties are available once that event occurs