I have a UI element that has two panels. Only one is visible at any given time so each panel has its own close link. Both these links should perform the same action - closing/hiding the element.
Initially I thought I could do this by toggling the class on html
and have the same class applied to the link that opens the UI element and the two that close it (below) but this didn't work.
const html = document.querySelector('html');
const button = document.querySelector('.trigger-cart');
button.addEventListener('click', e => {
e.preventDefault();
html.classList.toggle('cart-visible');
});
I've included an example of where my code is add now. I have remove the toggle for separate add/remove declarations. This is better but only the first close button works and the one that follows in the markup doesn't fire at all. I tried using querySelectorAll
but that doesn't seem to work either?
Can someone help me with this? Just getting the close buttons working is the priority but I might have several links on the page that could in theory open this UI element. Which is why I thought using a single class to toggle the class on html
might be best initially.
/* const html = document.querySelector('html');
const button = document.querySelector('.trigger-cart');
button.addEventListener('click', e => {
e.preventDefault();
html.classList.toggle('cart-visible');
});
*/
const html = document.querySelector('html');
const btnOpen = document.querySelector('.trigger-cart');
const btnClose = document.querySelector('.close-cart');
btnOpen.addEventListener('click', e => {
e.preventDefault();
html.classList.add('cart-visible');
});
btnClose.addEventListener('click', e => {
e.preventDefault();
html.classList.remove('cart-visible');
});
html,
body {
margin: 0;
padding: 0;
}
.cart {
background: #eee;
display: flex;
flex-direction: column;
height: 100vh;
position: fixed;
top: 0;
right: -375px;
transition: right .5s;
width: 375px;
}
.cart-visible .cart {
right: 0;
}
.panel-one,
.panel-two {
display: flex;
align-items: center;
justify-content: center;
height: 50vw;
align-content: center;
}
.panel-two {
background: #ddd;
}
<a href="#" >Display Cart</a>
<div >
<div >
<a href="#" >Close Link</a>
</div>
<div >
<a href="#" >Close Link</a>
</div>
</div>
CodePudding user response:
You have multiple link elements with the same class close-cart
and using querySelector
to get them will return only the first link element, that's why only the first link is working.
To resolve this-
- Use the
document. querySelectorAll()
method to find all elements of classclose-cart
. - Use the
forEach()
loop to iterate over the collection of the elements. - And then use
addEventListener()
method to add an event listener to each element.
Here is the working demo-
/* const html = document.querySelector('html');
const button = document.querySelector('.trigger-cart');
button.addEventListener('click', e => {
e.preventDefault();
html.classList.toggle('cart-visible');
});
*/
const html = document.querySelector('html');
const btnOpen = document.querySelector('.trigger-cart');
const allCloseButtons = document.querySelectorAll('.close-cart');
allCloseButtons.forEach(el => {
el.addEventListener('click', e => {
e.preventDefault();
html.classList.remove('cart-visible');
});
});
btnOpen.addEventListener('click', e => {
e.preventDefault();
html.classList.add('cart-visible');
});
html,
body {
margin: 0;
padding: 0;
}
.cart {
background: #eee;
display: flex;
flex-direction: column;
height: 100vh;
position: fixed;
top: 0;
right: -375px;
transition: right .5s;
width: 375px;
}
.cart-visible .cart {
right: 0;
}
.panel-one,
.panel-two {
display: flex;
align-items: center;
justify-content: center;
height: 50vw;
align-content: center;
}
.panel-two {
background: #ddd;
}
<a href="#" >Display Cart</a>
<div >
<div >
<a href="#" >Close Link</a>
</div>
<div >
<a href="#" >Close Link</a>
</div>
</div>
CodePudding user response:
The query selector method returns the first child,You can change your code like this
<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>
html,
body {
margin: 0;
padding: 0;
}
.cart {
background: #eee;
display: flex;
flex-direction: column;
height: 100vh;
position: fixed;
top: 0;
right: -375px;
transition: right 0.5s;
width: 375px;
}
.cart-visible .cart {
right: 0;
}
.panel-one,
.panel-two {
display: flex;
align-items: center;
justify-content: center;
height: 50vw;
align-content: center;
}
.panel-two {
background: #ddd;
}
</style>
</head>
<body>
<section id="cart_section">
<a >Display Cart</a>
<div >
<div >
<a onclick="closeCart()">Close Link</a>
</div>
<div >
<a onclick="closeCart()">Close Link</a>
</div>
</div>
</section>
<script>
const btnOpen = document.querySelector(".trigger-cart");
const btnClose = document.querySelector(".close-cart");
const cart_section = document.getElementById("cart_section");
btnOpen.addEventListener("click", (e) => {
e.preventDefault();
cart_section.classList.add("cart-visible");
});
function closeCart() {
cart_section.classList.remove("cart-visible");
}
</script>
</body>
</html>