1

I'm struggling with understanding JS loops. I found an online tutorial for a button changing random colors for a div id="container". However, it turns out that the random colors are frequently repeated after a click. I want to change the code and loop through the array colors one by one and change the color of the div#container after each click. This is my code:

let colors = ["blue", "yellow", "green", "brown", "orange"];
let btn = document.getElementById("btn");

btn.addEventListener("click", function () {
  let container = document.getElementById("container");
  for (i = 0; i < colors.length; i++) {
    let selectColor = colors[i];
  }

  container.style.backgroundColor = selectColor;
});

I get the error: assignment to undeclared variable i. Can someone help me out?

7
  • 1
    for (var i = 0; ...; you're never declaring i 🙂 (or let instead of var). There's other issues, but to address the "assignment to undeclared variable i", you need a variable keyword in your for() loop declaration.
    – Tim Lewis
    Commented Oct 13, 2021 at 17:45
  • Put „let“ in for (let i = ..) like here: stackoverflow.com/questions/31793924/…
    – Aydin K.
    Commented Oct 13, 2021 at 17:46
  • @TomDev you've edited your question and now the code has a significant difference from its original version. Are you sure you're still getting the same error? The code still won't produce the result you want, but I'm guessing the error isn't happening any more.
    – jnpdx
    Commented Oct 13, 2021 at 17:47
  • 2
    @jnpdx it's not THAT different when I look at the revisions. And the change wouldn't even matter, since in both the previous and the current version, selectColor is going to throw a ReferenceError when used outside the block it's declared. Even then, OP gets an error before that line.
    – VLAZ
    Commented Oct 13, 2021 at 17:48

4 Answers 4

4

You're looping through all the colors in the array at once, and then only use the last one to set the backgroundcolor.

You should only increment by one and then set the color

let colors = ["blue", "yellow", "green", "brown", "orange"];
let btn = document.getElementById("btn");
let i = 0;
let container = document.getElementById("container");

btn.addEventListener("click", function () {
  i++;
  if(i >= colors.length) i = 0;
  container.style.backgroundColor = colors[i];
});
3

You need to declare the variable i on line 6, so instead of

  for (i = 0; i < colors.length; i++) {
    let selectColor = colors[i];
  }

you would have

  for (let i = 0; i < colors.length; i++) {
    let selectColor = colors[i];
  }
2
  • 1
    True, but what is the point of the loop at all?
    – James
    Commented Oct 13, 2021 at 17:49
  • 2
    There is no point, but the question asked about the error message and JS loops so I provided the correct syntax.
    – PumpkinQL
    Commented Oct 13, 2021 at 17:51
1

you missed declaring "i" in the for loop.

for(let i = 0; i < colors.length; i++) {
    let selectColor = colors[i];
}
1
  • This has already been added as an answer and a comment; you don't need to add it again.
    – Tim Lewis
    Commented Oct 13, 2021 at 17:51
0

Just to add to Kokodoko's answer: you don't need a loop because all you need to do is cycle through the array indexes one-by-one when the button is clicked, not all the colours at once.

Here's a slightly different approach which doesn't rely on the array index being a global variable. Instead it returns a function (closure) to the listener that, when called, changes from one colour to another.

const colors = ['blue', 'yellow', 'green', 'brown', 'orange'];

const container = document.getElementById('container');
const btn = document.getElementById('btn');

// We call the function which returns a new function
// which is what the button calls
btn.addEventListener('click', handleClick(), false);

// Initially set `index` to 0
function handleClick(index = 0) {

  // This is the function the listener will call
  return function() {

    // Set the BG colour to the new index
    // if the index hasn't reached the end of the array
    // otherwise set it to zero, and start again.
    if (index < colors.length - 1) {
      container.style.backgroundColor = colors[index++];
    } else {
      index = 0;
    }
  }

}
#container {
  width: 100px, height: 100px;
}
<button id="btn">Click</button>
<div id="container">Container</div>

4
  • 1
    Thanks Andy but your approach is too advanced for me for the time being. I'm still a beginner. I'll figure it out some day. :) Need to learn the basics first.
    – TomDev
    Commented Oct 13, 2021 at 18:10
  • @TomDev, I've added some additional comments to the answer. It's ok if you don't understand it if you're a new coder, but closures are a very versatile method of programming.
    – Andy
    Commented Oct 13, 2021 at 18:15
  • One can meet great guys on this website. Thanks a lot again. I don't understand that"false" in the event listener. Why did you use it?
    – TomDev
    Commented Oct 13, 2021 at 18:21
  • 1
    No worries. It's the useCapture option. I tend to always include it. @TomDev. Good luck with the coding.
    – Andy
    Commented Oct 13, 2021 at 18:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.