Change color of boxes Javascript

Viewed 183

I have a problem I'm struggling to solve. I've made 3 boxes in html/css and have an eventListener so when one box is clicked it changes to red. What I want to do is make all boxes green once all boxes have been colored red. Here was my attempt:

var buttonOne = document.querySelector(".one");
var buttonTwo = document.querySelector(".two");
var buttonThree = document.querySelector(".three");

function makeBoxRed(event) {
  var boxClicked = event.target;
  boxClicked.style.backgroundColor = "red";
}

var boxes = document.querySelector(".boxes");
boxes.addEventListener("click", makeBoxRed);

if ((boxes.style.backgroundColor = "red")) {
  boxes.style.backgroundColor = "green";
}
div {
  border: 1px solid black;
  height: 100px;
  width: 100px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
</head>

<body>
  <section class="boxes">
    <div class="one"></div>
    <div class="two"></div>
    <div class="three"></div>
  </section>
</body>

</html>

4 Answers

The problem with your function is that the if statement only runs once at the start of the script, you should instead have it inside the event listening function

const buttonOne = document.querySelector(".one");
const buttonTwo = document.querySelector(".two");
const buttonThree = document.querySelector(".three");
const boxes = document.querySelector(".boxes");

function makeBoxRed(event) {
  const boxClicked = event.target;
  boxClicked.style.backgroundColor = "red";
  
  // Check if all the boxes are red
  for (const box of boxes.children) {
    // If a box is NOT red, abort function
    if (box.style.backgroundColor !== 'red') return;
  }
  
  // All boxes are red
  boxes.style.backgroundColor = 'green'
  alert('All boxes are red!')
}

for (const box of boxes.children) {
    // Assign event listener to each box
    box.addEventListener("click", makeBoxRed);
}
div {
  border: 1px solid black;
  height: 100px;
  width: 100px;
}
<section class="boxes">
  <div class="one"></div>
  <div class="two"></div>
  <div class="three"></div>
</section>

Hopefully this adresses your issue. Once all three boxes have been clicked, they get changed from red to green. This way, only the boxes respond to the click event, and not the container object.

const buttonOne = document.querySelector(".one");
const buttonTwo = document.querySelector(".two");
const buttonThree = document.querySelector(".three");
const boxes = document.querySelector(".boxes");

function makeBoxRed(event) {
  const boxClicked = event.target;
  boxClicked.style.backgroundColor = "red";
  
  // Check if all the boxes are red
  for (const box of boxes.children) {
    // If a box is NOT red, abort function
    if (box.style.backgroundColor !== 'red') return;
  }
  
  // All boxes are red, make them all green instead.
  for (const box of boxes.children) {
    box.style.backgroundColor = 'green'
  }
}

// Register the event separately for each box (so the parent object doesn't handle clicks)
for (const box of boxes.children) {
  box.addEventListener("click", makeBoxRed);
}
div {
  border: 1px solid black;
  height: 100px;
  width: 100px;
}
<section class="boxes">
  <div class="one"></div>
  <div class="two"></div>
  <div class="three"></div>
</section>

let box1 = document.getElementById("boxOne");
let box2 = document.getElementById("boxTwo");
let box3 = document.getElementById("boxThree");



box1.addEventListener("click", function(event) {
  box1.classList.remove("blue");
  box1.classList.add("red");
  CheckColors();
});
box2.addEventListener("click", function(event) {
  box2.classList.remove("blue");
  box2.classList.add("red");
  CheckColors();
});
box3.addEventListener("click", function(event) {
  box3.classList.remove("blue");
  box3.classList.add("red");
  CheckColors();
});

function CheckColors() {
  if (box1.classList.contains("red") && box2.classList.contains("red") && box3.classList.contains("red")) {
    box1.classList.remove("red");
    box2.classList.remove("red");
    box3.classList.remove("red");
    box1.classList.add("green");
    box2.classList.add("green");
    box3.classList.add("green");
  }

}
.holder {
  display: flex;
  flex-wrap: wrap;
}

.box {
  text-align: center;
  flex-basis: 33%;
  width: 50px;
  height: 50px;
}

.green {
  background-color: green;
}

.blue {
  background-color: blue;
}

.red {
  background-color: red;
}
<div class="holder">
  <div id="boxOne" class="box blue">
    Box 1
  </div>
  <div id="boxTwo" class="box blue">
    Box 2
  </div>
  <div id="boxThree" class="box blue">
    Box 3
  </div>

</div>

This would work

I left comments in the code for helpful reasons

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Document</title>
    <style>
      div {
        border: 1px solid black;
        height: 100px;
        width: 100px;
      }
    </style>
  </head>
  <body>
    <section class="boxes">
      <div class="one"></div>
      <div class="two"></div>
      <div class="three"></div>
    </section>

    <script>
    //Its better to get the boxes directly and add event listener
    var boxes = document.getElementsByTagName('div');
    boxes.addEventListener('click',makeBoxRed);
    function makeBoxRed(e){
        if(e.target.style.backgroundColor === 'red') //Check if box is red
            e.target.style.backgroundColor = 'green'; //turn it green
        else
            e.target.style.backgroundColor = 'red'; //else turn it red
    }
    </script>
  </body>
</html>
Related