Miah Tayen
Miah Tayen

Reputation: 63

How to Loop between two colors in pure JavaScript?

I am having trouble looping between 2 colours of the body forever. It only loops once.

I am using the 'enter' key to trigger the loop and the 'space' key to stop the loop.

const red= () => {
 document.body.style.backgroundColor = "red";
}

const blue= () => {
 document.body.style.backgroundColor = "blue"; 
}


const both =  () => {
setTimeout(() => red(), 1000);
 setTimeout(() => blue(), 2000);
}

document.body.addEventListener("keydown", function() {
 if (event.keyCode == 13) {
   setInterval(both(), 3000);
 }

 if (event.keyCode == 32) {
   clearInterval(both());
 }
});
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Looping Colors</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
    <script src="script.js"></script>
    </body>
</html>

Upvotes: 2

Views: 273

Answers (2)

Icepickle
Icepickle

Reputation: 12796

The error you make in your code currently, is that you:

  • you call the function red and blue and assign the value as the callback for the timeout (which is undefined)
  • both isn't returning the reference to the timeouts
  • setTimeout runs exactly once
  • clearInterval doesn't work on a function reference as you believe it is, but with the result of setInterval
  • setTimeout might be less appropriate, you could use setInterval easier

In the below code, I added an extra toggle method, that just uses an function property count to toggle between red and blue, both returns the value of setInterval and assigns it to a function property interval to keep track of that interval, and then clears that one

const red= () => {
 document.body.style.backgroundColor = "red";
}

const blue= () => {
 document.body.style.backgroundColor = "blue"; 
}

const toggle = () => {
  // when toggle.count doesn't exist, use 0 and increase with 1
  toggle.count = (toggle.count || 0) + 1;
  // when even -> call red() otherwise call blue()
  // you could also verify here what is the backgroundColor
  toggle.count % 2 === 0 ? red() : blue();
}

// returns the result of `setInterval` so the interval can be cleared
const both = () => setInterval( toggle, 1000 );


document.body.addEventListener("keydown", function keyhandler() {
 if (event.keyCode == 13 && !keyhandler.interval) {
   // keep the result of both (setInterval) as reference to the interval
   // mind you, pressing enter twice would leave 1 interval running indefinitely
   // unless you check if interval has a value
   keyhandler.interval = both();
 }

 if (event.keyCode == 32) {
   clearInterval( keyhandler.interval );
   // delete the interval property so you can restart the loop afterwards
   delete keyhandler.interval;
 }
});

Upvotes: 2

person
person

Reputation: 393

Your first problem is setTimeout and setInterval take an input of a function not the result of a function. Instead of setTimeout(red(), 1000) you would write setTimeout(red, 1000)

Your second problem is clearInterval doesn't take a function. Instead it takes the return value of the setInterval function:

var int = setInterval(both, 3000);
clearInterval(int);

Full updated code:

const red= () => {
 document.body.style.backgroundColor = "red";
}

const blue= () => {
 document.body.style.backgroundColor = "blue"; 
}

const both =  () => {
 setTimeout(red, 1000);
 setTimeout(blue, 2000);
}

document.body.addEventListener("keydown", () => {
 let bothInt;
 if (event.keyCode == 13) {
   bothInt = setInterval(both, 3000);
   bothIntClear = false;
 }
 else if (event.keyCode == 32) {
   clearInterval(bothInt);
 }
});

Keep in mind it might take a while for the colors to stop switching because the functions are still in the event queue.

Upvotes: 1

Related Questions