Custom Events in JavaScript
Javascript December 29th, 2009Usually I use jQuery for custom events, because it has a very nice model. However, recently I have been working on a JavaScript class that I want to be independant of other libraries, so I needed to create my own custom event model.
For the sake of this sample, I changed the namespace to “ns”. You can change that to whatever you’d like.
Eventify
To enable an object with events, you’ll use the ns.events.eventify(obj) method. Once that is done, your object will have “events” and “__listeners” properties, in addition to “dispatchEvent(eventType, eventData)”, “addEventListener(eventType, callback, bubbles)”, and “removeEventListener(eventType, callback||listener)” properties.
You may pass one or many objects to the eventify() method.
ns.events.eventify(obj);
or
ns.events.eventify(obj1, obj2, obj3);
You do not need to interact with the “events” and “__listeners” properties at all, unless you want to predefine a set of events for a particular object, usually for documentation purposes. Here’s an example of a custom class that uses this event model and predefines its events. Just to clarify, I am using the “id” property in this class primarily for the event bubbling example that follows. It is not needed at all for the events to work.
addEventListener() / dispatchEvent()
ns.MyClass = ({
function MyClass(id){
ns.events.eventify(MyClass.prototype);
this.id=id;
}
MyClass.prototype={
id:null,
events:{
ready:new ns.events.Event("ready"),
error:new ns.events.Event("error")
},
property:null,
method:function(){}
}
return MyClass;
})();
If you do not define the events explicitly in the events property, they will be added automatically when a listener is added to the object. For instance:
var my = new ns.MyClass("my");
my.addEventListener("ready", function(){
alert("my is ready");
});
Would define my.events.ready.
dispatchEvent() and passing data
To dispatch an event, use the dispatchEvent() method. To pass data with a dispatched event, use the eventData parameter. For example:
my.addEventListener("ready", function(evt, data){
alert(data.hello);
});
my.dispatchEvent("ready", {hello:"Hello from dispatcher."});
Event bubbling
Event bubbling is somewhat manual. Because these are custom objects with no inherent heirarchy, you must define the parent object as the event’s “bubbleTo” property. The object defined as “bubbleTo” must share the event type that is being dispatched on the current object (they do not need to be instances of the same class). Implement bubbling as follows:
var parent = new ns.MyClass("parent");
var child = new ns.MyClass("child");
child.events.ready.bubbleTo = parent;
child.addEventListener(”ready”, function(evt){
alert(”sincerely, “+evt.target.id+”.”);
});
parent.addEventListener(”ready”, function(evt){
alert(”Sincerely, “+evt.target.id+”. With regards, “+evt.currentTarget.id+”.”);
});
child.dispatchEvent(”ready”);
To prevent subsequent callbacks on an object, call evt.stopImmediatePropagation(). To stop the bubbling, call evt.stopPropagation().
You may also prevent the bubbling of an event when creating the listener by using the “bubbles” parameter of the “addEventListener()” method.
var listener = child.addEventListener("ready", function(evt){
alert("sincerely, "+evt.target.id+".");
}, false);
removeEventListener()
Finally, to remove a listener from an object, use the removeEventListener(listener||callback) method. This method will accept the listener or the callback function used. Note that in the above example I have assigned the listener to “var listener”.
child.removeEventListener("ready", listener);
You may also use the remove() method of the listener itself.
listener.remove();
Download
Right click and choose “Save Target As” to download events.js.
February 25th, 2010 at 6:51 pm
Great work! I will definitely have to try this out. Thanks