Wednesday, February 20, 2008

Javascript is just a hashtable...

I'm still new to AJAX and JavaScript. I've been developing using static languages (C#, C++, and Java) for several years now, but I finally had to break into ASP.Net AJAX and javascript for a web app at work.

The first thing to remember about javascript is that it's just a hashtable. If you are using some 3rd party javascript control library AJAXControlToolkit and you don't like some behavior... overwrite it! That's right, all a method is is an entry in a hashtable.

We ran into a case at work where we had to modify the Calendar styling to display different color styles to different dates on the calendar when it popped up. For example all weekdays needed to have a yellow background. Unfortunatelly the calendar doesn't provide a hook to style random dates different ways. So I went and dug through CalendarBehavior.js which comes as part of the AjaxControlToolkit, and found that the calendar sets the style for each date using a method named _getCssClass. That is part of:

AjaxControlToolkit.CalendarBehavior.prototype = {
[...]
_getCssClass : function(date, part) {
/// <summary>
/// Gets the cssClass to apply to a cell based on a supplied date
/// </summary>
/// <param type="Date" name="date">The date to match</param>
/// <param type="String" name="part">The most significant part of the date to test</param>
/// <returns type="String">

if (this._isSelected(date, part)) {
return "ajax__calendar_active";
} else if (this._isOther(date, part)) {
return "ajax__calendar_other";
} else {
return "";
}
}
[...]
}

For those of you that don't know the prototype is basically the class definition, so all objects of the CalendarBehavior type that get created will have all elements (functions and variables) defined in the prototype.

So now that we've found the method we just need to overwrite in on client side. Here you have two options.

  1. You can overwrite the prototype and all Calendars on the page will used this updated version.

  2. Or you can update the mehtod for a specific instance.

Either way you need to register with AJAX for the onload event.
Sys.Application.add_load(InitCalendars);

Then create the InitCalendars function and set _getCssClass to your new implementation.

function InitCalendars()
{
AjaxControlToolkit.CalendarBehavior.prototype._getCssClass =
function(date, part) {
[Your updated code here]
}
}

Your othe option is basically the same except you can find the control you want to modify the code for by assigning a BehaviorID to the control. Then you can do the following in the InitCalendars function

$find('the behavior id you assigned')._getCssClass =
function(date, part) {
[Your updated code here]
}

So what's wrong with this approach
Well this isn't perfect. The "_" in front of the function name usually means that this is an internal piece of code not meant for outside use. This means that the function name may change or it may be removed without braking the "interface" of the prototype. You could verify that _getCssClass equals something in testing so some sort of notice will occur if the method changes or gets removed from use. That's all I have to say 'bout that...

I hope someone finds this useful. Let me know if you have a better way.

0 comments:

Post a Comment