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?

Ram
  • 143,282
  • 16
  • 168
  • 197
thednp
  • 4,401
  • 4
  • 33
  • 45

7 Answers7

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/

Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • thanks, I like this code too. How can I change your code so it will work with $('#thisdiv').removeAllClass('class3'); Thanks again :) – thednp Jul 01 '12 at 08:11
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

thecodeparadox
  • 86,271
  • 21
  • 138
  • 164
  • 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'); – thednp Jul 01 '12 at 08:04
  • Thumbs up for the fastest and most precise answer. For sure the first round is on me. – thednp Jul 01 '12 at 08:46
  • 1
    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. – John Green Jul 01 '12 at 10:10
  • 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? – thednp Jul 01 '12 at 10:29
  • @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. – John Green Jul 01 '12 at 11:29
  • 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'); ? – thednp Jul 01 '12 at 13:11
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'));​
Tats_innit
  • 33,991
  • 10
  • 71
  • 77
  • 1
    +1 for the smart answer, removing the alerts shows the shortness of the answer. – Ram Jul 01 '12 at 06:13
1

try this:

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

Demo

Ram
  • 143,282
  • 16
  • 168
  • 197
  • we came out with so many ideas lol, crazy, If I may recommend use `.prop` http://stackoverflow.com/questions/5874652/prop-vs-attr rest +1 – Tats_innit Jul 01 '12 at 06:04
  • Thanks for your reply, appreciated, hope will help somebody :) – thednp Jul 01 '12 at 08:09
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).

Greg Pettit
  • 10,749
  • 5
  • 53
  • 72
  • 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. – Greg Pettit Jul 01 '12 at 05:47
  • 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. – Justin Summerlin Jul 01 '12 at 06:22
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.

John Green
  • 13,241
  • 3
  • 29
  • 51
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));
});
Justin Summerlin
  • 4,938
  • 1
  • 16
  • 10