3

This code adds a class (a border in this case) to an single element (a square) when the user clicks on that element. This part of the code is working fine.

I would then like to be able to remove however many borders were added (1-3 in this example), with the click of a single button, using a for loop.

I was able to do remove the borders by just repeating item1.classList.remove('.bigBorder'); (for example with item1) but that certainly does not scale well.

const item = document.querySelector('.item');

const item1 = document.querySelector('.item1');
const item2 = document.querySelector('.item2');
const item3 = document.querySelector('.item3');

const clearBordersButton = document.querySelector('.clearBorders');

const bigBorder = document.querySelector('.bigBorder');

item1.addEventListener('click', function() {
  item1.classList.add('bigBorder');
});

item2.addEventListener('click', function() {
  item2.classList.add('bigBorder');
});

item3.addEventListener('click', function() {
  item3.classList.add('bigBorder');
});

clearBordersButton.addEventListener('click', clearBorders);

function clearBorders() {
  for (let i = 0; i < item.length; i++) {
    item[i].classList.remove('bigBorder');
  }
};
* {
  box-sizing: border-box;
}

.container {
  width: 960px;
  margin: 20px auto;
  border: 1px solid black;
}

.boxes {
  display: flex;
  justify-content: space-around;
  border: 1px solid black;
}

.item1,
.item2,
.item3 {
  border: 2px solid blue;
  margin: 20px 0;
  width: 100px;
  height: 100px;
}

.bigBorder {
  border: 10px solid black;
}
<div class="container">
  <div class="boxes">
    <div class="item item1">item</div>
    <div class="item item2">item</div>
    <div class="item item3">item</div>
  </div>
  <button class="clearBorders">clear borders</button>
</div>

2 Answers 2

2

Instead of attaching a listener to each item you can use event delegation - attach one listener to the parent component (.boxes) and have that listen to events as they "bubble up" the DOM from its children.

If you also select all the item elements with querySelectorAll it's a simple process to iterate over them and remove the class.

// Cache the elements
const boxes = document.querySelector('.boxes');
const items = document.querySelectorAll('.item');
const clear = document.querySelector('.clear');

// Add listeners to the container, and the button
boxes.addEventListener('click', handleClick, false);
clear.addEventListener('click', clearBorders, false);

// Because we're using event delegation
// check that the child element that was clicked
// on was has a `.item` class, and then add the new class
function handleClick(e) {
  if (e.target.matches('.item')) {
    e.target.classList.add('bigBorder');
  }
}

function clearBorders() {
  items.forEach(item => {
    item.classList.remove('bigBorder');
  });
};
.boxes{display:flex;justify-content:space-around;width:250px}
.item{display:flex;justify-content:center;align-items:center;background-color:#efefef;border:10px solid white;margin:20px 0;width:50px;height:50px}
 .item:hover{cursor:pointer;background-color:#cdcdcd;}
.bigBorder{border:10px solid #000}
<div class="boxes">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
<button class="clear">clear borders</button>

Sign up to request clarification or add additional context in comments.

1 Comment

Always love a good example of event delegation, damn it, should have used it myself.
0

It's important to note that querySelector returns the first matching element where as querySelectorAll returns a node list of matching elements.

We can use the node list to assign the event lister and remove the class.

//Selects multimple itmes
const items = document.querySelectorAll('.item');
//selects first matching itme
const clearBordersButton = document.querySelector('.clearBorders');

const bigBorder = document.querySelector('.bigBorder');

//Iterate the items
items.forEach(function(element){  
  //add an event listern
  element.addEventListener("click", function(){
    //"this" is the item clicked
    this.classList.add("bigBorder");
  })
})


clearBordersButton.addEventListener('click', clearBorders);

function clearBorders() {
  //find the elements
  document.querySelectorAll(".item.bigBorder").forEach(function(element){
    //remove the class
    element.classList.remove("bigBorder");
  })
  
};
* {
  box-sizing: border-box;
}

.container {
  width: 960px;
  margin: 20px auto;
  border: 1px solid black;
}

.boxes {
  display: flex;
  justify-content: space-around;
  border: 1px solid black;
}

.item1,
.item2,
.item3 {
  border: 2px solid blue;
  margin: 20px 0;
  width: 100px;
  height: 100px;
}

.bigBorder {
  border: 10px solid black;
}
<div>
  <div class="container">
    <div class="boxes">
      <div class="item item1">item</div>
      <div class="item item2">item</div>
      <div class="item item3">item</div>
    </div>
    <button class="clearBorders">clear borders</button>
  </div>
</div>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.