Wednesday, December 16, 2009

Migrating to jQuery: My First Plugin

A couple posts ago I wrote about how I couldn't justify switching from Prototype to jQuery. Well I take it back (sort of).

After spending more time with jQuery's event handling, I wanted more out of Prototype and I couldn't justify trying to port what I wanted over from jQuery and expect it to work across all browsers. I'd rather let jQuery and its large, active community help me out with testing. So I've begun the process of converting a good portion of my applications over to jQuery.

While updating the code is more tedious than anything, I found myself missing the convenience of Prototype's direct access to DOM elements. For example, I no longer have the following:


if ( $('checkboxA').checked ) {
$('checkboxB').checked = false;
}


Granted with jQuery there are multiple ways to accomplish the same thing but, while they're not too much longer, they're still longer:


if ( $('#checkboxA').attr('checked') ) {
$('#checkboxB').attr('checked',false);
}

if ( $('#checkboxA').is(':checked') ) {
$('#checkboxB').removeAttr('checked');
}

if ( $('#checkbox:checked').length ) {
$('#checkboxB').attr('checked',false);
}


Since I like to write as little code as possible and everybody else seems to really like jQuery's plugin architecture, I figured I'd try write my own plugin. And since it's my first plugin, please don't make too much fun of it.


jQuery.each(('checked,disabled').split(','), function(i, name) {
jQuery.fn[name] = function() {
return arguments ? this.attr(name, arguments[0]) : this.attr(name);
};
});


It works similar to the built-in jQuery event helpers, such as $(selector).change() and $(selector).click(fn). In my plugin, if you pass an an argument, it sets the attribute's value. If you don't pass in an argument, it returns the attribute's value.

Here's how I can write my sample code now:


if ( $('#checkbox').checked() ) {
$('#checkboxB').checked(false);
}


I'll admit it's not much shorter, but it reads a lot better to me. Plus, I don't have to directly call .attr() anymore, which is basically just a generic getter/setter. And if you didn't notice, I also added the same logic for .disabled() for good measure.

I haven't decided if I want to fully embrace a plugin that accomplishes something so trivial, but for some reason I like it.

2 comments:

  1. Tony:

    jQuery also returns an array of DOM elements as part of the object, so:

    $('#checkboxA')[0].checked

    Would be the same as:

    $("checkboxA").checked

    That means you could do:

    var checkbox = $("#checkboxA")[0];

    if( checkbox.checked )
    ...

    Also, you could create a wrapper function to give you more Prototype-like functionality:

    window.$$ = function (s){
    return window.jQuery(s).get(0);
    }

    You could now just do:

    if ( $$('#checkboxA').checked ) {
    $$('#checkboxB').checked = false;
    }

    ReplyDelete
  2. @Dan,

    Yeah there's definitely a number of ways you could do it. I don't know how much I like the $$() wrapper, since Prototype uses $$() as its element selector method. Might be a little too confusing for people who are used to Prototype... :)

    ReplyDelete