Photo from Flickr: frenchiefoo/14751394 Photo by spacecadet @ flickr

Using jQuery for event handling on Objects

published on
January 4th, 2009
by Marko Mrdjenovic

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.

Opinions

  1. posted on
    June 2nd, 2009
    by Hélio Miranda

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

Express your opinion

My name is Marko Mrdjenovič and I’m a web developer and a manager from Ljubljana, Slovenia (N 46° 03.246,W 14° 30.265).

I like solving problems. I do that by writing code, managing projects and people. I like creating good experiences. And going to conferences. I work at Zemanta. I do freelance UX/front-end/back-end work, available from March.

Blog archive

Advertisments

Jobs

Come in, we're hiring

Full-time and freelance job opportunities available at Authentic Jobs:

  • Loading ...

Post a job and reach web professionals everywhere.