Delete all classes after a certain class
Asked Answered
M

7

3

I have a

< div id="thisdiv" class="class1 class2 class3 class4 class5"> text < /div>

I need to be able to delete all classes after class3 with jQuery.

something like

$('#thisdiv').removeClass(all after class3);

OR

$('#thisdiv').attr('class', all from class1 to class3);

Please how can I do that?

Moton answered 1/7, 2012 at 5:38 Comment(0)
P
3

You can try the following, but your classes might not be in the same order as they appear in the HTML source:

$('#thisdiv').attr('class', function(i, v)
{
    var classes = v.split(' '),
        position = $.inArray('class3', classes);

    return classes.slice(0, position + 1).join(' ');
});

Here's the fiddle: http://jsfiddle.net/FNUK2/


A more succinct way would be to just slice the string itself:

$('#thisdiv').attr('class', function(i, v)
{
    return v.substr(0, v.indexOf('class3') + 6);
});

but I find working with arrays easier.


If you want to use it in the jQuery chain, you'll have to first add it to jQuery's prototype:

$.fn.removeClassesAfter = function(className)
{
    return this.each(function()
    {
        $(this).attr('class', function(i, v)
        {
            var classes = v.split(' '),
                position = $.inArray(className, classes);

            return position == -1 ? v : classes.slice(0, position + 1).join(' ');
        });
    });
};

Here's the fiddle: http://jsfiddle.net/FNUK2/11/

Plush answered 1/7, 2012 at 5:45 Comment(1)
thanks, I like this code too. How can I change your code so it will work with $('#thisdiv').removeAllClass('class3'); Thanks again :)Moton
G
2
function removeAllClass(selector, after, before) {
    $(selector).attr('class', function(i, oldClass) {
        var arr = oldClass.split(' ');
        if (!before) {
            arr.splice(arr.indexOf(after)+1).join(' ');
            return arr.join(' ');
        } else {
            return arr.slice(arr.indexOf(after), arr.indexOf(before) + 1).join(' ');
        }
    });
}

Use:

  • all after class3

    removeAllClass('#thisdiv', 'class3');

    DEMO

  • from class1 to class3

    removeAllClass('#thisdiv', 'class1', 'class3');

    DEMO

According to comment

UPDATE: I wonder if I can make it work with $('#thisdiv').removeAllClass('class3');

$.fn.removeAllClass = function(after, before) {
    $(this).attr('class', function(i, oldClass) {
        var arr = oldClass.split(' ');
        if (!before) {
            arr.splice(arr.indexOf(after) + 1).join(' ');
            return arr.join(' ');
        } else {
            return arr.slice(arr.indexOf(after), arr.indexOf(before) + 1).join(' ');
        }
    });
}

Use:

  • all after class3

    $('#thisdiv').removeAllClass('class3');

    DEMO

  • from class1 to class3

    $('#thisdiv').removeAllClass('class1', 'class3');

    DEMO

Gastelum answered 1/7, 2012 at 6:54 Comment(6)
wow, amazing function works perfect no comment, I hope you liked the question :) UPDATE: I wonder if I can make it work with $('#thisdiv').removeAllClass('class3');Moton
Thumbs up for the fastest and most precise answer. For sure the first round is on me.Moton
I do caution you once more. There's nothing in any spec that suggests that there is any reason or desire to maintain the order of this attribute. In fact, for some reason, the w3c defines 3 sets of space separated tokens: 'Ordered set of unique space-separated tokens', 'Unordered set of unique space-separated tokens', and 'Set of space-separated tokens'. Class definitions fall into the last list, which does not define order... so writing to that is just writing to a design artifact and is more than likely to break at some point especially since there is little->no common usage precedence.Wensleydale
This code actually works fine because the classes added to the element are in a certain order and only that order PLUS this code only applies to CSS3 transitions capable browsers, so I don't see why so much caution, you don't seem to enjoy having a beer a?Moton
@Danny - Even if you never add a class back in, you're treating the structure as a string and it isn't -- it is a space-delimitted value list. As such, how that gets parsed, twisted, and rendered is not only up to the engine, but the engine version (since order isn't spec'd). This is just the kind of code that is likely to break and can likely be solved in a more bulletproof way if we're trying to solve the actual problem, rather than the cut-down 'write this code for me' bit. I do appreciate simple problems to solve, I'm just suggesting that it is more complex than you're treating it.Wensleydale
John, I like your code too, I just need it closer to my need, see this guy above gave the full working piece of code it's doing just what I need for a 4 classes set of elements. How can I use your code to do this $('#thisdiv').removeAllClass('class3'); ?Moton
M
1

Simple demo http://jsfiddle.net/XaBjX/

Behaviour: anything after class3 will be removed you can see the before and after alert on screen

APIs used: indexOf, prop, removeClass.

Hope this helps,

code

var getClass = $("#thisdiv").prop('class');
alert(" Classes before remove ==> " + getClass);

getClass = getClass.substr(getClass.indexOf('class3')+1);

$("#thisdiv").removeClass(getClass.toString());

alert("Classes After remove ==> "+ $("#thisdiv").prop('class'));​
Mod answered 1/7, 2012 at 5:54 Comment(1)
+1 for the smart answer, removing the alerts shows the shortness of the answer.Enrobe
E
1

try this:

var c = $('#thisdiv').prop('class')
$('#thisdiv').prop('class', c.slice(0, c.indexOf('3')+1))

Demo

Enrobe answered 1/7, 2012 at 5:57 Comment(2)
we came out with so many ideas lol, crazy, If I may recommend use .prop https://mcmap.net/q/40503/-prop-vs-attr rest +1Mod
Thanks for your reply, appreciated, hope will help somebody :)Moton
T
0

There's no built-in way of handling "classes" like this. But there should be no shortage of ways to handle chopping up a string, which is all this is.

Grab the string of classes (getClass()), modifying it using whatever string truncating technique seems to meet your requirements, and then set it again with .attr('class', newString).

Toaster answered 1/7, 2012 at 5:45 Comment(2)
Hrm... leaving this answer but just saw John's answer and I admit I think he's right. Grabbing the string of classes might not be in the order you expect.Toaster
I posted a method of doing it regardless of class order, but as I mention, it's significantly more expensive than making assumptions about it. If this can be stored elsewhere in memory instead of in the actual class attribute, such an assumption might be possible (and maintaining that list via some proxy add/remove/toggle class), but unless this behavior is extremely common, such an optimization seems unnecessary.Rociorock
W
0

No. There's no real guarantee that the classes will be in any sort of order.

If they are indexed somehow, you can parse them out... but otherwise this isn't going to work. If you're just attempting to store information, consider using the HTML5-modelled .data() functions.

Wensleydale answered 1/7, 2012 at 5:45 Comment(0)
R
0

To do something like this correctly might be a little bit expensive. You need to replace the class attr by iterating over existing classes and removing those that don't fit your criteria. The order of classes from the class attribute are not guaranteed to be in any order, in general:

function removeAbove(prefix, max) {
    var regex = new RegExp('^' + prefix + '(\\d+)$');
    return function (v) {
        var match = regex.exec(v);
        if (!match || parseInt(match[1], 10) <= max) {
          return v;
        }
    }
}

function processClasses(keys, fn) {
    var i = keys.length,
        result = [],
        temp;
    while (i--) {
        temp = fn(keys[i]);
        if (temp) {
            result.push(temp);
        }
    }
    return result.join(' ');
}

$('#thisdiv').attr('class', function (idx, cls) {
    return processClasses(cls.split(' '), removeAbove('class', 3));
});
Rociorock answered 1/7, 2012 at 6:7 Comment(1)
thanks for this too, hope this helps someone, for me the first did it brilliantlyMoton

© 2022 - 2024 — McMap. All rights reserved.