¿Qué es la función "hasClass" con JavaScript simple?

313

¿Cómo haces jQuery's hasClasscon JavaScript simple? Por ejemplo,

<body class="foo thatClass bar">

¿Cuál es la forma de preguntar JavaScript si <body>tiene thatClass?

Kyle
fuente
Supongo que tendría que analizar la classpropiedad (que en el caso de varias clases tendrá varios nombres de clase en orden aleatorio separados por un espacio) y verificar si su nombre de clase está en ella. No es terriblemente difícil, pero sigue siendo terriblemente inconveniente si no es para aprender :)
Pekka
77
No se si llego tarde a la fiesta, pero un sitio bueno que da alternativas a las funciones de jQuery es youmightnotneedjquery.com
Ithil

Respuestas:

116

Puede verificar si element.classNamecoincide /\bthatClass\b/.
\bcoincide con un salto de palabra.

O puede usar la propia implementación de jQuery:

var className = " " + selector + " ";
if ( (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(" thatClass ") > -1 ) 

Para responder a su pregunta más general, puede mirar el código fuente de jQuery en github o en la fuente hasClassespecíficamente en este visor de fuentes .

SLaks
fuente
66
+1 para la implementación de jQuery (por haber buscado (¿es este inglés correcto?) Lo que rclassrealmente es))
Felix Kling
66
¿No \bcoincidiría con "thatClass-anotherClass"?
Matthew Crumley
3
solo para completar: rclass en versiones recientes es "/ [\ n \ t \ r] / g" (\ r agregado)
Felix Schwarz
44
@FelixSchwarz tiene razón, en jQuery actual se actualizó la expresión regular /[\t\r\n\f]/g. También es bueno mencionar que /\bclass\b/puede fallar para los nombres de clase con -signo menos (aparte de eso funciona bien), es por eso que la implementación de jQuery es mejor y más confiable. Por ejemplo: /\bbig\b/.test('big-text')devuelve verdadero en lugar de esperado falso.
Stano
996

Simplemente use classList.contains():

if (document.body.classList.contains('thatClass')) {
    // do some stuff
}

Otros usos de classList:

document.body.classList.add('thisClass');
// $('body').addClass('thisClass');

document.body.classList.remove('thatClass');
// $('body').removeClass('thatClass');

document.body.classList.toggle('anotherClass');
// $('body').toggleClass('anotherClass');

Soporte de navegador:

  • Chrome 8.0
  • Firefox 3.6
  • IE 10
  • Opera 11.50
  • Safari 5.1

classList Soporte de navegador

Damien
fuente
55
Esto no es compatible con IE8 . IE8 puede recuperarse .classListcomo una cadena, pero no reconocerá los métodos más modernos como.classList.contains()
iono
77
@iono En la descripción de la implementación de Element.classList del MDN hay una cuña que extiende el soporte para este comportamiento a IE8 developer.mozilla.org/en-US/docs/Web/API/Element/classList
James
3
Estoy de acuerdo con @AlexanderWigmore, esto fue increíblemente útil y simple.
Jacques Olivier
Vota esto. Esta es una forma mucho más limpia de consultar clases
usuario2190488
@SLaks esto debería actualizarse para ser la respuesta aceptada ya.
Umur Karagöz
35

El revestimiento más efectivo que

  • devuelve un valor booleano (en oposición a la respuesta de Orbling)
  • No devuelve un falso positivo al buscar thisClassun elemento que tieneclass="thisClass-suffix" .
  • es compatible con todos los navegadores hasta al menos IE6

function hasClass( target, className ) {
    return new RegExp('(\\s|^)' + className + '(\\s|$)').test(target.className);
}
raveren
fuente
28

El atributo que almacena las clases en uso es className .

Entonces puedes decir:

if (document.body.className.match(/\bmyclass\b/)) {
    ....
}

Si desea una ubicación que le muestre cómo jQuery hace todo, le sugiero:

http://code.jquery.com/jquery-1.5.js

Orbling
fuente
1
Excelente. ¡El matchatributo vuelve a ser útil! ¿Realmente jQuery hace algo más de lo que es posible en JavaScript? Si no, jQuery es solo un peso innecesario de shorthands.
animaacija
1
Esto también coincide myclass-something, como \bcoincide con el guión.
Marc Durdin
1
@animaacija Todas las bibliotecas / complementos de javascript son básicamente shorthands de javascript porque están construidas con javascript. La cosa es: las manos cortas siempre son necesarias. Nunca reinventes la rueda.
Edwin Stoteler
¡Esta es una gran solución!
Manuel Abascal
28

// 1. Use if for see that classes:

if (document.querySelector(".section-name").classList.contains("section-filter")) {
  alert("Grid section");
  // code...
}
<!--2. Add a class in the .html:-->

<div class="section-name section-filter">...</div>

StiveAZ
fuente
44
@greg_diesel: ¡no desalientes las respuestas! Nuevas soluciones para problemas comunes son más que bienvenidas.
raveren
2
@Raveren, aunque las nuevas soluciones a los viejos problemas son bienvenidas, esta respuesta en particular no aporta nada nuevo. Solo agrega ruido a esta pregunta.
Emile Bergeron el
1
@raveren Esta no es una solución nueva, es lo mismo que esta respuesta pero con menos información.
Financia la demanda de Mónica
13

función hasClass:

HTMLElement.prototype.hasClass = function(cls) {
    var i;
    var classes = this.className.split(" ");
    for(i = 0; i < classes.length; i++) {
        if(classes[i] == cls) {
            return true;
        }
    }
    return false;
};

Función addClass:

HTMLElement.prototype.addClass = function(add) {
    if (!this.hasClass(add)){
        this.className = (this.className + " " + add).trim();
    }
};

Función removeClass:

HTMLElement.prototype.removeClass = function(remove) {
    var newClassName = "";
    var i;
    var classes = this.className.replace(/\s{2,}/g, ' ').split(" ");
    for(i = 0; i < classes.length; i++) {
        if(classes[i] !== remove) {
            newClassName += classes[i] + " ";
        }
    }
    this.className = newClassName.trim();
};
Gawin
fuente
11

Utilizo una solución simple / mínima, una línea, navegador cruzado, y también funciona con navegadores heredados:

/\bmyClass/.test(document.body.className) // notice the \b command for whole word 'myClass'

Este método es excelente porque no requiere polyfills y si los usa paraclassList ello es mucho mejor en términos de rendimiento. Al menos para mi.

Actualización: hice un pequeño polyfill que es una solución completa que uso ahora:

function hasClass(element,testClass){
  if ('classList' in element) { return element.classList.contains(testClass);
} else { return new Regexp(testClass).exec(element.className); } // this is better

//} else { return el.className.indexOf(testClass) != -1; } // this is faster but requires indexOf() polyfill
  return false;
}

Para la manipulación de otra clase, vea el archivo completo aquí .

thednp
fuente
2
¿Este viaje sobre una clase de notmyClassHere?
Teepeemm
2
También puedes preguntar si tu clase no está allí y !/myClass/.test(document.body.className)notar el !símbolo.
thednp
1
No estoy hablando de negar la pregunta. Estoy pensando que su función devolverá incorrectamente verdadero si el nombre de la clase es thisIsmyClassHere.
Teepeemm
1
Solo suponía que eso es lo que preguntas, no entendí exactamente lo que necesitas, pero ¿lo has intentado y no pudo devolver verdadero / falso como debería?
thednp
2
Esto no es perfecto ya que no es una prueba de subcadenas. Por ejemplo, cuando document.body.className = 'myClass123', entonces /myClass/.test(document.body.className) devuelve verdadero ...
Zbigniew Wiadro
9

Una buena solución para esto es trabajar con classList y contiene.

Lo hice así:

... for ( var i = 0; i < container.length; i++ ) {
        if ( container[i].classList.contains('half_width') ) { ...

Entonces necesita su elemento y verifique la lista de las clases. ¡Si una de las clases es la misma que la que busca, devolverá verdadero si no, devolverá falso!

Bastian Fießinger
fuente
6

Use algo como:

Array.prototype.indexOf.call(myHTMLSelector.classList, 'the-class');
Alejandro Nanez
fuente
3
¿No es esto equivalente a myHTMLSelector.classList.indexOf('the-class')? ¿No quieres también >=0al final?
Teepeemm
55
¿Cuál es el punto de usar [].indexOfsi classListtiene un containsmétodo?
Oriol
@Teepeemm no. myHTMLSelector.classList.indexOf('the-class')devuelve el error que myHTMLSelector.classList.indexOf is not a functionporque myHTMLSelector.classListno es una matriz. Pero supongo que cuando se llama usando Array.prototypealguna conversión sucede. Esto puede ser compatible con navegadores antiguos, aunque containstiene muy buen soporte.
Ehsan88
4
if (document.body.className.split(/\s+/).indexOf("thatClass") !== -1) {
    // has "thatClass"
}
Alexandr Karbivnichiy
fuente
2

Esta función 'hasClass' funciona en IE8 +, FireFox y Chrome:

hasClass = function(el, cls) {
    var regexp = new RegExp('(\\s|^)' + cls + '(\\s|$)'),
        target = (typeof el.className === 'undefined') ? window.event.srcElement : el;
    return target.className.match(regexp);
}
manufosela
fuente
1

Bueno, todas las respuestas anteriores son bastante buenas, pero aquí hay una pequeña función simple que preparé. Funciona bastante bien

function hasClass(el, cn){
    var classes = el.classList;
    for(var j = 0; j < classes.length; j++){
        if(classes[j] == cn){
            return true;
        }
    }
}
j0hnstew
fuente
3
¿Cuál es el punto de iterar si classListtiene un containsmétodo?
Oriol
1

¿Qué opinas sobre este enfoque?

<body class="thatClass anotherClass"> </body>

var bodyClasses = document.querySelector('body').className;
var myClass = new RegExp("thatClass");
var trueOrFalse = myClass.test( bodyClasses );

https://jsfiddle.net/5sv30bhe/

Marian07
fuente
2
Creo que estás mezclando los nombres de tus variables (¿activo === myClass?). ¿Pero este enfoque no dará un falso positivo class="nothatClassIsnt"?
Teepeemm
0

Aquí está la forma más simple:

var allElements = document.querySelectorAll('*');
for (var i = 0; i < allElements.length; i++) {
    if (allElements[i].hasAttribute("class")) {
         //console.log(allElements[i].className);
         if (allElements[i].className.includes("_the _class ")) { 
              console.log("I see the class");
         }
    }
}
Comunidad Ans
fuente