What I like about Atlas: Behaviors

So I've been hacking away with Atlas now for the better part of two months.  As I got to playing with it, what I really focused in on was behaviors and control extenders.  You can really improve a website's experience without much pain by using them.

A behavior is a class written in Javascript that kind of attaches itself to a running element in the browser.

A control extender is an ASP.NET server-side control that helps you connect a control on the page to your behavior.  I'll talk about those later.

Behaviors are cool mostly because the Atlas script framework is super sweet.  I've always hated programming in script for a couple of reasons.  One of them hasn't gotten any better, so far at least, and that's that the tools experience around script is pretty weak.  No compiler, a minimal debugger, almost no Intellisense, etc.  The other issue is that it's just kind of scattered all over the place.  It's in random blocks through the HTML file, or in quotes as attribute values of tags or whatever.  Ick.

The script framework allows me to do away will all of that.  The framework puts some structure around the world, so even without the tooling, I'm able to do things much more effeciently.

Imagine a basic behavior that pops up a confirm box when you click a button.  To do this in script, it's something like:

<asp:Button ID="Button1" runat="server" Text="Button"

OnClientClick="return confirm('are you sure?');" />

Which isn't too bad but it's error prone, completely non-debuggable, and I have to sprinkle it all over my website, even though it's not a lot of code, and if there's something wrong with it (e.g. the above doesn't work in Mozilla), it's tough to change.  Of course, I could break the functionality out into a, er, function, but it doesn't greatly improve things.

Atlas gives me a nice way to handle this with a behavior.  Now, the following is a lot more code, but it's boilerplate, and it's maintainable and easily extensible if I decide I want to add more features.  The part that's specific to this guy is in bold:

Type.registerNamespace(

'MyNS');

MyNS.ConfirmButtonBehavior =

function() {

MyNS.ConfirmButtonBehavior.initializeBase(

this);

var _ConfirmTextValue;

var _clickHandler;

this.initialize = function() {

MyNS.ConfirmButtonBehavior.callBaseMethod(

this, 'initialize');

// Initialize member variables

_clickHandler = Function.createDelegate(

this, this._onClick);

// Attach event handlers

this.control.element.attachEvent("onclick", _clickHandler);

}

this.dispose = function() {

// Detach event handlers

if (_clickHandler) {

this.control.element.detachEvent("onclick", _clickHandler);

_clickHandler =

null;

}

MyNS.ConfirmButtonBehavior.callBaseMethod(

this, 'dispose');

}

this.getDescriptor = function() {

var td = MyNS.ConfirmButtonBehavior.callBaseMethod(this, 'getDescriptor');

td.addProperty(

'ConfirmText', String);

return td;

}

this._onClick = function () {

event .returnValue = window.confirm(_ConfirmTextValue);

}

this.get_ConfirmText = function() {

return _ConfirmTextValue;

}

this.set_ConfirmText = function(value) {

_ConfirmTextValue = value;

}

}

MyNS.ConfirmButtonBehavior.registerSealedClass(

'MyNS.ConfirmButtonBehavior', Sys.UI.Behavior);

Sys.TypeDescriptor.addType('MyNS

', 'ConfirmButtonBehavior', MyNS.ConfirmButtonBehavior);

So, yeah, it's more code but it's nice and structured.  There's an initialize method where I set up my state, a dispose method where I tear it down, an _onClick method where I work my magic, and a couple of property accessors.  And if I want to add some functionality or some logic to run, I've got well-structured places to do it.  What's more is that this won't collide with other behaviors.  If you've got something else that you want to happen when a button is clicked, it will co-exist peacefully with this behavior.  Not so with the old script method.

So how do you use this on a web page?  Well that's a little trickier, and I'll give you a hint that extenders help.  But without extenders, here's how I hook it up:

1) Add a ScriptManager to my page

<

atlas:ScriptManager ID="ScriptManager1" runat="server"/>

2) Add a control that's going to be the target of this behavior.  We'll add two.

<

asp:Button ID="Button1" runat="server" Text="Button" />

<asp:Button ID="Button2" runat="server" Text="Button" />

3) Add the xmlscript to hook the things together.

<

script type="text/xml-script">

<page xmlns:script=

"https://schemas.microsoft.com/xml-script/2005" xmlns:MyNS="MyNS">

<references>

<add src=

"ConfirmButtonScript.js"/>

</references>

<components>

<control id=

"Button1">

<behaviors>

<MyNS:ConfirmButtonBehavior ConfirmText=

"Click Button1?"/>

</behaviors>

</control>

<control id=

"Button2">

<behaviors>

<MyNS:ConfirmButtonBehavior ConfirmText=

"Click Button2?"/>

</behaviors>

</control>

</components>

</page>

</script>

And boom, you've got your behavior hooked up, and you can hook that one behavior up to as many controls on the page as you like.  Much nicer.

Again, extenders make this experience much nicer.  I'll talk about those in a post soon.