jQuery removeClass-Platzhalter

370

Gibt es eine einfache Möglichkeit, alle übereinstimmenden Klassen zu entfernen, z.

color-*

Also, wenn ich ein Element habe:

<div id="hello" class="color-red color-brown foo bar"></div>

nach dem Entfernen wäre es

<div id="hello" class="foo bar"></div>

Vielen Dank!

atp
quelle
1
Ein regulärer Ausdruck wie in der "akzeptierten Antwort" wird an Nicht-Raum-Wortgrenzen unterbrochen. Ich habe unten eine alternative Lösung veröffentlicht. Siehe auch: stackoverflow.com/questions/57812/…
sarink
@KabirSarin Die akzeptierte Antwort wurde seitdem aktualisiert, um dies zu beheben.
Emile Bergeron
CSS Wildcards surfingsuccess.com/css/…
Max Hodges

Antworten:

679

Die Funktion removeClass verwendet seit jQuery 1.4 ein Funktionsargument .

$("#hello").removeClass (function (index, className) {
    return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});

Live-Beispiel: http://jsfiddle.net/xa9xS/1409/

jimmystormig
quelle
4
Ich dachte, es wäre erwähnenswert, dass dies ein führendes Leerzeichen von übereinstimmenden Klassen erfassen wird, die nicht am Anfang beginnen. Javascript unterstützt kein positives Lookbehind, sodass Sie eine Problemumgehung für die Capture-Gruppe verwenden müssen. Es ist jedoch ein Streitpunkt, da die Funktion removeClass für Sie überclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip
Diese Lösung gefällt mir am besten! Wie kann ich prüfen, ob zwei oder mehr Klassen entfernt werden sollen? dh sport-, nav-und color-?
Lowtechsun
Wie würden Sie dies tun, um zu einem Klassenende zu passen *-color?
Kreis B
3
@lowtechsun kannst du so in deine Regex einfügen (color-|sport-|nav-). Es wird übereinstimmen color-, oder sport-, oder nav-. Die obige Antwort würde also werden /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie
1
Die akzeptierte Antwort ist richtig, aber idiomatisch würde ich \ b verwenden, das an jeder Wortgrenze übereinstimmt, anstatt an den wortreicheren (^ | \ s). Um beispielsweise alle Klassen zu entfernen, die aus dem Wort Magie bestehen, gefolgt von einer nicht negativen Ganzzahl, und nur diese, würde ich auf / \ bmagic \ d + \ b / übereinstimmen.
CarlEdman
98
$('div').attr('class', function(i, c){
    return c.replace(/(^|\s)color-\S+/g, '');
});
Kobi
quelle
5
Ich mag das, weil es den Overhead reduziert und direkt auf den Punkt kommt. Warum remove class verwenden, wenn attr den Job besser macht?
Angry Dan
2
Ich denke, Sie müssen sich vor leeren Klassen schützen ( c is undefined)? Zumindest als ich es unten in meinem Plugin auf dieser Seite $('a').stripClass('post', 1)ausprobiert habe , warf "TypeError: Methode 'replace' von undefined kann nicht aufgerufen werden"
drzaus
1
@Kobi Ja, ich glaube nicht, dass es möglich ist, nach einem Attribut zu filtern und ein Ergebnis zurückzugeben, das es nicht hat - $('div[class]')sollte nur Elemente mit zurückgeben class, unabhängig davon, ob sie einen Wert haben oder nicht. Testszenarien: jsfiddle.net/drzaus/m83mv
drzaus
1
@Kobi - Ich glaube, ich sehe, worauf du hinaus willst. In den Randfällen wie .removeProp('class')oder .className=undefinedder Filter gibt [class]immer noch etwas zurück, sie sind einfach undefined. Technisch gesehen hat es also immer noch eine Klasse (im Gegensatz zu .removeAttr('class'), weshalb es Ihre Funktion bricht, aber nicht meine Variante. Jsfiddle.net/drzaus/m83mv/4
drzaus
1
Das Hinzufügen eines Schnelltests funktioniert für mich:return c && c.replace(/\bcolor-\S+/g, '');
Schmied
50

Ich habe ein Plugin namens alterClass geschrieben, das Elementklassen mit Platzhalterübereinstimmung entfernt. Fügen Sie optional Klassen hinzu: https://gist.github.com/1517285

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )
Pete B.
quelle
1
Sehr schön in der Tat ... hat mir geholfen, Code wiederzuverwenden, bei dem ich nur Twitter BoostrapKlassen wie diese entfernen musste:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri
15

Ich habe dies in ein Jquery-Plugin verallgemeinert, das einen regulären Ausdruck als Argument verwendet.

Kaffee:

$.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(' ');
  });
};

In diesem Fall wäre die Verwendung also (sowohl Kaffee als auch Javascript):

$('#hello').removeClassRegex(/^color-/)

Beachten Sie, dass ich die Array.filterFunktion verwende, die in IE <9 nicht vorhanden ist. Sie können stattdessen die Filterfunktion von Underscore oder Google für eine Polyfüllung wie diese WTFPL verwenden .

tremby
quelle
11

Wenn Sie es an anderen Orten verwenden möchten, empfehle ich Ihnen eine Erweiterung. Dieser funktioniert gut für mich.

 $.fn.removeClassStartingWith = function (filter) {
    $(this).removeClass(function (index, className) {
        return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
    });
    return this;
};

Verwendungszweck:

$(".myClass").removeClassStartingWith('color');
Charly Guirao
quelle
4

Wir können alle Klassen von .attr("class")und zu Array und Loop & Filter abrufen:

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]);
    }
}

Demo: http://jsfiddle.net/L2A27/1/

meni181818
quelle
Hinzugefügt var prefix='color';und geändert ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C
4

Ähnlich wie @ tremby die Antwort ist hier @ Kobi die Antwort als ein Plugin , das entweder Präfixe oder Suffixe übereinstimmen.

  • ex) Streifen btn-miniund btn-dangeraber nicht btnwannstripClass("btn-") .
  • ex) Streifen horsebtnund cowbtnaber nicht btn-minioder btnwannstripClass('btn', 1)

Code:

$.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;
};

https://gist.github.com/zaus/6734731

drzaus
quelle
1
Ich bin nicht der Meinung, dass dies einfacher ist.
Tremby
@tremby sorry, ich meinte einfacher in der typischen Verwendung (dh Präfixe und Suffixe), da Sie nicht jedes Mal einen
regulären Ausdruck
3
Ich bin immer noch anderer Meinung. Bei Ihrer Methode müssen Sie die Dokumentation lesen und sich merken, was genau der Wert sein endOrBeginmuss. Es ist nicht selbsterklärend. Was ist schwer daran, einen regulären Ausdruck zu schreiben? /^match-at-start/und /match-at-end$/sind jedem JS-Entwickler bekannt. Aber jeder für sich.
Tremby
1
@tremby andere als reguläre Ausdrücke missbraucht zu betteln, eine nicht-regex Option passt sich enger an den bestehenden Unterschrift addClass, removeClassund toggleClass, die jedem jQuery - Entwickler bekannt ist. Was ist schwer am Lesen von Dokumentation? ;)
drzaus
2
Es ist nicht schwer, Dokumentation zu lesen, aber wie @tremby sagt, ist seine Lösung selbsterklärend, während Ihre Dokumentation erfordert. Selbsterklärende Lösungen sind per Definition einfacher zu verwenden.
Francisco Hodge
2

Versuchen Sie dies für ein jQuery-Plugin

$.fn.removeClassLike = function(name) {
    return this.removeClass(function(index, css) {
        return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
    });
};

oder dieses

$.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;
};
ARS81
quelle
2

Basierend auf der Antwort von ARS81 (die nur mit Klassennamen übereinstimmt, die mit beginnen), ist hier eine flexiblere Version. Auch eine Regex-Version.hasClass()

Verwendungszweck: $('.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;
};
Pascal Polleunus
quelle
2

Dadurch werden effektiv alle Klassennamen, die mit beginnen, prefixaus dem classAttribut eines Knotens entfernt . Andere Antworten unterstützen keine SVG- Elemente (zum Zeitpunkt des Schreibens), aber diese Lösung bietet:

$.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, ''));
    });
};
vsync
quelle
Wäre es nicht effizienter, das RegExpObjekt aus jedem Rückruf einmal zu erstellen ?
Emile Bergeron
1
@ EmileBergeron - ja das wäre es! Ich werde Änderungen vornehmen
vsync
2

Ich hatte das gleiche Problem und fand Folgendes, das die _.filter-Methode des Unterstrichs verwendet. Als ich herausfand, dass removeClass eine Funktion übernimmt und Ihnen eine Liste von Klassennamen zur Verfügung stellt, war es einfach, diese in ein Array umzuwandeln und den Klassennamen herauszufiltern, um zur removeClass-Methode zurückzukehren.

// 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;
});
Nynynie
quelle
1
Können Sie erklären, was der Unterstrich in _.filter
bart
2

Sie können dies auch mit Vanille-JavaScript mithilfe von Element.classList tun . Es ist auch nicht erforderlich, einen regulären Ausdruck zu verwenden:

function removeColorClasses(element) { for (let className of Array.from(element.classList)) if (className.startsWith("color-")) element.classList.remove(className); }

Hinweis: Beachten Sie, dass wir vor dem Start eine ArrayKopie von erstellen. Dies classListist wichtig, da classListes sich um ein Live handelt, DomTokenListdas aktualisiert wird, wenn Klassen entfernt werden.

kzar
quelle
1

Sie können auch die classNameEigenschaft des DOM-Objekts des Elements verwenden:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));
Alexander Wallin
quelle
1

Eine generische Funktion, die alle Klassen entfernt, beginnend mit 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>

Fifi
quelle
0

Eine Regex-Aufteilung an der Wortgrenze \bist hierfür nicht die beste Lösung:

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

oder als 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;
};
Sarink
quelle
0

Wenn Sie mehr als ein Element mit dem Klassennamen 'Beispiel' haben, können Sie Folgendes tun, um Klassen von 'Farbe' in allen zu entfernen: [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\-]*/,'');
}

Wenn Sie [a-z1-9 -] * nicht in Ihre Regex einfügen, werden die Klassen nicht entfernt, deren Namen eine Zahl oder ein '-' enthalten.

mohammad eslahi sani
quelle
0

Wenn Sie nur die zuletzt eingestellte Farbe entfernen müssen, passt möglicherweise Folgendes zu Ihnen.

In meiner Situation musste ich dem Body-Tag bei einem Klickereignis eine Farbklasse hinzufügen und die zuletzt festgelegte Farbe entfernen. In diesem Fall speichern Sie die aktuelle Farbe und suchen dann das Daten-Tag, um die zuletzt festgelegte Farbe zu entfernen.

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

Könnte nicht genau das sein, was Sie brauchen, aber für mich war es das und dies war die erste SO-Frage, die ich mir ansah. Ich dachte, ich würde meine Lösung teilen, falls sie jemandem hilft.

redfox05
quelle
Das ist hier irrelevant. Sie hätten Ihre eigene Frage beantworten können, da dies ein ermutigtes Verhalten bei SO ist.
Emile Bergeron
@ Emile: Das stimmt. Ich könnte das tun, da es die ursprüngliche Frage nicht direkt beantwortet. Soll ich diese Antwort offen lassen oder entfernen?
Redfox05
Zu diesem Zeitpunkt erfolgt dies auf eigenes Risiko. Es wurde noch nicht herabgestimmt oder hochgestimmt. Sie können es also ohne Risiko auf Ihre eigene Frage verschieben. Versuchen Sie auch, Duplikate zu vermeiden, indem Sie prüfen, ob dies bereits eine Frage ist.
Emile Bergeron
0

Eine alternative Möglichkeit, dieses Problem anzugehen, besteht darin, Datenattribute zu verwenden, die von Natur aus eindeutig sind.

Sie würden die Farbe eines Elements wie folgt einstellen: $el.attr('data-color', 'red');

Und Sie würden es in CSS wie folgt stylen: [data-color="red"]{ color: tomato; }

Dies macht die Verwendung von Klassen überflüssig, was den Nebeneffekt hat, dass alte Klassen entfernt werden müssen.

rorymorris89
quelle