Using jQuery for event handling on Objects

I’m working on a few projects with jQuery that need event handling. Since I like the way event handling is done in jQuery, I decided to use it to add event handling to internal objects with jQuery (1.2.6 at the time of writing). This seems very easy:

internalObject = {/* code here */};
eventHandler = $(internalObject);

This means that you could now do

eventHandler.bind('customEvent', function (ev) {
	// this is a reference to internalObject
});

and of course also

eventHandler.trigger('customEvent', {some: 'data'});

which is great.

But in a part of my code this just wouldn’t work. Unfortunately it was my first try at doing jQuery({/* custom object */}) and since I obviously wasn’t at my best when writing it I was sure this couldn’t be done. So I hacked around it.

A few weeks ago I made me a test case and figured out it works when passed an empty object ({}). So I implemented it everywhere and sure enough a part of the code stopped working. Which made me delve into the code to figure out why – a bit of debugging made me think the bug was somewhere in jQuery and I found out that there is a problem with the makeArray function. When it’s trying to create an Array it will test if the object has a length property. But as the comment in uncompressed code neatly points out //the window, strings and functions also have ‘length’ it checks a few things that allows it to handle these objects differently.

This means that

eventHandler = $({});

will work normally, while

eventHandler = $({length:0});

won’t because eventHandler length will be 0.

My problem was that the object I was passing had a length property. As such it got sucked into the else that processes arrays and other array like objects (like arguments and most probably also NodeLists). This meant that what I got back was nothing since length was initially set at 0.

Important update: Don’t do this:

eventHandler = {};
internalObject = {
	customEvent: function () {
		eventHandler.trigger('customEvent');
		/* some other handling code */
	},
	/* more code */
};
eventHandler = $(internalObject);
eventHandler.bind('customEvent', function (ev) {
	// this is a reference to internalObject
});
internalObject.customEvent();

You will inadvertently create an indefinite recursion as jQuery will try to trigger the native event and will execute elem[ type ](); where elem will be your object and type your event name. If you need an event that has the same name as a method on the object you can use triggerHandler as it will not trigger the default event.

One Response to “Using jQuery for event handling on Objects”

  1. It’s great that you’ve nailed this one. I was dwelling with this same problem a few hours now. Thanks!

Leave a Reply