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 );
});
};
....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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With