Thursday, December 10, 2009

Firing Native JavaScript Events using Prototype

I've been using Prototype as my JavaScript library of choice for a couple years now. While I'll admit I would probably choose jQuery if I were to rewrite all of my code from scratch, that's simply not an option at this point. I can't justify rewriting perfectly good code for the sake of rewriting it -- if it ain't broke, don't fix it.

For the most part, Prototype has everything I need: Ajax, CSS selectors, DOM manipulation, event handling, and a slew of convenience methods for working with objects and classes. However, I've always been a little bothered by the inability to fire native JavaScript events, meaning there's no way to fire an element's change event. While Prototype allows you to fire custom events using Element.fire, all event names must be namespaced using a colon, which rules out $(id).fire('change').

So today, after some quick Googling, I wrote my own Prototype-based version of jQuery's change() method in order to fire native events. Here's what I came up with:


(function() {
var methods = {};
var events = 'blur,change,click,dblclick,error,'+
'focus,keydown,keypress,keyup,load,'+
'mousedown,mouseenter,mouseleave,'+
'mousemove,mouseout,mouseover,mouseup,'+
'resize,scroll,select,submit,unload';
events.split(',').each(function(event) {
methods[event] = function(element, fn) {
if (fn == undefined) {
if(document.createEvent) {
var evt = document.createEvent('HTMLEvents');
evt.initEvent(event,true,true);
return !element.dispatchEvent(evt);
}
else {
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
}
else {
element.observe(event,fn);
}
}
});
Element.addMethods(methods);
})();


With this, you can simply call $(id).change() to fire the element's change event or $(id).change(function(){...}) to add an observer to the element's change event.

I did a quick test and it seems to work in both IE8 and Firefox, but I can't guarantee anything about older browsers, so use at your own risk.

On a final note, I don't know why Prototype seems to be overlooked by so many people in favor of jQuery. I actually prefer the Prototype syntax in many cases, but that's probably because I've been working with it longer. Maybe it's because developers who weren't too familiar with JavaScript stumbled upon jQuery one day and decided they didn't have to look at any other libraries out there, which seems really wrong to me. That would be the same as choosing Mach-II without looking at Model-Glue or ColdBox. Or choosing PHP without looking at ColdFusion or Ruby. You really can't know if you've made the right decision unless you've evaluated all your options.

1 comment:

  1. In case anyone cares, the newly added Element.select() method conflicts with scriptaculous. To fix this, I simply reduced the methods I was adding to only the ones I cared about: blur, change, click, dblclick, focus, keydown, keyup, keypress, and keyup.

    ReplyDelete