ctown4life
ctown4life

Reputation: 965

Javascript class not scoping as expected

Hoping someone can point me in the right direction.

I'm not new to OOP but I am not as familiar with how it works in Javascript. I understand the notion that classes in js are objects.

I'm writing a script that will write some html and allow the user to add or remove some elements. Everything works fine except when you click on "Add Checkbox" for any of the instances the html is updated in the last instance as opposed to itself (this is what leads me to believe there is some kind of scoping or encapsulation failure).

I have simplified the problem and posted a fiddle, click on "Add Checkbox" for the "colors" instance and you'll see that the html is added to the "animals" group instead. Note my js comment on line 25.

http://jsfiddle.net/XrJ3D/

var CheckboxGroup = function(label){
  return this.init(label);
}
CheckboxGroup.prototype = {
  type: "checkbox",
  label: null,      
  description: null,
  $label: null,              
  init: function(label){
    if(!label) label = "Checkboxes";
    self = this;         
    this.$wrap = $("<div class='checkBoxGroup'></div>");
    this.$label = $("<div>"+label+"</div>").appendTo(this.$wrap);
    this.$options = $("<div></div>").appendTo(this.$wrap); 
    this.$add = $("<div class='n'>Add Checkbox</div>").appendTo(this.$wrap);

    this.$add.click(function(){          
      self.addOption("New Option");
    });

    this.options = [];       
    return this;          
  },
  addOption: function(label){
    $option = $("<div class='c'><input type='checkbox' name='"+label+"'><span class='l'>"+label+"</span></div>").appendTo(this.$options);

    $remove = $("<span class='rm'>x</span>").appendTo($option);        
    $remove.click(function(){
      var r=confirm("Remove Option?");
      if (r==false) return;                    
      $(this).parents('.c').remove();
    });
    this.options.push($option);
    return $option;
  },
  get: function(){
    return this.$wrap;
  }
}

// === CREATE SOME INSTANCES ===

a = new CheckboxGroup("Colors");
a.addOption('red');
a.addOption('green');
a.addOption('blue');    

$('body').append(a.get());

b = new CheckboxGroup("Animals");
b.addOption('dog');
b.addOption('cat');

$('body').append(b.get());

Thanks for any insight.

Upvotes: 2

Views: 55

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50787

As well as Blender's obviously correct answer, there are several other things you might want to fix:

  • The first line of your `init function should probably read

    this.label = label || "Checkboxes";

  • There is no need for your Constructor function or your init function to return anything. Doing so out of the Constructor is, in fact, slightly wasteful.

Upvotes: 0

Blender
Blender

Reputation: 298076

Your self variable is global and will be overridden by the object that was initialized last:

self = this;

Add var before it to make it local to your init function:

var self = this;

Demo: http://jsfiddle.net/XrJ3D/5/

Upvotes: 5

Related Questions