How to create a jQuery plugin with methods? How to create a jQuery plugin with methods? javascript javascript

How to create a jQuery plugin with methods?


According to the jQuery Plugin Authoring page (http://docs.jquery.com/Plugins/Authoring), it's best not to muddy up the jQuery and jQuery.fn namespaces. They suggest this method:

(function( $ ){    var methods = {        init : function(options) {        },        show : function( ) {    },// IS        hide : function( ) {  },// GOOD        update : function( content ) {  }// !!!    };    $.fn.tooltip = function(methodOrOptions) {        if ( methods[methodOrOptions] ) {            return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));        } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {            // Default to "init"            return methods.init.apply( this, arguments );        } else {            $.error( 'Method ' +  methodOrOptions + ' does not exist on jQuery.tooltip' );        }        };})( jQuery );

Basically you store your functions in an array (scoped to the wrapping function) and check for an entry if the parameter passed is a string, reverting to a default method ("init" here) if the parameter is an object (or null).

Then you can call the methods like so...

$('div').tooltip(); // calls the init method$('div').tooltip({  // calls the init method  foo : 'bar'});$('div').tooltip('hide'); // calls the hide method$('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method

Javascripts "arguments" variable is an array of all the arguments passed so it works with arbitrary lengths of function parameters.


Here's the pattern I have used for creating plugins with additional methods. You would use it like:

$('selector').myplugin( { key: 'value' } );

or, to invoke a method directly,

$('selector').myplugin( 'mymethod1', 'argument' );

Example:

;(function($) {    $.fn.extend({        myplugin: function(options,arg) {            if (options && typeof(options) == 'object') {                options = $.extend( {}, $.myplugin.defaults, options );            }            // this creates a plugin for each element in            // the selector or runs the function once per            // selector.  To have it do so for just the            // first element (once), return false after            // creating the plugin to stop the each iteration             this.each(function() {                new $.myplugin(this, options, arg );            });            return;        }    });    $.myplugin = function( elem, options, arg ) {        if (options && typeof(options) == 'string') {           if (options == 'mymethod1') {               myplugin_method1( arg );           }           else if (options == 'mymethod2') {               myplugin_method2( arg );           }           return;        }        ...normal plugin actions...        function myplugin_method1(arg)        {            ...do method1 with this and arg        }        function myplugin_method2(arg)        {            ...do method2 with this and arg        }    };    $.myplugin.defaults = {       ...    };})(jQuery);


What about this approach:

jQuery.fn.messagePlugin = function(){    var selectedObjects = this;    return {             saySomething : function(message){                              $(selectedObjects).each(function(){                                $(this).html(message);                              });                              return selectedObjects; // Preserve the jQuery chainability                             },             anotherAction : function(){                               //...                               return selectedObjects;                             }           };}// Usage:$('p').messagePlugin().saySomething('I am a Paragraph').css('color', 'red');

The selected objects are stored in the messagePlugin closure, and that function returns an object that contains the functions associated with the plugin, the in each function you can perform the desired actions to the currently selected objects.

You can test and play with the code here.

Edit: Updated code to preserve the power of the jQuery chainability.