¿Cómo cambio la clase de un elemento en JavaScript puro?

128

Estoy buscando una forma de convertir este código jQuery (que se usa en la sección del menú receptivo) a JavaScript puro.

Si es difícil de implementar, está bien usar otros marcos de JavaScript.

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

    if (typeof masonryGallery != 'undefined') 
        masonryGallery();
});
max imax
fuente
11
document.getElementById("menu").classList.toggle("hidden-phone"):-)
Bergi
classList no es compatible con algunos navegadores: caniuse.com/classlist
Kevin Whitaker
6
Hola @max, ¿quieres elegir una respuesta ya?
mikemaccana

Respuestas:

213

Respuesta de 2014 : classList.toggle()es el estándar y es compatible con la mayoría de los navegadores .

Los navegadores más antiguos pueden usar classlist.js para classList.toggle () :

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

Además, no debería utilizar ID ( filtran globales en el windowobjeto JS ).

mikemaccana
fuente
si no podemos usar ID, ¿cómo podemos hacerlo?
Goku
pero, entonces tendremos la misma cantidad de clases en lugar de IDs antiguos, y usaremos algo como var myList = document.getElementsByClassName ("abc")?
Goku
1
Las clases @goku no aparecen debajo del objeto de la ventana. Solo las identificaciones lo hacen. Ver 2ality.com/2012/08/ids-are-global.html
mikemaccana
1
Compatible con IE10 e IE11 excepto por el segundo parámetro
debajo del radar
1
Muchas gracias! Está funcionando ahora :) Agrego más opciones para el ciclo: var All = document.querySelectorAll ('. Menu'); for (var i = 0; i <All.length; i ++) {All [i] .classList.toggle ('teléfono oculto'); }
Blue Tram
11

Aquí está la solución implementada con ES6

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

ejemplo de uso

toggleClass(document.querySelector('div.active'), 'active'); // The div container will not have the 'active' class anymore
Gor
fuente
3
ES6 es excelente, pero esta solución simplemente usa 'document.querySelector' y 'element.classList.toggle' según las otras respuestas existentes.
mikemaccana
Ninguna solución es válida si está "orientada al proveedor", Internet está orientada a estándares abiertos .
Peter Krauss
esta no es una solución para una multitud de archivos. no funciona con querySelectorAll (al menos en FF), por lo que para aquellos que buscan alternar clases en varios elementos
siga
9

Eche un vistazo a este ejemplo: 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
fuente
9
¿Y si tuviera una clase después de "red" llamada "redOther"?
Tiffany Lowe
4

Este también funciona en versiones anteriores de 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
fuente
\bEl límite de la palabra no es consistente con los separadores de nombre de clase CSS. por ejemplo, no funciona si el nombre de la clase contiene un guión ("-") char: btn, ¡¡btn-red coincidirán '\\b' + 'btn' + '\\b'!!
S.Serpooshan
3

Esto es quizás más sucinto:

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
fuente
0

Prueba esto (con suerte funcionará):

// 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
fuente
0

Aquí hay un código para IE> = 9 usando split ("") en el 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
fuente
0

Si desea cambiar una clase a un elemento usando una solución nativa, puede probar esta sugerencia. Lo he probado en diferentes casos, con o sin otras clases sobre el elemento, y creo que funciona bastante bien:

(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
fuente