1

I'm beginning with jQuery plugins, apologies for the newbie question. My objective is to have a single plugin instantiated twice, where each instance has its own variables values. However, they seem to share the namespace.

For example, given the following plugin:

(function ( $ ) {

    var x = false;

    $.fn.test = function() {

        alert(x);

        if ( !x )
           x = true;

        return this;

    };

}( jQuery ));

that is invoked from the following divs:

$( "div1" ).test();
$( "div2" ).test();

The alert displays first false, then true, when the objective is to have to sets of variables where the alert would display false twice.

is this possible?

ps0604
  • 1,227
  • 23
  • 133
  • 330
  • possible duplicate of [jQuery global variable best practice & options?](http://stackoverflow.com/questions/2866866/jquery-global-variable-best-practice-options) – TheNorthWes Jun 20 '14 at 17:32

3 Answers3

2

There is some confusion in your question. Your plugin is a simple function. You don't "instantiate" a function by calling it. So you don't "instantiate" your plugin either.

You can instantiate things in your function, and persist them somewhere.

Since the outer scope runs only once, in your original solution you only get one instance of variable x.

If you create it inside the function, a new instance gets created every time you call it.

I assume you want to create an instance for every element you call this plugin on. A good solution would be to attach your data to the DOM element you initiate your plugin on, like:

(function ( $ ) {
    $.fn.test = function() {
        var vars = this.data('testPlugin');
        if (!vars) {
            vars = {
                x: false,
                something: 'else'
            };
            this.data('testPlugin', vars);
        }

        alert(vars.x);
        vars.x = !vars.x;

        return this;
    };
}( jQuery ));

Try this fiddle.

vinczemarton
  • 7,756
  • 6
  • 54
  • 86
  • thanks, I said "instantiate" because I see the plugin as an object with attributes and functions. – ps0604 Jun 20 '14 at 18:30
0

You should put

var x = false;

inside $.fn.test function, otherwise the x variable is the same for all test() functions, and set to true after first call.

You can read more here about javascript variable scoping.

Daniele Santi
  • 771
  • 3
  • 24
  • 31
  • Thanks, but it didn't work. I put `var x = false;` inside `$.fn.test function` and obviously the variable is always set to false, not only after the first call. – ps0604 Jun 20 '14 at 17:46
0

Actually, this is much easier than the previous answers. The context of this in your plugin is the jQuery object for the DOM element you're receiving based on the selector you provided. To gain uniqueness, simply iterate over each element, like so:

(function($) {
  $.fn.test = function() {
    return this.each(function() {
      var x = false;

      alert(x);

      if (!x) {
        x = true;
      } 
    });
  }
}(jQuery));

$("div1").test();  //false
$("div2").test();  // false

Here's a JSFiddle to confirm: http://jsfiddle.net/Z6j7f/

James Lee Baker
  • 797
  • 6
  • 9
  • `alert(x)` will always alert false here, and since nothing else accesses the inner scope the `if...` part is completely unnecessary since nothing else will access `x` ever. Is this intended? `return this.each(function () { alert(false); });` would do exactly the same. – vinczemarton Jun 21 '14 at 21:10
  • From my interpretation of the original problem posted, the conditional check was arbitrary and used to evaluate if the state of `x` changed. I would agree with you that the condition is unnecessary. – James Lee Baker Jun 22 '14 at 18:44