JQuery .hasClass para múltiples valores en una declaración if

81

Tengo una simple declaración if como tal:

if ($('html').hasClass('m320')) {

// do stuff 

}

Esto funciona como se esperaba. Sin embargo, quiero agregar más clases para if statementverificar si alguna de las clases está presente en la <html>etiqueta. Lo necesito para que no sean todos, sino solo la presencia de al menos una clase, pero puede ser más.

Mi caso de uso es que tengo clases (por ejemplo m320, m768) agregadas para varios anchos de ventana, por lo que solo quiero ejecutar cierto Jquery si es un ancho específico (clase).

Esto es lo que he probado hasta ahora:

1.

if ($('html').hasClass('m320', 'm768')) {

// do stuff 

}

2.

if ($('html').hasClass('m320')) || ($('html').hasClass('m768')) {

 // do stuff 

}

3.

 if ($('html').hasClass(['m320', 'm768'])) {

 // do stuff 

    }

Sin embargo, ninguno de estos parece funcionar. No estoy seguro de qué estoy haciendo mal, pero lo más probable es que mi sintaxis o estructura.

Danny Englander
fuente
1
En lugar de adivinar cómo funciona una API, debería leer los documentos. api.jquery.com/hasclass Además, debe tener la consola de desarrollador a mano / abierta durante el desarrollo.
acantilados de la locura
posible duplicado de jQuery hasClass () - comprobar si hay más de una clase
Stephan Weinhold

Respuestas:

74

Acaba de tener algunos paréntesis desordenados en su segundo intento.

var $html = $("html");

if ($html.hasClass('m320') || $html.hasClass('m768')) {

  // do stuff 

}
James Montagne
fuente
6
Realmente debería almacenar $('html')en caché en una variable en lugar de tener que buscarla varias veces.
epascarello
1
@epascarello Muy cierto, actualizando la respuesta para la posteridad.
James Montagne
161

Podrías usar en is()lugar de hasClass():

if ($('html').is('.m320, .m768')) { ... }
elclanrs
fuente
3
Sí, hasClass()es probablemente más rápido, pero is()es mucho más conveniente la mayor parte del tiempo
elclanrs
1
Por cierto, aquí podemos ver los puntos de referencia de rendimiento para is()yhasClass()
Jignesh Gohel
1
Así que es mucho más lento, pero también super rápido en general. Si solo se escanean algunos elementos, parece que no es un gran problema para un código mucho más limpio.
jerclarke
27

Para divertirme, escribí un pequeño método de complemento de jQuery que verificará cualquiera de los múltiples nombres de clase:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        if (this.hasClass(arguments[i])) {
            return true;
        }
    }
    return false;
}

Luego, en su ejemplo, podría usar esto:

if ($('html').hasAnyClass('m320', 'm768')) {

// do stuff 

}

Puede pasar tantos nombres de clases como desee.


Aquí hay una versión mejorada que también le permite pasar varios nombres de clases separados por un espacio:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        var classes = arguments[i].split(" ");
        for (var j = 0; j < classes.length; j++) {
            if (this.hasClass(classes[j])) {
                return true;
            }
        }
    }
    return false;
}

if ($('html').hasAnyClass('m320 m768')) {
    // do stuff 
}

Demostración de trabajo: http://jsfiddle.net/jfriend00/uvtSA/

jfriend00
fuente
Excelente, esto funciona bien ... ¡también en varios navegadores! Probado en FF e IE.
crmpicco
Hice una pequeña modificación para que se ajuste a las convenciones de jQuery para .addClass y .removeClass (). ( stackoverflow.com/a/14887517/170456 )
CyberMonk
25

Esta puede ser otra solución:

if ($('html').attr('class').match(/m320|m768/)) {  
  // do stuff   
}  

según jsperf.com, también es bastante rápido.

Kolja
fuente
¡Muy bonito, mucho más rápido!
Philip
9
Esto también coincidirá con la clase 'ZZZm320WWW' y similares. Intente ... emparejar (/ \ b (m320 | m768) \ b /) donde las \ b coinciden con el principio y el final de una palabra.
Juan Lanús
solo para dar seguimiento (7 años después :)). Esto funciona muy bien, pero si el elemento html que define no tiene ninguna clase, disparará un error "No se puede leer la propiedad" coincidente "de indefinida". Si este es el caso, pruebe si el elemento tiene el atributo 'clase' (o pruebe para asegurarse de que el atributo 'clase' no sea nulo).
Sanya
5

Para cualquiera que se pregunte acerca de algunos de los diferentes aspectos de rendimiento con todas estas opciones diferentes, he creado un caso de jsperf aquí: jsperf

En resumen, usando element.hasClass('class') es lo más rápido.

La siguiente mejor apuesta es usar elem.hasClass('classA') || elem.hasClass('classB') . Una nota sobre este: ¡el orden importa! Si es más probable que se encuentre la clase 'classA', ¡indíquela primero! Las declaraciones de condición OR regresan tan pronto como se cumple una de ellas.

El peor rendimiento con diferencia fue el uso element.is('.class') .

También se enumeran en jsperf la función de CyberMonk y la solución de Kolja .

Ryan Steffer
fuente
¡Muy interesante! No tenía idea de jsperf. Gracias por ilustrar todas las diferentes variaciones.
Danny Englander
3

Aquí hay una ligera variación en la respuesta ofrecida por jfriend00:

$.fn.hasAnyClass = function() {
    var classes = arguments[0].split(" ");
    for (var i = 0; i < classes.length; i++) {
        if (this.hasClass(classes[i])) {
            return true;
        }
    }
    return false;
}

Permite el uso de la misma sintaxis que .addClass () y .removeClass (). Por ejemplo, .hasAnyClass('m320 m768') necesita prueba de balas, por supuesto, ya que asume al menos un argumento.

CyberMonk
fuente
0
var classes = $('html')[0].className;

if (classes.indexOf('m320') != -1 || classes.indexOf('m768') != -1) {
    //do something
}
adeneo
fuente
1
Si va a hacer eso, ¿por qué molestarse en usar jquery para obtener el elemento?
James Montagne
Bueno, no lo haría, pero ¿al menos solo recibe las clases una vez? Parecía tan aburrido sin un poco de jQuery, ¡así que reemplacé getElementsByTagName con un poco de magia jQ solo para ti!
adeneo
0

El método hasClass aceptará una matriz de nombres de clase como argumento, puede hacer algo como esto:

$(document).ready(function() {
function filterFilesList() {
    var rows = $('.file-row');
    var checked = $("#filterControls :checkbox:checked");

    if (checked.length) {
        var criteriaCollection = [];

        checked.each(function() {
            criteriaCollection.push($(this).val());
        });

        rows.each(function() {
            var row = $(this);
            var rowMatch = row.hasClass(criteriaCollection);

            if (rowMatch) {
                row.show();
            } else {
                row.hide(200);
            }
        });
    } else {
        rows.each(function() {
            $(this).show();
        });
    }
}

    $("#filterControls :checkbox").click(filterFilesList);
    filterFilesList();
});
Ron Sims II
fuente
0

Esto es en caso de que necesite ambas clases presentes. Para cualquiera o la lógica, simplemente use ||

$('el').hasClass('first-class') || $('el').hasClass('second-class')

Siéntase libre de optimizar según sea necesario

qwerty_igor
fuente
1
Esto está mal. El primer ejemplo que dio funciona solo porque el método tiene una desinfección deficiente de la entrada y piensa que toda la cadena es un nombre de clase. No funciona si las clases están en un orden diferente o no están una al lado de la otra. Ver ejemplo: jsfiddle.net/0d57ekty
MightyPork
@MightyPork gracias por comprobarlo. tienes razón, solo debe usarse por clase
qwerty_igor
-1

Prueba esto:

if ($('html').hasClass('class1 class2')) {

// do stuff 

}
Robert Łoziński
fuente
¡Bienvenido a Stack Overflow! Agregue una explicación de por qué este código ayuda al OP. Esto ayudará a proporcionar una respuesta de la que los futuros espectadores puedan aprender. Consulte Cómo responder para obtener más información.
Heretic Monkey