Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the most elegant way to create a jQuery plugin?

I would just like to know whats the best of these 3 approaches, and perhaps why?

1)

(function($) {
    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    var $el         = $(this),

                    /* some variables */
                        $selector1  = $el.find('container'),
                        count       = $selector1.length,
                        $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    doSomething1();
                    doSomething2();

                    function doSomething1() {
                        $selector1.css('width' , '300px');
                    };

                    function doSomething2() {
                        $selector2.each(function(i) {
                            //do something
                        });
                    };  
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.pluginName' );
        }
    };
})(jQuery);

2)

(function($) {
    var internal= {
        doSomething1    : function($selector1) {
            $selector1.css('width' , '300px');
        },
        doSomething1    : function($selector2) {
            $selector2.each(function(i) {
                //do something
            });
        }
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    /* 
                    The variables are declared here
                    other methods are declared in the internal obj literal
                    */
                    var $el         = $(this),

                    /* some variables */
                        $selector1  = $el.find('container'),
                        count       = $selector1.length,
                        $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    internal.doSomething1($selector1);
                    internal.doSomething2($selector2);
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.pluginName' );
        }
    };
})(jQuery);

3)

(function($) {
    /* 
    The variables are declared here
    */
    var $el,
        $selector1,
        count,
        $selector2;

    var internal= {
        doSomething1    : function() {
            $selector1.css('width' , '300px');
        },
        doSomething1    : function() {
            $selector2.each(function(i) {
                //do something
            });
        }
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    /* 
                    The variables are set here
                    other methods are declared in the internal obj literal
                    */
                    $el         = $(this),
                    $selector1  = $el.find('container'),
                    count       = $selector1.length,
                    $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    internal.doSomething1();
                    internal.doSomething2();
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.pluginName' );
        }
    };
})(jQuery);
like image 271
Ricardo Avatar asked Feb 28 '11 16:02

Ricardo


People also ask

What is a jQuery plugin?

A jQuery plugin is simply a new method that we use to extend jQuery's prototype object. By extending the prototype object you enable all jQuery objects to inherit any methods that you add. As established, whenever you call jQuery() you're creating a new jQuery object, with all of jQuery's methods inherited.

Are jQuery plugins free?

It's lightweight, and because it is extendable, there are jQuery plugins freely available for almost every functionality you can think of. Table of Contents: Web & Mobile Layouts Plugins. Menu & Navigation Plugins.

Where can I download jQuery plugins?

There are plenty of jQuery plug-in available which you can download from repository link at https://jquery.com/plugins.


1 Answers

2) is the correct answers.

For 1) there is no reason to create a new instance of the two functions for each .pluginName call since they are static.

For 3) I consider it bad practice to make those local .pluginName call specific variables static to your plugin. It may not cause an error right now but it's likely to induce subtle bugs.

Basically everything inside the init function should be specific to the call where as everything inside your (function($) { closure should be static to your plugin.

Have you tried 4) ?

(function($) {
    var MyObject = function($el) {
        /* 
        The variables are declared here
        other methods are declared in the internal obj literal
        */
        /* some variables */
        this.$selector1  = $el.find('container');
        var count       = $selector1.length;
        this.$selector2  = $el.find('pictures');

        /* do something e.g.*/
        this.doSomething1($selector1);
        this.doSomething2($selector2);
    };

    MyObject.prototype.doSomething1 = function() {
       this.$selector1.css('width' , '300px');
    };
    MyObject.prototype.doSomething2 = function() {
       this.$selector2.each(function(i) {
           //do something
       });
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    new MyObject($(this));
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.pluginName' );
        }
    };
})(jQuery);

As a general comment having an API of $(obj).pluginName("method", ...) can be annoying/unintuitive as an API design.

I would recommend allow you to $(obj).pluginName().method(...) aswell to keep the jQuery chaining thing going.

like image 189
Raynos Avatar answered Nov 30 '22 03:11

Raynos