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


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 ).


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

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

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>


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

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`

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 += " ";
            }
        }
    }
}

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');
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.