Is there any easy way to remove all classes matching, for example,
color-*
so if I have an element:
<div id="hello" class="color-red color-brown foo bar"></div>
after removing, it would be
<div id="hello" class="foo bar"></div>
Thanks!
Is there any easy way to remove all classes matching, for example,
color-*
so if I have an element:
<div id="hello" class="color-red color-brown foo bar"></div>
after removing, it would be
<div id="hello" class="foo bar"></div>
Thanks!
The removeClass function takes a function argument since jQuery 1.4.
$("#hello").removeClass (function (index, className) {
return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});
Live example: http://jsfiddle.net/xa9xS/1409/
$('div').attr('class', function(i, c){
return c.replace(/(^|\s)color-\S+/g, '');
});
I've written a plugin that does this called alterClass – Remove element classes with wildcard matching. Optionally add classes: https://gist.github.com/1517285
$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )
If you want to use it in other places I suggest you an extension. This one is working fine for me.
$.fn.removeClassStartingWith = function (filter) {
$(this).removeClass(function (index, className) {
return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
});
return this;
};
Usage:
$(".myClass").removeClassStartingWith('color');
I've generalized this into a Jquery plugin which takes a regex as an argument.
Coffee:
$.fn.removeClassRegex = (regex) ->
$(@).removeClass (index, classes) ->
classes.split(/\s+/).filter (c) ->
regex.test c
.join ' '
Javascript:
$.fn.removeClassRegex = function(regex) {
return $(this).removeClass(function(index, classes) {
return classes.split(/\s+/).filter(function(c) {
return regex.test(c);
}).join(' ');
});
};
So, for this case, usage would be (both Coffee and Javascript):
$('#hello').removeClassRegex(/^color-/)
Note that I'm using the Array.filter
function which doesn't exist in IE<9. You could use Underscore's filter function instead or Google for a polyfill like this WTFPL one.
For a jQuery plugin try this
$.fn.removeClassLike = function(name) {
return this.removeClass(function(index, css) {
return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
});
};
or this
$.fn.removeClassLike = function(name) {
var classes = this.attr('class');
if (classes) {
classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim();
classes ? this.attr('class', classes) : this.removeAttr('class');
}
return this;
};
Edit: The second approach should be a bit faster because that runs just one regex replace on the whole class string. The first (shorter) uses jQuery's own removeClass method which iterates trough all the existing classnames and tests them for the given regex one by one, so under the hood it does more steps for the same job. However in real life usage the difference is negligible.
A generic function that remove any class starting with begin
:
function removeClassStartingWith(node, begin) {
node.removeClass (function (index, className) {
return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
});
}
http://jsfiddle.net/xa9xS/2900/
var begin = 'color-';
function removeClassStartingWith(node, begin) {
node.removeClass (function (index, className) {
return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
});
}
removeClassStartingWith($('#hello'), 'color-');
console.log($("#hello")[0].className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello" class="color-red color-brown foo bar"></div>
Similar to @tremby's answer, here is @Kobi's answer as a plugin that will match either prefixes or suffixes.
btn-mini
and btn-danger
but not btn
when stripClass("btn-")
.horsebtn
and cowbtn
but not btn-mini
or btn
when stripClass('btn', 1)
$.fn.stripClass = function (partialMatch, endOrBegin) {
/// <summary>
/// The way removeClass should have been implemented -- accepts a partialMatch (like "btn-") to search on and remove
/// </summary>
/// <param name="partialMatch">the class partial to match against, like "btn-" to match "btn-danger btn-active" but not "btn"</param>
/// <param name="endOrBegin">omit for beginning match; provide a 'truthy' value to only find classes ending with match</param>
/// <returns type=""></returns>
var x = new RegExp((!endOrBegin ? "\\b" : "\\S+") + partialMatch + "\\S*", 'g');
// https://stackoverflow.com/a/2644364/1037948
this.attr('class', function (i, c) {
if (!c) return; // protect against no class
return c.replace(x, '');
});
return this;
};
we can get all the classes by .attr("class")
, and to Array, And loop & filter:
var classArr = $("#sample").attr("class").split(" ")
$("#sample").attr("class", "")
for(var i = 0; i < classArr.length; i ++) {
// some condition/filter
if(classArr[i].substr(0, 5) != "color") {
$("#sample").addClass(classArr[i]);
}
}
You could also do this with vanilla JavaScript using Element.classList. No need for using a regular expression either:
function removeColorClasses(element)
{
for (let className of Array.from(element.classList))
if (className.startsWith("color-"))
element.classList.remove(className);
}
Note: Notice that we create an Array
copy of the classList
before starting, that's important since classList
is a live DomTokenList
which will update as classes are removed.
An alternative way of approaching this problem is to use data attributes, which are by nature unique.
You'd set the colour of an element like: $el.attr('data-color', 'red');
And you'd style it in css like: [data-color="red"]{ color: tomato; }
This negates the need for using classes, which has the side-effect of needing to remove old classes.
I had the same issue and came up with the following that uses underscore's _.filter method. Once I discovered that removeClass takes a function and provides you with a list of classnames, it was easy to turn that into an array and filter out the classname to return back to the removeClass method.
// Wildcard removeClass on 'color-*'
$('[class^="color-"]').removeClass (function (index, classes) {
var
classesArray = classes.split(' '),
removeClass = _.filter(classesArray, function(className){ return className.indexOf('color-') === 0; }).toString();
return removeClass;
});
Based on ARS81's answer (that only matches class names beginning with), here's a more flexible version. Also a hasClass()
regex version.
Usage: $('.selector').removeClassRegex('\\S*-foo[0-9]+')
$.fn.removeClassRegex = function(name) {
return this.removeClass(function(index, css) {
return (css.match(new RegExp('\\b(' + name + ')\\b', 'g')) || []).join(' ');
});
};
$.fn.hasClassRegex = function(name) {
return this.attr('class').match(new RegExp('\\b(' + name + ')\\b', 'g')) !== null;
};
This will effectively remove all class names which begins with prefix
from a node's class
attribute. Other answers do not support SVG elements (as of writing this), but this solution does:
$.fn.removeClassPrefix = function(prefix){
var c, regex = new RegExp("(^|\\s)" + prefix + "\\S+", 'g');
return this.each(function(){
c = this.getAttribute('class');
this.setAttribute('class', c.replace(regex, ''));
});
};
You could also use the className
property of the element's DOM object:
var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));
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(" ");
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 = classes.join(" ");
});
return this;
};
if you have more than one element having a class name 'example', to remove classes of 'color-'in all of them you can do this:[using jquery]
var objs = $('html').find('.example');
for(index=0 ; index < obj1s.length ; index++){
objs[index].className = objs[index].className.replace(/col-[a-z1-9\-]*/,'');
}
if you don't put [a-z1-9-]* in your regex it won't remove the classes which have a number or some '-' in their names.
If you just need to remove the last set color, the following might suit you.
In my situation, I needed to add a color class to the body tag on a click event and remove the last color that was set. In that case, you store the current color, and then look up the data tag to remove the last set color.
Code:
var colorID = 'Whatever your new color is';
var bodyTag = $('body');
var prevColor = bodyTag.data('currentColor'); // get current color
bodyTag.removeClass(prevColor);
bodyTag.addClass(colorID);
bodyTag.data('currentColor',colorID); // set the new color as current
Might not be exactly what you need, but for me it was and this was the first SO question I looked at, so thought I would share my solution in case it helps anyone.