I'm working on a jQuery plugin but I'm encountering issues with the "scope" of variables. Each plugin will need to keep track of a considerably sized multidimensional array, as well as the root element that the jQuery plugin was attached to.
As shown below, I've defined var $rootEl = null;
and var multidArray = null;
at the top of the plugin code; however, when I run $(anySelector).pluginName("value");
on multiple elements (or when I call .pluginName()
twice with different selectors), it would appear that these variables are not sandboxed / scoped to the plugin instance, so the second instance overwrites both of the values and the first instance looks blank in the DOM (because all jQuery actions are applied on $rootEl
with the original value being overwritten on the second jQuery plugin call).
(function ($) {
var $rootEl = null;
var multidArray = null;
directChildren = function(uuid) {
return $rootEl.children("[data-uuid=" + uuid + "]");
},
incrementCounter = function() {
this.counter++;
},
resetGenIteration = function() {
this.counter = 0;
},
process = function(item) { // Will be called from a callback(val) in another
// javascript file but still needs to have access to the local variables
// of the current jQuery plugin
incrementCounter();
...
},
...
$.fn.pluginName = function(rootvar) {
this.each(function() {
$rootEl = $(this);
resetGenIteration();
populate(rootvar);
$rootEl.addClass("pluginName").delegate("div", "click", divClick);
});
}
}(jQuery));
Yesterday I attempted to convert the plugin to use init and this.varname
to store the values, and it appeared to hold onto the this.$rootEl
property correctly for each instance of the plugin, but I had to move all my functions inside of var PluginName = { ... }
and switch them from funcName = function()
to funcName: function()
to be able to see the plugin instance's "local" variables. Then I encountered numerous errors where functions were not defined, so I tried prefixing all my function calls with this.
and PluginName.
to read as this.functionName()
or PluginName.functionName()
respectively, which worked for some functions, but not all. Some of my functions are called from another jQuery plugin that runs a callback function and passes data to it, and in these cases, this.$rootEl
becomes undefined
.
(function ($){
var PluginName = {
init: function(options, rootEl) {
this.options = $.extend({}, this.options, options);
this.rootEl = rootEl;
this.$rootEl = $(rootEl);
this.setListeners();
return this;
},
options: {
rootvar: "test"
},
...
setListeners:function (){
var self = this;
this.$rootEl.on("div", "click", function () {
$.proxy(self.divClick, self);
});
}
};
...
$.fn.pluginName = function(options) {
this.init = function(options, rootEl) {
this.options = $.extend({}, this.options, options);
this.rootEl = rootEl;
this.$rootEl = $(rootEl);
this.multidArray = null;
return this;
};
this.each(function() {
var plugInstance = Object.create(PluginName);
plugInstance.init(options, this);
$.data(this, 'pluginName', plugInstance);
});
}
}(jQuery));
How do I refactor my code to store the multi-dimensional array and root element in a way that only that given plugin can internally retrieve and modify? Surely I should not be using .data()
for large arrays?
Thanks!