Saturday, September 13, 2008 1:19 PM Aurelien

[ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

As we seen in my last post, declarative is very powerful. Let's now see how simple it is to use his own custom behavior.

First of all, we need to create a behavior. In this example, we will use a simple HoverBehavior. His goal is just to swap a CSS class when mouse is over a DOM element.

To create a behavior, you'll need to:

  • Inherits from Sys.UI.Control
  • Override initialize and dispose methods
  • Implement your behavior logic

Our behavior is really simple, only one public property to define the hoverCssClass, the actual one is internally track into a private member.

Aurelien.UI.HoverBehavior.prototype = {
    _actualCssClass: '',                                            // Private member used to track original css class
    _hoverCssClass: '',                                             // Private member for hoverCssClass Property
    _hoverHandler: null,                                            // Private member used to track hover handler
    _blurHandler: null,                                             // Private member used to track blur handler
    initialize: Aurelien$UI$HoverBehavior$initialize,               // Initialize override
    dispose: Aurelien$UI$HoverBehavior$dispose,                     // Dispose overrive
    _hover: Aurelien$UI$HoverBehavior$_hover,                       // Private method used to handle hover event
    _blur: Aurelien$UI$HoverBehavior$_blur,                         // Private method used to handle blur event
    get_hoverCssClass: Aurelien$UI$HoverBehavior$get_hoverCssClass, // hoverCssClass getter
    set_hoverCssClass: Aurelien$UI$HoverBehavior$set_hoverCssClass  // hoverCssClass setter
}
 
Aurelien.UI.HoverBehavior.registerClass('Aurelien.UI.HoverBehavior', Sys.UI.Control);

If you wonder why I'm using this strange "$" syntax in function name then you should have a look to Bertrand Leroy's post around JavaScript Stack Trace.

In the Initialize override, we define and attach event handlers for "mouseover" and "mouseout":

function Aurelien$UI$HoverBehavior$initialize() {
    if (arguments.length !== 0) throw Error.parameterCount();
    if (this._hoverHandler == null) {
        this._hoverHandler = Function.createDelegate(this, this._hover);
        $addHandler(this.get_element(), 'mouseover', this._hoverHandler);
    }
    if (this._blurHandler == null) {
        this._blurHandler = Function.createDelegate(this, this._blur);
        $addHandler(this.get_element(), 'mouseout', this._blurHandler);
    }
    Aurelien.UI.HoverBehavior.callBaseMethod(this, 'initialize');
}

Don't forget to release them in the Dispose override:

function Aurelien$UI$HoverBehavior$dispose() {
    if (arguments.length !== 0) throw Error.parameterCount();
    if (this._hoverHandler != null) {
        $removeHandler(this.get_element(), 'mouseover', this._hoverHandler);
        this._hoverHandler = null;
    }
    if (this._blurHandler != null) {
        $removeHandler(this.get_element(), 'mouseout', this._blurHandler);
        this._blurHandler = null;
    }
    Aurelien.UI.HoverBehavior.callBaseMethod(this, 'dispose');
}

Last part is around events handling. We track the actual CSS class and swap to hoverCssClass in the "mouseover" event handler to set it back through "mouseout" one:

function Aurelien$UI$HoverBehavior$_hover(eventElement) {
    this._actualCssClass = this.get_element().className;
    this.get_element().className = this.get_hoverCssClass();
}
 
function Aurelien$UI$HoverBehavior$_blur(eventElement) {
    this.get_element().className = this._actualCssClass;
}

Let's now take a look to the declarative part of this example.

We first need some CSS classes:

.HoverCountry
{
    color: Red;
}
.HoverCity
{
    color: Blue;
}

To use our own behavior, we need to include our JavaScript file through ScriptManager:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="false" EnablePageMethods="false"
    EnablePartialRendering="false" EnableSecureHistoryState="false">
    <Scripts>
        <asp:ScriptReference Path="~/AjaxPreview2/MicrosoftAjaxTemplates.debug.js" />
        <asp:ScriptReference Path="~/Aurelien.UI.HoverBehavior.debug.js" />
    </Scripts>
</asp:ScriptManager>

We also need to declare a namespace on the <body> tag:

<body xmlns:sys="javascript:Sys" 
      xmlns:dataview="javascript:Sys.UI.DataView" 
      xmlns:hover="javascript:Aurelien.UI.HoverBehavior"
      sys:activate="dataview1">

We're now ready to use our behavior declaratively in our template:

<div id="dataview1" class="sys-template" sys:attach="dataview" dataview:data="{{ arrayCountries }}">
    <ul>
        <li sys:attach="hover" hover:hovercssclass="HoverCountry">{{ CountryName }}
            <ul class="sys-template" sys:attach="dataview" dataview:data="{{ Cities }}">
                <li sys:attach="hover" hover:hovercssclass="HoverCity">{{ CityName }}</li>
            </ul>
        </li>
    </ul>
</div>

And here's the result:

declarativecustombehavior

Tips:

As you can see in the template, the behavior property is lowercased.

Actually, if you want to use hover:hoverCssClass as defined in the behavior, don't use the .debug.js version of the preview because it will throw an InvalidOperationException: "Invalid attribute name 'hoverCssClass'. Declared attribute names must be in lowercase".

Seem's strange? Actually not. For me, there is two reasons for that. First one is technical, if you look at the JavaScript code, all the string comparison around object/method properties are in lowercase. The second reason, for me, is that the Framework ensure the XHTML Compliance Rule: Attributes names should be in lowercase.

Exception is not thrown with the release version of the JavaScript file because compacted version doesn't contains exceptions handling.

Filed under: , , , ,

Comments

# re: [ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

Saturday, September 13, 2008 2:25 PM by InfinitiesLoop

The reason for requiring lowercase attribute names isn't only because it's an XHTML rule. Some browsers actually convert attribute names to lower case, even if they are declared otherwise. Rather than allow mixed case attributes to work in IE, which doesn't do that, and not work in other browsers, we just enforce it for all browsers.

# re: [ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

Monday, September 15, 2008 2:06 PM by Bertrand Le Roy

You could save a lot of code in initialize by using $addHandlers, which creates several handlers in one line, and also takes care of creating the delegates for you. Also, you should use Sys.UI.DomElement.addCssClass and the corresponding remove method instead of just overwriting the whole class. Cool stuff. Thanks for the great posts.

# re: [ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

Thursday, February 23, 2012 10:36 PM by Evangelist

Wow, sreupb blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your web site is magnificent, let alone the content!

# re: [ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

Saturday, February 25, 2012 4:48 AM by asrzibxw

J3WWeL  <a href="xfrxrbqjgcxy.com/.../a>

# re: [ASP.NET AJAX] - CodePlex Preview 2 - Declarative Custom Behavior

Wednesday, February 29, 2012 1:46 PM by nwwivgdupr

WjxmZT  <a href="nmykylkrnfkt.com/.../a>

Leave a Comment

(required) 
(required) 
(optional)
(required)