Speeding Up Prototype’s $$ Selector

June 29, 2006 | Leave a Comment

prototype.gif Prototype, as I've stated in the past, is our Javascript library of choice for Ajax at Plymouth State University and in the current re-writing of MasterWish. As of version 1.5 of Prototype there has been a sweet Selector function $$ which is best used when manipulating more than one dom element of the same type...i.e. updating all buddies in a buddy list at MasterWish with some property.

Here's a simple example that we use at MasterWish:

JavaScript:
  1. mw_b.prototype.checkAll = function()
  2.   {
  3.     $$('.buddy_checkbox').each(function(e){e.checked=true;});
  4.   };

All that example does is iterates over all elements in the DOM that have the class buddy_checkbox and sets their checked value to true. Short and sweet. However, with version 1.5 of Prototype, it could be dog slow at times with more complex selector queries.

I was ecstatic when I found (via Ajaxian) that Sylvain Zimmer has sped up the $$ function quite a bit. I implemented it in the test area of MasterWish and have been very pleased with the results! Here's what Sylvain has to say on his mod:

Prototype’s current code is quite elegant (as always!) but very slow, so I wrote an add-on that makes this function up to 20 times faster in most usual cases (tested on IE6, Firefox 1.5 and Opera).

[...]

Here are the main ideas of this add-on :

  • Forwarding the call to the old $$ if the selector expression is too complicated (currently : if it uses attributes)
  • Replacing regular expressions with a simple parser
  • Minimizing the number of operations done on each iteration.
  • Trying to use getDocumentById() instead of getDocumentByTagName() when possible.
  • Avoiding recursive functions with return values.
  • Not being afraid of some “old-style” code if it speeds up the execution ;-)

All you need do is get his mod and include it in a script tag after the Prototype inclusion. Simple as that!

Oooo event:Selectors for Prototype

March 21, 2006 | 1 Comment

event_selectorsMy article on the Separation of Layout and Logic touched on a key point of heavy Javascript use in an Ajax rich environment...the need for separation of Javascript code - namely events - from the HTML. Behaviour was my suggested CSS/Javascript event selector framework.

Behaviour is a stand-alone event framework. You can use it regardless of whether or not you are using Prototype (or some other Ajax/Javascript library) - which is pretty cool. But...if you are using Prototype there is a lot of code duplication between the two libraries. Luckily, Mir.aculo.us has brought event:Selectors to my attention which is causing me to sing a different tune! Justin Palmer, event:Selector's creator is crediting Behaviour for the idea, but he's has what Behaviour has done a few steps further.

  • event:Selectors is dependant on Prototype which reduces code duplication.
  • It has reduced the layer of complexity of event selecting by one layer of abstraction.
  • The framework allows concatenation of CSS elements for event assignment.
  • Lastly, its added a loaded event that is triggered when an element loads.

Here's an example of Behaviour event handlining:

JavaScript:
  1. var rules = {
  2.     '#item li': function(element) {
  3.       Event.observe(element, 'click', function(event) {
  4.         var element = Event.element(element);
  5.         element.setStyle('color': '#c00');
  6.       });
  7.     },
  8.    
  9.     '#otheritem li': function(element) {
  10.       Event.observe(element, 'click', function(event) {
  11.         var element = Event.element(element);
  12.         element.setStyle('color': '#c00');
  13.       });
  14.     }
  15.   };
  16.   Behaviour.register(rules);

Here's the equivalent in event:Selectors:

JavaScript:
  1. var Rules = {
  2.     '#item li:click, #otheritem li:click': function(element) {
  3.       element.setStyle('color': '#c00');
  4.     }
  5.   };
  6.  
  7. EventSelectors.start(Rules);

Simplification makes me happy. I'm a convert.