Instead of creating our own makeshift interval I used the builtin setInterval
function. Both setInterval
and setTimeout
return a number that you can pass to either clearInterval
or clearTimeout
to stop the async code execution.
const button = document.querySelector('#btn');
let changeColorInterval;
button.addEventListener('click', function() {
// if we currently have an interval running, e.g. != undefined
if (changeColorInterval) {
// remove the interval, e.g. stop the execution of makeRGB
clearInterval(changeColorInterval);
// set the variable back to undefined, otherwise next time
// you click the button this branch of the if statement
// will be executed, even though the interval is not
// actually running anymore.
changeColorInterval = undefined;
// restore the background to white like you wanted.
document.body.style.backgroundColor = "white";
// If we don't have an interval, create one
} else changeColorInterval = setInterval(makeRGB, 100);
})
function makeRGB() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
const colorID = `rgb(${r},${g},${b})`;
document.body.style.backgroundColor = colorID;
}
h1 {
text-align: center;
}
button {
margin: auto;
display: block;
}
<h1 id="heading">Welcome!</h1>
<button id="btn">Change Color! </button>
Why it seems like it's only called once
if (!flag) {
return;
}
The event listener itself is called every time you press the button. You can see that if you place a console.log("click")
inside of your click callback, right before loop()
. The issue is that you never assigned your variable back to true
so it always exists the function.
Don't add event listeners inside event listeners... unless you really intend to
button.onclick = function stop() {
flag = false;
document.body.style.backgroundColor = 'white';
}
You assign an "old school style" event listener inside an event listener which doesn't seem like a good idea. See: addEventListener vs onclick
Why not use var
You most likely don't want to use var
. You more likely than not never want to use var
. Just use let
to declare variables you intent to modify, and const
for variables that should be constant. If you actually care as to why google something like "javascript var vs let vs const". But if you're just starting to learn javascript, it's probably best to just avoid var
until you understand it.
Incorrect color generation
Your color generation is just a tad wrong. As described by mozilla
The Math.random() function returns a floating-point, pseudo-random number in the range 0 to less than 1 (inclusive of 0, but not 1)
So 0 <= Math.random() < 1
. You will never get 1
as the upper bound is exclusive.
So let's say you get 9.99999999...
and multiply that by 255
. You will never get 255
but something smaller than that. And then you floor it. So the max number you will get is 254
. To fix that I would just recommend multiplying by 256
.
Write a comment for additional help
If you need any additional help understanding the code, please get back to me in the comments of this answer :)