addEventListener and changing background color

Hello, I’m having some difficulty understanding events and calling functions inside addEventListener
I’m attempting to change the background color of the body of the page each time I click on the <button> element. The background changes once and then remains red, never changing back to blue. I’m having a hard time understanding what happens when the function is complete and why it does not start over again at blue. I’ve tried the following:

var button = document.querySelector("button");

button.addEventListener("click",function(){
	document.body.style.backgroundColor = "red";
	document.body.style.backgroundColor = "blue";});

My first instinct was to use a for loop, however as there is only one element we’re targeting and not really looping through elements, I figured it wouldn’t be appropriate here. I also attempted to define two separate functions and run like below, again no dice.

var button = document.querySelector("button");

function red(){
	document.body.style.backgroundColor = "red";
};
function blue(){
	document.body.style.backgroundColor = "blue";
};


button.addEventListener("click", red);
button.addEventListener("click", blue);

Would anyone be able to help me understand what’s going on? I could easily look at code but feel this is critical to know. Thanks!

The function you supply to the event listener is a callback function, it gets called once addEventListener() deems that it’s appropriate to do so, and it does whatever inside that function exactly as it is written.

Let’s just ignore addEventListener for a moment and consider what this code would do if that’s all the JavaScript in your page:

document.body.style.backgroundColor = "red";
console.log(document.body.style.backgroundColor);
document.body.style.backgroundColor = "blue";

With this code you would only see a blue background. And that’s it.

It’s not because the first line (change background to red) doesn’t work—it’s simply because it gets changed to red, and then immediately after that, to blue. (Technically, and in this case, I think the JavaScript just keeps running and the browser would only re-render once the script has finished, so you would never actually see red.)

You can verify this by checking the background colour of body in between:

document.body.style.backgroundColor = "red";
console.log(document.body.style.backgroundColor); // red
document.body.style.backgroundColor = "blue";
console.log(document.body.style.backgroundColor); // blue

For similar reasons, restructuring the code to the second snippet that you posted would produce similar results because, presumably, event listeners are executed in the order they are added to an element. Again, you can verify this by:

var button = document.querySelector("button");

function red(){
	document.body.style.backgroundColor = "red";
  console.log(document.body.style.backgroundColor); // red
};
function blue(){
	document.body.style.backgroundColor = "blue";
  console.log(document.body.style.backgroundColor); // blue
};


button.addEventListener("click", red);
button.addEventListener("click", blue);

The solution, assuming that you want to toggle between red and blue, is to check whether the colour is red or blue:

var button = document.querySelector("button");

button.addEventListener("click", function() {
    const curColour = document.body.style.backgroundColor;

    if (curColour === 'red') {
        document.body.style.backgroundColor = "blue";
    }
    else {
        document.body.style.backgroundColor = "red";
    }
});

By using a ternary operator, you can simply the code above to:

var button = document.querySelector("button");

button.addEventListener("click", function() {
    const curColour = document.body.style.backgroundColor;

    document.body.style.backgroundColor = curColour === 'red' ? 'blue' : 'red';
});

I hope that helps!

4 Likes

Wow! Thanks so much for breaking it down. You really helped me understand this. I kept thinking that when the event “fires” and the function is called the background changes when you click, pauses, then, executes the next line. But what is happening is the color is being changed rather quickly so that you cannot see it. Very much appreciated.

1 Like

Thanks. You solved the exact same problem that I had.