Jak przełączyć klasę elementu w czystym JavaScript?

128

Szukam sposobu na przekonwertowanie tego kodu jQuery (który jest używany w responsywnej sekcji menu) na czysty JavaScript.

Jeśli trudno jest zaimplementować, możesz użyć innych frameworków JavaScript.

$('.btn-navbar').click(function()
{
    $('.container-fluid:first').toggleClass('menu-hidden');
    $('#menu').toggleClass('hidden-phone');

    if (typeof masonryGallery != 'undefined') 
        masonryGallery();
});
max imax
źródło
11
document.getElementById("menu").classList.toggle("hidden-phone"):-)
Bergi
classList nie jest obsługiwany przez niektóre przeglądarki: caniuse.com/classlist
Kevin Whitaker
6
Hej @max, chcesz już wybrać odpowiedź?
mikemaccana

Odpowiedzi:

213

Odpowiedź 2014 : classList.toggle()jest standardem i obsługiwana przez większość przeglądarek .

Starsze przeglądarki mogą używać classlist.js dla classList.toggle () :

var menu = document.querySelector('.menu') // Using a class instead, see note below.
menu.classList.toggle('hidden-phone');

Na marginesie, nie powinieneś używać identyfikatorów ( przeciekają one wartości globalne do windowobiektu JS ).

mikemaccana
źródło
jeśli nie możemy używać identyfikatorów, to jak możemy to zrobić?
Goku
ale wtedy będziemy mieli tę samą liczbę klas zamiast starych identyfikatorów i użyjemy czegoś takiego jak var myList = document.getElementsByClassName ("abc")?
Goku
1
Klasy @goku nie pojawiają się pod obiektem okna. Tylko identyfikatory. Zobacz 2ality.com/2012/08/ids-are-global.html
mikemaccana
1
Obsługiwane przez IE10 i IE11, z wyjątkiem drugiego parametru
Poniżej radaru
1
Dziękuję bardzo! Teraz już działa :) Dodałem więcej opcji pętli: var All = document.querySelectorAll ('. Menu'); for (var i = 0; i <All.length; i ++) {All [i] .classList.toggle ('hidden-phone'); }
Blue Tram
11

Oto rozwiązanie zaimplementowane w ES6

const toggleClass = (el, className) => el.classList.toggle(className);

przykład użycia

toggleClass(document.querySelector('div.active'), 'active'); // The div container will not have the 'active' class anymore
Gor
źródło
3
ES6 jest świetny, ale to rozwiązanie wykorzystuje po prostu „document.querySelector” i „element.classList.toggle” do innych istniejących odpowiedzi.
mikemaccana
Żadne rozwiązanie nie jest poprawne, jeśli jest „zorientowane na dostawcę”, Internet jest zorientowany na otwarte standardy .
Peter Krauss
nie jest to rozwiązanie dla wielu plików. nie działa z querySelectorAll (przynajmniej w FF), więc dla tych, którzy chcą przełączać klasy na wiele elementów, przeczytaj :-) (na początku nie czytałem - stąd mój komentarz!)
kev1807
9

Spójrz na ten przykład: JS Fiddle

function toggleClass(element, className){
    if (!element || !className){
        return;
    }

    var classString = element.className, nameIndex = classString.indexOf(className);
    if (nameIndex == -1) {
        classString += ' ' + className;
    }
    else {
        classString = classString.substr(0, nameIndex) + classString.substr(nameIndex+className.length);
    }
    element.className = classString;
}
Eugene Yastrebov
źródło
9
A co gdybym miał zajęcia po „czerwonym” o nazwie „redOther”?
Tiffany Lowe
4

Ten działa również we wcześniejszych wersjach IE.

function toogleClass(ele, class1) {
  var classes = ele.className;
  var regex = new RegExp('\\b' + class1 + '\\b');
  var hasOne = classes.match(regex);
  class1 = class1.replace(/\s+/g, '');
  if (hasOne)
    ele.className = classes.replace(regex, '');
  else
    ele.className = classes + class1;
}
.red {
  background-color: red
}
div {
  width: 100px;
  height: 100px;
  margin-bottom: 10px;
  border: 1px solid black;
}
<div class="does red redAnother " onclick="toogleClass(this, 'red')"></div>

<div class="does collapse navbar-collapse " onclick="toogleClass(this, 'red')"></div>

RRK
źródło
\bgranica słowa nie jest zgodna z separatorami nazw klas CSS. na przykład nie działa, jeśli nazwa klasy zawiera myślnik („-”) znak: btn, btn-red będą pasować zarówno '\\b' + 'btn' + '\\b'!
S.Serpooshan,
3

To jest być może bardziej zwięzłe:

function toggle(element, klass) {
  var classes = element.className.match(/\S+/g) || [],
      index = classes.indexOf(klass);

  index >= 0 ? classes.splice(index, 1) : classes.push(klass);
  element.className = classes.join(' ');
}
mushishi78
źródło
0

Spróbuj tego (miejmy nadzieję, że zadziała):

// mixin (functionality) for toggle class 
function hasClass(ele, clsName) {
    var el = ele.className;
    el = el.split(' ');
    if(el.indexOf(clsName) > -1){
        var cIndex = el.indexOf(clsName);
        el.splice(cIndex, 1);
        ele.className = " ";
        el.forEach(function(item, index){
          ele.className += " " + item;
        })
    }
    else {
        el.push(clsName);
        ele.className = " ";
        el.forEach(function(item, index){
          ele.className += " " + item;
        })
    }
}

// get all DOM element that we need for interactivity.

var btnNavbar =  document.getElementsByClassName('btn-navbar')[0];
var containerFluid =  document.querySelector('.container-fluid:first');
var menu = document.getElementById('menu');

// on button click job
btnNavbar.addEventListener('click', function(){
    hasClass(containerFluid, 'menu-hidden');
    hasClass(menu, 'hidden-phone');
})`enter code here`
Rajbir Sharma
źródło
0

Oto kod dla IE> = 9 przy użyciu split („”) w className:

function toggleClass(element, className) {
    var arrayClass = element.className.split(" ");
    var index = arrayClass.indexOf(className);

    if (index === -1) {
        if (element.className !== "") {
            element.className += ' '
        }
        element.className += className;
    } else {
        arrayClass.splice(index, 1);
        element.className = "";
        for (var i = 0; i < arrayClass.length; i++) {
            element.className += arrayClass[i];
            if (i < arrayClass.length - 1) {
                element.className += " ";
            }
        }
    }
}
P. Lefèvre
źródło
0

Jeśli chcesz przełączyć klasę na element za pomocą rozwiązania natywnego, możesz wypróbować tę sugestię. Próbowałem go w różnych przypadkach, z innymi klasami na elemencie lub bez, i myślę, że działa prawie:

(function(objSelector, objClass){
   document.querySelectorAll(objSelector).forEach(function(o){
      o.addEventListener('click', function(e){
        var $this = e.target,
            klass = $this.className,
            findClass = new RegExp('\\b\\s*' + objClass + '\\S*\\s?', 'g');

        if( !findClass.test( $this.className ) )
            if( klass ) 
                $this.className = klass + ' ' + objClass;
            else 
                $this.setAttribute('class', objClass);
        else 
        {
            klass = klass.replace( findClass, '' );
            if(klass) $this.className = klass;
            else $this.removeAttribute('class');
        }
    });
  });
})('.yourElemetnSelector', 'yourClass');
Christiyan
źródło