Reputation: 50338
I'm writing a simple jQuery plugin, but I'm having trouble being able to use multiple instances on a page.
For instance, here is a sample plugin to illustrate my point:
(function($) {
$.fn.samplePlugin = function(options) {
if (typeof foo != 'undefined')
{
alert('Already defined!');
} else {
var foo = 'bar';
}
};
})(jQuery);
And then if I do this:
$(document).ready(function(){
$('#myDiv').samplePlugin({}); // does nothing
$('#myDiv2').samplePlugion({}); // alerts "Already defined!"
});
This is obviously an over-simplified example to get across the point. So my question is, how do I have two separate instances of the plugin? I'd like to be able to use it across multiple instances on the same page.
I'm guessing that part of the problem might be with defining the variables in a global scope. How can I define them unique to that instance of the plugin then?
Thank you for your guidance!
Upvotes: 18
Views: 34576
Reputation: 119
Just throwing my solution in here:
(function ($){
$.fn.plugin = function (options){
var settings = $.extend({}, $.fn.plugin.defaults, options);
settings.that = $(this);
$.fn.plugin.init (settings);
};
$.fn.plugin.defaults = { objval: 'default' };
$.fn.plugin.init = function (settings){
settings.that.val (settings.objval);
};
}( jQuery ));
$('#target1').plugin ({objval: 'not default'});
$('#target2').plugin ();
The settings variable is isolated every time you initialize the object.
Upvotes: 2
Reputation: 973
html:
<code class="resize1">resize1</code>
<code class="resize2">resize2</code>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.resize1').ratiofix({message:'resize1'});
$('.resize2').ratiofix({message:'resize2'});
});
</script>
I have found 2 solutions - the first one is jquery widget factory http://jqueryui.com/widget/ js code:
$.widget("custom.ratiofix",{
options:{
message:"nothing"
},
_create:function (){
var self=this;
this.setListeners();
},
setListeners:function (){
var self=this;
$(window).on('resize',$.proxy(self.printMsg,self));
},
printMsg:function (){
console.log(this.options.message);
}
});
And the second (without widget factory):
(function ($){
var Ratiofix = {
init: function(options, elem) {
this.options = $.extend({},this.options,options);
this.elem = elem;
this.$elem = $(elem);
this.setListeners();
return this;
},
options: {
message: "No message"
},
printMsg: function(){
console.log(this.options.message);
},
setListeners:function (){
var self=this;
this.$elem.on('click',function (){
console.log(self.options.message);
});
$(window).on('resize',$.proxy(self.printMsg, self));
}
};
$.fn.ratiofix=function (options){
this.init= function(options, elem) {
this.options = $.extend({},this.options,options);
this.elem = elem;
this.$elem = $(elem);
return this;
};
if ( this.length ) {
return this.each(function(){
var ratiofix = Object.create(Ratiofix);
ratiofix.init(options, this);
$.data(this, 'ratiofix', ratiofix);
});
}
};
})(jQuery);
In both cases plugins work separately and have own settings. In my case - 2 widgets listen to window resize and print to console own options.message
Upvotes: 3
Reputation: 1
This worked a treat for me! I had specific parameters for which pages/places I wanted to run a plugin and was able to achieve success by using a simple if statement. Hope this helps someone!
<!-- Begin JQuery Plugin Foo -->
<script src="js/foo_fun.js"></script>
<?php
if(substr_count(strtolower($currentUrl),"member")>0)
{
?>
<script>
$(document).ready(function(){
$('#vscroller').vscroller({newsfeed:'news_employee.xml', speed:1000,stay:2000,cache:false});
});
</script>
<?php
}
else
{
?>
<script>
$(document).ready(function(){
$('#vscroller').vscroller({newsfeed:'news_company.xml', speed:1000,stay:2000,cache:false});
});
</script>
<?php
}
?>
<!-- End JQuery Foo-->
Upvotes: -1
Reputation: 1
I had the same problem : how to use many instances of a plugin on only one form ? The usual way fails because in fact, the instance is not an instance of the plugin : it is an instance of jQuery. So, if more than one element is defined to be managed by a plugin, each definition overrides the previous parameters.
It was necessary to have a look on the problem from another side.
A plugin is usually made to react on a specific event for a specific element. e.g.. onclick on a button, or when the mouse is over the element. In my case, I had to use an autocomplete plugin for a city field, but my form has 5 tabs and in total 4 fields for the cities for 4 different parts of the information to be collected. For each fields, parameters are specifics.
By the way, I've realised iI don't need to have the plugin active everytime : just on the appropriate event on the field is enough.
So I had an idea : an event manager for each element. When the event appends, so I define the plugin action. Some code will be more efficient to explain : imagine you have 3 div blocks and your plugin must change the colours, but with specifics colours depending on which div is affected.
$(document).ready(function(){
// Wich elements are affected by the plugin
var ids = ['myDiv1','myDiv2','myDiv3'];
// foe each one :
for (v in ids)
{
//define from an event :
$('#'+ ids[v]).focus(function()
{
// depending which id is active :
var aParams, idDiv = $(this).attr('id');
// Choosing the right params
switch(idDiv)
{
case 'myDiv1':
aParams = {'color': '#660000', 'background-color': '#0000ff'};
break;
case 'myDiv2':
aParams = {'color': '#006600', 'background-color': '#ff00ff'};
break;
case 'myDiv3':
aParams = {'color': '#000066', 'background-color': '#ff0000'};
break;
default:
aParams = {'color': '#000000', 'background-color': '#ffffff'};
};
// Defining the plugin on the right element with the right params
$(this).myPlugin(
{
colors: aParams
});
});
}
});
And this works fine.
Sorry if my English is not perfect - I hope you understand well.
Upvotes: -4
Reputation: 9924
You need to use this.foo
instead of var foo
, so that the variable is only related to the current object.
Upvotes: 1
Reputation: 1948
instead of writing this
$("#divid1").samplePlugin();
$("#divid2").samplePlugin();
you can do this way
$.plugin('samplePlugin1', samplePlugin);
$("#divid1").samplePlugin1();
$.plugin('samplePlugin2', samplePlugin);
$("#divid2").samplePlugin2();
You can have much details from here http://alexsexton.com/?p=51
Upvotes: 1
Reputation: 179
I have the very same problem but i find a very handy solution i´ll post it for someone who may have this problem
when you define your variables insinde the plugin you could use the .data() to store all the variables you define
like this
(function($) {
$.fn.samplePlugin = function(options) {
var base = this;
this.foo // define foo
// do stuff with foo and other variables
// Add a reverse reference to the DOM object
this.data("pluginname", base);
};})(jQuery);
And when you want to use the same foo variable you should retrive the reference with this:
base = this.data("pluginname");
base.foo
Hope it helps
Logan
Upvotes: 17
Reputation: 126122
I'm not sure what you mean by having more than one instance of a plugin. A plugin would be available to use on any element.
This comment doesn't clarify much for me:
So say that it was a plugin that took a "color" parameter and turned the object into that color. Well, in that case you'd need multiple instances, as you're dealing with more than one page element turning more than one color.
In this case, you would pass in different colors are arguments as needed:
$('div#foo').makeColor('red');
$('div#bar').makeColor('blue');
Each time you call the plugin, it will use whatever arguments you give it. The plugin isn't a class that needs instances.
Upvotes: 2
Reputation: 39986
To answer your question directly, you can use jQuery.noconflict() to avoid namespace collisions and thus potentially have multiple instantiations on a page..
var $j = jQuery.noConflict();
// Use jQuery via $j(...)
$j(document).ready(function() {
// etc
check here
But I question your design. Why are you writing a plugin that appears to not operate on a jQuery wrapped set ? .. Plugins should be written to assume they are operating on a jQuery array held in 'this'. In which case any state can be stored in each of the items being acted upon... But maybe you are building something different?
Please review this page
Upvotes: 1