1

Below is a loop that creates six boxes with different colors. When clicking on a box, the variable "color" changes to the color of the box. There is an obvious problem with the code and that's closures (all the boxes gets the last class in the array and boxColors[i] isn't possible to use inside the event (undefined).

How can I solve this in an elegant way? Thanks in advance.

var boxColors = ['red', 'green', 'blue', 'yellow', 'white', 'black'];

for (var i = 0; i < boxColors.length; i++){
    $('<div/>', {
        'class': boxColors[i]
    }).appendTo(toolboxSection1).click(function(){
        color = boxColors[i];
    });     
}
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
holyredbeard
  • 19,619
  • 32
  • 105
  • 171
  • *"...all the boxes gets the last class in the array..."* You sure about that? Each element should get a unique class from the Array, so the only issue should be with the event handler (which could easily access the element's `className` property). –  Jan 10 '12 at 00:08

2 Answers2

4

An example of this problem and how to solve it in the general case is described in JavaScript closure inside loops – simple practical example.

However, jQuery allows you to pass additional data to an event handler (see the documentation), which is another way to solve this problem:

for (var i = 0; i < boxColors.length; i++){
    $('<div/>', {
        'class': boxColors[i]
    })
    .appendTo(toolboxSection1)
    .click({color:  boxColors[i]}, function(event){
        // event.data.color
    });     
}
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

The problem is your for loop is capturing the single variable i instead of boxColors.length count of them. The easiest way to fix this is to create a new function which takes the index as a parameter and hence creates a new i for every iteration

var action = function(i) {
    $('<div/>', {
        'class': boxColors[i]
    }).appendTo(toolboxSection1).click(function(){
        color = boxColors[i];
    });  
};

for (var index = 0; index < boxColors.length; index++) {
    action(index);
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454