Comment basculer la classe d'un élément en JavaScript pur?

128

Je cherche un moyen de convertir ce code jQuery (qui est utilisé dans la section du menu réactif) en JavaScript pur.

S'il est difficile de l'implémenter, vous pouvez utiliser d'autres frameworks JavaScript.

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

    if (typeof masonryGallery != 'undefined') 
        masonryGallery();
});
max imax
la source
11
document.getElementById("menu").classList.toggle("hidden-phone"):-)
Bergi
classList n'est pas pris en charge par certains navigateurs: caniuse.com/classlist
Kevin Whitaker
6
Hey @max, tu veux déjà choisir une réponse?
mikemaccana le

Réponses:

213

Réponse 2014 : classList.toggle()est la norme et prise en charge par la plupart des navigateurs .

Les navigateurs plus anciens peuvent utiliser use classlist.js pour classList.toggle () :

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

En passant, vous ne devriez pas utiliser d'ID ( ils fuient des globaux dans l' windowobjet JS ).

Mikemaccana
la source
si nous ne pouvons pas utiliser d'identifiants, comment pouvons-nous faire cela?
Goku
mais, alors nous aurons la même quantité de classes au lieu d'anciens ID, et utiliserons quelque chose comme var myList = document.getElementsByClassName ("abc")?
Goku
1
Les classes @goku n'apparaissent pas sous l'objet window. Seuls les ID le font. Voir 2ality.com/2012/08/ids-are-global.html
mikemaccana
1
Pris en charge par IE10 et IE11 sauf pour le deuxième paramètre
En dessous du radar
1
Merci beaucoup! Cela fonctionne maintenant :) J'ajoute plus d'options pour la boucle: var All = document.querySelectorAll ('. Menu'); for (var i = 0; i <All.length; i ++) {All [i] .classList.toggle ('hidden-phone'); }
Blue Tram
11

Voici la solution implémentée avec ES6

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

exemple d'utilisation

toggleClass(document.querySelector('div.active'), 'active'); // The div container will not have the 'active' class anymore
Gor
la source
3
ES6 est génial, mais cette solution utilise simplement «document.querySelector» et «element.classList.toggle» pour les autres réponses existantes.
mikemaccana
Aucune solution n'est valable si elle est "orientée fournisseur", Internet est orienté standard ouvert .
Peter Krauss
ce n'est pas une solution pour une multitude de fichiers. ne fonctionne pas avec querySelectorAll (au moins dans FF) donc pour ceux qui cherchent à basculer les classes sur plusieurs éléments lisez :-) (je n'ai pas lu au début - donc mon commentaire!)
kev1807
9

Jetez un œil à cet exemple: 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;
}
Eugène Yastrebov
la source
9
Et si j'avais une classe après "red" nommée "redOther"?
Tiffany Lowe du
4

Celui-ci fonctionne également dans les versions antérieures d'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
la source
\bLa limite des mots n'est pas cohérente avec les séparateurs de noms de classes css. par exemple, cela ne fonctionne pas si le nom de la classe contient tiret ("-") char: btn, btn-red correspondra tous les deux '\\b' + 'btn' + '\\b'!!
S.Serpooshan
3

C'est peut-être plus succinct:

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
la source
0

Essayez ceci (j'espère que cela fonctionnera):

// 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
la source
0

Voici un code pour IE> = 9 en utilisant split ("") sur le 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
la source
0

Si vous souhaitez basculer une classe vers un élément à l'aide d'une solution native, vous pouvez essayer cette suggestion. Je l'ai goûté dans différents cas, avec ou sans d'autres classes sur l'élément, et je pense que cela fonctionne à peu près:

(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
la source