Politics, Programming and Possibilities
29 Apr
I’ve been told that jQuery has been around since January of 2006. At some point during the last year, many developers within the Ruby community began to embrace it as an alternative to Prototype and Scriptaculous. Many of the programmer friends I look up to in the Merb community, specifically, are big advocates of jQuery.
So this post is an attempt at summarizing the strengths I’ve found in jQuery as opposed to the two other javascript libraries that I’ve worked closely with: mooTools and Prototype / Scriptaculous. My motivation for this is a soon-to-be-made decision regarding the javascript library that will be used in a browser-based application that I’m working on at a company in Chicago. The application needs a simple user interface and fairly powerful front-end. I’ve advocated the use of jQuery, and thought it would be useful to set out the reasons for my preference here on the InquiryLabs blog.
There is a fine set of documentation at jquery.com. Scriptaculous hasn’t seen much improvement in its documentation in over a year. Prototype’s documentation is (in my opinion) pretty, but still lacking.
It uses as its central paradigm the idea of “querying” the DOM for the desired elements and returning a collection (like a dataset, but with DOM elements) and then acting on the result, or set of elements. The reason it can be concise is that the element sets are chainable. For example:
documentreadyfunction
for var i = 0; i <= 6; i++
$‘h‘ + i + ‘ [@id]‘eachfunction
$‘<a class=”anchorlink”>\u00B6</a>‘
attr‘href‘‘#‘ + thisid
attr‘title‘‘Permalink to this headline‘
appendTothis;
;
;
(Hat tip, lucumr) In the above example, anchor tags are added to all headlines in the document. Note the clever use of chaining which reduces the size of the code, yet retains its expressiveness.
Whether it’s a simple function or an entire plugin, jQuery is built for extending. The ability to query for “element sets” and then act directly on those results is not limited by the core code. Since it’s so easy to add custom functions to element sets, it becomes natural. For example, I found that I often needed to add or subtract a value from a CSS property. I solved this problem by extending the jQuery core element set, like so:
var value = parseIntthiscssproperty;
return thiscsspropertyvalue + delta + “px“;
;
Using the above code, I can query for a set of elements and adjust the height property (for example) in one fell swoop. This will now add 5 pixels to the height of each “rack-item” element:
$‘.rack-item‘cssDelta‘height‘5;
According to Jeff Robbins and John Resig, the Drupal team chose it over Prototype because it is a mere 15k compared to Prototype’s 80k. The Dojo library is even larger.
Update:I decided to test this out myself to see what results I’d get. Resig’s comment was probably from jQuery’s earlier days when it was a micro framework. As far as I understand, it’s still possible to compress the jQuery library down to 18k or so, but that’s possible for Prototype, too. In fact, my tests show that un-gzipped, compressed code gets both down to 51k using Dojo’s ShrinkSafe online app.
Update 2:Thanks to Peter Higgins below for commenting on the size of Dojo. For comparison, its compressed (but un-gzipped) size is 77k.
Feedburner, Technorati, Drupal, Edgewall Trac, etc.
Here are some examples of the concise nature of jQuery, taken from the jQuery blog:
// AJAX Updater in Prototype:
‘placeholder‘url method: ‘get‘parameters: par ;
// AJAX Updater In jQuery:
$‘#placeholder‘loadurl + par;
// Note: This example doesn’t deal with the obvious
// iteration benefits we get if we wanted to load the
// response into every <p> object, for instance.
// Adding a class to an element in Prototype:
ElementaddClassName‘element‘‘className‘;
// Adding a class to an element in jQuery:
$‘#element‘addClass‘className‘;
// Adding a class to a group of elements in Prototype:
$$‘.element‘eachfunctionnode
ElementaddClassNamenode‘className‘;
// Adding a class to a group of elements in jQuery:
$‘.element‘addClass‘className‘;
“That last one is the clearest example of the difference in methodology. Because jQuery is passing messages to jQuery objects, the code is barely changed. jQuery doesn’t care that we’re now adding a class to a group of objects instead of one object; the underlying code is the same (add the class to the set of elements in the object). Prototype, on the other hand, requires an iterator.”
“And as your code becomes more complex, jQuery’s scales easily, while nested loops become the norm in frameworks like Prototype.”
13 Responses for "What Makes jQuery a Good Choice?"
I see where you compare jQuery to Prototype/Scriptaculous, but I can’t see any comparison with MooTools at all, which is what would interest me much more. I think Prototype is not really competition for MooTools and jQuery anymore anyway.
I’m used to prototype, but giving JQuery a whirl for the fun of it.
-
Actually, jquery is 94Kb uncompressed (the 15kb quoted is the minified and gzipped size). Both prototype and jquery gzip down to about the same size.
-
This:
$$(‘.element‘).each(function(node) {
Element.addClassName(node, ‘className‘);
}
I would write as:
$$(’.element’).invoke(’addClassName’,'className’)
Oh, I missed this one:
Element.addClassName(‘element‘, ‘className‘);
Actually, in prototype, all the element methods are automatically added to all dom elements when you grab them. So actually this would be written like this in prototype:
$(’element’).addClassName(’className’);
I have published my thoughts on this subject at my blog:
http://maximkulkin.blogspot.com/2008/04/on-prototype-vs-jquery.html
I hear great things about jQuery.
But I personally prefer MooTools 1.2
If you need it small, you can customize your file to include only the parts of mootools that you actually use.
I have a new MooTools bundle up on Macromates’ Review branch http://macromates.com/svn/Bundles/trunk/Review/Bundles/JavaScript%20MooTools.tmbundle/
And there’s also a jQuery textmate bundle up there too http://macromates.com/svn/Bundles/trunk/Bundles/JavaScript%20jQuery.tmbundle/
@Duane: Thanks for the post. Apart from jQuery’s ease-of-use, another important distinction is the community and support from the jQuery team. We’re always looking for new ways to provide support and information to jQuery developers and I honestly believe we do an outstanding job at that.
In addition, our extensions list is absolutely amazing with hundreds of community-contributed extensions providing tremendous functionality. And with jQuery UI v1.5 due out shortly, the jQuery project will have a fabulous UI & effects lib that will greatly enhance the ability to build compelling applications.
We work very hard to to help jQuery developers and look forward to reading more of your posts about jQuery. Please be sure to follow us on Twitter at @jquery.
Thanks
Rey
jQuery project team
@Duane: Without getting into the details, it is true that other libraries are able to emulate jQuery’s behavior. However, without it being a central part of the library’s philosophy, the power of the technique (operating on sets of elements) is quickly diluted and eventually lost altogether.
Because jQuery is all about sets, every plugin available on the web, and every extension you write will drop in seamlessly into your project. $(”sel”).addClass(”foo”) easily becomes $(”sel”).addClass(”foo”).tabs().
It also makes techniques like jQuery’s liveQuery and new element data-store particularly powerful.
LiveQuery allows you to bind events to elements that gain a certain selector, even later on. For instance $(”p.alive”).liveQuery(”click”, function() { … }) will bind the click handler to any p.alive when it gets created, and unbind it when the element no longer matches the selector. It has exactly the same semantics as a typical event handler (”this” is the element that was bound, return false stops propagation and prevents default, etc.)
LiveQuery can also replace each to activate and deactivate behavior for elements on the fly: $(”p.alive”).liveQuery(function() { /* do this when the element first matches the selector */ }, function() { /* do this when the element no longer matches the selector */ }).
The per-element data-store, now a feature of Mootools as well, is made especially powerful because of how it interacts with jQuery’s core philosophy. You add elements to the data store via $(”sel”).data(”key”, val) and retrieve the elements via $(”sel”).data(”key”). Of course, the setter function is just a typical jQuery function, and so it can be chained like any other.
There’s an awesome plugin called effen by Nick Kallen that makes use of the data-store to allow you to bind functions to specific elements: $(”sel”).fn(”name”, function() { … }) to set and $(”sel”).fn(”name”) to activate.
Combined with liveQuery, you can do something like $(”p.awesome”).liveQuery(function() { $(this).fn({func: function() { … }, func2: function() { … }}). Later, you will be able to do $(”p.awesome”).fn(”func”), and you don’t need to track when elements get p.awesome.
Nick uses this for polymorphism (different elements can have functions with the same name, like “save”, with different actions).
The point of all of that was that a central philosophy can really build on itself, so it’s pointless to compare libraries feature-by-feature. Other libraries have provided mechanisms for copying jQuery on a feature-by-feature basis, but there can be only one
@Yehuda Although both of the examples come out looking very similar in both frameworks, it’s the result of two differing philosophies happening to be expressed in the same code. The reason the the original prototype examples were too verbose is because they were written from a JQuery mindset.
JQuery seems to be summed up in “perform OPERATIONS on a SET of selected things.” Prototypes is “THINGS automatically have the METHODS you want on them”
$(‘#element‘).addClass(‘className‘);
JQuery thinks of this as “get a Set and perform the add class Operation on it”.
$(‘element‘).addClass(‘className‘);
Prototype looks at this as “get a Thing and call a method on it”.
The syntax is only one character different, but that’s mostly because in good frameworks, simple things should be simple.
Taking the philosophy from one framework to write code in the other is a sure way to be both verbose and to irritate the heck out of yourself.
Just to clarify, Base dojo.js is much smaller than 80k.
Before ShrinkSaf:e ~448k
Before gzip: 77k
Standard 27k:
http://o.aolcdn.com/dojo/1.1.0/dojo/dojo.js
X-Domain 30k:
http://o.aolcdn.com/dojo/1.1.0/dojo/dojo.xd.js
You can use the entire toolkit without providing any of your own additional bandwidth by including the x-domain .js link in a script tag in your page.
It may seem larger, and in many cases is. If you start adding in “plugins” you will be sending additional code either way. It all adds up quickly.
The linked online ShrinkSafe program is built into the Dojo package system, which makes the optimizations to css and js automatically. (for the record, the online version might not be working properly either, I should update the page to reflect that … )
There was an interesting blog showing how dojo.query can be used to write code in a similar convention as jQuery, while retaining the full power of the build and package system:
http://www.sitepen.com/blog/2008/04/28/3-ways-to-upgrade-your-html-with-dojo/
Sorry to go on, the “80k, and Dojo is even bigger” caught my eye
Regards -
Peter Higgins
@Rey: Good point. The community around jQuery is fantastic, and something that definitely got my attention to begin with. One framework I know of has a closed sort of “don’t ask me anything until you’ve scoured the documentation” attitude which soured my first impression. Not mentioning any names… (mad4milk *ahem*)
@Peter: Thanks for the measurements, I should have done it myself before waving my hands like that
If I understand the comparison correctly, you’re saying that the ShrinkSafe version is 77k, which would be just slightly larger than jQuery’s and Prototype’s 51k each. Nice work on Dojo, by the way. It gets points in my book just for the level of respect it has in the corporate world.
@Yehuda: Wow! Thanks for pointing out some of the hidden treasures that come from consistently applying the set/operations and publisher/subscriber model within the framework. I think I will really dig LiveQuery and the effen library.
@duane - yes, the 448k is un-shrunk with inline comments, the 77k is the “default” release size. The 26k is obtained by server-side gziping. It is larger than an uncompressed jQuery or Prototype, though I’ve not done a comparison on what functionality each kit has vs the others (in the “single.js” sense) …
That would probably be an interesting blog, actually. All handle the issues we as web developers face with different conventions, though on a core level, provide near identical functionality. Events, CSS Selectors, Ajax/XHR, Animation, Package Systems, i18n, a11y, etc, etc …
Either way, thanks for the kind words. A lot of really great people from all walks of life work really really hard to keep things all running …
Regards,
Peter Higgins
Just to be clear, liveQuery is a plugin, albeit a very popular and frequently used one that is maintained by a member of the jQuery core team
But yeah… jQuery’s emphasis on a single “DOM” type really pulls together as you write more complex apps.
[...] this blog post on What Makes jQuery a Good Choice? Thought this provided a pretty good [...]
Leave a reply