Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a jQuery Plugin, How do I do Custom Scopes?

I would like to create a jQuery plugin with an API something like this:

$("#chart").pluginName().attr("my_attr");

Instead of these:

$("#chart").pluginName_attr("my_attr");
$.pluginName.attr("#chart", "my_attr");

Basically, instead of having to namespace every method that acts similar to ones in jQuery, I'd like to "scope" the methods to a custom api, where $("#chart).pluginName() would return an object such that get, attr, find, and a few others would be completely rewritten.

I'm sure this is not a well-liked idea as it breaks convention (does it?), but it's easier and more readable, and probably more optimized, than the two options above. What are your thoughts?

like image 985
Lance Avatar asked Jun 15 '10 20:06

Lance


1 Answers

I'm experimenting with the idea.

Seems like you could just modify the functions for the jQuery object that the plugin receives, and return that.

Something like this:

$.fn.tester = function() {  // The plugin

    this.css = function() {  // Modify the .css() method for this jQuery object
        console.log(this.selector);   // Now it just logs the selector
        return this;     // Return the modified object
    }
    return this;   // Return the modified object

}

http://jsfiddle.net/EzzQL/1/ (updated from original to overwrite .html() as well)

$.fn.tester = function() {
    this.css = function() {  
        console.log(this.selector);  // This one logs the selector
        return this;
    }
    this.html = function() {
        alert(this.selector); // This one alerts the selector
        return this;
    }
    return this;
};

// Because .css() and .html() are called after .tester(),
// they now adopt the new behavior, and still return a jQuery
//    object with the rest of the methods in tact
$('#test1').tester().css().html().animate({opacity:.3}); 


// .css() and .html() still behave normally for this one
//    that doesn't use the plugin
$('#test2').css('backgroundColor','blue').html('new value');​

EDIT:

Alternatively, if you're going to cache the elements to which the custom methods should be applied, you could .apply() the methods before you use them.

To build on the example above:

var $test1 = $('#test1');  // Cache the elements

$.fn.tester.apply($test1,[this]);  // apply() the new methods

$test1.css().html().animate({opacity:.3});  // Use the new methods

like image 163
user113716 Avatar answered Oct 26 '22 00:10

user113716