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 >
<div >
<div >item</div>
<div >item</div>
<div >item</div>
</div>
<button >clear borders</button>
</div>
CodePudding user response:
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 >
<div >1</div>
<div >2</div>
<div >3</div>
</div>
<button >clear borders</button>
CodePudding user response:
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 >
<div >
<div >item</div>
<div >item</div>
<div >item</div>
</div>
<button >clear borders</button>
</div>
</div>