开发者

How to extend jQuery plugin's methods?

In the following code i tried to extend my test plugin. I want to add a new method definition to existing plugin.

(function($) {
    var settings = {
        bg: 'white'
    };

    var methods = {
        init: function(options) {
            options = $.extend({}, options, settings);
            return this.each(function () {
                $(this).data("test", options);
            });
        },
        whiten: function() {
            var options = this.data("test");
            this.css('background-color', options.bg);
        }
    };

    $.fn.test = function(method) {
        if (methods[method]) {
            re开发者_Go百科turn 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');
        } 
    }  

})(jQuery);

// New Method Definition
 var methods = {     
        newMethod: function(){
            alert('umut');   
      }
 };


// Extending test plugin with newMethod
$.fn.extend(true,$.fn.test, methods );

$(document).ready(function() {
    $('ul').test().css('background-color', 'wheat');
    $('#go').click(function() {
        $('ul').test("whiten");
        // Calling newMethod
        $('ul').test("newMethod");    
    });
});

But i got following error at firebug console:

uncaught exception: Method newMethod does not exist

How can i extend

var methods = {
}

block inside my test plugin?

Here is the jsfiddle link.


For those who use the plugin structure recommended by jQuery team, it will be hard to add methods given that there is only one function added to the $.fn object and thus, only one public function. So, in my case, I decided that the best solution was to add a method to the plugin that extends the methods variable. This will be accessible from outside the plugin as any other function. Example here:

(function($) {
    var settings = {
        bg: 'white'
    };

    var methods = {
        init: function(options) {
            options = $.extend({}, options, settings);
            return this.each(function () {
                $(this).data("test", options);
            });
        },
        whiten: function() {
            var options = this.data("test");
            this.css('background-color', options.bg);
        },
        extendMethods: function(newMethods) {
            $.extend(true, methods, newMethods);
            return $(this);
        }
    };

    $.fn.test = 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');
        } 
    }  

})(jQuery);

Voila! Then you just need to call it like this:

$.fn.test('extendMethods',{...Methods object here...});

Note: I'm aware that this requires you to edit the plugin code in the first place, but there's not much to add and may be viable in many cases. Hope it helps someone!


Edit: I'm changing my answer. This may be the simpler solution, since it requires less code change. Add methods as a property of your plugin. Add this line after you define your plugin function:

$.fn.test.methods = methods;

This needs to be inside your closure that defines the plugin. The rest of your code should just work, extending test via $.extend() as you are already doing.

Here's my original answer:

If you want to be able to extend your plugin in this way, your plugin must expose a way to do so. You could add methods as a property in settings and then deeply extend settings.methods with options.methods in your init method.

If you intend for settings to be the defaults, and options to override settings, you've got your arguments reversed in your call to .extend(). Reverse your arguments, then add true as the first parameter to make it a deep extend:

options = $.extend(true, {}, settings, options);

Then put your methods in settings:

var settings = {
    bg: "white",
    methods: {
        init: function(options) {
            options = $.extend(true, {}, settings, options);
            ... // etc.
         },
         ...
    }
};

Then, instead of extending your plugin's methods via $.extend(), do it in your init call:

$(".foo").test("init", { methods: methods });


You can't as methods is only local to the function. You can only extend it if you make it accessible from the outside.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜