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.
It’s great that you’ve nailed this one. I was dwelling with this same problem a few hours now. Thanks!