开发者

jQuery Plugin Authoring - Set different options for different elements

I have created a jQuery plugin that works great with the exception of being able to call the plugin on different objects and each object retaining the options it was given. The problem is that if I call the plugin on one object, say:

$('#myDiv1').myPlugin({
    option1: 'some text',
    option2: true,
    option3: 'another option value'
});

then call the plugin again on another object, say:

$('#myDiv2').myPlugin({
    option1: 'different text',
    option2: false,
    option3: 'value for myDiv2'
});

Then if I go back and try to do something with #myDiv1 that needs its original options to still be intact, ie:

$('#myDiv1').myPlugin.update();

it won't have it's original options, but they will be overridden by the options for #myDiv2. What's the proper way to do this so that each object will retain the original options given to it? (And here's some example code of what I'm doing in the plugin)

(function($) {
$.fn.myPlugin = function(options) {

    // build main options before element iteration
    var opts = $.extend({}, $.fn.myPlugin.defaults, options);

    _option1 = opts.option1;
    _option2 = opts.option2;
    _option3 = opts.option3;

    // iterate all matched elements
    return this.each(function() {
        callPluginFunctions( this, opts );
    });

};

    .开发者_JAVA技巧...code continued....

I realize this is some kind of scope creep or something. So, how do I get my options to stay attached and remain in the scope of the original object (ie #myDiv1) that they were given to.

EDIT: In doing some research I see that you can store data to an object using jQuery's .data function, and the docs say jQuery UI uses it extensively. Would the proper thing to do here be store the options on the object using .data, then when referenced later use the options stored in .data ???


First, you will generally want to handle the command within your extension method. Second, you should be attaching configurations to each item...

(function($){
var defaultOptions = { /* default settings here */ };

//called on the native object directly, wrap with $(obj) if needed.
function initializeObject(obj, options) {
  //assign the options to the object instance.
  $(obj).data('myPlugin-options', $.extend(defaultOptions, options) );
  //do other initialization tasks on the individual item here...
}

function updateObject(obj) {
  // use $(obj).data('myPlugin-options');
}

function setOption(obj, key, value) {
  var d = $(obj).data('myPlugin-options');
  d[key] = value;
  $(obj).data('myPlugin-options', d);
}

$.fn.myPlugin = function(command, option, val) {
  if (typeof command == "object") {
    //initialization
    return this.each(function(){
      initializeObject(this, command);
    });
  }
  if (typeof command == "string") {
    // method or argument query
    switch (command.toLowerCase()) {
      case 'option':
        //get value, return the first item's value
        if (typeof val == undefined) return this.eq(0).data('myPlugin-options')[option];
        //set option value
        return this.each(function() {
          setOption(this, option, val);
        });

      case 'update':
        return this.each(function() {
          updateObject(this);
        });
      //other commands here.
    }
  }
}
})(jQuery)

With the above example, you have a generic template for a jQuery extension, It's usually good form to have the following convention for use..

Initialization:
  $(...).myPlugin({ initialization-options-here });
Command:
   $(...).myPlugin('command-name'); //where command can be update, etc.
Get Option:
  var myValue = $(...).myPlugin('option', 'option-name');
Set Option:
  $(...).myPlugin('option', 'option-name', newValue);

Updated to use .data off of each individual obj.


I've been having the same problem, but only functions passed were being overwritten. Straight up properties were persisting.

Anyway, to further explain what ~reinierpost meant, changing your code to this should work. You'll have to pass 'opts' everywhere, but I think that's necessary to take the options out of the plugin-wide namespace.

$.fn.myPlugin = function(options) {

    // iterate all matched elements
    return this.each(function() {
        // build main options before element iteration
        var opts = $.extend({}, $.fn.myPlugin.defaults, options);
        callPluginFunctions( this, opts );
    });
};

Edit: Here's code from my plugin

this.each(function() {
    var thisConfig = config;
    thisConfig = $.extend(thisConfig,settings);
    $.attach($(this),thisConfig);
});

...

$.attach = function($target,config){

So I have no plugin-wide "config" - just inside each function.


Your options are plugin-wide. Move them inside the each(). (Why are you asking this question? You pretty much spell out the solution yourself.)

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜