Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

for loops & onclick

trying to use a for loop to set up multiple event listeners, this does not seem to be working only the last event listener in the loop works after this code runs

// Interactive console engine //
for (i = 0;i < 12; i++){
document.getElementById(PFPconsole[i].buttonLabel).onclick = function(){

//clicked button turns green//
document.getElementById(PFPconsole[i].buttonLabel).style.backgroundColor = "green";

//change content in text window when button is clicked//
document.getElementById("textWidgetContent").innerHTML = PFPconsole[i].textContent;

//change content in video window when button is clicked//
document.getElementById("videocontent").setAttribute("src",PFPconsole[i].videoContent); 
};
};

1 Answer

Unfortunately, this happens whenever you define a function within a loop. The value of i within the anonymous function is allowed to keep changing even after the function is defined and assigned, so by the time it is actually called, the value is always 11.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops.3A_A_common_mistake

I can't thoroughly test a solution because this is pretty environment dependent, but I think something like this will work:

function getClickCallback(i) {
  return function() {

    //clicked button turns green//
    document.getElementById(PFPconsole[i].buttonLabel).style.backgroundColor = "green";

    //change content in text window when button is clicked//
    document.getElementById("textWidgetContent").innerHTML = PFPconsole[i].textContent;

    //change content in video window when button is clicked//
    document.getElementById("videocontent").setAttribute("src",PFPconsole[i].videoContent); 

  };
}

for (i = 0;i < 12; i++){
  document.getElementById(PFPconsole[i].buttonLabel).onclick = getClickCallback(i);
}

This worked perfectly, thank you Need to read up on scope and closure