Saturday, January 15, 2005

Multiple Event Handlers in JavaScript (daisy-chaining event handlers)

 

Problem

 

A distinct drawback of the traditional JavaScript event handling model is that the onclick property can contain only one function. This becomes a problem when you want to register multiple event handlers for one event.

 

For instance, suppose you’ve written a module that makes it possible to drag and drop a layer. The module registers an onclick event handler to an element so that clicking on it starts the drag and drop. You have also written a module that silently keep track of user clicks and sends this information to the server onunload, so you can find out how your pages are used. This module, too, registers an onclick event handler to an element.

So what you’d really like to do is

 

element.onclick = startDragDrop;
element.onclick = spyOnUser;

 

However, it’s here that things start to go wrong. The second registration of a function to onclick overwrites the first one so that only spyOnUser() is executed when the user clicks on the element.

Solution

Register an anonymous function that executes both other functions:

element.onclick = function () {startDragDrop(); spyOnUser()}

But suppose that you don’t use both modules on every page in your site. Now if you’d do

 element.onclick = function () {startDragDrop(); spyOnUser()}

 you could get error messages because one of the two functions might be undefined. So you have to be more careful in registering your event handlers. When we want to register spyOnUser() while startDragDrop() may (or may not) be registered, we do:

var old = (element.onclick) ? element.onclick : function () {};
element.onclick = function () {old(); spyOnUser()};

First you define a variable old. If the element currently has an onclick event handler, put this event handler in old, if it hasn’t, put an empty function in old. Now you register a new event handler to element div. It is a function that first executes old() and afterwards spyOnUser().
Now the new event handler is added to the element, while previously registered handlers (if any) are preserved.

 Andrew's Addendum

The code above works great if you only need to replace the event  handler of one element. If you are dealing with multiple elements in a loop though, you have a new problem. This code:

for (i = 0; i < textboxes.length; i++) {
     var old = (textboxes[i].onclick) ? textboxes[i].onclick : function () {};
    element.onclick = function () {old(); spyOnUser()};
}

does not work because when onclick is finally executed old() actually has the last value that was assigned to it (in this case the original event handler of the last textbox in the list). In other words, all onclick events will execute the same old() function, and not the one that was originally assigned to each textbox.
 
The solution is to construct an array of event handlers (which of course has to be a global variable):
 
var eventHandlers = new Aarray();


...  
     
           eventHandlers.length = textboxes.length;
for (i = 0; i < textboxes.length; i++)
{
    eventHandlers[i] = (textboxes[i].onchange) ? textboxes[i].onchange : function() {};
    eval("textboxes[i].onchange = function() {eventHandlers[" + i + "](); spyOnUser();}");
}

 

Wednesday, January 12, 2005

VS.net IDE Tips

Friday, January 07, 2005

GUID / UUID Algorithm

I always wanted to know how the Microsoft GUIDs (globally unique identifier) used for class identification in the registry and other purposes are generated. Here's a spec:

Sunday, January 02, 2005

EOM

Yahoo! Finance Weekend

The Problem: Your inbox is overflowing with e-mails from colleagues that say nothing more than "got it" or "OK."

The Fix: Introduce your workplace to EOM, shorthand for "end of message." Slapping these three letters onto the end of an e-mail message is a signal to the recipient that the exchange is complete and he or she doesn't need to send a reply.

Usage of EOM has evolved. Traditionally, it has been employed on the subject line to indicate that the entire message is contained there, saving the recipient from having to click to open the message only to find nothing in it.

Other people now are using the acronym to minimize unnecessary e-mail traffic. Reading and sending superfluous messages can sap hours of productivity. Between 10% and 30% of all e-mail messages are simply unnecessary, estimates Martin Hall, managing director of the twice-yearly e-mail conference INBOX.

The proliferation of these one or two word e-mails usually is the result of politeness gone awry. EOM lets the recipient off the hook. But it only works if everyone in your office -- or family -- knows what it means. Otherwise, it is apt to be seen as a lame attempt to imitate the latest teen slang.