user3143218
user3143218

Reputation: 1816

Add/Remove all classes except event

Is there an easy way to remove all other classes except the eventarget in with JavaScript.

For example, if I have a UL:

<ul>
     <li>list element</li>
     <li>list element</li>
     <li>list element</li>
     <li>list element</li>
     <li>list element</li>
     <li>list element</li>
</ul>

And I add click event listener with an event handler:

var UL = document.querySelector('ul');

function eventHandler(e) {
    var thiz = e.target;
    document.querySelectorAll('ul li').classList.remove("active");
    thiz.classList.add("active");
}

UL.addEventListener('click', function (e) {
    eventHandler(e);
});

How can I add a class on the element being clicked, while removing all the other "active" classes.

Here's a fiddle http://jsfiddle.net/298ZV/

Upvotes: 0

Views: 778

Answers (2)

David Thomas
David Thomas

Reputation: 253446

Without jQuery:

[].forEach.call(document.querySelectorAll('ul li'), function(a){
    a.classList.remove('active');
});

JS Fiddle demo.

This uses the Array.prototype.forEach() to iterate over the NodeList and executes the function on each element.

You could also 'simplify' (though do note the scare-quotes...) a little further and do everything within the same forEach():

function eventHandler(e) {
    var thiz = e.target;
    [].forEach.call(document.querySelectorAll('ul li'), function(a){
        a.classList[a == e.target ? 'add' : 'remove']('active');
    });
}

JS Fiddle demo.

With regards to concerns expressd by @adeneo, in comments to his answer, that should the li elements contain other elements they will become the event.target I've added a simple closest() function to find the element you're looking for:

var UL = document.querySelector('ul');

function closest(origin, elem) {
    var current = origin;
    elem = elem.toLowerCase();
    while (current.tagName.toLowerCase() !== 'body' && current.tagName.toLowerCase() !== elem) {
        current = current.parentNode;
    }
    return current;
}

function eventHandler(e) {
    var that = closest(e.target, 'li');
    [].forEach.call(document.querySelectorAll('ul li'), function(a) {
        a.classList[that === a ? 'add' : 'remove']('active');
    });
}

UL.addEventListener('click', function (e) {
    eventHandler(e);
});

JS Fiddle demo.

References:

Upvotes: 4

adeneo
adeneo

Reputation: 318312

Do it a little differently, attach the event handler to the LI's, and keep them in a variable, then iterate over the LI's and remove the class from the ones that aren't this

var LI = document.querySelectorAll('ul li');

for (var i=LI.length; i--;) {
    LI[i].addEventListener('click', eventHandler);
}

function eventHandler() {
    this.className = 'active';

    for (var i=LI.length; i--;) {
        if (LI[i] != this) LI[i].className = '';
    }
}

FIDDLE

Upvotes: 1

Related Questions