I can't figure out how to close one submenu when another one is open. I'm not sure if html is needed here, so I'm just attaching JS code here:
const burgerBtn = document.querySelector(".header__burger"),
menu = document.querySelector(".menu"),
body = document.querySelector(".body"),
filter = document.querySelector(".filter"),
blockFilter = document.querySelectorAll(".block-filter"),
dropdown = document.querySelectorAll(".block-filter__dropdown");
if (filter) {
blockFilter.forEach(item => {
item.addEventListener("click", event => {
item.querySelector(".block-filter__dropdown").classList.toggle("block-filter__dropdown_state_active");
item.querySelector(".block-filter__icon").classList.toggle("block-filter__icon_state_active");
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent = event.target.textContent;
}
})
})
}
<div >
<form >
<div >
<div >
<div >
<span >Purpose</span>
<div ></div>
</div>
<span >Buy</span>
</div>
<div >
<span >Buy</span>
<span >Sell</span>
</div>
</div>
CodePudding user response:
Sure, just remove the class from the active one first:
item.addEventListener("click", (event) => {
// get active, and if it exists, remove active
document.querySelector(".block-filter__dropdown_state_active")?.classList.remove("block-filter__dropdown_state_active");
item.querySelector(".block-filter__dropdown").classList.toggle(
"block-filter__dropdown_state_active"
);
item.querySelector(".block-filter__icon").classList.toggle(
"block-filter__icon_state_active"
);
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent =
event.target.textContent;
}
});
We use ?.
here to prevent us from going further (and causing an error) if there is no active dropdown already.
CodePudding user response:
What you need to do is look for a currently active item first and "de-activate" them. You should also check that the currently active item is not the clicked item as you already have logic defined for that.
I've expanded on your snippet to create a solution.
NOTE: It might be useful creating a separate function/s for handling to "activate" and "de-activate" code where you pass in a .block-filter
element.
const burgerBtn = document.querySelector(".header__burger"),
menu = document.querySelector(".menu"),
body = document.querySelector(".body"),
filter = document.querySelector(".filter"),
blockFilter = document.querySelectorAll(".block-filter"),
dropdown = document.querySelectorAll(".block-filter__dropdown");
if (filter) {
blockFilter.forEach(item => {
item.addEventListener("click", event => {
const active_dropdown = document.querySelector(".block-filter__dropdown_state_active");
if(active_dropdown !== null){
// get parent until we find ".block-filter"
const active_item = active_dropdown.closest(".block-filter");
// check it's not the current item
if(active_item !== null && active_item !== item){
// apply same logic as below to remove active state
active_item.querySelector(".block-filter__dropdown").classList.remove("block-filter__dropdown_state_active");
active_item.querySelector(".block-filter__icon").classList.remove("block-filter__icon_state_active");
}
}
// your original logic
item.querySelector(".block-filter__dropdown").classList.toggle("block-filter__dropdown_state_active");
item.querySelector(".block-filter__icon").classList.toggle("block-filter__icon_state_active");
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent = event.target.textContent;
}
})
})
}
/* base styles */
* {
box-sizing: border-box;
}
html {
font-family: sans-serif;
background-color: #f3f3f3;
}
.filter.hero__filter {
width:600px;
margin:auto;
border: 2px solid #eee;
background-color: #fff;
}
.filter__form {
display:flex;
}
.filter__block {
flex: 1;
padding: 5px;
position: relative;
}
.block-filter__header {
font-weight:600;
font-size:12px;
color: #555;
}
.block-filter__dropdown {
display:none;
position:absolute;
top:100%;
left:0;
right:0;
background-color:#fff;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
border-radius:4px;
}
.block-filter__dropdown_state_active {
display: block;
}
.block-filter__item {
padding: 5px 10px;
display:block;
border-bottom: 1px solid #eee;
}
.block-filter__item:last-child {
border-bottom: none;
}
<div >
<form >
<div >
<div >
<div >
<span >Purpose</span>
<div ></div>
</div>
<span >Buy</span>
</div>
<div >
<span >Buy</span>
<span >Sell</span>
</div>
</div>
<div >
<div >
<div >
<span >Second</span>
<div ></div>
</div>
<span >Alpha</span>
</div>
<div >
<span >Bravo</span>
<span >Charlie</span>
<span >Delta</span>
</div>
</div>
</form>
</div>