2

I am trying to create custom tab widget in Javascript and jquery. I have created the tab object but facing problem while assigning click event take a look towards code. I have attached event but it is working only on last object. Can someone suggest better way to do this

function TabTitleBox(TabName){
  this.SelectedBox = 0;
  this.TitleBoxContainer = $('<div>'+TabName+'</div>');
  this.TitleBoxContainer.addClass("STATSTab");
  this.TitleBoxContainer.addClass("UnSelectedTab");
  this.TitleBoxContainer.on('mouseenter',function(){
    CurrentColor = $(this).css('background-color');
    var t = tinycolor(CurrentColor);
    var NewColor = tinycolor.saturate(t,50);
    $(this).css("background-color",NewColor);
  }).on('mouseleave',function(){
    $(this).removeAttr('style','background-color');
  });

  this.SelectTab = function(){
    if(this.SelectedBox == 0){
    $(this.TitleBoxContainer).removeClass("UnSelectedTab");
    $(this.TitleBoxContainer).addClass("SelectedTab");
    this.SelectedBox = 1;
    }
  }

  this.RemoveStyle = function(){
    $(this.TitleBoxContainer).removeAttr('style','background-color');
  }

  this.UnSelectTab = function(){
    if(this.SelectedBox == 1){
    $(this.TitleBoxContainer).removeClass("SelectedTab");
    $(this.TitleBoxContainer).addClass("UnSelectedTab");
    this.SelectedBox = 0;
    }
  }

  return this;
}


TabContainer = new Array();
TabContainer.push(new TabTitleBox("Is first tab"));
TabContainer.push(new TabTitleBox("Is Second tab"));
TabContainer.push(new TabTitleBox("Is Third tab"));
TabContainer.push(new TabTitleBox("Is Fourth tab"));

for(var x = 0; x < TabContainer.length ; x++){
  Tab = TabContainer[x];
  $('body').append(Tab.TitleBoxContainer);
  $(Tab.TitleBoxContainer).on('click', function(){
    if(Tab.SelectedBox == 1){
      Tab.UnSelectTab();
      Tab.SelectedBox = 0;
    }else{
      Tab.SelectTab();
      Tab.SelectedBox = 1;
    }
    Tab.RemoveStyle();
  });
}

found out the solution thanks for the answer changes done in my code as follows. Link can be found here http://skondgekar.comeze.com/Test.php

        TabContainer = new Array();
        TabContainer.push(new TabTitleBox("Is first tab"));
        TabContainer.push(new TabTitleBox("Is Second tab"));
        TabContainer.push(new TabTitleBox("Is Third tab"));
        TabContainer.push(new TabTitleBox("Is Fourth tab"));

        var funcs = [];

        for(var x = 0; x < TabContainer.length ; x++){
            Tab = TabContainer[x];
            funcs[x] = (function(Tab){
                return function(){
                    $(Tab.TitleBoxContainer).on('click', function(){
                            if(Tab.SelectedBox == 1){
                                Tab.UnSelectTab();
                            }else{
                                Tab.SelectTab();
                            }
                            Tab.RemoveStyle();
                        });
                }
                })(Tab);

            funcs[x]();
            $('body').append(Tab.TitleBoxContainer);
        }
  • What are the values of TabContainer.length before entering the loop, and x after the final closing parenthesis? Are all 4 tabs added to the body? What did you use to verify if the events are attached? – user1853181 Jan 15 '14 at 16:31
  • I am Able to get the elements in my browser and also able to get their innerHTML using alert statement using click event but on clicking on the element it only changing class of last object and not of the object being clicked – Sudarshan Kondgekar Jan 16 '14 at 13:37
  • You need to implement a proper closure on your click function, or try to reference the active object with $(this) instead of Tab, since when the click functions are executed the Tab refers to the last Tab processed. – user1853181 Jan 16 '14 at 13:41
  • I have uploaded my code here http://skondgekar.comeze.com/Test.php I am totally stuck up tried everything. Please help – Sudarshan Kondgekar Jan 16 '14 at 14:45
  • I have added two examples of how you can solve your problem, by implementing closures. – user1853181 Jan 16 '14 at 14:45
  • After changing values to this I am getting only one Tab which is the first tab and also click event not working – Sudarshan Kondgekar Jan 16 '14 at 15:00
  • Did you try both examples? Do you have any errors in your console? – user1853181 Jan 16 '14 at 15:02
  • Thanks you helped me a lot. I figured out the solution. Also I installed firebug which helped me – Sudarshan Kondgekar Jan 16 '14 at 16:15

1 Answers1

0

You need to implement a proper closure on your click handler.

Let me point you in the right direction:

// (This is untested, but should be pretty close to what you need)

for(var x = 0; x < TabContainer.length ; x++){
  Tab = TabContainer[x];
  $('body').append(Tab.TitleBoxContainer);
  $(Tab.TitleBoxContainer).on('click', myClosure(Tab)); // Calling the closure
}

function myClosure(Tab) { // Binding the current value of the Tab to the function it
    return function()     // and returning the function
        if(Tab.SelectedBox == 1){
          Tab.UnSelectTab();
          Tab.SelectedBox = 0;
        }else{
          Tab.SelectTab();
          Tab.SelectedBox = 1;
        }
        Tab.RemoveStyle();
    });
}

Another way to write the closure would be:

for(var x = 0; x < TabContainer.length ; x++){
  Tab = TabContainer[x];
  $('body').append(Tab.TitleBoxContainer);
  $(Tab.TitleBoxContainer).on('click', function(theRealTab) { // Creating closure
    return function(){
      if(theRealTab.SelectedBox == 1){
        theRealTab.UnSelectTab();
        theRealTab.SelectedBox = 0;
      }else{
        theRealTab.SelectTab();
        theRealTab.SelectedBox = 1;
      }
      theRealTab.RemoveStyle();
    }
  })(Tab);    // Binding the current value of Tab to the function variable theRealTab
}

Without the closure, the Tab variable in your click functions will always be the current value of the variable (in this example - the last Tab processed if your for loop).

For more info:

Closures inside loops - The accepted answer has an example very similar to this

How do closures work

Community
  • 1
  • 1
user1853181
  • 813
  • 6
  • 12