Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
170 views
in Technique[技术] by (71.8m points)

javascript - jQuery plugin - update settings after initialization

I have a jQuery plugin, and I want to be able to change options on the fly, like this example: $('.element').pwstabs('options','effect',scale) or something simular to it. I tried adding update: function, tried adding Plugin.prototype.update, but still cant figure out how to do that :)

Here's the structure of the plugin:

    ;(function ($, window, document, undefined) {

  var pluginName = "pwstabs",
    defaults = {
      effect: 'scaleout',
      defaultTab: 1,                
      containerWidth: '100%',       
      tabsPosition: 'horizontal',   
      horizontalPosition: 'top',    
      verticalPosition: 'left',     
      responsive: false,            
      theme: '',                    
      rtl: false,                   
      controlls: false,
      next: '',
      prev: '',
      first: '',
      last: '',
      auto: false,
      play: '',
      pause: ''
    };


  function Plugin(element, options) {
    this.element = $(element);
    this.$elem = $(this.element);
    this.settings = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }

  Plugin.prototype = {

    init: function(){

      // Here's the code for the plugin

    }

  };

  $.fn[pluginName] = function ( options ) {
    return this.each(function () {
      new Plugin( this, options );
    });
  };

})(jQuery, window, document);

So now I use the plugin like:

$('.element').pwstabs({
  effect: 'scalein',
  defaultTab: 2
});

And when I click a button, i want to change effect to lets say scaleout. With code like:

$('.button').click(function(){
  $('.element').pwstabs('options','effect','scalein');
});

So how do I implement this in the plugin?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Currently the only supported invocation pattern in that plugin is to send in an object literal containing the settings to overwrite the defaults. E.g.:

$('.element').pwstabs({
  effect: 'scalein',
  defaultTab: 2
});

That invocation pattern is defined in the following method:

$.fn[pluginName] = function ( options ) {
    return this.each(function () {
        new Plugin( this, options );
    });
};

As you see, a dictionary of options is sent as the only parameter to the constructor function Plugin() to build the plugin and initialize it.

To support the invocation pattern you need, you would have to modify this method to support both invocation patterns (initialization with an object literal, but also invoking any method with more params, like your options setting method).

Here is an improved function that will handle both invocation patterns. In addition it will also store the instance of a plugin on an element, so you can access the existing settings etc. on subsequent invocations (e.g. settings changes) on the same element.

$.fn[pluginName] = function (options) {

    // get the arguments 
    var args = $.makeArray(arguments),
        after = args.slice(1);

    return this.each(function () {

        // check if there is an existing instance related to element
        var instance = $.data(this, pluginName);

        if (instance) {
            if (instance[options]) {
                instance[options].apply(instance, after);
            } else {
                $.error('Method ' + options + ' does not exist on Plugin');
            }
        } else {
            // create the plugin
            var plugin = new Plugin(this, options);

            // Store the plugin instance on the element
            $.data(this, pluginName, plugin);
            return plugin;
        }
    });
}

This would allow you to invoke the plugin as requested:

$('.element').pwstabs('options','effect','slidedown');

However, this implies you have an 'options' method in the Plugin prototype, so make sure to add one:

Plugin.prototype = {

    options: function (option, val) {
        this.settings[option] = val;
    },

    // Constructing Tabs Plugin
    init: function () {
        // omitted code for brevity
    }
}

As you see the options settings just sets the new option on the existing instance. Very simple and efficient. The new setting will be picked up by the click method handler and voila!

Here is a jsFiddle with example code in case you have trouble implementing what i was describing so far:

http://jsfiddle.net/7whs3u1n/6/

Update: I have much improved my answer to get rid of unneeded stuff, include more details and a full implementation that works (check the fiddle above) ;) i hope that this answers your question!

Adding statefulness to your plugin wasn't hard, but when you have spare time also check the alternative mechanism for writing stateful jQuery stateful plugins called jQuery widget factory:

http://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/

In the future you can consider rewriting your plugin to use the widget factory. It would certainly make your code simpler ;)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...