I'm able to add a class of is-active
to a nav item when it's clicked. However, i'd like to remove the class and add it to another nav item when another is clicked.
Here's what I'm currently working with:
JS:
const links = document.querySelectorAll('a');
links.forEach(function(link, index){
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
this.classList.add('is-active');
}
});
});
This attempt adds the class, but doesn't remove it when another link is clicked.
How would I remove the class? Thanks in advance.
You just loop through the links that aren't this
:
const links = document.querySelectorAll('a');
links.forEach(function(link, index){
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
this.classList.add('is-active');
links.forEach(l => { // ***
if (l !== this) { // ***
l.classList.remove('is-active'); // ***
} // ***
});
}
});
});
(See below for the for-of
version.)
Alternately, you can do a new query of just the is-active
links:
document.querySelectorAll('a').forEach(function(link, index){
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
document.querySelectorAll('a.is-active').forEach(activeLink => { // ***
activeLink.classList.remove('is-active'); // ***
}); // ***
this.classList.add('is-active');
}
});
});
Or if you like, since there should be only one, querySelector
:
document.querySelectorAll('a').forEach(function(link, index){
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
const activeLink = document.querySelector('a.is-active'); // **
if (activeLink) { // **
activeLink.classList.remove('is-active'); // **
} // **
this.classList.add('is-active');
}
});
});
Side note: The NodeList
from querySelectorAll
doesn't have forEach
in some browsers (it was added relatively recently). See this answer for how to add it if it's missing, and (on ES2015+ platforms) how to ensure it's iterable as well (as it's also meant to be).
And if you can rely on iterability, here are for-of
versions of those:
for-of
version of the first example:
const links = document.querySelectorAll('a');
for (const link of links) {
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
this.classList.add('is-active');
for (const l of links) {
if (l !== this) {
l.classList.remove('is-active');
}
}
}
});
}
for-of
version of the second example:
for (const link of document.querySelectorAll('a')) {
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
for (const activeLink of document.querySelectorAll('a.is-active')) {
activeLink.classList.remove('is-active');
}
this.classList.add('is-active');
}
});
}
And the third:
for (const link of document.querySelectorAll('a')) {
link.addEventListener('click', function() {
if(this.classList.contains('is-active')) {
this.classList.remove('is-active');
} else {
const activeLink = document.querySelector('a.is-active'); // **
if (activeLink) { // **
activeLink.classList.remove('is-active'); // **
} // **
this.classList.add('is-active');
}
});
}
A common requirement - you can do this:
get an iterable representation of the DOM Elements using spread syntax
like [...document.querySelectorAll('a')]
use forEach
to loop through the links
you can use the classList.toggle
function instead of having the if-else conditions
See demo below:
// get an iterable representation using the spread syntax const elements = [...document.querySelectorAll('a')]; elements.forEach(e => e.addEventListener('click', () => { // remove active class from all links elements.forEach(e => e.classList.remove('is-active')); // add active to the clicked link e.classList.toggle('is-active'); }));
.is-active { color: red; }
<a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a>
this
in the function refers to the elements that is clicked. You should hide all the elements every time using forEach
in each click. And then show the desired one
const links = [...document.querySelectorAll('a')];
links.forEach(function(link, index){
link.addEventListener('click', function() {
let temp = this.classList.contains('is-active')
links.forEach(x => x.classList.remove('is-active'))
if(!temp) {
this.classList.add('is-active');
}
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.