Remove all classes that begin with a certain string
Asked Answered
U

17

118

I have a div with id="a" that may have any number of classes attached to it, from several groups. Each group has a specific prefix. In the javascript, I don't know which class from the group is on the div. I want to be able to clear all classes with a given prefix and then add a new one. If I want to remove all of the classes that begin with "bg", how do I do that? Something like this, but that actually works:

$("#a").removeClass("bg*");
Ulcerative answered 11/9, 2008 at 22:32 Comment(0)
M
63

With jQuery, the actual DOM element is at index zero, this should work

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Mucin answered 12/9, 2008 at 9:5 Comment(3)
Careful with this one. Word boundary splits on dash character ('-') and dots and others, so class names like "bg.a", "bg-a" etc. will not be removed but replaced with ".a", "-a" etc. So if you have classnames with punctuation characters you may run into trouble by just running a simple regex replace. Here is a SO thread about word boundary definitionSkirret
Kabir Sarin's answer below with split(' ') and indexOf is better IMO because it won't cause those special-charactered "zombie" classes to pop up.Skirret
This method can still be used with a better regex, such as the one found here: https://mcmap.net/q/86188/-jquery-removeclass-wildcardWestlund
B
120

A regex splitting on word boundary \b isn't the best solution for this:

var prefix = "prefix";
var classes = el.className.split(" ").filter(function(c) {
    return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ").trim();

or as a jQuery mixin:

$.fn.removeClassPrefix = function(prefix) {
    this.each(function(i, el) {
        var classes = el.className.split(" ").filter(function(c) {
            return c.lastIndexOf(prefix, 0) !== 0;
        });
        el.className = $.trim(classes.join(" "));
    });
    return this;
};

2018 ES6 Update:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();
Baku answered 31/5, 2012 at 14:17 Comment(5)
This is better approach than using RegExp with \b (word boundary check) because it prevents 'zombie classes' from popping up. If you have classes like "prefix-suffix", the 'best answer' in this thread will leave the class '-suffix' because \b will split before '-' char. Your split-map-join solution works around that :) I created a tiny jQuery plugin around your solution, Kabir: (gist.github.com/2881585)Skirret
+1 I as well concur, every other answer appears to just be a simple regex that would break on non-space word boundaries. If I have time tomorrow I'll supply a unit test that proves this.Isolate
I like it although this actually isn't valid code, since the anonymous function in filter must return a boolean. This will work: var classes = $(e).attr("class").split(" "); $(classes).each(function(i, item) { classes[i] = item.indexOf("prefix") === -1 ? item : "prefix-new"); }); $(e).attr("class", classes.join(" "));Triolein
A more valid solution uses map: $e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));Experimentalize
This approach works the best. I used @JakubP's plugin. One suggestion if I may: What it does, when it now returns the classes, it causes a lot of space. For instance class="blackRow blackText orangeFace blackHead" will return class=" orangeFace " if you run removeClassPrefix("black");. I solved this by trimming the result like so: el.className = $.trim(classes.join(" "));.Gsuit
M
63

With jQuery, the actual DOM element is at index zero, this should work

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Mucin answered 12/9, 2008 at 9:5 Comment(3)
Careful with this one. Word boundary splits on dash character ('-') and dots and others, so class names like "bg.a", "bg-a" etc. will not be removed but replaced with ".a", "-a" etc. So if you have classnames with punctuation characters you may run into trouble by just running a simple regex replace. Here is a SO thread about word boundary definitionSkirret
Kabir Sarin's answer below with split(' ') and indexOf is better IMO because it won't cause those special-charactered "zombie" classes to pop up.Skirret
This method can still be used with a better regex, such as the one found here: https://mcmap.net/q/86188/-jquery-removeclass-wildcardWestlund
O
33

I've written a simple jQuery plugin - alterClass, that does wildcard class removal. Will optionally add classes too.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 
Othella answered 24/12, 2011 at 12:59 Comment(1)
Thanks Pete! Just used your plugin and it works great...saved me some time!Firefly
H
14

You don't need any jQuery specific code to handle this. Just use a RegExp to replace them:

$("#a").className = $("#a").className.replace(/\bbg.*?\b/g, '');

You can modify this to support any prefix but the faster method is above as the RegExp will be compiled only once:

function removeClassByPrefix(el, prefix) {
    var regx = new RegExp('\\b' + prefix + '.*?\\b', 'g');
    el.className = el.className.replace(regx, '');
    return el;
}
Hendecasyllable answered 11/9, 2008 at 22:36 Comment(1)
If the prefix ends with a dash, you need to change the regular expression. new RegExp('\\b' + prefix + '[\\S]*\\b', 'g')Achernar
F
10

Using 2nd signature of $.fn.removeClass :

// Considering:
var $el = $('<div class="  foo-1 a b foo-2 c foo"/>');

function makeRemoveClassHandler(regex) {
  return function (index, classes) {
    return classes.split(/\s+/).filter(function (el) {return regex.test(el);}).join(' ');
  }
}

$el.removeClass(makeRemoveClassHandler(/^foo-/));
//> [<div class=​"a b c foo">​</div>​]
Fruitarian answered 5/3, 2013 at 22:13 Comment(1)
Since jQuery v1.4, this is the best approach.Imide
D
6

For modern browsers:

let element = $('#a')[0];
let cls = 'bg';

element.classList.remove.apply(element.classList, Array.from(element.classList).filter(v=>v.startsWith(cls)));
Dannielledannon answered 26/10, 2018 at 5:45 Comment(1)
using string.starsWith() (or string.endsWith()) was perfect for me!Zinazinah
E
4

An approach I would use using simple jQuery constructs and array handling functions, is to declare an function that takes id of the control and prefix of the class and deleted all classed. The code is attached:

function removeclasses(controlIndex,classPrefix){
    var classes = $("#"+controlIndex).attr("class").split(" ");
    $.each(classes,function(index) {
        if(classes[index].indexOf(classPrefix)==0) {
            $("#"+controlIndex).removeClass(classes[index]);
        }
    });
}

Now this function can be called from anywhere, onclick of button or from code:

removeclasses("a","bg");
Embryologist answered 12/3, 2015 at 6:0 Comment(0)
C
3

http://www.mail-archive.com/[email protected]/msg03998.html says:

...and .removeClass() would remove all classes...

It works for me ;)

cheers

Cholinesterase answered 9/3, 2009 at 18:3 Comment(2)
This is a better choice! Works.Restrict
The question doesn't ask how to remove all classes it asks how to remove all classes beginning with a certain string. These two things are very, very different.Youngman
C
3

I was looking for solution for exactly the same problem. To remove all classes starting with prefix "fontid_" After reading this article I wrote a small plugin which I'm using now.

(function ($) {
        $.fn.removePrefixedClasses = function (prefix) {
            var classNames = $(this).attr('class').split(' '),
                className,
                newClassNames = [],
                i;
            //loop class names
            for(i = 0; i < classNames.length; i++) {
                className = classNames[i];
                // if prefix not found at the beggining of class name
                if(className.indexOf(prefix) !== 0) {
                    newClassNames.push(className);
                    continue;
                }
            }
            // write new list excluding filtered classNames
            $(this).attr('class', newClassNames.join(' '));
        };
    }(fQuery));

Usage:

$('#elementId').removePrefixedClasses('prefix-of-classes_');
Colligate answered 14/10, 2013 at 20:18 Comment(1)
This is nothing more than my solution with 10x more lines and a less efficient "string starts with" check :-/Baku
P
3

In one line ... Removes all classes that match a regular expression someRegExp

$('#my_element_id').removeClass( function() { return (this.className.match(/someRegExp/g) || []).join(' ').replace(prog.status.toLowerCase(),'');});
Perm answered 3/7, 2017 at 11:23 Comment(0)
P
2

I know it's an old question, but I found out new solution and want to know if it has disadvantages?

$('#a')[0].className = $('#a')[0].className
                              .replace(/(^|\s)bg.*?(\s|$)/g, ' ')
                              .replace(/\s\s+/g, ' ')
                              .replace(/(^\s|\s$)/g, '');
Pelag answered 28/9, 2012 at 6:54 Comment(1)
In 2020, the disadvantage is jQuery.Margaux
U
1

Prestaul's answer was helpful, but it didn't quite work for me. The jQuery way to select an object by id didn't work. I had to use

document.getElementById("a").className

instead of

$("#a").className
Ulcerative answered 12/9, 2008 at 1:19 Comment(2)
or $("#a")[0].className as className is only available on the DOM element and not the jQuery objectIndication
this is a comment for someones answer, not an answerAbscind
I
1

I also use hyphen'-' and digits for class name. So my version include '\d-'

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');
Importunity answered 19/7, 2010 at 20:10 Comment(0)
G
1
(function($)
{
    return this.each(function()
    {
        var classes = $(this).attr('class');

        if(!classes || !regex) return false;

        var classArray = [];

        classes = classes.split(' ');

        for(var i=0, len=classes.length; i<len; i++) if(!classes[i].match(regex)) classArray.push(classes[i]);

        $(this).attr('class', classArray.join(' '));
    });
})(jQuery);
Giefer answered 19/12, 2012 at 2:47 Comment(0)
N
1

This is a fairly old post. But I worked out a solution that worked for me.

$('[class*=classtoremove]').each(function( index ) {
    var classArray = $(this).attr('class').split(' ');
    $.each( classArray, function( key, value ) {
        if(value.includes('classtoremove')) {
            console.log(value);
            $('.' + value).removeClass(value);
        }
    });
});

Essentially it will get any class that contains classtoremove regardless what is added on the end. So it could be classtoremove234164726 or classtoremove767657576575 it will find the two classes, split all the classes then for each class thats in the array will check to see if the value includes the class to remove. it then gets that class and removes the class without having to replace or re-add anything.

$('[class*=classtoremove]').each(function( index ) {
    var classArray = $(this).attr('class').split(' ');
    $.each( classArray, function( key, value ) {
        if(value.includes('classtoremove')) {
            console.log(value + ' has been removed');
            $('.' + value).removeClass(value);
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class='classtoremove235235235 chicken omlets wrapper'></div>
<div class='classtoremove354645745 chicken omlets wrapper'></div>
<div class='classtoremoveesdfdfh5645 chicken omlets wrapper'></div>
<div class='classtoremove3425423wdt chicken omlets wrapper'></div>
<div class='classtoremovewdgrt346 chicken omlets wrapper'></div>
<div class='classtoremovesdgsbfd4454 chicken omlets wrapper'></div>
<div class='classtoremove45454545 chicken omlets wrapper'></div>
<div class='classtoremove666eed chicken omlets wrapper'></div>
Necolenecro answered 14/2 at 16:47 Comment(0)
F
0

The top answer converted to jQuery for those wanting a jQuery only solution:

const prefix = 'prefix'
const classes = el.attr('class').split(' ').filter(c => !c.startsWith(prefix))
el.attr('class', classes.join(' ').trim())
Fascista answered 21/6, 2021 at 7:17 Comment(0)
A
-5
$("#element").removeAttr("class").addClass("yourClass");
Aristotle answered 13/2, 2013 at 14:22 Comment(2)
I don't think you read the question very well. The user was not asking about simply removing a class and adding another one.Bullough
@Andrew Barber: you're right this is not the right answer, but majorsk8 suggested how to clear all the classes (removeAttr), not just a single one ;)Adulteress

© 2022 - 2024 — McMap. All rights reserved.