jQuery como encontrar um elemento baseado em um valor de atributo de dados?

994

Eu tenho o seguinte cenário:

var el = 'li';

e há cinco <li>na página, cada um com um data-slide=numberatributo (número sendo 1,2,3,4,5, respectivamente) .

Agora, preciso encontrar o número do slide atualmente ativo, mapeado var current = $('ul').data(current);e atualizado a cada alteração do slide.

Até o momento, minhas tentativas não tiveram êxito, tentando construir o seletor que corresponderia ao slide atual:

$('ul').find(el+[data-slide=+current+]);

não corresponde / retorna nada…

O motivo pelo qual não posso codificar a lipeça é que essa é uma variável acessível ao usuário que pode ser alterada para um elemento diferente, se necessário, portanto nem sempre é uma li.

Alguma idéia do que estou perdendo?

Jannis
fonte
6
você tem certeza de que dentro do seu .find(el+[data-slide=+current+]);código está escrito? parece que você perdeu algumas citações para"[data-slide]"
xandy 16/11
Isso foi o que me ajudou a selecionar todos os atributos de dados (independentemente do valor): $('*[data-slide]')Você pode usá-lo com, por exemplo$('*[data-slide]').each( function() { ... });
Kai Noack

Respostas:

1481

Você deve injetar o valor de currentem um seletor de Igual a Atributo :

$("ul").find(`[data-slide='${current}']`)

Para ambientes JavaScript mais antigos ( ES5 e versões anteriores):

$("ul").find("[data-slide='" + current + "']"); 
Frédéric Hamidi
fonte
8
@ Jannis, você poderia fazer $("ul").find(el + "[data-slide='" + current +"']");.
Frédéric Hamidi
7
@ c00lryguy, a interface do usuário do jQuery define uma e existem implementações independentes . Parece que as tentativas de adicioná-lo ao jQuery Core foram rejeitadas . Duas vezes .
Frédéric Hamidi
6
esta resposta em um borne semelhante tem um exemplo da função de filtro
drzaus
77
Eu me preocupo que isso não funcione se os dados forem adicionados via função jQuery .data (...), pois isso nem sempre renderiza um atributo e, por vezes, usa um mecanismo de armazenamento específico do navegador. Outro motivo pelo qual desejo que o núcleo do jQuery tenha um seletor de dados específico.
31412 AaronLS
77
Observe que ele não funciona para elementos nos quais você define dados com $ ('# element'). Data ('some-att-name', value); mas apenas para aqueles com atributo codificado. Eu tenho esse problema e fazê-lo funcionar com dados do conjunto, escrevendo o atributo diretamente $ ('# element'). Attr ('data-some-att-name', value);
Pawel
463

caso você não queira digitar tudo isso, veja uma maneira mais curta de consultar por atributo de dados:

$("ul[data-slide='" + current +"']");

FYI: http://james.padolsey.com/javascript/a-better-data-selector-for-jquery/

KevinDeus
fonte
31
Para aqueles que se importam, dada a estrutura, <ul><li data-slide="item"></li></ul>o seletor dessa resposta retornará indefinido para que não funcione de acordo com o cenário do usuário. Esta resposta funcionará para a estrutura <ul data-slide="item"><li></li></ul> Embora eu entenda por que sua popularidade devido à brevidade, é tecnicamente uma resposta incorreta. jsfiddle.net/py5p2abL/1
akousmata
4
Não se esqueça de tratá-lo como uma matriz. Use [0]para acessar o primeiro elemento encontrado.
Aminah Nuraini
Um efeito colateral bizarro ... esse método funcionou combinando o elemento com o atributo data quando .find("[data-attrib='value']")não funcionou. Eu não sei se os valores foram dados atributos foram adicionados pelo jQuery ou não ...
erroric
1
Não é bizarro, porque as duas respostas fazem duas coisas diferentes. encontra$.find especificamente os descendentes desse elemento, mas o uso da sintaxe de filtro na cadeia de seleção simplesmente filtra os resultados.
Phil
227

Ao pesquisar com [data-x = ...], cuidado, ele não funciona com o setter jQuery.data (..) :

$('<b data-x="1">'  ).is('[data-x=1]') // this works
> true

$('<b>').data('x', 1).is('[data-x=1]') // this doesn't
> false

$('<b>').attr('data-x', 1).is('[data-x=1]') // this is the workaround
> true

Você pode usar isso:

$.fn.filterByData = function(prop, val) {
    return this.filter(
        function() { return $(this).data(prop)==val; }
    );
}

$('<b>').data('x', 1).filterByData('x', 1).length
> 1
psicopata brm
fonte
1
o $.fn.filterByDataé brilhante; no entanto, este é um aviso para os copiadores que estão por aí ... você só precisa $('<b>').filterByData('x', 1)encontrar <b>tags data-x="1". se você copiar e colar a .data(x, 1)parte ... você definirá seu data-x"1" antes de filtrar.
WEBjuju 17/03
39

I melhorado extensão filterByData de brm psico para jQuery.

Onde a extensão anterior pesquisou em um par de valor-chave, com essa extensão, você também pode procurar a presença de um atributo de dados, independentemente de seu valor.

(function ($) {

    $.fn.filterByData = function (prop, val) {
        var $self = this;
        if (typeof val === 'undefined') {
            return $self.filter(
                function () { return typeof $(this).data(prop) !== 'undefined'; }
            );
        }
        return $self.filter(
            function () { return $(this).data(prop) == val; }
        );
    };

})(window.jQuery);

Uso:

$('<b>').data('x', 1).filterByData('x', 1).length    // output: 1
$('<b>').data('x', 1).filterByData('x').length       // output: 1

Ou o violino: http://jsfiddle.net/PTqmE/46/

bPratik
fonte
34

Sem JQuery, ES6

document.querySelectorAll(`[data-slide='${current}']`);

Eu sei que a pergunta é sobre JQuery, mas os leitores podem querer um método JS puro.

rap-2-h
fonte
33

Eu enfrentei o mesmo problema ao buscar elementos usando o jQuery e o atributo data- *.

portanto, para sua referência, o código mais curto está aqui:

Este é o meu código HTML:

<section data-js="carousel"></section>
<section></section>
<section></section>
<section data-js="carousel"></section>

Este é o meu seletor jQuery:

$('section[data-js="carousel"]');
// this will return array of the section elements which has data-js="carousel" attribute.
user1378423
fonte
19
$("ul").find("li[data-slide='" + current + "']");

Espero que isso funcione melhor

obrigado

Jomin George Paul
fonte
15

Este seletor $("ul [data-slide='" + current +"']");funcionará para a seguinte estrutura:

<ul><li data-slide="item"></li></ul>  

Embora isso $("ul[data-slide='" + current +"']");funcione para:

<ul data-slide="item"><li></li></ul>

Matas Vaitkevicius
fonte
12

Voltando à sua pergunta original, sobre como fazer isso funcionar sem conhecer o tipo de elemento com antecedência, o seguinte é o seguinte:

$(ContainerNode).find(el.nodeName + "[data-slide='" + current + "']");
Bryan Garaventa
fonte