In this sample we will guide you step-by-step through the
creation of a client behavior, MyHoverBehavior, which is able to
programmatically change the CSS class associated with a DOM element in response
to its events. Figure 4 and 5 respectively correspond to the two run-time
snapshots of Sample 2.
Figure 4: Snapshot 1 for Sample 2

When you move the mouse over the <DIV> element in
yellow background in Figure 4, you will get the snapshot of Figure 5.
Figure 5: Snapshot 2 for Sample 2

Based on what you have learned in the previous sections, our
task is to encapsulate the client logic into a behavior. Now let us dissect the
logics in programming a behavior piece by piece.
Author's Note: Here we try to
simulate the style (in a separate location) of MS AJAX script library to define
the functionality for a property or method rather than in the commonly-used inline
style.
Prototype Definition
First, as usual, after registering the namespace and
defining constructor, we declare private properties, and specifying all the
property related get and set accessors, methods initialize
and dispose, and all the related event handlers in the
following prototype block.
Listing 4: Prototype block
ZXZSamples.MyHoverBehavior.prototype = {
_hoverElement : null,
_unhoverDelay : 0,
_hoverCount : 0,
_hoverHandler : null,
_unHoverHandler : null,
get_hoverElement: ZXZSamples$MyHoverBehavior$get_hoverElement,
set_hoverElement: ZXZSamples$MyHoverBehavior$set_hoverElement,
get_unhoverDelay: ZXZSamples$MyHoverBehavior$get_unhoverDelay,
set_unhoverDelay: ZXZSamples$MyHoverBehavior$set_unhoverDelay,
initialize: ZXZSamples$MyHoverBehavior$initialize,
dispose: ZXZSamples$MyHoverBehavior$dispose,
add_hover: ZXZSamples$MyHoverBehavior$add_hover,
remove_hover: ZXZSamples$MyHoverBehavior$remove_hover,
_onhover: ZXZSamples$MyHoverBehavior$_onhover,
add_unhover: ZXZSamples$MyHoverBehavior$add_unhover,
remove_unhover: ZXZSamples$MyHoverBehavior$remove_unhover,
_onunhover: ZXZSamples$MyHoverBehavior$_onunhover,
_delayedUnhoverHandler:ZXZSamples$MyHoverBehavior$_delayedUnhoverHandler
}
Here we defined field _hoverElement to
specify the DOM element the behavior would be bound to, field _unhoverDelay
to specify the maximum time limit the mouse hover over the target element (i.e.
after the _unhoverDelay second the target's style will
change acccordingly), and field _hoverCount only to
remember the count the mouse hover over the target element. The two handler
fields, _hoverHandler and _unHoverHandler,
are to represent delegates used by the behavior that route the mouseover/focus
and mouseout/blur events data to two corresponding event handlers, _onhover and _onunhover.
Initialization and Handling Events
Now, let us look into the method initialize.
Listing 5: initialize() method
function ZXZSamples$MyHoverBehavior$initialize() {
ZXZSamples.MyHoverBehavior.callBaseMethod(this, 'initialize');
this._hoverHandler = Function.createDelegate(this, this._onhover);
this._unHoverHandler = Function.createDelegate(this, this._unhoverDelay?
this._delayedUnhoverHandler :this._onunhover);
$addHandler(this.get_element(), "mouseover", this._hoverHandler);
$addHandler(this.get_element(), "focus", this._hoverHandler);
$addHandler(this.get_element(), "mouseout", this._unHoverHandler);
$addHandler(this.get_element(), "blur", this._unHoverHandler);
if (this._hoverElement){
$addHandler(this._hoverElement, "mouseover", this._hoverHandler);
$addHandler(this._hoverElement, "focus", this._hoverHandler);
$addHandler(this._hoverElement, "mouseout", this._unHoverHandler);
$addHandler(this._hoverElement, "blur", this._unHoverHandler);
}
}
Here, we first called method initialize
of base class. Next, we invoked the built-in global method Function.createDelegate
to bind two delegates, _hoverHandler and _unHoverHandler, to the event handlers _onhover
and _onunhover, respectively. Note if the user
specifies the property _unhoverDelay then we call
handler _delayedUnhoverHandler which will further wrap
handler _onunhover and better deal with the mouseover/focus
event delay problem via window.setTimeout method. Once the
delegates are created, they can be used to hook the related events directly to the
event handlers using MS AJAX $addHandler method. For
details about method $addHandler, you can refer to the official website of ASP.NET AJAX.
Next, let us discuss the two event handlers, whose codes are
listed as below.
Listing 6: _onhover handler
function ZXZSamples$MyHoverBehavior$_onhover(){
this._hoverCount++;
var handler = this.get_events().getHandler("hover");
if (handler) {
handler(this, Sys.EventArgs.Empty);
}
}
function ZXZSamples$MyHoverBehavior$_onunhover(){
this._hoverCount--;
if (this._hoverCount ==0){
var handler = this.get_events().getHandler("unhover");
if (handler) {
handler(this, Sys.EventArgs.Empty);
}
}
}
In the first handler function, we added 1 to the hover time
counter _hoverCount. Then we got the special handler associated with event "unhover"
from the Sys.EventHandlerList instance that was
maintained by parent Component. Finally, we fired the
special event. (Note, stored here in the handler
variable is a function that, when called, executes all the related handlers for
the specific event "unhover.")
In the second handler function, however, things were nearly
the opposite with those in the first. Here, only when the time counter equals to
0 can we fire the special event "unhover."
The Descriptor Block
Listing 7: Descriptor block definition
ZXZSamples.MyHoverBehavior.descriptor ={
properties: [
{ name: 'hoverElement', type: Object,isDomElement:true,readOnly:true},
{ name: 'unhoverDelay', type: Number}
],
events: [
{name: 'hover'} ,
{name: 'unhover'}
]
}
Note that the MS AJAX XML-script engine needs a type
descriptor to parse the markup code into an instance of a client component, therefore
only those client components that provide a type descriptor can be used in XML-script
code. Here, in behavior MyHoverBehavior, we exposed two
properties, hoverElement and unhoverDelay,
and two events, hover and unhover.
Using Behavior MyHoverBehavior
Note, in order to use the custom behavior, we would better
create the sample website (named MyHoverBehavior) using the "ASP.NET
CTP-enabled Website" template. For brevity, we only listed the xml-script
block.
Listing 8: Descriptor block definition
<script type="text/xml-script">
<span lang=FR><page xmlns:script="http://schemas.microsoft.com/xml-script/2005"</span>
<span lang=FRxmlns:cc="javascript:ZXZSamples"></span>
<components>
<control id="panel1">
<behaviors>
<cc:MyHoverBehavior unhoverDelay="300" >
<hover>
<setPropertyAction target="panel1"
property="element"
propertyKey="className" value="hover"/>
</hover>
<unhover>
<setPropertyAction target="panel1"
property="element"
propertyKey="className" value="start"/>
</unhover>
</cc:MyHoverBehavior>
</behaviors>
</control>
<application>
<load>
<setPropertyAction target="panel1" property="element"
propertyKey="className" value="start"/>
</load>
</application>
</components>
</page>
</script>
Here, we first declared a custom XML namespace named ZXZSamples. Next, we attached our custom behavior MyHoverBehavior to an HTML DIV element (with ID being 'panel1").
When the object Application was loaded, we initialized
the CSS style of the DIV element "panel1." Next, we defined two
events, hover and unhover, of
the custom behavior. With each of the two events fired, the CSS style of the
DIV element "panel1" would change accordingly.