jQuery switching between more than two classes
Asked Answered
B

3

0

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

Beller answered 28/7, 2013 at 15:36 Comment(1)
A quick fix would be to delegate the handler to a parent element, or the body if there is no common parent. this takes the form $('body').on('click', 'div.priority#priority'+id, function() { $(this).removeClass('priority').addClass('priority-low'); }); . This allows you to bind events on classes that don't exist yet.Vestibule
D
2

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');
    }
});
Durmast answered 28/7, 2013 at 15:50 Comment(1)
Thanks a lot! This worked! Although I do not fully understand the second variant, but I will try to use it too just to learn more about this method.Beller
A
1

[edit: working demo]

Assuming you have 'priority' as the default class already on the element at the initialization phase, this will cycle through the others:

$('div#priority' + id)
    .data('classes.cycle', [
        'priority',
        'priority-low',
        'priority-medium',
        'priority-normal',
        'priority-high',
        'priority-emergency'
    ])
    .data('classes.current', 0)
    .on('click', function () {
        var $this = $(this),
            cycle = $this.data('classes.cycle'),
            current = $this.data('classes.current');

        $this
            .removeClass(cycle[current % cycle.length])
            .data('classes.current', ++current)
            .addClass(cycle[current % cycle.length]);
    });
Ashram answered 28/7, 2013 at 16:4 Comment(0)
C
1

I have tried myself to do this with the sole help of toggleClass() and didn't succeeded. Try my method that declares an array with your five classes and toggles dynamically through them.Do adapt to your own names.

//variable for the classes array
var classes=["one","two","three","four","five"];
//add a counter data to your divs to have a counter for the array
$('div#priority').data("counter",0);
$(document).on('click','div#priority',function(){
    var $this=$(this);
    //the current counter that is stored
    var count=$this.data("counter");
    //remove the previous class if is there
    if(($this).hasClass(classes[count-1])){
        $(this).removeClass(classes[count-1]));
    }

    //check if we've reached the end of the array so to restart from the first class.
    //Note:remove the comment on return statement if you want to see the default class applied.
    if(count===classes.length){
        $this.data("counter",0);
        //return;//with return the next line is out of reach so class[0] wont be added
    }
    $(this).addClass(classes[count++]);
    //udpate the counter data
    $this.data("counter",count);
});
//If you use toggleClass() instead of addClass() you will toggle off your other classes.Hope is a good answer.
Centralize answered 28/12, 2013 at 18:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.