Using JQuery removeClass() to remove all classes but one
Asked Answered
D

5

7

Okay, I've got an interesting one (well, interesting to me, anyway :) ).

I've got a situation where I have a div with a static class value, but it also can have a single, "secondary class" assigned that is dynamic. When the user makes a selection, any existing secondary class needs to be removed and the new class added.

Ignoring using an id value (standards for the project use the class . . . can't be changed), is there an elegant way to simply ignore the first class and remove whatever other class is there, before adding the new one?

Example Starting HTML:

<div class="staticClass dynaClass1" />

Example JS:

function updateClass(newSecondaryClass) {
    $(".staticClass") . . . **** remove any class besides "staticClass" ****
    $(".staticClass").addClass(newSecondaryClass);
}

If the function is called using updateClass("dynaClass2");, the resulting HTML should be:

<div class="staticClass dynaClass2" />

I can think of ways of doing it involving just removing all classes using removeClass(); and adding "staticClass" back in when adding the new class, or using attr("class", "staticClass " + newSecondaryClass);, but I'm wondering if there isn't a way to handle it without having to touch the static class at all?

In the end, I guess this is an academic question, more than anything . . . just seems like it's something that should be doable, but I don't know how to do it. :D

Dryclean answered 14/1, 2013 at 16:14 Comment(16)
Is staticClass known beforehand or we must handle as such whatever class name comes first?Xerophthalmia
try this : https://mcmap.net/q/86850/-jquery-change-class-nameHimyarite
Note that thinking in terms of "first class" and "other class" is a little off-base; there's no order to classes in the set of those present for an element.Remscheid
Removing all classes and re-assigning that specific class is indeed the most "elegant" way. jQuery doesn't offer any pattern match for those methods.Dinnie
Álvaro - Well, the class is used as the selector, so it would be known, but ideally, it would not be hard-coded, so that it could be reused more easily. Maybe passed in as a second parameter to the function.Dryclean
Pointy - fair enough . . . just trying to differentiate between the two "types" of class in the example . . . you are correct, that the order is unimportant in this situation.Dryclean
To answer your question, yes you have to touch the static class. The browser isn't simply going to know that staticClass is supposed to stay there, you need to tell it. Just like you are going to tell it to remove the tertiary class and add a new one.Pycno
@Dinnie not true, look at my answer. Removing and reassigning is not the best solution. If for example display: block and display:none are bound to a class, assigning and reassigning might result in a flicker.Trimming
@BeatRichartz: I commented your answer. I'm aware of regex solutions, but I'd never say thats more "elegant". But then again, that might be personal opinion.Dinnie
@Dinnie with a removeClass.addClass chain, removeClass would have to be given all the classes to be removed, which is potentially a very long string, which is not very elegant. Also a personal opinion.Trimming
@BeatRichartz: nope, calling .removeClass() without arguments will clean any class name.Dinnie
@Beat Richartz: The "flicker issue" is exactly why I was looking for a way to avoid touching the static class. In the particular case that got me thinking about this, there can be a lot of styles associated with the static class, so I'd rather not ever have it "unassigned", even for the shortest moment.Dryclean
@Dinnie got me there, ugh...Trimming
@Dryclean If flickering is no option, use the function / regexp solution. If you do the regexp right, its surely what you're looking for. removeClass.addClass may be more readable, but it has its bad sides.Trimming
So, in the end, it seems like, if you want to avoid touching the static class as much as possible, there are two options: (1) use .removeClass() and give it a function that dynamically determines which of the current classes to remove, or (2) use the more generic .attr('class', '<final list of classes>') Excellent . . . thanks for the discussion. Not sure which answer to select since it seems like a combination of multiple ones.Dryclean
See also https://mcmap.net/q/204538/-remove-all-classes-except-one/292060Handmaiden
T
6

You can pass a function to remove class, which returns all but the static Classes:

$('.staticClass').removeClass(function(index, klass) { 
  return klass.replace(/(^|\s)+staticClass\s+/, ''); 
})

This is returning all the classes that are on the object, without the static one, and therefore removes all classes but the static one.

Trimming answered 14/1, 2013 at 16:22 Comment(7)
two problems with that. First, it won't create a space if there is any class / word coming after the matched string and second, it would also match foostaticClassbar.Dinnie
@Dinnie you're right about the match, but wrong about the space creation. The return value is passed to removeClass, where jQuery takes over and assigns the new values.Trimming
This is the kind of the thing that I think I was looking for, but jAndy makes good points about the having to handle the placement of the static class in the returned group.Dryclean
@Dryclean jQuery does take over the return value and passes it to removeClass. The function only replaces the static value in the string by nothing, therefore assuring that jquery only removes the classes in the returned string.Trimming
FYI - while the .attr('class', '<final list of classes>') approach is likely the most efficient way to handle the particular situation, this answer really addressed what I was looking for, which was a way to exclude classes using removeClass(). Thanks to everybody for the input.Dryclean
The concept is sound, but the RegEx needs improvement. I posted an update that addresses the issue. Also, this method is necessary when you don't want to replace the existing classes with other classes as in .attr('class', '<final list of classes>'), but instead just want to remove those that don't match a list of classes.Graben
Why invoke $(this).attr('class') inside the function when the original class is already passed to that function as a parameter?Daugherty
G
11

You can remove all classes and add the one you want to leave:

$(".staticClass").removeClass().addClass('staticClass');

Calling removeClass() without a parameter removes all classes.

If you don't want to do that then you can simply modify the class attribute:

$(".staticClass").attr('class', 'staticClass');
Gumbo answered 14/1, 2013 at 16:17 Comment(3)
Cool, but this guy has thought of that anyway ( look @ the end of the question )Windle
@drinchev I should read the questions until the end I guess. I updated with a different suggestion.Gumbo
This method doesn't allow for the possibility of an element that doesn't already have 'staticClass' from not getting it added when that may not be your intention. That is to say <div class="someClass"> would become <div class="staticClass">, but to be true to the concept of removing all classes except a specified class, the result in this example should be <div class="">. Passing a RegEx replace function to .removeClass() allows the selected element to keep the specified class if it has it, but removes all classes for the element that doesn't already have the specified class.Graben
T
6

You can pass a function to remove class, which returns all but the static Classes:

$('.staticClass').removeClass(function(index, klass) { 
  return klass.replace(/(^|\s)+staticClass\s+/, ''); 
})

This is returning all the classes that are on the object, without the static one, and therefore removes all classes but the static one.

Trimming answered 14/1, 2013 at 16:22 Comment(7)
two problems with that. First, it won't create a space if there is any class / word coming after the matched string and second, it would also match foostaticClassbar.Dinnie
@Dinnie you're right about the match, but wrong about the space creation. The return value is passed to removeClass, where jQuery takes over and assigns the new values.Trimming
This is the kind of the thing that I think I was looking for, but jAndy makes good points about the having to handle the placement of the static class in the returned group.Dryclean
@Dryclean jQuery does take over the return value and passes it to removeClass. The function only replaces the static value in the string by nothing, therefore assuring that jquery only removes the classes in the returned string.Trimming
FYI - while the .attr('class', '<final list of classes>') approach is likely the most efficient way to handle the particular situation, this answer really addressed what I was looking for, which was a way to exclude classes using removeClass(). Thanks to everybody for the input.Dryclean
The concept is sound, but the RegEx needs improvement. I posted an update that addresses the issue. Also, this method is necessary when you don't want to replace the existing classes with other classes as in .attr('class', '<final list of classes>'), but instead just want to remove those that don't match a list of classes.Graben
Why invoke $(this).attr('class') inside the function when the original class is already passed to that function as a parameter?Daugherty
G
4

Pass a function to .removeClass()

A revision of Beat Richartz's answer on this page.

Note: I tried to post this as an edit and it was rejected. The concept is identical, with an improved RegEx.

Improved RegEx provides word-boundary matching with multiple classes

// Remove all classes except those specified
$('span').removeClass(function () { 
    return $(this).attr('class').replace(/\b(?:hello|world)\b\s*/g, ''); 
});

Before:

<span class="hello foo">hello</span> <span class="world bar">world</span>`

After:

<span class="hello">hello</span> <span class="world">world</span>`

Try it: http://jsfiddle.net/gfullam/52eeK/3/

Try it as a jQuery plugin: http://jsfiddle.net/gfullam/52eeK/5/

FWIW: This method is necessary when you don't want to replace the existing classes with other classes as in .attr('class', '<final list of classes>'), but instead just want to remove those that don't match a list of classes.

Graben answered 27/6, 2014 at 19:50 Comment(1)
And the opposite - if you just want to remove classes that do match a list is: $('span').removeClass('hello world');Jocasta
T
2

You can set it's required classes using the .attr() function. So:

$('.staticClass').attr('class','<any classes required');

This will replace any classes that were originally there, and add the new ones.

Twitch answered 14/1, 2013 at 16:20 Comment(0)
W
0

All of your classes are manipulated by calling the Javascript DOM element.className, so basically jQuery's addClass just replaces that string. You can see that in the Github source.

Which all means that if you call

$('.staticClass').addClass('someClass');

The element.className is replaced anyway, but with the new class included. ( this means that your staticClass is actually touched :)

When you call

$('.staticClass').removeClass().addClass('staticClass');

you will replace that string twice and there is no problem doing that.

Windle answered 14/1, 2013 at 16:28 Comment(1)
I guess my concern with using a default "removeClass" here would be the extra interval (however brief) when the static class was unassigned to the div, meaning that any styles associated with it would be gone. But I see your point about how the static class will always be "touched" when using "addClass".Dryclean

© 2022 - 2024 — McMap. All rights reserved.