Event Selector Showdown

Posted on by

Simple Challenge: Find all the LI elements underneath two different elements (using their #ID as reference) and bind a click handler which changes the color of the LI’s text. Here is how you would do that in all of the popular event/selector libraries.

Behaviour + Prototype

Behaviour.register({
  '#item li': function(element) {
    Event.observe(element, 'click', function(event) {
      Event.element(element).setStyle({color: '#c00'});
    });
  },
    
  '#otheritem li': function(element) {
    Event.observe(element, 'click', function(event) {
      Event.element(element).setStyle({color: '#c00'});
    });
  }
});

Prototype 1.5.0

$$('#item li, #otheritem li').each(function(li){
  Event.observe(li, 'click', function(event) {
    Event.element(li).setStyle({color: '#c00'});
  });
});

event:Selectors

EventSelectors.start({
  '#item li:click, #otheritem li:click': function(){
    this.setStyle({'color': '#c00'});
  }
});

jQuery

$("#item li, #otheritem li").click(function(){
  $(this).css('color', '#c00');
});

I like to think that the code speaks for itself, as to which one is the easiest to use and understand. I find it interesting how Prototype is migrating closer to what jQuery has now – while jQuery itself is blasting away with some very cool new stuff. Definitely keep your eyes peeled for new releases, as they’ll be coming soon.

31 thoughts on “Event Selector Showdown

  1. Wow, the jQ solution is by far the most obvious choice. I’m only recently starting to dig into it, after seeing what Cody did with it recently via Thickbox. I’m very impressed by how concise and logical it is, and am looking forward to the new release.

  2. falcon on said:

    A few quick questions:
    1. I can’t find an svn url that I can use from command line (svn co …), is it is not on purpose, perhaps you could provide this.
    2. Is it possible to have a more open forum…one where I don’t need to subscribe? I get enough email, I only need to interact once in a while, it seems silly to have to subscribe…perhaps google groups is a good option.
    3. When is the next release coming out? I saw som drag&drop code in svn (web), perhaps a writeup of what can be expected?
    4. This one is probably appropriate for the forum (see #2). Is there a way to query the DOM, and have the results returned as trees rather than an array? I have a bunch of nested divs, tables, etc. that represent something similar to a parse tree, I need to build expressions out of those trees, that is not easy (impossible?) if I get back a flattened set of nodes.

    By the way, this looks really cool :)

  3. Hi John,

    Great work on this and JQuery as a whole. The API is great.

    I have some constructive comments about JQuery. I want to explore jQuery more, but one thing really turns me off about it and that is the brevity of the code. Variable names like a, b, c have no meaning and it makes jQuery’s code very hard to read and understand.

    I’m assuming this is a file size decision, but we have compression tools for things such as this. While I can certainly read the jQuery docs to address usage, in order to have a deeper understanding of the code itself, we have to be able to read it.

    Also on your selector stuff you’ve done. I wanted to note that you also have access to the Event object with event:Selectors, and you also have access to the object in context with the ‘this’ keyword. And finally, with event:Selectors you can do multiple event types per rule (e.g. #item:click, #item2:mouseover: function(e) {} …).

  4. Hi Justin – Nice to see you drop by!

    That’s a great point about the variable naming problems. Using short variable names has become sort of ‘ingrained’ into my code-writing habit, and it’s absolutely one that I need to break.

    Excellent point about the this keyword, I now have your code using that, instead of the ‘e’ argument. The binding of multiple event types is definitely a big win for event:Selctors, thanks for mentioning that.

  5. This is a great demonstration of the simplicity of your approach in jQuery. Looking forward to more…

    Regards
    Ashutosh

  6. Jon Baer on said:

    This may seem odd but Im a big fan of both JQuery and Prototype/Scriptaculous but is there a point in competing vs. each others API? For example why would you not contribute work to Prototype and/or vice versa? Or even as a start .. JQuery included in Rails :defaults? Am I missing something? These libraries are starting to become the real norm in development and everyone is seeking the ultimate one liners to simple problems like this .. either way, excellent work!

  7. Jon – Thanks for the feedback! Prototype and Scriptaculous are both great libraries containing invaluable amounts of excellent code – but they both have things that jQuery does not focus on:

    1) They’re written for a specific purpose (e.g. Prototype is written to work well with Ruby on Rails, Scriptaculous is written to effects well) – and a rather defensive when it comes to new input.
    2) They’re incredibly feature-heavy (and, therefore, large downloads).

    More than anything else, we just want jQuery to be the simplest library to use, while still packing the largest ‘punch’. So, instead of providing dozens of obtuse animations (for example) we provide just a handful, but leave the API open for future improvments/plugins.

    So to get to you question: We’ll definitely consider committing some stuff to Prototype and/or Scriptaculous – but for now we’re mostly concerned with keeping this library nice and small and fixing all the bugs that pop up :-)

  8. Hi John,

    What I would *really* love to see is a comparison like this done for the :hover events.

    I stopped looking at Prototype and Dojo when I found JQuery (or at least until I have heavier stuff to get done) — so they might have this too –, but I love how your implementation of hover that takes care of all the nesting and bubbling… just works.

    Being able to strap JQuery on Suckerfish Dropdowns (or anything that requires *:hover for IE) with just 3-4 lines of code was a winning situation for me, and I think it will really prove your poing once again.

  9. Pingback: La potencia de JQuery » ingeniuz :: desarrollo web útil

  10. Pingback: Event Selector Showdown

  11. This is neat. But for what it’s worth; on behalf of the YUI Team:
    YAHOO.util.Event.on([YAHOO.util.Dom.get('item').getElementsByTagName('li'),
    YAHOO.util.Dom.get('otheritem').getElementsByTagName('li')],
    'click',function(){ YAHOO.util.Dom.setStyle(this,'color','#c00'); });};

    Not bad considering YUI is not an Event Selector library. The only main difference between the jQuery on the yQuery (for sake of calling this a query) is the namespacing of ‘YAHOO.foo.bar’ vs ‘$’ on this particular example. Oh, and the two getElementsByTagName, otherwise you’ve got a real nice thing going on here :) – let’s do some more challenges, this is fun.

  12. Pingback: jQuery wins the Event Selector Showdown

  13. Pingback: jQuery wins the Event Selector Showdown

  14. Hmm, personally I’m more a fan of the event:Selectors, and I think at the very least – both of them come out pretty much at the same place.

    Dustin: As for YUI… sorry dude, but that code is horrendus (even w/out the namespace issue) compared to event:Selectors/jQuery :)

    For future versions, it would be cool if you included a raw JS version… for a nice comparison of the wonderful world afforded to us by frameworks.

  15. Kyle, horrendus? Lest we forget (like I said) Y! wasn’t in it to change the language itself… and it’s still less code than Prototype (for this particular example). Was it because I actually had to write out getElementsByTagName? Gosh that’s harsh.

  16. Joel Birch on said:

    @Dustin, no matter how much I recheck your code snippet, I end up with a superfluous closing curly bracket and semi-colon (the last two characters of your snippet). Am I missing something?

  17. Joel, I indeed messed up the code insertion. It was admidst other code around it and I accidently pasted in two more characters than necessary. Just remove the last “};”

  18. Joel Birch on said:

    Thanks for clearing that up – I thought my knowledge of javascript was even worse than it actually is for while there.
    I love your work.

  19. Pingback: Dee’s-Planet! » Event Selector Showdown : the jQuery Challenge

  20. Pingback: Episode 13: JavaScript Libraries Overview

  21. Pingback: CODE POETRY » jQuery - New Wave Javascript

  22. Latte Boy on said:

    Tried to use the Prototype 1.5 example, but a few bugs made it unusable. Here is the edited version that worked for me:

    $$(‘#item li’,’#otheritem li’).each(function(li){
    Event.observe(li, ‘click’, function(event) {
    Event.element(event).setStyle({color: ‘#c00’});
    });
    });

    The two fixes:
    1) Add the different search strings as separate arguments in $$
    2) Event.element(event) instead of Event.element(li)

  23. I think I prefer eventSelectors. For one, the setStyle hash just seems much better suited to CSS since they’re both name/value pairs. Not having used jQuery I might be missing something, but the arguments array method of setting the values just doesn’t do it for me.

    No offense intended, but the event wire-ups in jQuery strike me as pure unmitigated evil. ;-) Setters should indicate that they’re setters. Prepending with “set” isn’t necessary, but a verb like “click” instantly makes me think of some DSL driven functional testing frameworks. It’s not performing an action, so it shouldn’t indicate so. Sorry if that came off a bit harsh…

    Other than that they both definitely sparked my interest enough to commit to abandoning Behaviour. It’s served me well, but perhaps it’s time has passed.

    As for the YUI, yeah, client-side JavaScript is all about DOM manipulation, so the verbosity of getElementsByTagName and the excessive namespacing really hurts it here I think.

  24. I am quite surprised to see the comments against the YUI version, although maybe it is a function of the audience being pro-jQuery. jQuery seems interesting, but it would be difficult to argue the fact that its code is unreadable to anyone not rather familiar with the library. What the heck is $$()? If I were managing a project and I was deciding between a library which encourages code like this:

    $(“#item li, #otheritem li”).click(function(){
    $(this).css(‘color’, ‘#c00’);
    });

    versus a library that encourages code like this:

    YAHOO.util.Event.on([YAHOO.util.Dom.get(‘item’).getElementsByTagName(‘li’),
    YAHOO.util.Dom.get(‘otheritem’).getElementsByTagName(‘li’)],
    ‘click’,function(){ YAHOO.util.Dom.setStyle(this,’color’,’#c00′); });

    I would be doing my client/company a disservice by introducing large additional maintainability costs if I chose anything but the latter. The verbosity of YUI is a *feature* allowing it to remain in its own namespace. If you don’t like it, it takes only 1 line to alias anything you’d like. The difference then is that the alias is used only in custom code (not the library itself) and is chosen by the user, not the authors of the library. To argue against the length of the getElementsByTagName function name is not to argue against YUI. That is a part of DOM — a part of the language. If you change the name of the method just for the sake of changing it, then you force your library’s users to learn your brand of JavaScript. The different solutions in this showdown, to me, is simply evidence of how far in the wrong direction today’s libraries are going. 4 non-standard, low-readability methods to accomplish something that can already be accomplished in a standard way with JavaScript alone or with the aid of *utilities* (not rewrites of the language) like those in YUI.

    A JS library is supposed to assist the JavaScript developer. Anything else is just ego.

  25. $D = YAHOO.util.Dom;
    $E = YAHOO.util.Event;

    $E.on([$Dom.get(‘item’).getElementsByTagName(‘li’), $D.get(‘otheritem’).getElementsByTagName(‘li’)],’click’,function(){ $D.setStyle(this,’color’,’#c00′);
    });

  26. And I think a method of doing it with no libraries should be taken into consideration as a “control”:

    var tags = {
    "item": document.getElementById("item").getElementsByTagName("li"),
    "otheritem": document.getElementById("otheritem").getElementsByTagName("li")
    }
    window.onload = function() {
    for (tag in tags) {
    tag.onclick = function() {
    this.style.color = "#c00";
    }
    }
    }

  27. Adrienne Travis on said:

    In response to the guy talking about how Yahoo’s code is more maintainable, because more verbose — i just found jQuery recently. I’m a designer and HTML hacker, and i don’t know very much Javascript. I’m always just out surfing for other people’s nice, unobtrusive solutions to my JS problems — and that’s how i found jQuery. And you know what? I’d seen other JS frameworks before (Behaviour, event:Selectors, Yahoo!) — and they really hadn’t made much sense to me. They seem like the same kind of semi-gibberish that JS has always seemed like.

    But jQuery? I *get it*. I grokked, INSTANTLY, how things *work* in jQuery, and how to use it to do stuff. I wrote a (very simple, admittedly) plugin for jQuery within TEN MINUTES of downloading the framework and going through the tutorial!

    So from the perspective of a mostly-artsy, Photoshop/HTML/CSS hacker, jQuery gets it SO RIGHT.

    And in a LOT of organizations, *we’re* the ones who end up having to update the Javascript, since the “real developers” are busy on back-end stuff. So a library that makes sense to US is a HUGE help!

    –Adrienne

  28. mwarden on said:

    Adrienne,

    Your point is that you don’t know JavaScript and you therefore found YUI confusing. You say that you understood jQuery easily because it is something other than typical JavaScript. This is exactly my point. Just because you do not want to have to learn JavaScript doesn’t mean that your JavaScript programmers should have to learn jQuery.

  29. Sam Smoot on said:

    mwarden,

    I think your comparision of jQuery and YUI is superficial. You say it’s only one line to alias YUI’s excessive namespacing and verbosity. I say I’d much rather work with a library that starts out terse, and is well documented, than jump into another developer’s own workarounds to the verbosity of YUI.

    It’s not more maintainable if it’s so painful to use that your developers will end up implmenting their own undocumented framework (or even just a collection of aliases) to wrap it.

  30. I realize this is an old article, but I just thought I would point out that with prototype 1.6.0, you can do the following:

    $$(‘#item li, #otheritem li’).invoke(‘observe’, ‘click’, function() {
    $(this).setStyle({color: ‘#c00’});
    });