jQuery Syntax for Easy Portability?

published:
2009.06.03
topics:
javascript

I have to say, I find the syntax of the jQuery JavaScript library to be very logical, efficient, and readable. I realized today that jQuery code also has the very interesting property of being relatively easy to port to any other JavaScript library. And jQuery, or a jQuery-like syntax, seems to be a reasonable starting point for creating JavaScript-library-agnostic code — that is, JavaScript code that depends on a JavaScript library to function, but can be easily made to work with any library.

As an example, lets consider the following jQuery call:

$('#foo,#bar').addClass('test').css('color', 'blue');
Now lets look at code that does the same thing written for YUI and Dojo:

// YUI
YAHOO.util.Dom.addClass(['foo', 'bar'], 'test');
YAHOO.util.Dom.setStyle(['foo', 'bar'], 'color', 'blue');

// Dojo
dojo.query('#foo,#bar').addClass('test').style('color', 'blue');

Lets say we wanted to keep the jQuery syntax shown in the very first example above, but instead of including jquery.js and all of the jQuery code, we wanted to use the YUI JavaScript library. How could we make the jQuery style call use YUI? Here's some code that maps those calls to the YUI library:

function UseYUI(selector) {
    this.nodes = YAHOO.util.Selector.query(selector);

    this.addClass = function (className) {
        YAHOO.util.Dom.addClass(this.nodes, className);

        return this;
    }

    this.css = function (property, value) {
        if (typeof value == 'undefined') {
            return YAHOO.util.Dom.getStyle(this.nodes, property);

        } else {
            YAHOO.util.Dom.setStyle(this.nodes, property, value);

            return this;
        }
    }
}

function $(selector) {
    return new UseYUI(selector);
}

After adding the above code to your page you could keep the jQuery syntax — i.e. $('#foo,#bar').addClass(… — but include the YUI library code and files instead of the code and files for jQuery.

And actually, if we had many methods like addClass where they are the same in jQuery and YUI except for the first argument, we could create a helper function to generate the mapped functions for us:

function UseYUI(selector) {
    this.nodes = YAHOO.util.Selector.query(selector);
    
    this.mapMethodToYUIDom = function(method) {
        this[method] = function () {
            var args = new Array();
            args.push(this.nodes);
            for (var i = 0; i < arguments.length; i++) {
                args.push(arguments[i]);
            }
        
            YAHOO.util.Dom[method].apply(null, args)
        
            return this;
        }
    }

    this.mapMethodToYUIDom('addClass');
    this.mapMethodToYUIDom('removeClass');
}

Mapping the jQuery style calls to Dojo in this case is even easier than YUI. Much easier:

function $(selector) {
    var nodes = dojo.query(selector);

    nodes.css = nodes.style;

    return nodes;
}

It would be a fair amount of work, and a decent bulk of code, to completely map all jQuery style calls to either YUI or Dojo, or any other JavaScript library for that matter. Obviously, when porting from one JavaScript library to another, going through line by line and replacing each call would result in slightly faster and more file-size efficient code. But that's no walk in the park either.

With the method I've described in this post, you could actually put in the one-time effort towards creating the code to dynamically map from jQuery syntax to any other framework thereby making any and all projects you build and distribute library-agnostic. What do you think? It seems like such mappings would come in useful.