Donnerstag, Januar 18, 2007

Building JavaScript Behaviors - 3

Methods for event handling

The methods that are used to handle events from the mouse, keyboard or system are identified by their name prefix "on". When the behavior is bound to the HTML element these methods are not just copied over from the JavaScript behavior declaration to the html element but are wrapped by a special function that looks like

function() {
  return method.apply(htmlElement, arguments);
}

This wrapper is generated automatically for all on__ methods to ensure that the JavaScript "this" pointer is pointing to the htmlElement the method belongs to. This really simplifies writing event code.

Simple Events

The first sample already used an event (onclick) and registered a method to calculate a new random number for the dice.

// classical event handler implementation

onclick: function(evt) { evt = evt window.event; var src = evt.srcElement; src.rolling = 50; src.count = 0; src.rollNext(); }

Because the this pointer is adjusted to the htmlElement we can use it instead of finding the right element through the event property srcElement:

// simpler event handler implementation

onclick: function(evt) { this.rolling = 50; this.count = 0; this.rollNext(); }

Global Events

Sometimes it is not possible to implement an event code by using this simple on__ naming scheme because the event that the behavior needs is not thrown to the htmlElement of the behavior.

If you are interested in global events you need to attach a method by using the AttachEvent method that is available through the jcl object. Don't use the on___ naming scheme for this method:

jcl.AttachEvent(document, "onmousedown", this._onmousemove);

If you are not interested in these events all the time the handler can be detached by calling:

jcl.DetachEvent(document, "onmousemove", this._onmousemove);

Mouse Events

Mouse events are a little bit special when implementing a drag&drop scenario. The onmousedown will always be raised on the element that will be dragged around but the other 2 events mousemove (while dragging) and onmouseup (when dragging ends and the drop occours) may be raised on any other elent on the page or even on the document object itself. Because the event "bubbles up" we can get all the events by attaichg these 2 methods to the document object.

The sample at VBoxDemo.aspx is using the VBox.js behavior that allows changing the width of the vertical separation by dragging the line between the left and right content.

You can download the updated files from http://www.mathertel.de/Downloads/Start_JSBTutorial.aspx.

del.icio.us tags: , ,

Montag, Januar 08, 2007

Building JavaScript Behaviors - 2

The sample from the last post about building JavaScript Behaviors is not very realistic, because it is not configurable and missing parameters.

Properties, Attributes and Parameters

The way parameters are passed to the behavior implementation is some kind of tricky:

  1. you write down a parameter into the *.aspx source file.
  2. when the page is called from the server the parameter is passed to the server side control.
  3. the parameter is then written out into the response (html) stream and send to the client.
  4. when the behavior is attached to the html element it is made available to javascript.
  5. the behavior implementation is using the parameter by using this.parameter.

There are some traps and tricks on the way.

Take care of uppercase characters in the parameter name. Parameters with uppercase characters work fine on the server but using them on the client breaks the xhtml format spec. You can use lowercase parameters on the server and the client and you don't get confused when writing code for the server platform and the client platform the same time.

If you want to make a parameter available to the server control you have to add a public property or a public field to the class.

Using public fields is working fine but Visual Studio will not help with intellisense then so I prefer using a encapsulated private field using a public property:

private string _datatype = String.Empty;

public string datatype {
  get { return _datatype; }
  set { _datatype = value; }
} // datatype

public string working_but_no_intellisense = String.Empty;

Passing null through a parameter just doesn't work because you cannot specify an attribute for a xml or html tag with a null value. I am using empty strings instead.

If no attribute value is specified in the source code you need to define a default value. The easiest is to assign the default value to the private server field declaration and always render the attribute into the response stream.

The firefox browser makes a big difference between attributes of a html element and a property of an object so when attaching a behavior to a html element all the attributes are copied into object properties.

Don't use any reserved words you know from C#, VB.NET, JAVA, JavaScript, HTML or the DOM specification as a name and don't start a name with "on" because this naming convention is used for identifying event handlers.

1. Adding a parameter to the dice sample server control

The sample up to now is only showing random numbers from 1 to 6. A new parameter named "maxnumber" should make it possible to get random numbers between 1 and any positive number greater than 2.:

private int _maxnumber = 6;

public int maxnumber {
  get { return _maxnumber; }
  set { _maxnumber = value; }
} // maxnumber

This parameter is not needed on the server side and we just pass it to the client through a html attribute:

<div id="<%=this.ClientID %>" class="Wuerfel" maxnumber="<%=this.maxnumber %>"
  unselectable="on">click</div>

You can find this implementation in wuerfel2.ascx.

2. Adding a parameter to the behavior

On the client side we need to declare tha parameter as well. The given assignment will always be overwritten be the attribute the server adds to the html element.

And then we must use.

// parameter to set the maximum number
maxnumber : 6,

// find a random number
var n = Math.floor(Math.random()*(this.maxnumber-1))+1;

You can find this implementation in wuerfel2.js.

3. Using the new feature

Now the new parameter can be used on any wuerfel2 tag:

<uc1:Wuerfel2 ID="Wuerfel2" maxnumber="42" runat="server" />

You can find it in Wuerfel_05.aspx.

You can download the updated files from http://www.mathertel.de/Downloads/Start_JSBTutorial.aspx.

del.icio.us tags: , ,

Freitag, Januar 05, 2007

AJAX Aspects is now available under the BSD license

After some discussions and some reading I decided to change the license of my public software available from http://www.mathertel.de to a BSD style license. It's a better license for software projects then the previously used Creative Commons Attribution 2.0 Germany License.

The new license text is available at http://www.mathertel.de/License.aspx. The source code comments pointing to the license will be adjusted in the next days.