jQuery plugin - update settings after initialization

给你一囗甜甜゛ 提交于 2019-11-30 07:34:36

问题


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?


回答1:


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 ;)




回答2:


Try this pattern

(function ($) {
    var defaults = {
        "text": "abcdefg",
    }
    , options = $.extend({}, defaults, options);
    $.fn.plugin = function (options) {
        var options = (function (opts, def) {
            var _opts = {};
            if (typeof opts[0] !== "object") {
                _opts[opts[0]] = opts[1];
            };
            return opts.length === 0 
                   ? def 
                   : typeof opts[0] === "object" 
                     ? opts[0] : _opts
        }([].slice.call(arguments), defaults));
        return $(this).text(options.text)
    }
}(jQuery));

$(".results:eq(0)").plugin(); // return `defaults`
$(".results:eq(1)").plugin({"text":"gfedcba"}); // return `options`
$(".results:eq(2)").plugin("text", 123); // return `arguments` as `options`

    (function ($) {
        var defaults = {
            "text": "abcdefg",
        }
        , options = $.extend({}, defaults, options);
        $.fn.plugin = function (options) {
            var options = (function (opts, def) {
                var _opts = {};
                if (typeof opts[0] !== "object") {
                    _opts[opts[0]] = opts[1];
                };
                return opts.length === 0 
                       ? def 
                       : typeof opts[0] === "object" 
                         ? opts[0] : _opts
            }([].slice.call(arguments), defaults));
            return $(this).text(options.text)
        }
    }(jQuery));
    
    $(".results:eq(0)").plugin(); // return `defaults`
    $(".results:eq(1)").plugin({"text":"gfedcba"}); // return `options`
    $(".results:eq(2)").plugin("text", 123); // return `arguments` as `options`
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="results"></div><br />
<div class="results"></div><br />
<div class="results"></div>


来源:https://stackoverflow.com/questions/28395652/jquery-plugin-update-settings-after-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!