Public functions from within a jQuery plugin

Daniel picture Daniel · Jun 23, 2009 · Viewed 33.5k times · Source

I love the jQuery plugin architecture, however, I find it frustrating (probably due to a lack of understanding on my part) when I want to retain a reference to the plugin instance to access properties or methods later on in my code.

Edit: I want to clarify that what I am really trying to do is retain a reference to the methods and properties used within the plugin, so that I can use them later

Lets take the case of a AJAX loading icon. In a more traditional OOP environment, I could do:

var myIcon = new AJAXIcon();
myIcon.start();
//some stuff
myIcon.stop();

The methods and properties of my object are stored on a variable for later use. Now if I want to have the same functionality in a jQuery plugin, I would call it from my main code somewhat like this:

$("#myId").ajaxIcon()

By convention, my plugin needs to return the original jQuery object passed to my plugin allowing for chainability, but if I do that, I loose the ability to access methods and properties of the plugin instance.

Now, I know that you can declare a public function in my plugin, somewhat along the lines of

$.fn.ajaxIcon = function(options) {
    return this.each(function () {
        //do some stuff
    }
}

$.fn.ajaxIcon.stop = function() {
    //stop stuff
}

However, without breaking the convention of returning the original jQuery object, I can't retain a reference to the specific instance of the plugin that I want to refer to.

I would like to be able to do something like this:

var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon 
myIcon.start();
//some stuff
myIcon.stop();

Any thoughts?

Answer

DEfusion picture DEfusion · Jun 25, 2009

If you do something like the following:

(function($){

$.fn.myPlugin = function(options) {
    // support multiple elements
    if (this.length > 1){
        this.each(function() { $(this).myPlugin(options) });
        return this;
    }

    // private variables
    var pOne = '';
    var pTwo = '';
    // ...

    // private methods
    var foo = function() {
        // do something ...
    }
    // ...

    // public methods        
    this.initialize = function() {
        // do something ...
        return this;
    };

    this.bar = function() {
        // do something ...
    };
    return this.initialize();
}
})(jQuery);

Then you can access any of your public methods:

var myPlugin = $('#id').myPlugin();

myPlugin.bar();

This is taken from this very helpful article (May 2009) from trulyevil.com which is itself an extension on this article (Oct 2007) from learningjquery.com.