Kivylius
Kivylius

Reputation: 6547

Toggle between selected classes

I find my self doing this a lot:

$(document).on("click","li",function(){
    $(".selected").removeClass("selected"); // Remove any old selected
    $(this).addClass("selected"); // Apply selected to this element
});

Is there a better and less repetitive way of doing a task like this? Like toggle a class. Btw, only one element can be selected at a given time.

Thanks.

Upvotes: 5

Views: 167

Answers (5)

TecHunter
TecHunter

Reputation: 6131

After debating with Jack I propose mine. Assuming your list is here :

var $myList = $('#list');

Then:

$myList.on("click","li",function(){
    $(".selected",$myList).removeClass("selected"); // Remove any old selected
    $(this).addClass("selected"); // Apply selected to this element
});

or

$myList.on("click","li",function(){
    $(this).siblings(".selected").removeClass("selected"); // Remove any old selected
    $(this).addClass("selected"); // Apply selected to this element
});

Your way of doing it is good enough for me but Jack's is faster and mine is in between both. I like this one because you don't need to assume there will only be one selected element. And searching is faster when we provide context as far as I know

Upvotes: 1

user663031
user663031

Reputation:

The notion of keeping track of the current element is the same as the other answers, but you can wrap this logic up cleanly in a function such as

function class_swapper=function(cls){
    var cur;
    return function(elt){
        if (cur) { cur.classList.remove(cls); }
        elt.classList.add(cls);
        cur=elt;
    };
};

A call to class_swapper returns a function used to actually apply the specified class to a particular element (and remove it from the previous one, which is remembered inside the function). You can use this as follows:

var swapper=class_swapper("selected");
swapper(elt1);
swapper(elt2);

or in terms of your example

$(document).on("click","li",function(){swapper(this);});

I've used classList.add and classList.remove, which is a classy way (ouch) of manipulating classes in modern browsers, but of course these could be replaced by jQuery's addClass etc. as necessary.

Upvotes: 1

Ja͢ck
Ja͢ck

Reputation: 173552

A more efficient way is to keep track of the last selected item:

var $selected = null;

$(document).on("click", "li", function() {
    if ($selected) {
        $selected.removeClass('selected');
    }
    $selected = $(this).addClass('selected');
});

Of course, this should work as long as that particular function is the only one that will ever add / remove the selected class.

This could optionally be wrapped inside a closure to remove the $selected variable.

Btw, using document as the anchor for your delegation isn't best practice. It's better to choose the nearest node that will not get removed from the document.

Update

As Kevin B has mentioned, you could eliminate the branch like so:

var $selected = $();

$(document).on("click", "li", function() {
    $selected.removeClass('selected');
    $selected = $(this).addClass('selected');
});

The ability to use $() was introduced in 1.4; before that you would use $([]).

Upvotes: 6

Chris Dixon
Chris Dixon

Reputation: 9167

Thinking about this, you could keep your list elements in a variable, such as:

var $liElements = $('#yourContainer > li');

$(document).on("click","li",function(){
    $liElements.not($(this)).removeClass("selected");
    $(this).addClass("selected");
});

Upvotes: 1

edonbajrami
edonbajrami

Reputation: 2206

You can do this:

<script>
  $(document).ready(function(){
     $(this).on("click", "li", function() {
        $(this).addClass('selected').siblings().removeClass('selected');
     });
  });
</script>

Upvotes: 2

Related Questions