Classy Query


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

» View Source to 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:

  1. <script src="jquery.js"></script>
  2. <script src="classy.js"></script>
  3. <script>
  4. jQuery.Events.addEventListener(document, "ready", function(){
  5.   jQuery.querySelectorAll("div").forEach(function(elem){
  6.     jQuery.DOM.append(elem, " <b>More...</b>");
  7.   });
  8.  
  9.   jQuery.querySelectorAll("div b").forEach(function(elem){
  10.     jQuery.Events.addEventListener(elem, "click", function(elem, event){
  11.       var next = jQuery.Traversal.nextSibling(elem);
  12.       var animation = jQuery.Effects.buildAnimation( next, {height: "toggle"});
  13.       amimation.start();
  14.     });
  15.   });
  16. });
  17. </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.

  1. jQuery.DOM.boldWrapInner = jQuery.DOM.wrapInner.extend({
  2.   attach: function(elem){
  3.     this._super(elem, "<b></b>");
  4.   }
  5. });
  6.  
  7. jQuery.querySelectorAll("div").forEach(function(elem){
  8.   jQuery.DOM.boldWrapInner(elem);
  9. });

Additionally you can treat pieces of functionality as if they were attachable behaviors, like so:

  1. 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:

  1. var Person = jQuery.Class.create({
  2.   init: function(name){
  3.     this.name = name;
  4.   }
  5. });
  6.  
  7. var ClassyDude = Person.extend({
  8.   sipWine: function(){
  9.     return "Has a beautiful bouquet.";
  10.   }
  11. });

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).

  1. jQuery.Effects.collapse = jQuery.Effects.buildAnimation.extend({
  2.   attach: function(elem){
  3.     this._super(elem, {height: "hide", width: "hide"});
  4.   }
  5. });

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.

  1. jQuery.querySelectorAll("div")
  2.   .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’.

  1. jQuery.querySelectorAll("div").forEach(function(elem){
  2.   jQuery.DOM.addClassName(elem, "current");
  3. });

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.

  1. jQuery.querySelectorAll("div").forEach(function(elem){
  2.   jQuery.Effect.hide( elem );
  3. });
  4.  
  5. jQuery.Effect.hide( jQuery.querySelector("#item") )

» View Source to Classy Query

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.

Posted: April 1st, 2008


If you particularly enjoy my work, I appreciate donations given with Gittip.

65 Comments (Show Comments)



Comments are closed.
Comments are automatically turned off two weeks after the original post. If you have a question concerning the content of this post, please feel free to contact me.


Secrets of the JavaScript Ninja

Secrets of the JS Ninja

Secret techniques of top JavaScript programmers. Published by Manning.

Ukiyo-e Database and Search

Ukiyo-e.org

Japanese woodblock print database and search engine.


John Resig Twitter Updates

@jeresig

Infrequent, short, updates and links.


via Ad Packs