Tuesday, March 01, 2005

Multiple event handler functions for javascript events

Wow, what a sexy title!

This little function will allow you specify multiple event handler functions for any javascript event using the object.event (traditional) event registration method. (see http://www.quirksmode.org/js/introevents.html for more on javascript events).

Why? Well, often you want to register multiple handlers for the same event, where one dynamic html page might be split across multiple files. A good example would be an ASP.NET page and the user controls which make up that page. You might want to do something against window.onload in the main page and also in a part of the page where this code is in a different file. Without the extra eventAddHandler function below it's not possible to register more than one function in different locations.

i'm heavily indebted to Simon's article on this http://simon.incutio.com/archive/2004/05/26/addLoadEvent of which this code is an extension.

This code has been tested in Firefox 1.0, IE 6.02, Opera 7.5 on PC and IE 5.01, IE 5.2 and Safari 1.2 on the Mac. I've no reason to believe it won't work on any browser that supports Javascript 1.2 as i'm not doing anything particularly browser specific in the event registration.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script type="text/javascript">

// event worker object constructor
function EventWorker(){
 this.addHandler = EventWorker.addHandler;
}

// event worker static method
EventWorker.addHandler =
 function (eventRef, func) {
  var eventHandlers = eval(eventRef);
  if (typeof eventHandlers == 'function') { // not first handler
   eval(eventRef + " = function(event) {eventHandlers(event); func(event);}");  
  } else { // first handler
   eval(eventRef + " = func;");
  }
 }

// use EventWorker to add window.onload and 2 btnClick events
// note: calls to EventWorker.addHandler can be made anywhere on the page

EventWorker.addHandler("window.onload", function() {
 EventWorker.addHandler("btnClick.onclick", test1);
 EventWorker.addHandler("btnClick.onclick", test2);   
});


function test1(e)
{
 displayEventDetails(e);
 alert("success 1");
}

function test2(e)
{
 displayEventDetails(e);
 alert("success 2");
}

function displayEventDetails(e) {
 if (!e) e = window.event; 
 alert(e.type); // event type
}

</script>
</head>
<body>

<input type="button" value="Click me" id="btnClick" />

</body>
</html>

Friday, March 18, 2005 4:36:33 PM (New Zealand Daylight Time, UTC+13:00)
Great work! I did run into a problem that perhaps you can shed some light on. If you attempt to run the following you will see that the 'this' within the Tester class references seems to reference the window object and not the class:

function Tester(foo) {
this.FooBar = Tester.FooBar;
this.foo = foo;
}
Tester.FooBar = function() {
alert("Tester.FooBar() called");
alert(this.foo);
}
var t = new Tester('hello');
EventWorker.addHandler("window.onload", t.FooBar);

Any ideas on how to fix this?

Thanks.

Friday, March 18, 2005 11:34:24 PM (New Zealand Daylight Time, UTC+13:00)
Hi,

If you just called Tester.FooBar(), you would get the alert(this.foo) as undefined, in the same way as you do when you pass t.FooBar to wire up to the window.onload event. I'm not 100% sure why, but the function you are passing in actually gets used as if it were calling Testing.FooBar().

This is likely because when window.onload is fired, t does not exist as an object, and so the static method is used instead. The object t you have created is therefore out of scope when the event is called.

A solution to all this confusion is to just wire up a normal function against events, then you can control what happens from inside that function.

For example, the following works and would do what you intend i think:

function Tester(foo) {
this.FooBar = Tester.FooBar;
this.foo = foo;
}
Tester.FooBar = function() {
alert("Tester.FooBar() called");
alert(this.foo);
}


function testOnload() {
var t = new Tester('hello');
// t is in scope, we have just made object!
t.FooBar();
}

EventWorker.addHandler("window.onload", testOnload());
Friday, May 11, 2007 7:06:32 PM (New Zealand Standard Time, UTC+12:00)
Great Presentations!

I see. Thanks anyway :)
Comments are closed.