Event Dispatcher

2009-03-11

For the dispatcher / observer / listener model, here's a simple script to help you.

EventDispatcher:

Code: (JS)
/**
* This is a singleton that handles CustomEvent objects
*/
var EventDispatcher = {
objEvents: {}
};

/**
* Add a custom event object to the dispatcher
* Overwrites one if it exists
*/
EventDispatcher.addEvent = function(objCustomEvent) {
this.objEvents[objCustomEvent.strEventName] = objCustomEvent;
};

/**
* Create a custom event and add it to the dispatcher
* Overwrites one if it exists
*/
EventDispatcher.createEvent = function(strName) {
this.addEvent(new CustomEvent(strName));
};

/**
* Fire an event.
* The arguments will be passed on to the listener, without strName and objSource.
* objSource will be accessible through 'this' in the listener.
*/
EventDispatcher.fire = function(strName, objSource, mixArg) {
// now arguments contains the real arguments
if (this.objEvents[strName]) this.objEvents[strName].fire(objSource, mixArg);
};

/**
* Attach a listener to a custom event
*/
EventDispatcher.addListener = function(strName, funcListener, boolCheckForDuplicate) {
// if the event type doesn't exist, add it
if (!this.objEvents[strName]) {
this.createEvent(strName);
}
// add the listener to this event
this.objEvents[strName].addListener(funcListener, boolCheckForDuplicate);
};

CustomEvent:

Code: (JS)
/**
* Custom Event Observer
* Lazily copied from http://stikiflem.wordpress.com/2008/09/10/create-custom-events-in-javascript/
* and edited from there on.
*/

/**
* This is an event
*/
function CustomEvent(strEventName){
this.strEventName = strEventName;
this.arrListeners = [];
};

/**
* Add a new listener for this event
* Returns given listener
*/
CustomEvent.prototype.addListener = function(funcListener, boolCheckForDuplicate){
// ensure this function isnt added already
if (boolCheckForDuplicate) {
for (var i=0; i if (arrListeners[i ] === funcListener)
return funcListener;
}
}
this.arrListeners.push(funcListener);
return funcListener;
};

/**
* Remove a listener, just for the sake of completion
* Only removes first occurrence
* Returns given listener
*/
CustomEvent.prototype.removeListener = function(funcListener){
for (var i=0; i if (arrListeners[i ] === funcListener)
return arrListeners.splice(i,1);
}
return funcListener;
};

/**
* Fire an event
* Listeners can refer to the object passed on as the first element as this
* unless objThis evals to false. mixArg is passed on to the listener.
*/
CustomEvent.prototype.fire = function(objThis, mixArg) {
// now call each listener with objThis as 'this'
for(var i = 0; i < this.arrListeners.length; i++){
if (objThis) this.arrListeners[i ].call(objThis, mixArg);
else this.arrListeners[i ](mixArg);
}
};
Yes most of the CustomEvent code comes from http://stikiflem.wordpress.com/2008/09/10/create-custom-events-in-javascript/, but I had to edit it anyways and give it more of an observer kind of look and feel.

Anyways, this works by adding listeners for certain events and by firing those events at some 'event'.

To add a new listener:

Code: (JS)
EventDispatcher.addListener('onDOMReady', function(){ /* do stuff here */ });
This will create a new CustomEvent by the name of onDOMReady (if it doesn't already exist) and add the function as an observer.

You can call this multiple times with different functions to create several observers for the same event (that's the whole point).

To fire an event:

Code: (JS)
EventDispatcher.fire('onDOMReady');
Now all the observers get called.

fire has three parameters. The first parameter is the event name that should fire. The second parameter is an object that should serve as 'this' in the callback, this is optional. The third argument will be passed on to the observer as it's first argument.

Note that it's nothing new. I just put it here so I can easily find it when I need it, without having to include some huge lib.

Hope it helps you.