Obter lista de classes para o elemento com jQuery

657

Existe uma maneira no jQuery de percorrer ou atribuir a uma matriz todas as classes atribuídas a um elemento?

ex.

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

Vou procurar uma classe "especial" como em "dolor_spec" acima. Eu sei que eu poderia usar hasClass (), mas o nome da classe real pode não ser necessariamente conhecido no momento.

Buggabill
fonte
Se você não souber o nome da classe no momento, impedindo o uso de hasClass (), como pretende saber qual é o array?
Doomspork 04/08/09
Estou criando um formulário no qual estou fazendo alguma validação preliminar com o jQuery. Estou acrescentando o ID do elemento de entrada à lista de classes do erro div, se um for gerado. Estou possibilitando clicar na div de erro para focar o elemento de entrada incorreto. Este script será usado para mais de um formulário. Portanto, não quero codificar os IDs no script.
Buggabill 04/08/09
1
Certo, entendo por que você não gostaria de codificar. Mas se você parar um momento para examinar o exemplo do redsquare, verá que precisa codificar 'someClass' no bloco if. De qualquer maneira, você pode conseguir isso com uma variável.
Doomspork 04/08/09
Em vez de usar o atributo de classe, você poderia ter uma variável da lista de erros dentro do seu espaço para nome que continha referências DOM aos elementos com erros. Assim, eliminando a necessidade de puxar a lista de atributos a cada vez, itere-a, encontre o elemento DOM e concentre-o.
Doomspork 04/08/09

Respostas:

732

Você pode usar document.getElementById('divId').className.split(/\s+/);para obter uma matriz de nomes de classe.

Em seguida, você pode iterar e encontrar o que deseja.

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

jQuery realmente não ajuda você aqui ...

var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
    if (item === 'someClass') {
        //do something
    }
});
quadrado vermelho
fonte
4
isso é exatamente o que eu teria feito, mas não tinha certeza se havia uma função de compilação na jQuery que fornecia uma coleção das classes.
Sander
36
FYI: o jQuery usa className.split (/ \ s + /)
kͩeͣmͮpͥ
70
Adicionar um plugin jQuery-se:$.fn.classList = function() {return this[0].className.split(/\s+/);};
ripper234
1
ou então você pode: if ($.inArray("someclass",classList)>=0) { /* hasClass someclass*/ }
sambomartin 19/10/12
Não é um especialista em javascript aqui. Você pode me dizer se dividir (/ \ s + /) é melhor do que simplesmente dividir ("")? Funciona da mesma forma para mim no FF23 / Chrome28 / IE8.
Roberto Linares
288

Por que ninguém simplesmente listou.

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

EDIT: Como o @MarkAmery aponta, você não pode apenas .split(' ')porque os nomes das classes podem ser separados por qualquer tipo de espaço em branco.

Dreamr OKelly
fonte
6
Isso faz parte da resposta aceita ... Eu precisava de todas as classes que foram aplicadas a um elemento.
Buggabill
54
Porque está errado! As classes podem ser separadas por qualquer tipo de espaço em branco (por exemplo, você pode agrupar um atributo de classe longo em seu HTML em várias linhas), mas essa resposta não explica isso. Tente colar $('<div class="foo bar baz">').attr("class").split(' ')no console do navegador (há um caractere de tabulação); você receberá em ["foo", "bar baz"]vez da lista correta de classes de ["foo", "bar", "baz"].
Mark Amery
2
@MarkAmery está certo. Se você tivesse um class="foo <lots of spaces here> bar", você acabaria com uma matriz com elementos de string vazios.
Jacob van Lingen
4
Eu acho que em 99% dos casos essa solução é eficaz, ou seja, desde que você esteja controlando o HTML. Não consigo pensar em nenhuma razão para precisarmos suportar a possibilidade de guias ou vários espaços entre os nomes das classes, mesmo que os padrões HTML permitam isso.
Gordon Rouse
5
@GordonRouse Um espaço extra entrando em uma lista de classes é bastante comum, especialmente se algum tipo de lógica estiver escrevendo a lista de classes.
Eric
142

Nos navegadores de suporte, você pode usar a classListpropriedade dos elementos DOM .

$(element)[0].classList

É um objeto de matriz que lista todas as classes que o elemento possui.

Se você precisar oferecer suporte a versões antigas de navegadores que não suportam a classListpropriedade, a página MDN vinculada também incluirá um calço para ela - embora mesmo o calço não funcione nas versões do Internet Explorer abaixo do IE 8.

Pehmolelu
fonte
Resposta limpa e não reinventa a roda.
Marco Sulla
@Marco Sulla: isso realmente tem uma outra falha que não o suporte a software obsoleto. .classListnão é uma matriz verdadeira e métodos como esse .indexOf(⋯)não funcionam. É apenas um "objeto parecido com um array", enquanto .className.split(/\s+/).indexOf(⋯)(a partir da resposta aceita) funciona.
Incnis Mrsi 28/01
Você pode facilmente converter qualquer iterável para um Arrayuso [...iterable]ouArray.from(iterable)
Marco Sulla
142

Aqui está um plugin jQuery que retornará uma matriz de todas as classes que os elementos correspondentes possuem

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

Use-o como

$('div').classes();

No seu caso retorna

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

Você também pode passar uma função para o método a ser chamado em cada classe

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

Aqui está um jsFiddle que eu configurei para demonstrar e testar http://jsfiddle.net/GD8Qn/8/

Javascript reduzido

;!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);
Vai
fonte
Ajuste perfeito para o FullCalendar ao copiar classes para o atributo className de um evento.
Dan Power
78

Você deve tentar este:

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

Retorna uma matriz de todas as classes atuais do elemento.

P.Petkov
fonte
isso é muito mais claro que a resposta aceita, existe alguma razão para não usar esse método?
RozzA
5
Bem, eu não sei. Mas esta é a maneira correta de obter propriedade do elemento DOM. E "classList" é uma propriedade que fornece uma matriz de classes css aplicadas ao elemento.
P.Petkov
@RozzA Talvez não estivesse disponível na época? Mas eu diria que este é o método mais apropriado a partir de agora, a menos que você não use o jQuery, onde .classLista solução é simples - você só precisa prestar atenção às inconsistências e / ou à falta de suporte ao navegador.
Dennis98
@ Dennis98 boa chamada, às vezes esqueço a rapidez com que novos recursos foram lançados recentemente. Também fiz js simples .classListque funciona muito bem em navegadores modernos
ROZZA
1
Observe que a classListpropriedade não funciona no IE 10/11 para elementos SVG (embora funcione para elementos HTML). Veja developer.mozilla.org/pt-BR/docs/Web/API/Element/classList
Métoule
17
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){

     //do something

});
Carlisle
fonte
7

Atualizar:

Como @Ryan Leonard apontou corretamente, minha resposta realmente não corrige o que eu disse ... Você precisa aparar e remover espaços duplos com (por exemplo) string.replace (/ + / g, "") .. Ou você pode dividir o el.className e remover valores vazios com (por exemplo) arr.filter (booleano).

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

ou mais moderno

const classes = element.classList;

Velho:

Com todas as respostas fornecidas, você nunca deve esquecer do usuário .trim () (ou $ .trim ())

Como as classes são adicionadas e removidas, pode acontecer que haja vários espaços entre as strings da classe. Por exemplo, 'class1 class2 class3' ..

Isso se transformaria em ['class1', 'class2', '', '', '', 'class3'] ..

Quando você usa o recorte, todos os vários espaços são removidos.

DutchKevv
fonte
2
Isso está incorreto (e não é uma resposta). Tanto String.trim () quanto $ .trim () removem todos os espaços em branco à esquerda e à direita e deixam o restante da string em paz. jsconsole.com /?% 22% 20% 20a% 20% 20b% 20% 20% 22.trim ()
Ryan Leonard
Você já deu uma olhada nas respostas? Todas as soluções nativas JS não verificar para esquerda e à direita espaços em branco, dando, assim, uma lista de classe com defeito, pois não haveria aulas vazias na matriz .. jQuery faz o mesmo internamente com guarnição quando lê as classes
DutchKevv
2
Eu vi as outras respostas e concordo que o espaço em branco deve ser removido entre os nomes das classes. Eu estava apontando que a) isso deve ser um comentário sobre as outras soluções, pois não é uma resposta completa b) .trim () não remove vários espaços para alcançar o que você precisa.
Ryan Leonard
1
Você está totalmente correto de verdade ... Desculpe pelo meu comentário rápido. Ele não remove os espaços entre ... s.trim (). Replace (/ + / g, "") ou seria necessário algo para remover todos os múltiplos espaços entre as classes .. Junto a isso, el.classList é quase amplamente suportado, fixando tudo suponho ..
DutchKevv
1
sem problema algum. Felizmente votado, .classListé uma abordagem muito mais limpa!
Ryan Leonard
7
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
alexche8
fonte
2
Este é um abuso horrível de .map; use .eachse você não precisar .mapdo valor de retorno. Dividir os espaços em vez de qualquer espaço em branco também está quebrado - veja meu comentário em stackoverflow.com/a/10159062/1709587 . Mesmo se nenhum desses pontos for verdadeiro, isso não adiciona nada de novo à página. -1!
Mark Amery
3

Isso pode ajudá-lo também. Eu usei essa função para obter classes de 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();
    });
}

No seu caso, você quer a classe doler_ipsum que você pode fazer assim agora calsses[2];.

Fénix
fonte
2

Obrigado por isso - eu estava tendo um problema semelhante, pois estou tentando relacionar objetos de forma programática com nomes de classes hierárquicos, mesmo que esses nomes não sejam necessariamente conhecidos pelo meu script.

No meu script, quero que uma <a>tag ative / desative o texto de ajuda, atribuindo a <a>tag [some_class]mais a classe de togglee, em seguida, dando a ela o texto de ajuda da classe [some_class]_toggle. Este código está localizando com sucesso os elementos relacionados usando o 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.
fonte
Obrigado Alan, estou fazendo algo semelhante, estou surpreso por não haver uma maneira mais simples de fazer isso.
Eric Kigathi 31/01
- 1 - tl; dr, dispara em uma tangente não diretamente relevante para a questão.
Mark Amery
2

Tente isto. Isso fornecerá os nomes de todas as classes de todos os elementos do 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);

});

Aqui está o exemplo de trabalho: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/

Sumit Raju
fonte
1

Eu tive um problema semelhante, para um elemento do tipo imagem. Eu precisava verificar se o elemento era de uma determinada classe. Primeiro eu tentei com:

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

mas recebi uma boa "esta função não está disponível para este elemento".

Depois, inspecionei meu elemento no explorador DOM e vi um atributo muito bom que eu poderia usar: className. Ele continha os nomes de todas as classes do meu elemento separadas por espaços em branco.

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

Depois de conseguir isso, basta dividir a corda como de costume.

No meu caso, isso funcionou:

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

Estou assumindo que isso funcionaria com outros tipos de elementos (além de img).

Espero que ajude.

eva
fonte
0

javascript fornece um atributo classList para um elemento de nó no dom. Simplesmente usando

  element.classList

retornará um objeto de formulário

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

O objeto possui funções como contém, adiciona e remove as quais você pode usar

Anuj J
fonte
Duplicação inferior de stackoverflow.com/a/5457148/1709587, publicada 3 anos antes de você; -1.
Mark Amery
-3

Um pouco atrasado, mas o uso da função extend () permite chamar "hasClass ()" em qualquer elemento, por exemplo:
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
fonte
10
Essa não era a questão.
Tomas
5
Além disso, o jQuery possui essa função integrada desde a versão 1.2.
Andrew
-3

A questão é o que o Jquery foi projetado para fazer.

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

E por que ninguém deu .find () como resposta?

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

Também há classList para navegadores que não sejam o IE:

if element.classList.contains("dolor_spec") {  //do stuff
john ktejik
fonte
3
1; entre outros problemas, seus dois primeiros trechos de código não estão relacionados à pergunta e seu trecho final é um erro de sintaxe.
Mark Amery
-4

Aqui está, apenas a resposta do readquare ajustada para retornar uma matriz de todas as classes:

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

Passe um elemento jQuery para a função, para que uma chamada de amostra seja:

var myClasses = classList($('#myElement'));
Gregra
fonte
3
Por que iterar pela matriz classList, adicionar todos os elementos à matriz de classes e retornar a matriz de classes? Apenas retornar a classList deve fazer o mesmo truque, certo?
Martijn
Não. Como estamos nos referindo a uma situação em que existem muitas classes para o mesmo elemento. Se fosse tão fácil, não estávamos aqui sobre este tópico :)
Gregra
8
Este tópico trata de retornar uma lista de classes e simplesmente retornar $(elem).attr('class').split(/\s+/)isso. Talvez eu esteja enganado, mas não vejo nenhum motivo para percorrer uma coleção, copiar o conteúdo para uma nova coleção e retornar essa nova coleção.
Martijn
-4

Eu sei que esta é uma pergunta antiga, mas ainda assim.

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

var className=".dolor_spec" //dynamic

Se você deseja manipular o elemento

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

Se você deseja verificar se o elemento tem classe

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

se várias classes

//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
fonte
1
Nenhum desses trechos aborda a pergunta feita; -1.
22815 Mark Amery