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*");
Ćwiek
źródło

Odpowiedzi:

59

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

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Poklepać
źródło
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();
sarink
źródło
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' ) 
Pete B.
źródło
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;
}
Prestaul
źródło
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>​]
abernier
źródło
Od wersji 1.4 jQuery jest to najlepsze podejście.
Dinei
3

http://www.mail-archive.com/[email protected]/msg03998.html mówi:

... i .removeClass () usunie wszystkie klasy ...

Mi to pasuje ;)

Twoje zdrowie


źródło
To lepszy wybór! Pracuje.
Afshin Mehrabani
12
Pytanie nie pyta, jak usunąć wszystkie klasy, ale pyta, jak usunąć wszystkie klasy zaczynające się od określonego ciągu. Te dwie rzeczy są bardzo, bardzo różne.
Chris Harrison
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");
nhahtdh
źródło
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_');
Paweł
źródło
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)));
Maks
źródło
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, '');
Jan J.
źródło
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(),'');});
Adam111p
źródło
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
Ćwiek
źródło
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, '');
Jamland
źródło
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);
Obrabować
źródło
-6
$("#element").removeAttr("class").addClass("yourClass");
majorsk8
źródło
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