outbreak

Me

My name is Marko Mrdjenovič. I’m a web developer, manager and an entrepreneur from Ljubljana, Slovenia.

Bio

I like solving problems. I do that by writing code, managing projects and people. I like creating good experiences. And going to conferences.

Availability

I work full time on Klevio so I'm currently not available for freelance work (UX, frontend, backend).

Elsewhere:
LinkedIn
Twitter
Facebook
Quora
Flickr

Archives

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.

Opinions

express yours below
  1. 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