NOTE: This was an April Fools joke for April 1st, 2008.
Over the past two years, seeing hundreds of thousands of people use jQuery, a major point has become apparent: jQuery simply isn’t able to scale to handle the development needs of most power users. It lacks the clarity and power functionality that most developers need in order build applications in a collaborative environment.
For this reason I’ve put a lot of work into a new library (which sits on top of jQuery), called:
Classy Query
If one thing has become apparent to me it’s that users enjoy working with the typical Class-style of object creation and inheritance. Because of this I’ve constructed the entirety of Classy Query in an classical manner (you can inherit and override any piece of functionality that you desire).
Before we go too far, let’s take a look at the type of clearly-defined code that you can now write with Classy Query:
<script src="jquery.js"></script> <script src="classy.js"></script> <script> jQuery.Events.addEventListener(document, "ready", function(){ jQuery.querySelectorAll("div").forEach(function(elem){ jQuery.DOM.append(elem, " <b>More...</b>"); }); jQuery.querySelectorAll("div b").forEach(function(elem){ jQuery.Events.addEventListener(elem, "click", function(elem, event){ var next = jQuery.Traversal.nextSibling(elem); var animation = jQuery.Effects.buildAnimation( next, {height: "toggle"}); amimation.start(); }); }); }); </script>
You can even sub-class functionality, creating your own pieces of encapsulation. All of the class and inheritance functionality is taken care of by the Simple JavaScript Inheritance code released last week.
jQuery.DOM.boldWrapInner = jQuery.DOM.wrapInner.extend({ attach: function(elem){ this._super(elem, "<b></b>"); } }); jQuery.querySelectorAll("div").forEach(function(elem){ jQuery.DOM.boldWrapInner(elem); });
Additionally you can treat pieces of functionality as if they were attachable behaviors, like so:
jQuery.querySelectorAll("div").attach(new jQuery.DOM.boldWrapInner());
There’s a number of core features encompassed in Classy Query that really help to transform the traditional jQuery experience into something much more usable.
Class creation
The full Simple JavaScript Inheritance API is included in Classy Query, allowing you to extend and create JavaScript ‘classes’, like so:
var Person = jQuery.Class.create({ init: function(name){ this.name = name; } }); var ClassyDude = Person.extend({ sipWine: function(){ return "Has a beautiful bouquet."; } });
Inheritance
It’s possible to inherit from any existing piece of Classy Query functionality, supporting a true ‘programming in the large’ mindset. You can inherit from, or completely override, existing methods with ease (especially since they’re all classes).
jQuery.Effects.collapse = jQuery.Effects.buildAnimation.extend({ attach: function(elem){ this._super(elem, {height: "hide", width: "hide"}); } });
Behaviors
Behaviors tend to encapsulate a portion of functionality which is applied against an element (such as making a table sortable or making an item draggable). Classy Query supports a technique to make this particular implementation trivial.
jQuery.querySelectorAll("div") .attach(new jQuery.DOM.addClassName("current"));
No more ‘this’
The ‘this’ keyword is confusing and frequently misused. To counter this all access to elements (within functions) is done by the first argument, rather than through ‘this’.
jQuery.querySelectorAll("div").forEach(function(elem){ jQuery.DOM.addClassName(elem, "current"); });
Re-Structuring
The hierarchy of jQuery has been completely re-organized. Rather than having a single, flat, interface through which to access all methods functionality has been broken down into individual groupings of methods. These groupings tend to, also, coordinate with the jQuery Documentation for convenience.
Additionally, nearly all the method names have been re-named in order to provide a greater level of clarity to developers. Frequently it was found that the concise method names of jQuery provided too much confusion to developers just getting started with the library. The end result is a library that is easier to read and understand for developers.
The full list of categories and changed methods can be found in the following table:
jQuery | Classy Query |
---|---|
jQuery | jQuery.querySelectorAll |
each | forEach |
prepend | jQuery.DOM.prepend |
append | jQuery.DOM.append |
before | jQuery.DOM.insertBefore |
after | jQuery.DOM.insertAfter |
wrap | jQuery.DOM.wrap |
wrapInner | jQuery.DOM.wrapInner |
wrapAll | jQuery.DOM.wrapAll |
clone | jQuery.DOM.clone |
empty | jQuery.DOM.empty |
remove | jQuery.DOM.remove |
replaceWith | jQuery.DOM.replaceWith |
removeAttr | jQuery.DOM.removeAttribute |
addClass | jQuery.DOM.addClassName |
hasClass | jQuery.DOM.hasClassName |
removeClass | jQuery.DOM.removeClassName |
offset | jQuery.DOM.getOffset |
text | jQuery.DOM.getText |
text | jQuery.DOM.setText |
html | jQuery.DOM.getHTML |
html | jQuery.DOM.setHTML |
attr | jQuery.DOM.getAttribute |
attr | jQuery.DOM.setAttribute |
val | jQuery.DOM.getValue |
val | jQuery.DOM.setValue |
height | jQuery.DOM.getHeight |
height | jQuery.DOM.setHeight |
width | jQuery.DOM.getWidth |
width | jQuery.DOM.setWidth |
css | jQuery.DOM.getCSS |
css | jQuery.DOM.setCSS |
children | jQuery.Traverse.getChildElements |
find | jQuery.Traverse.getDescendantElements |
next | jQuery.Traverse.getNextSiblingElements |
nextAll | jQuery.Traverse.getAllNextSiblingElements |
parent | jQuery.Traverse.getParentElements |
parents | jQuery.Traverse.getAncestorElements |
prev | jQuery.Traverse.getPreviousSiblingElements |
prevAll | jQuery.Traverse.getAllPreviousSiblingElements |
siblings | jQuery.Traverse.getSiblingElements |
filter | jQuery.Traverse.filterSelector |
bind | jQuery.Events.addEventListener |
unbind | jQuery.Events.removeEventListener |
trigger | jQuery.Events.triggerEvent |
hover | jQuery.Events.hover |
toggle | jQuery.Events.toggle |
show | jQuery.Effects.show |
hide | jQuery.Effects.hide |
toggle | jQuery.Effects.toggle |
animate | jQuery.Effects.buildAnimation |
queue | jQuery.Effects.queue |
dequeue | jQuery.Effects.dequeue |
$.ajax | jQuery.Ajax.request |
load | jQuery.Ajax.loadAndInsert |
ajaxSetup | jQuery.Ajax.setup |
serialize | jQuery.Ajax.getSerializedString |
serializeArray | jQuery.Ajax.getSerializedArray |
querySelector and querySelectorAll
Finally, rather than having a generic, catch-all, method as jQuery selector functionality is deferred to the new querySelector and querySelectorAll methods. These methods only support pure CSS 1-3 selectors (nothing extra) in an attempt to avoid any unpleasant situations when a browser’s native querySelectorAll is implemented.
jQuery.querySelectorAll("div").forEach(function(elem){ jQuery.Effect.hide( elem ); }); jQuery.Effect.hide( jQuery.querySelector("#item") )
I hope this particular library will be of use to the general jQuery-using population. I hope we can start to have an open dialog, moving forward, getting everyone to adopt a more standard approach to JavaScript development. There’s no reason why we shouldn’t be using this tried-and-true approach to application development. It’s worked in an untold number of existing applications, it’s bound to work here as well. Enjoy.
Bramus! (April 1, 2008 at 3:32 am)
Sweet! This really was something I’ve been waiting for. Gonna give it a spin :)
atom (April 1, 2008 at 3:35 am)
happy new year =)
Felix Geisendörfer (April 1, 2008 at 3:35 am)
This is great! This fits perfectly with the jQuery philosophy … ; )
Tim Koschuetzki (April 1, 2008 at 3:35 am)
Haha awesome. ;]
Gabriel Walt (April 1, 2008 at 3:39 am)
Nice, but to me it feels like a verbose jQuery.
J.W (April 1, 2008 at 3:41 am)
Really nice “classic” implementation of jQuery B-)
André Neves (April 1, 2008 at 3:46 am)
Happy April fools day John!!
It didn’t “feel” right :)
Johann (April 1, 2008 at 3:48 am)
I have been waiting for this for ages! The jQuery syntax has always been too short and concise for my tastes.
Bohdan Ganicky (April 1, 2008 at 3:50 am)
The logo is very classy as well :D
Már (April 1, 2008 at 3:51 am)
LOL… Good one!
Gabriel Walt (April 1, 2008 at 3:51 am)
If this is an April joke, it’s by far the best I’ve seen!!! :-D
Dave (April 1, 2008 at 3:55 am)
Wouldn’t class behavior actually be useful for some people? It’s nice to know how easy it is to change the name of everything. You could make jQuery look like YUI (eg YAHOO.util.Dom.getStyle) really easily.
Asbjørn Ulsberg (April 1, 2008 at 4:00 am)
Fabulous! Now you can accomplish the exact same as you’ve always been able to do with jQuery, but with a lot more code! ;-]
Will Kelly (April 1, 2008 at 4:14 am)
No, no, John only wants to make you all think
Will Kelly (April 1, 2008 at 4:15 am)
^ that it’s an April fools joke ;)
(sorry post got truncated).
Richard D. Worth (April 1, 2008 at 4:32 am)
write more. do less?
It’s about time!
Eric Wahlforss (April 1, 2008 at 4:34 am)
Very amusing :)
Borgar (April 1, 2008 at 4:52 am)
The real question here is why someone would have made a purple hat with a leopard print band, and not put a feather in it!?
Mega69 (April 1, 2008 at 5:53 am)
Ah ah!! Awesome :D
Angel Fradejas (April 1, 2008 at 5:59 am)
Finally I will be able to deploy enterprisey-classy-jQuery and continue being paid by source-code weight.
It was not very pleasant the light and concise source-code I was producing until now.
But please, consider inflating classy.js from its 6kb. Most managers and decision-makers I know only consider frameworks from 1MB and up.
Jacob Rus (April 1, 2008 at 7:12 am)
Now all you need is a script to convert old jQuery code to the new classier kind, so we don’t accidentally leave all that confusing concise old code lying around where a new developer might find it, and, not knowing any better, try to imitate it.
Howie (April 1, 2008 at 7:29 am)
Brilliant! Any chance you can package each class seperately too? I also think you also need some heavy-weight documentation of each Class/method/attribute.
Ryan Breen (April 1, 2008 at 7:49 am)
The hat is a nice touch. :-)
Rich Thornett (April 1, 2008 at 7:49 am)
The documentation for this joke is better than that of most frameworks. I am in awe.
Joan Piedra (April 1, 2008 at 8:05 am)
Haha, I love the logo =)
Jake McGraw (April 1, 2008 at 8:17 am)
pimp hat = win
Richard@Home (April 1, 2008 at 8:24 am)
I don’t know which is worse: the fact I fell for this completely, or the fact I know a Stylin’ Purple Hat when I see one…
http://www.wowhead.com/?screenshot=view&3.25680#17225
Dylan (April 1, 2008 at 8:24 am)
Finally, a jQuery release that I would use! ;)
gonchuki (April 1, 2008 at 8:50 am)
I guess you forgot YUI on the inspiration credits… sweet verbosity :)
Andrew (April 1, 2008 at 9:04 am)
Sorry, John, but I’d better keep using YUI! Has anyone bothered to look at the source code? This library is simply too short to be useful in real-world! What should I tell to my boss?
Rey Bango (April 1, 2008 at 9:24 am)
LOL! Classic!
keif (April 1, 2008 at 10:19 am)
What, no feather in the hat?
Nate Cavanaugh (April 1, 2008 at 10:24 am)
I would love to be there when someone unsuspectingly adds this to the project, and the boss takes a look at the top of the source.
Seeing the whole thing go down would be pretty hilarious…
ryan (April 1, 2008 at 10:38 am)
The pimp hat gave it away…
Gordon (April 1, 2008 at 10:42 am)
I’m glad that you’ve seen the light. Us old guys don’t want none of your fandangled duck-type magic fancypants crap.
The old ways are the best ways!
Jörn Zaefferer (April 1, 2008 at 10:44 am)
Creating animations is still quite a mess. You should introduce a factory, making the code more verbose, more readable and easier understandable, something like this:
// pass window and document to the animation factory factory method,
// enabling us to create animations for other windows/documents as well
var animationFactory = jQuery.Effects.createAnimationFactory(window, document);
// now create animation, using the reusable animationFactory
var animation = animationFactory.buildAnimation( next, {height: "toggle"});
// we could also use a different factory to start the animation, allowing
// cross-window animations, when implemented by browsers
animationFactory.startAnimation(animation);
Alecs Galindo (April 1, 2008 at 10:53 am)
great joke!!! Happy April fools!!
I can’t belive all your work just for this day, hohoho nice!! (y)
Sean McBride (April 1, 2008 at 11:17 am)
I hate April Fools Day. Is it so bad that I understand class-based development better than “plugin architecture?” Fooey.
PENIX (April 1, 2008 at 11:25 am)
It’s about time JQuery got a clue. JQuery was worthless without classes.
Doug (April 1, 2008 at 11:47 am)
Needs more XML.
Dean Edwards (April 1, 2008 at 1:29 pm)
Looks fine to me. :-)
Dustin Diaz (April 1, 2008 at 1:33 pm)
Let it go down in history that John himself said jQuery “lacks the clarity and power functionality that most developers need in order build applications in a collaborative environment.”
Lindsey Simon (April 1, 2008 at 1:39 pm)
POWER FUNCTIONALITY
chrismarx (April 1, 2008 at 1:51 pm)
whew, dont scare us like that! who would ever want a verbose javascript framework, yuck!!
Bertrand Le Roy (April 1, 2008 at 1:54 pm)
Nice try. At the same time, this is actually useful as a list of anti-patterns.
Stephen Tudor (April 1, 2008 at 2:52 pm)
Awesome, this really gives plain old jQuery the power boost it needed. Nice work! I measure the usefulness of code I write in how long it takes to type the idioms, so you’re definitely on the right track with this :p
cristian (April 1, 2008 at 4:33 pm)
I’m sorry john, but you’re late to the party. ms ajax has been around for over a year by now. this is close but no cigar
Ariel Flesler (April 1, 2008 at 4:40 pm)
That really scared me to death.. :)
jquertil (April 1, 2008 at 5:00 pm)
LOL
ROFL
Erik (April 1, 2008 at 5:04 pm)
Totally awesome. The only thing to “get” me today. Most April Fools stuff is so weak it’s just sad, but this was brilliant.
Jorn, Doug, Dean, and Dustin’s comments make it even better.
Zach (April 1, 2008 at 6:49 pm)
I was reading this in growing horror until realizing it was an April Fool’s joke. Incredible. Nice one John.
Francisco Brito (April 1, 2008 at 9:31 pm)
Hopefully it’s also slow. I get dizzy with fast scripts.
Trideep Gogoi (April 2, 2008 at 12:48 am)
Simply AWESOME!!!
I cant believe I fell for this. I was thinking this looks vaguely familiar. Hey Francisco, Yea I hope the same. haha Slow as Hill.
jQuery for Life haha.
Jeremy Martin (April 2, 2008 at 7:55 am)
Sounds awesome – I think this addresses the only two reservations I really had about jQuery. A growing library really needs clear and well organized namespaces, and classical inheritance is so well suited to so many of my needs; I can’t wait to play with it!
Jeremy Martin (April 2, 2008 at 7:56 am)
Oh man… it’s completely too late to delete that. That’s what I get for reading this a day late…. lol
Les (April 2, 2008 at 8:35 am)
I also like it :)
CTAPbIu_MABP (April 3, 2008 at 6:36 am)
I think this is a logic extension of http://ejohn.org/blog/simple-javascript-inheritance/
But now i don’t see any practical usage of it, or new functionality, it’s just for fun and beauty
SpawN (April 4, 2008 at 12:20 pm)
JQuery was worthless without classes
منتدى (April 5, 2008 at 1:37 pm)
POWER FUNCTIONALITY
raymond (April 6, 2008 at 12:34 am)
If this is the future of jQuery then I want nothing to do with it! :)
I like jQuery’s simple and straight forward API.
jQuery = Write Less, Do More
Classy Query = Write More, Do Less
Ernest (April 7, 2008 at 4:52 pm)
I wish this wasn’t a joke since I completely agree with the first paragraph of the article.
Phil Mander (April 19, 2008 at 10:08 pm)
Hi John,
I have a couple of (hopefully) constructive criticisms.
Firstly I get frustrated with the term ‘class’ being associated with Javascript. It can cause confusion with Javascript being a prototypal OO language.To the user Classy Query is just using namespaced functions to perform its operations as opposed to functions on a prototype. In Java, one would generally call the equivalent approach a static method rather than a class method. Maybe call it Staticy Query :)
Also, usually I’d really advocate strong namespacing to clearly organise code libraries, but in jQuery’s case I think it might be a bit overkill. For a library which is likely to be used as commonly as jQuery within a particular codebase, the extra namespacing could make code too verbose (this a problem with YUI) I think jQuery.append() etc will suffice. Further package namespacing should be reserved for extensions, eg: jQuery.ui.draggable();
Besides these points I really like the approach your taking here. Although, I think jQuery’s great, I don’t like the way it has the potential to masquerade itself as a scripting language on top of Javascript. This will make pedantic JS developers such as myself much happier :)
Henrik Sarvell (April 23, 2008 at 7:25 am)
One of the most serious jokes I’ve seen in a long time. I had to actually click myself here from the rss reader and read the comments before I could be 100% sure that it was in fact a joke and not insanity. Awesome!
Ian (May 2, 2008 at 8:55 am)
you son of a bitch.
Luã de Souza (May 12, 2008 at 8:48 am)
Maybe some people would love this way…