user1141649 user1141649 - 3 months ago 9
jQuery Question

How to get the name of the class in JQuery removeClass(function)?

I am trying to find a way how to do it when I have a string of classes like that:

last_class;=next_class;^=mce;*=tiny;~=wysiwyg
. Where every class is separated with semicolon. It can contain a selector like =,^=,*= or ~=. My first idea was to use selectors to locate the elements which contains these classes because I expect that it is not possible to use these selectors directly in $.removeClass(). But the problem which I need to solve is how to refer to the result found by the selector (I mean the operator like *=,~=,^=). When I found the tag, I need to get the name of the class which I need to remove. How to do it? I know I could use the .removeClass( function ) syntax, but I have no idea what to write inside the function.

What I tried till now:

var selectors = "last_class;=next_class;^=mce;*=tiny;~wysiwyg"
selectors.split(';');
for ( var i = 0; i<selectors.length; i++ )
{
if ( selectors[i][1] == "=") // ..mce.., ..tiny.. , ..wysiwyg..
{
switch ( selectors[i][0])
{
case "^": // starts with
var selector = 'class^="' + selectors[i].substring(2, 0) + '", '
break;
case "*": // contains
var selector = 'class*="' + selectors[i].substring(2, 0) + '", '
break;
case "~": // contains word
var selector = 'class~="' + selectors[i].substring(2, 0) + '", '
break;
}

}
else // last_class or next_class
{
var selector;
if ( selectors[i][0] == "=") // next_class
selector = selectors[i].substring(1, 0);
selector = '."' + selectors[i].substring(1, 0) + '", '
$.removeClass(selector);
}
}


Final goal is to remove all the classes which are in the list.

Edit:
Here is my second try. Not completed, but at this moment I cannot find out why when I return class_name the class is not removed from the element. I debugged it and found the class name is correct.

var selectors = "^=col;~=cl;*=-art-"["remove_classes"].split(';');
for ( var i = 0; i<selectors.length; i++ )
{
if ( selectors[i][1] == "=")
{
var search = selectors[i].substring(2, selectors[i].length );
switch ( selectors[i][0])
{
case "^": // starts with
var selector = '[class^="' + search + '"]'
var regex = new RegExp( "^" + search + ".*", 'i');
$(selector).removeClass(
function(){
for ( var word in this.className.split(" ") )
{
var class_name = this.className.match(regex);
if (class_name)
return class_name;
}
}
)
break;
case "*": // contains
var selector = '[class*="' + search + '"]'
break;
case "~": // contains word
var selector = '[class~="' + search + '"]'
break;
}

}
else
{
var selector;
if ( selectors[i][0] == "=")
selector = selectors[i].substring(1, 0);
selector = '."' + selectors[i].substring(1, 0) + '", '
$.removeClass(selector);
}
}

Answer

This is not that straightforward. When you have ^=mce you'll want to both of the following elements:

<div class="mce_edit other_class"></div>
<div class="other_class mce_edit"></div>

If you translate that selector to [class^=mce] and do $('[class^=mce]'), then you'll only match the first element. In fact, the selector to get both of them should be (space is intended in second part):

$('[class^=mce],[class*= mce]')

For the same reasons, the ~= comparator is not that special, and corresponds to the .classname selector.

Here is a solution to both find the elements and then get the class name(s) from the found elements that need to be removed:

var selectors = 'last_class;=next_class;^=mce;*=tiny;~=wysiwyg';
selectors = selectors.replace(/;/g, '\n'); // to use convenient `m` modifier

var classExtractor = new RegExp(selectors
    .replace(/^(\~?=)?([\w-].*)/gm, ' $2(?![^ ])')
    .replace(/^\*=(.*)/gm, '[^ ]*$1[^ ]*')
    .replace(/^\^=(.*)/gm, ' $1[^ ]*')
    .replace(/^\$=(.*)/gm, '[^ ]*$1(?![^ ])')
    .replace(/\n/g, '|'), 'g');

var selectors = selectors
    .replace(/^(\~?=)?([\w-].*)/gm, '.$2')
    .replace(/^\*=(.*)/gm, '[class*=$1]')
    .replace(/^\^=(.*)/gm, '[class*= $1],[class^=$1]')
    .replace(/^\$=(.*)/gm, '[class*=$1 ],[class$=$1]')
    .replace(/\n/g, ',');

$(selectors).each(function (i, elem) {
    (' ' + this.className).match(classExtractor).forEach(function (match) {
        $(elem).removeClass(match);
    });
});

I left out the less-popular |= CSS comparator, but if you need that one as well, it should not be too hard to add the necessary code.

Remarks about your code

I did not look into your code in detail, but here are a few hints as to why .removeClass() fails:

  • First of all, it would help you debug, if you would log (with console.log()) the final values you pass to .removeClass(). It would certainly help discover some of the reasons of the failures;

  • .match(regex) returns an array, so that explains why the ^= case fails in your second code version. You'd have to return className[0];. There could be other issues though, I did not test this further;

  • You had built some selectors like 'class*="' + search + '"' which should really be in square brackets, like: '[class*="' + search + '"]'.