Usuń wszystkie klasy, które zaczynają się od określonego ciągu


99

Mam element DIV, do id="a"którego może być dołączona dowolna liczba klas z kilku grup. Każda grupa ma określony prefiks. W javascript nie wiem, która klasa z grupy znajduje się w div. Chcę mieć możliwość wyczyszczenia wszystkich klas z podanym prefiksem, a następnie dodania nowego. Jeśli chcę usunąć wszystkie klasy zaczynające się od „bg”, jak mam to zrobić? Coś takiego, ale to faktycznie działa:

$("#a").removeClass("bg*");

Odpowiedzi:


59

W jQuery rzeczywisty element DOM ma indeks zerowy, to powinno działać

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

34
Ostrożnie z tym. Granice słowa są podzielone na myślnik („-”), kropki i inne, więc nazwy klas, takie jak „bg.a”, „bg-a” itp. Nie zostaną usunięte, ale zastąpione przez „.a”, „-a” itp. Więc jeśli masz nazwy klas ze znakami interpunkcyjnymi, możesz napotkać problemy, wykonując po prostu proste zastąpienie wyrażenia regularnego. Oto wątek SO dotyczący definicji granic słów
Jakub P.

6
Odpowiedź Kabira Sarina poniżej z podziałem ('') i indexOf jest lepszym IMO, ponieważ nie spowoduje pojawienia się tych specjalnych klas "zombie".
Jakub P.

2
Ta metoda może być nadal używana z lepszym wyrażeniem regularnym, takim jak ten znaleziony tutaj: stackoverflow.com/a/2644364/1333402
ssmith

109

Dzielenie wyrażeń regularnych na granicy słów \bnie jest najlepszym rozwiązaniem:

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

lub jako mixin jQuery:

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

Aktualizacja ES6 2018:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();

9
Jest to lepsze podejście niż używanie RegExp z \ b (sprawdzaniem granic słowa), ponieważ zapobiega to wyskakiwaniu „klas zombie”. Jeśli masz klasy takie jak „prefix-suffix”, „najlepsza odpowiedź” w tym wątku pozostawi klasę „-suffix”, ponieważ \ b zostanie podzielone przed znakiem „-”. Twój split-map-przyłączyć rozwiązanie działa wokół tego :) stworzyłem mały jQuery plugin wokół swoje rozwiązanie, Kabir ( gist.github.com/2881585 )
Jakub P.

3
+1 Ja również zgadzam się, każda inna odpowiedź wydaje się być po prostu prostym wyrażeniem regularnym, które łamie granice słów innych niż spacje. Jeśli jutro będę miał czas, dostarczę test jednostkowy, który to udowodni.
rusza

1
Podoba mi się, chociaż w rzeczywistości nie jest to prawidłowy kod, ponieważ funkcja anonimowa w filtermusi zwracać wartość logiczną. To zadziała: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(" "));
Tim

Bardziej poprawne rozwiązanie wykorzystuje mapę:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller

2
To podejście działa najlepiej. Użyłem wtyczki @ JakubP. Jedna sugestia, jeśli mogę: co robi, kiedy zwraca teraz klasy, powoduje dużo miejsca. Na przykład class="blackRow blackText orangeFace blackHead"zwróci, class=" orangeFace "jeśli uruchomisz removeClassPrefix("black");. Rozwiązałem to przez przycinanie wynik taki sposób: el.className = $.trim(classes.join(" "));.
Albert,

29

Napisałem prostą wtyczkę do jQuery - alterClass , która usuwa klasę symboli wieloznacznych. Opcjonalnie doda również klasy.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 

Dzięki Pete! Właśnie użyłem twojej wtyczki i działa świetnie ... zaoszczędził mi trochę czasu!
jordan.baucke

11

Nie potrzebujesz żadnego kodu specyficznego dla jQuery, aby to obsłużyć. Po prostu użyj RegExp, aby je zastąpić:

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

Możesz to zmodyfikować, aby obsługiwać dowolny prefiks, ale szybsza metoda jest powyżej, ponieważ RegExp zostanie skompilowana tylko raz:

function removeClassByPrefix(el, prefix) {
    var regx = new RegExp('\\b' + prefix + '.*?\\b', 'g');
    el.className = el.className.replace(regx, '');
    return el;
}

9

Korzystanie 2nd podpis z $.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>​]

Od wersji 1.4 jQuery jest to najlepsze podejście.
Dinei


3

Podejście, którego użyłbym przy użyciu prostych konstrukcji jQuery i funkcji obsługi tablic, polega na zadeklarowaniu funkcji, która przyjmuje identyfikator kontrolki i prefiks klasy i usuwa wszystkie sklasyfikowane. Kod w załączeniu:

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

Teraz tę funkcję można wywołać z dowolnego miejsca, jednym kliknięciem przycisku lub z kodu:

removeclasses("a","bg");

2

Szukałem rozwiązania dla dokładnie tego samego problemu. Aby usunąć wszystkie klasy zaczynające się od przedrostka „fontid_” Po przeczytaniu tego artykułu napisałem małą wtyczkę, której teraz używam.

(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));

Stosowanie:

$('#elementId').removePrefixedClasses('prefix-of-classes_');

To nic innego jak moje rozwiązanie z 10 razy większą liczbą wierszy i mniej wydajnym „ciągiem znaków zaczynającym się od” check: - /
sarink

2

W przypadku nowoczesnych przeglądarek:

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

element.classList.remove.apply(element.classList, Array.from(element.classList).filter(v=>v.startsWith(cls)));

1

Wiem, że to stare pytanie, ale znalazłem nowe rozwiązanie i chcę wiedzieć, czy ma wady?

$('#a')[0].className = $('#a')[0].className
                              .replace(/(^|\s)bg.*?(\s|$)/g, ' ')
                              .replace(/\s\s+/g, ' ')
                              .replace(/(^\s|\s$)/g, '');

1

W jednej linii ... Usuwa wszystkie klasy, które pasują do wyrażenia regularnego someRegExp

$('#my_element_id').removeClass( function() { return (this.className.match(/someRegExp/g) || []).join(' ').replace(prog.status.toLowerCase(),'');});

0

Odpowiedź Prestaula była pomocna, ale nie do końca mi się to udało. Sposób jQuery do wybierania obiektu według identyfikatora nie działał. Musiałem użyć

document.getElementById("a").className

zamiast

$("#a").className

lub $ ("# a") [0] .className as className jest dostępne tylko w elemencie DOM, a nie w obiekcie jQuery
Naeem Sarfraz

to jest komentarz do czyjejś odpowiedzi, a nie odpowiedź
TJ

0

Używam również łącznika '-' i cyfr jako nazwy klasy. Więc moja wersja zawiera „\ d-”

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');

0
(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);

-6
$("#element").removeAttr("class").addClass("yourClass");

3
Nie sądzę, żebyś dobrze przeczytał pytanie. Użytkownik nie pytał o zwykłe usunięcie klasy i dodanie kolejnej.
Andrew Barber

1
@Andrew Barber: masz rację, to nie jest dobra odpowiedź, ale majorsk8 zasugerował, jak wyczyścić wszystkie klasy (removeAttr), a nie tylko jedną;)
Tilt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.