I have a list item menu which when I click the current li
it toggles the .active
class and makes the background green. However when I click another li
it still shows the green background for the previous li that was clicked. How do I make it so that when an item is clicked, it toggles its background when clicked but also removes it when another li is clicked?
<ul >
<li><a >item 1</a></li>
<li><a >item 1</a></li>
<li><a >item 1</a></li>
</ul>
$(".template-in-conversation .js-accordion-header").on("click", function() {
$(this).toggleClass("active");
$(this).siblings("a").removeClass("active");
});
CodePudding user response:
You don't need jQuery for this trivial task. Just use element.classList.toggle('active', bool)
. No need to fumble around with siblings etc.
const items = document.querySelectorAll('.js-accordion-header');
document.querySelector('.menu-wrapper').addEventListener(
'click',
({target}) => {
for (const item of items) item.classList.toggle('active', target === item);
}
);
.active {
background-color: yellow;
}
<ul >
<li><a >item 1</a></li>
<li><a >item 2</a></li>
<li><a >item 3</a></li>
</ul>
The second parameter decides whether toggle
acts as add
(if the boolean is true
) or remove
(if the boolean is false
):
target === item
The goal is simply achieved by answering the question "Was the element clicked the one that is currently iterated?". If yes, add the class, if not, remove it.
If you also need to allow toggling an already active element off by clicking it again, you need to expand the condition:
target === item && !target.classList.contains('active')
const items = document.querySelectorAll('.js-accordion-header');
document.querySelector('.menu-wrapper').addEventListener(
'click',
({target}) => {
for (const item of items) {
item.classList.toggle('active', target === item && !target.classList.contains('active'));
}
}
);
.active {
background-color: yellow;
}
<ul >
<li><a >item 1</a></li>
<li><a >item 2</a></li>
<li><a >item 3</a></li>
</ul>
CodePudding user response:
The problem is that $(this)
in the context of your handler is the anchor, and when you call .siblings()
on it you get no siblings, because the anchor has no siblings inside of the parent <li/>
that contains it. Instead, you can navigate to the parent, get the siblings from there, then target the anchor inside of it:
$(".template-in-conversation .js-accordion-header").on("click", function() {
$(this).toggleClass("active");
$(this).parent().siblings().find("a").removeClass("active");
});
.active {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li><a >item 1</a></li>
<li><a >item 1</a></li>
<li><a >item 1</a></li>
</ul>
CodePudding user response:
The anchors are not siblings of each other, the solution is to go up to the ul
using parents()
and then find all a
in that ul
$(() => {
$(".js-accordion-header").on("click", function() {
$(this).parents("ul").find("a.active").removeClass("active");
$(this).toggleClass("active");
});
});
.active {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li><a >item 1</a></li>
<li><a >item 1</a></li>
<li><a >item 1</a></li>
</ul>
CodePudding user response:
If you need to also toggle the same clicked element, you can do something like this:
$(".template-in-conversation .js-accordion-header").on("click", function() {
$(this).toggleClass('active');
$(this).parent().siblings().children().removeClass('active');
});
.active {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li><a >item 1</a></li>
<li><a >item 1</a></li>
<li><a >item 1</a></li>
</ul>