Search code examples
javascriptjquerytoggleaddclassremoveclass

jQuery switching between more than two classes


I've already posted a question about jQuery toggle method here But the problem is that even with the migrate plugin it does not work.

I want to write a script that will switch between five classes (0 -> 1 -> 2 -> 3 -> 4 -> 5).

Here is the part of the JS code I use:

$('div.priority#priority'+id).on('click', function() {
        $(this).removeClass('priority').addClass('priority-low');
    });
    $('div.priority-low#priority'+id).on('click' ,function() {
        $(this).removeClass('priority-low').addClass('priority-medium');
    });
    $('div.priority-medium#priority'+id).on('click', function() {
        $(this).removeClass('priority-medium').addClass('priority-normal');
    });
    $('div.priority-normal#priority'+id).on('click', function() {
        $(this).removeClass('priority-normal').addClass('priority-high');
    });
    $('div.priority-high'+id).on('click', function() {
        $(this).removeClass('priority-high').addClass('priority-emergency');
    });
    $('div.priority-emergency'+id).on('click', function() {
        $(this).removeClass('priority-emergency').addClass('priority-low');
    });

This is not the first version of the code - I already tried some other things, like:

    $('div.priority#priority'+id).toggle(function() {
     $(this).attr('class', 'priority-low');
}, function() {
     $(this).attr('class', 'priority-medium');
}, function() {
     ...)

But this time it only toggles between the first one and the last one elements.

This is where my project is: strasbourgmeetings.org/todo


Solution

  • The thing is that your code will hook your handlers to the elements with those classes when your code runs. The same handlers remain attached when you change the classes on the elements.

    You can use a single handler and then check which class the element has when the click occurs:

    $('div#priority'+id).on('click', function() {
        var $this = $(this);
        if ($this.hasClass('priority')) {
            $this.removeClass('priority').addClass('priority-low');
        }
        else if (this.hasClass('priority-low')) {
            $this.removeClass('priority-low').addClass('priority-medium');
        }
        else /* ...and so on... */
    });
    

    You can also do it with a map:

    var nextPriorities = {
        "priority":           "priority-low",
        "priority-low":       "priority-medium",
        //...and so on...
        "priority-emergency": "priority"
    };
    $('div#priority'+id).on('click', function() {
        var $this = $(this),
            match = /\bpriority(?:-\w+)?\b/.exec(this.className),
            current = match && match[0],
            next = nextPriorities[current];
        if (current) {
            $this.removeClass(current).addClass(next || 'priority');
        }
    });