Obtenga la lista de clases para el elemento con jQuery

657

¿Hay alguna manera en jQuery para recorrer o asignar a una matriz todas las clases que están asignadas a un elemento?

ex.

<div class="Lorem ipsum dolor_spec sit amet">Hello World!</div>

Buscaré una clase "especial" como en "dolor_spec" arriba. Sé que podría usar hasClass () pero el nombre de la clase real no necesariamente se conoce en ese momento.

Buggabill
fuente
Si no conoce el nombre de la clase en ese momento, lo que le impide usar hasClass (), ¿cómo piensa saber cuál es en la matriz?
doomspork
Estoy diseñando un formulario donde estoy haciendo una validación preliminar con jQuery. Estoy agregando la identificación del elemento de entrada a la lista de clases del error div si se genera uno. Entonces estoy haciendo posible hacer clic en el error div para enfocar el elemento de entrada errante. Este script se usará para más de una forma. Por lo tanto, no quiero codificar los identificadores en el script.
Buggabill
1
Bien, entiendo por qué no querrías codificar. Pero si se toma un momento para mirar el ejemplo de Redsquare, verá que debe codificar 'someClass' en el bloque if. De cualquier manera, podría lograr esto con una variable.
doomspork
En lugar de utilizar el atributo de clase, podría tener una variable de lista de errores dentro de su espacio de nombres que contuviera referencias DOM a los elementos con errores. Eliminando así la necesidad de extraer la lista de atributos cada vez, iterarla, encontrar el elemento DOM y enfocarlo.
doomspork

Respuestas:

732

Puede usarlo document.getElementById('divId').className.split(/\s+/);para obtener una matriz de nombres de clase.

Luego puedes iterar y encontrar el que deseas.

var classList = document.getElementById('divId').className.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
    if (classList[i] === 'someClass') {
        //do something
    }
}

jQuery realmente no te ayuda aquí ...

var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
    if (item === 'someClass') {
        //do something
    }
});
cuadrado rojo
fuente
44
eso es exactamente lo que habría hecho, pero no estaba seguro de si había una función de compilación en jQuery que le diera una colección de las clases.
Sander el
36
FYI: jQuery usa className.split (/ \ s + /)
kͩeͣmͮpͥ ͩ
70
Agregue un complemento jQuery usted mismo:$.fn.classList = function() {return this[0].className.split(/\s+/);};
ripper234
1
o entonces podrías: if ($.inArray("someclass",classList)>=0) { /* hasClass someclass*/ }
sambomartin
No es un experto en JavaScript aquí. ¿Me puede decir si dividir (/ \ s + /) es mejor que simplemente dividir ("")? Funciona igual para mí en FF23 / Chrome28 / IE8.
Roberto Linares
288

¿Por qué nadie tiene simplemente una lista?

$(element).attr("class").split(/\s+/);

EDITAR: Como señala @MarkAmery, no puede simplemente .split(' ')porque los nombres de clase pueden estar separados por cualquier tipo de espacio en blanco.

Dreamr OKelly
fuente
66
Esa es parte de la respuesta aceptada ... Necesitaba todas las clases que se aplicaron a un elemento.
Buggabill
54
¡Porque está mal! Las clases pueden estar separadas por cualquier tipo de espacio en blanco (por ejemplo, puede ajustar un atributo de clase larga en su HTML en varias líneas), pero esta respuesta no tiene en cuenta eso. Intente pegar $('<div class="foo bar baz">').attr("class").split(' ')en la consola de su navegador (hay un carácter de tabulación allí); obtendrá en ["foo", "bar baz"]lugar de la lista de clases correcta de ["foo", "bar", "baz"].
Mark Amery
2
@ MarkAmery tiene razón. Si tuviera un class="foo <lots of spaces here> bar", terminaría con una matriz con elementos de cadena vacíos.
Jacob van Lingen
44
Creo que en el 99% de los casos esta solución es efectiva, es decir, siempre que esté controlando el HTML. No se me ocurre ninguna razón por la que debamos admitir la posibilidad de pestañas o espacios múltiples entre los nombres de clase, incluso si los estándares HTML lo permiten.
Gordon Rouse
55
@GordonRouse un espacio extra que se arrastra en una lista de clases es bastante común, especialmente si algún tipo de lógica está escribiendo la lista de clases.
Eric
142

En los navegadores compatibles, puede usar la classListpropiedad de elementos DOM .

$(element)[0].classList

Es un objeto tipo matriz que enumera todas las clases que tiene el elemento.

Si necesita admitir versiones antiguas del navegador que no admitan la classListpropiedad, la página MDN vinculada también incluye una cuña, aunque incluso la cuña no funcionará en las versiones de Internet Explorer por debajo de IE 8.

Pehmolelu
fuente
Respuesta limpia y no reinventa la rueda.
Marco Sulla
@Marco Sulla: esto tiene una deficiencia además del soporte en software obsoleto. .classListno es una matriz verdadera, y métodos como .indexOf(⋯)no funcionan en ella. Es solo un "objeto tipo matriz", mientras que .className.split(/\s+/).indexOf(⋯)(de la respuesta aceptada) funciona.
Incnis Mrsi
Puede convertir fácilmente cualquier iterable a un Arrayuso [...iterable]oArray.from(iterable)
Marco Sulla
142

Aquí hay un complemento jQuery que devolverá una matriz de todas las clases que los elementos coincidentes tienen

;!(function ($) {
    $.fn.classes = function (callback) {
        var classes = [];
        $.each(this, function (i, v) {
            var splitClassName = v.className.split(/\s+/);
            for (var j = 0; j < splitClassName.length; j++) {
                var className = splitClassName[j];
                if (-1 === classes.indexOf(className)) {
                    classes.push(className);
                }
            }
        });
        if ('function' === typeof callback) {
            for (var i in classes) {
                callback(classes[i]);
            }
        }
        return classes;
    };
})(jQuery);

Úselo como

$('div').classes();

En tu caso vuelve

["Lorem", "ipsum", "dolor_spec", "sit", "amet"]

También puede pasar una función al método que se llamará en cada clase

$('div').classes(
    function(c) {
        // do something with each class
    }
);

Aquí hay un jsFiddle que configuré para demostrar y probar http://jsfiddle.net/GD8Qn/8/

Javascript Minificado

;!function(e){e.fn.classes=function(t){var n=[];e.each(this,function(e,t){var r=t.className.split(/\s+/);for(var i in r){var s=r[i];if(-1===n.indexOf(s)){n.push(s)}}});if("function"===typeof t){for(var r in n){t(n[r])}}return n}}(jQuery);
Será
fuente
Ajuste perfecto para FullCalendar al copiar clases en el atributo className de un evento.
Dan Power
78

Deberías probar este:

$("selector").prop("classList")

Devuelve una matriz de todas las clases actuales del elemento.

P.Petkov
fuente
esto es mucho más claro que la respuesta aceptada, ¿hay alguna razón para no usar este método?
RozzA
55
Pues no lo se. Pero esta es la forma correcta de obtener propiedades del elemento DOM. Y "classList" es una propiedad que le brinda una matriz de clases css aplicadas al elemento.
P.Petkov
@RozzA ¿Quizás no estaba disponible en ese entonces? Pero diría que este es el método más apropiado a partir de ahora, a menos que no use jQuery, donde un simple .classListes la solución: solo debe prestar atención a las inconsistencias y / o la falta de soporte del navegador ...
Dennis98
@ Dennis98 buena llamada, a veces se me olvida cuán rápidamente han aparecido nuevas funciones recientemente. También he hecho simplemente js .classList, funciona bastante bien en los navegadores modernos
RozzA
1
Tenga en cuenta que la classListpropiedad no funciona en IE 10/11 para elementos SVG (aunque funciona para elementos HTML). Ver developer.mozilla.org/en-US/docs/Web/API/Element/classList
Métoule
17
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){

     //do something

});
Carlisle
fuente
7

Actualizar:

Como @Ryan Leonard señaló correctamente, mi respuesta realmente no soluciona el punto que hice yo mismo ... Necesita recortar y eliminar espacios dobles con (por ejemplo) string.replace (/ + / g, "") .. O puede dividir el.className y luego eliminar valores vacíos con (por ejemplo) arr.filter (booleano).

const classes = element.className.split(' ').filter(Boolean);

o más moderno

const classes = element.classList;

Antiguo:

Con todas las respuestas dadas, nunca debe olvidarse del usuario .trim () (o $ .trim ())

Debido a que las clases se agregan y eliminan, puede suceder que haya múltiples espacios entre la cadena de clase ... por ejemplo, 'clase1 clase2 clase3'

Esto se convertiría en ['class1', 'class2', '', '', '', 'class3'] ..

Cuando usa trim, todos los espacios múltiples se eliminan.

DutchKevv
fuente
2
Esto es incorrecto (y no es una respuesta). Tanto String.trim () como $ .trim () eliminan todos los espacios en blanco iniciales y finales, y dejan solo el resto de la cadena. jsconsole.com /?% 22% 20% 20a% 20% 20b% 20% 20% 22.trim ()
Ryan Leonard
¿Has echado un vistazo a las respuestas? Todas las soluciones nativas de JS no verificaron los espacios en blanco iniciales y finales, dando así una lista de clases defectuosa, ya que habría clases vacías en la matriz ... jQuery hace lo mismo internamente con trim cuando lee las clases
DutchKevv
2
Vi las otras respuestas, y estoy de acuerdo en que el espacio en blanco debe eliminarse entre los nombres de clase. Estaba señalando que a) este debería ser un comentario sobre las otras soluciones, ya que no es una respuesta completa b) .trim () no elimina múltiples espacios para lograr lo que necesita.
Ryan Leonard
1
De hecho, tienes toda la razón ... Perdón por mi comentario rápido ... No elimina los espacios entre ... s.trim (). Replace (/ + / g, "") o se necesitaría algo para eliminar todos los espacios múltiples entre clases ... Además de eso, el.classList es casi ampliamente compatible, lo soluciono todo, supongo ..
DutchKevv
1
no hay problema. Felizmente votado, ¡ .classListes un enfoque mucho más limpio!
Ryan Leonard el
7
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
alexche8
fuente
2
Este es un horrible abuso de .map; utilícelo .eachsi no necesita .mapel valor de retorno. La división en espacios en lugar de cualquier espacio en blanco también está rota: vea mi comentario en stackoverflow.com/a/10159062/1709587 . Incluso si ninguno de estos puntos fuera cierto, esto no agrega nada nuevo a la página. -1!
Mark Amery
3

¿Podría esto también ayudarte? He usado esta función para obtener clases del elemento childern.

function getClickClicked(){
    var clickedElement=null;
    var classes = null;<--- this is array
    ELEMENT.on("click",function(e){//<-- where element can div,p span, or any id also a class
        clickedElement = $(e.target);
        classes = clickedElement.attr("class").split(" ");
        for(var i = 0; i<classes.length;i++){
            console.log(classes[i]);
        }
        e.preventDefault();
    });
}

En su caso, desea la clase doler_ipsum que puede hacer así ahora calsses[2];.

Fénix
fuente
2

Gracias por esto: estaba teniendo un problema similar, ya que estoy tratando de relacionar programáticamente los objetos con los nombres de clase jerárquicos, aunque esos nombres no sean necesariamente conocidos por mi script.

En mi secuencia de comandos, quiero una <a>etiqueta para activar / desactivar el texto de ayuda dando la <a>etiqueta [some_class]más la clase de toggle, y luego dando su clase de texto de ayuda [some_class]_toggle. Este código está encontrando con éxito los elementos relacionados usando jQuery:

$("a.toggle").toggle(function(){toggleHelp($(this), false);}, function(){toggleHelp($(this), true);});

function toggleHelp(obj, mode){
    var classList = obj.attr('class').split(/\s+/);
    $.each( classList, function(index, item){
    if (item.indexOf("_toggle") > 0) {
       var targetClass = "." + item.replace("_toggle", "");
       if(mode===false){$(targetClass).removeClass("off");}
       else{$(targetClass).addClass("off");}
    }
    });
} 
Alan L.
fuente
Gracias Alan, estoy haciendo algo similar, me sorprende que no haya una forma más sencilla de hacerlo.
Eric Kigathi
- 1 - tl; dr, sale en una tangente no directamente relevante a la pregunta.
Mark Amery
2

Prueba esto. Esto le dará los nombres de todas las clases de todos los elementos del documento.

$(document).ready(function() {
var currentHtml="";
$('*').each(function() {
    if ($(this).hasClass('') === false) {
        var class_name = $(this).attr('class');
        if (class_name.match(/\s/g)){
            var newClasses= class_name.split(' ');
            for (var i = 0; i <= newClasses.length - 1; i++) {
                if (currentHtml.indexOf(newClasses[i]) <0) {
                    currentHtml += "."+newClasses[i]+"<br>{<br><br>}<br>"
                }
            }
        }
        else
        {
            if (currentHtml.indexOf(class_name) <0) {
                currentHtml += "."+class_name+"<br>{<br><br>}<br>"
            }
        }
    }
    else
    {
        console.log("none");
    }
});
$("#Test").html(currentHtml);

});

Aquí está el ejemplo de trabajo: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/

Sumit Raju
fuente
1

Tuve un problema similar, para un elemento de tipo de imagen. Necesitaba verificar si el elemento era de cierta clase. Primero probé con:

$('<img>').hasClass("nameOfMyClass"); 

pero obtuve un buen "esta función no está disponible para este elemento".

Luego inspeccioné mi elemento en el explorador DOM y vi un atributo muy bueno que podía usar: className. Contenía los nombres de todas las clases de mi elemento separadas por espacios en blanco.

$('img').className // it contains "class1 class2 class3"

Una vez que obtenga esto, simplemente divida la cadena como de costumbre.

En mi caso esto funcionó:

var listOfClassesOfMyElement= $('img').className.split(" ");

Supongo que esto funcionaría con otros tipos de elementos (además de img).

Espero eso ayude.

eva
fuente
0

javascript proporciona un atributo classList para un elemento de nodo en dom. Simplemente usando

  element.classList

devolverá un objeto de forma

  DOMTokenList {0: "class1", 1: "class2", 2: "class3", length: 3, item: function, contains: function, add: function, remove: function…}

El objeto tiene funciones como contiene, agrega, elimina, que puedes usar

Anuj J
fuente
Duplicado inferior de stackoverflow.com/a/5457148/1709587 que se publicó 3 años antes que usted; -1.
Mark Amery
-3

Un poco tarde, pero el uso de la función extend () le permite llamar a "hasClass ()" en cualquier elemento, por ejemplo:
var hasClass = $('#divId').hasClass('someClass');

(function($) {
$.extend({
    hasClass: new function(className) {
        var classAttr = $J(this).attr('class');
        if (classAttr != null && classAttr != undefined) {
            var classList = classAttr.split(/\s+/);
            for(var ix = 0, len = classList.length;ix < len;ix++) {
                if (className === classList[ix]) {
                    return true;
                }
            }
        }
        return false;
    }
}); })(jQuery);
gesellix
fuente
10
Esa no era la pregunta.
Tomás
55
Además, jQuery ha incorporado esta función desde la versión 1.2.
Andrew
-3

La pregunta es para qué está diseñado Jquery.

$('.dolor_spec').each(function(){ //do stuff

¿Y por qué nadie ha dado .find () como respuesta?

$('div').find('.dolor_spec').each(function(){
  ..
});

También hay classList para navegadores que no son IE:

if element.classList.contains("dolor_spec") {  //do stuff
john ktejik
fuente
3
- 1; entre otros problemas, sus dos primeros fragmentos de código no están relacionados con la pregunta formulada y su fragmento final es un error de sintaxis.
Mark Amery
-4

Aquí tienes, solo modificó la respuesta de readsquare para devolver una matriz de todas las clases:

function classList(elem){
   var classList = elem.attr('class').split(/\s+/);
    var classes = new Array(classList.length);
    $.each( classList, function(index, item){
        classes[index] = item;
    });

    return classes;
}

Pase un elemento jQuery a la función, para que una llamada de muestra sea:

var myClasses = classList($('#myElement'));
Gregra
fuente
3
¿Por qué recorrer en iteración la matriz classList, agregar todos los elementos a la matriz de clases y devolver la matriz de clases? Solo devolver la classList debería hacer el mismo truco, ¿verdad?
Martijn
No Como nos referimos a una situación en la que hay muchas clases para el mismo elemento. Si fue tan fácil, no estábamos aquí en este hilo :)
Gregra
8
Este hilo se trata de devolver una lista de clases, y simplemente regresar lo $(elem).attr('class').split(/\s+/)hace. Tal vez me estoy equivocando, pero no veo ninguna razón para recorrer una colección, copiar el contenido a una nueva colección y devolver esa nueva colección.
Martijn
-4

Sé que esta es una vieja pregunta, pero aún así.

<div id="specId" class="Lorem ipsum dolor_spec sit amet">Hello World!</div>

var className=".dolor_spec" //dynamic

Si quieres manipular un elemento

$("#specId"+className).addClass('whatever');

Si quieres comprobar si el elemento tiene clase

 $("#specId"+className).length>0

si varias clases

//if you want to select ONE of the classes
var classNames = ['.dolor_spec','.test','.test2']
$("#specId"+classNames).addClass('whatever');
$("#specId"+classNames).length>0
//if you want to select all of the classes
var result = {className: ""};
classNames.forEach(function(el){this.className+=el;},result);
var searchedElement= $("#specId"+result.className);
searchedElement.addClass('whatever');
searchedElement.length>0
dulebov.artem
fuente
1
Ninguno de estos fragmentos aborda la pregunta formulada en absoluto; -1.
Mark Amery