views:

1492

answers:

5

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!

A: 

jQuery is largely stateless, so why would you need more than one version on a page?

I would think that this means that your design may be flawed.

But, though I haven't tried it, you may be able to get them in different iframes perhaps, if they come from different urls, so at a minimum the javascript files need a unique name.

James Black
I'm talking about more than one instance of a particular plugin, not jQuery as a whole. 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. Does that help explain better?
James Skidmore
Yes, that clears up my confusion. I would be concerned about a plugin that is tied to just one element. For example, the jQuery datepicker can be attached to any number of elements, and that is a good design. You should be able to have more than one instance, assuming they used OOP in their javascript. If you can only have one on a page the problem is that you can load multiple versions, but how to access one and differentiate from the others will be the problem. Without more information I don't know how much more I could help, as I would have to guess too much.
James Black
Thanks for the reply James. I guess my question essentially is, how do I encapsulate the plugin options inside of the object instance, so each instance can be unique?
James Skidmore
I just realized something that I didn't understand... it makes sense now. Thank you for your help James.
James Skidmore
Glad I could help, wish I knew what I said for your Eureka moment. <g>
James Black
+1  A: 

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.

Nathan Long
Thanks Nathan, I appreciate it!
James Skidmore
A: 

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

Scott Evernden
A: 

Hi, I had the same problem : how to use many instances of a plugin on only one form ? The usual way fail 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 overide the previous parameters.

It was necessary to have a lok on the problem from another side.

A plugin is usualy made to react on an specific event for a specific element. I.E. 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 informations to be collected. For each fields, parameters are specifics.

By the way, I've realised i don't need to have the plugin active everytime : just on the appropriate event on the field is enought.

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 blocs and your plugin must change the colours, but with specifics colours depending witch 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 wich 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 plungin 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.

Enjoy ;)

Cyrano_fr
A: 

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

Logan