I am working on a jQuery plugin, but I am having some trouble with the design pattern, which combines the defaults and options, data and namespacing techniques from jQuery’s best practices. Here’s the abstracted version of my code:
(function($) {
var defaults = {
key1: 'value1',
key2: 'value2'
};
var settings = {};
var methods = {
init: function() {
return this.each(function() {
var $this = $(this), data = $this.data('pluginname');
console.log('init called');
// If the plugin hasn't been initialized yet
if (!data) {
//Do more setup stuff here
$this.data('pluginname', {
key3: 'value3',
key4: 'value4'
});
}
//test for settings and data
console.log(settings);
console.log(data);
});
},
methodname: function() {
return this.each(function() {
var $this = $(this), data = $this.data('pluginname');
console.log('methodname called');
//test for settings and data
console.log(settings);
console.log(data);
});
}
};
$.fn.pluginname = function(method, options) {
settings = $.extend({}, defaults, options);
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 on jQuery.pluginname' );
}
};
$(document).ready(function() {
$('body').pluginname();
$('body').pluginname('methodname', {key1: 'overriding default value for key 1'});
});
})(jQuery);
If you run that code with the latest version of jQuery you will see that I am calling both the init and methodname functions and logging the settings and data objects in each. In the methodname call, I can access both settings and data, but in the init call itself, the data object returns undefined. If I set a breakpoint in the script at line 21, I can call back the data object with $this.data('pluginname') in the console. Anyone see what I am doing wrong here? I should just be able to write data.key3 inside the init, function, right?
In your
initmethod, at the very beginning of the.eachloop you assign the object stored in the currently iterated element to yourdatavariable. If there is no data available for the specified key,datais undefined.You then test
datafor truthiness, and if it is evaluates to false you go ahead and assign a data object to the current element.Then later on, you call
console.log(data);and it gives youundefined. This is expected, asdatawas initially assignedundefined– and that’s what it still refers to. To fix: