Donnerstag, April 05, 2007

Using Inheritance in JavaScript Behaviors

While working on some samples using (different) menubar, I found it helpful to inherit a JavaScript Behavior from a more general JavaScript Behavior. This would give me the chance to implement the common general Javascript methods only once and leave specific functionality in the derived Behavior.

Here is the sample:

// this is a basic behavior definition for menubars var MenubarBehavior = {   init: function () { // activate the hover effect on all menu items var allitems = this.getElementsByTagName("*"); for (var o in allitems) if (allitems[o].className == "VEMenu") {         allitems[o].hover = true;       }   },

 

onkeypress: function(evt) { evt = evt || window.event; var kc = String.fromCharCode(evt.keyCode); if ((this._attachedBehaviour.onclick != null)

&& (evt != null) && ((kc == " ") || (kc == "\r"))) { this._attachedBehaviour.onclick.call(this, evt); } // if } // onkeypressed } // MenubarBehavior

This is a basic implemenation that enables the hover effect for all VEMenu items found inside the menubar and to simulate a click event if the spacebar or return key is used while the focus is on a menuitem.

// this is a basic behavior definition for menubars var EditMenubarBehavior = {   inheritFrom: MenubarBehavior,

  init: function() {     MenubarBehavior.init.call(this);   },

onclick: function(evt) { evt = evt || window.event; var src = evt.srcElement; var cmd = src.name; if (cmd != null) { cmd = cmd.split(';'); HtmlEditBehaviour.Command(cmd[0], cmd[1]); } } // onclick } // EditMenubarBehavior

This is the implementation of the derived Behavior definition.

If you ask why I do not use the JavaScript inheritance mechanism, then you have a good question - i tried.

Using the new operator and the prototype mechanism does not work here because we attach methods to HTML elements and some other problems came up too.

The article of Nicholas C. Zakas at: http://www.sitepoint.com/article/javascript-objects also describes the topic.

You can find the state of the current implementation here:

http://www.mathertel.de/AJAXEngine/S04_VisualEffects/InlineEditDemo.aspx

(see the page source by using the view link in the upper right corner)

 

The only code I had to add to the LoadBehaviour method (that does something very similar to the extends method of Zakas) are these 3 lines of code to recursively bind the Behaviors starting with the base class.

 

if (behaviour.inheritFrom != null) { this.LoadBehaviour(obj, behaviour.inheritFrom); this.List.pop();

}

See controls/jcl.js (view source)

 

(I'll publish a new version of the framework as a zip here file when this sample is finished).

Kommentare:

Andrew Sazonov hat gesagt…

There is another approach to implement JavaScript inheritance - a “lazy” inheritance which has all benefits of “prototype” based approach like typed classes, but also eliminates necessity to declare external scripts in proper order and automatically resolves and loads (if necessary) dependencies to external scripts that contains related classes.
This approach is supported by JSINER library - you can find more about it on http://www.soft-amis.com/jsiner/inheritance.html

Anonym hat gesagt…

Great.
That reduced my implementations by some dozens lines.
Have a look at DataFade (can inherit DataOutput...