jQuery jak znaleźć element na podstawie wartości atrybutu danych?

994

Mam następujący scenariusz:

var el = 'li';

a na stronie znajduje się 5 <li>z data-slide=numberatrybutem (odpowiednio 1,2,3,4,5) .

Teraz muszę znaleźć numer aktywnego slajdu, który jest mapowany var current = $('ul').data(current);i aktualizowany przy każdej zmianie slajdu.

Do tej pory moje próby zakończyły się niepowodzeniem, próbując skonstruować selektor pasujący do bieżącego slajdu:

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

nic nie pasuje / nie zwraca…

Powodem, dla którego nie mogę na stałe zakodować liczęści, jest to, że jest to zmienna dostępna dla użytkownika, którą w razie potrzeby można zmienić na inny element, więc nie zawsze może to być li.

Jakieś pomysły na to, czego mi brakuje?

Jannis
źródło
6
na pewno w swoim .find(el+[data-slide=+current+]);kodzie jest kod, który piszesz? wygląda na to, że przegapiłeś kilka cytatów z"[data-slide]"
Xandy
To pomogło mi wybrać wszystkie atrybuty danych (niezależnie od wartości): $('*[data-slide]')Możesz go używać np. Z$('*[data-slide]').each( function() { ... });
Kai Noack

Odpowiedzi:

1481

Musisz wprowadzić wartość currentdo selektora Attribute Equals :

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

W przypadku starszych środowisk JavaScript ( ES5 i wcześniejszych):

$("ul").find("[data-slide='" + current + "']"); 
Frédéric Hamidi
źródło
8
@Jannis, możesz to zrobić $("ul").find(el + "[data-slide='" + current +"']");.
Frédéric Hamidi
7
@ c00lryguy, interfejs użytkownika jQuery definiuje jeden, a wokół istnieją autonomiczne implementacje . Wygląda na to, że próby dodania go do jQuery Core zostały odrzucone . Dwukrotnie .
Frédéric Hamidi
6
ta odpowiedź na podobny post ma przykład funkcji filtrowania
drzaus
77
Obawiam się, że to nie zadziała, jeśli dane zostaną dodane za pomocą funkcji jQuery .data (...), ponieważ nie zawsze renderuje to atrybut i czasami używa mechanizmu przechowywania specyficznego dla przeglądarki. Kolejny powód, dla którego chciałbym, aby rdzeń jQuery miał selektor specyficzny dla danych.
AaronLS
77
Zauważ, że to nie działa dla elementów, w których ustawiasz dane za pomocą $ ('# element'). Data ('some-att-name', value); ale tylko dla osób z zakodowanym atrybutem. Mam ten problem i aby działał, ustaw dane, pisząc atrybut bezpośrednio $ ('# element'). Attr ('data-some-att-name', wartość);
Paweł
463

w przypadku, gdy nie chcesz wpisywać tego wszystkiego, oto krótszy sposób na zapytanie według atrybutu danych:

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

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

KevinDeus
źródło
31
Dla tych, którym zależy, ze względu na strukturę <ul><li data-slide="item"></li></ul>selektor odpowiedzi zwróci niezdefiniowany, więc nie będzie działał, biorąc pod uwagę scenariusz użytkownika. Ta odpowiedź DZIAŁA dla struktury <ul data-slide="item"><li></li></ul> Chociaż rozumiem, dlaczego jest popularna ze względu na zwięzłość, jest to technicznie nieprawidłowa odpowiedź. jsfiddle.net/py5p2abL/1
akousmata
4
Nie zapomnij potraktować tego jako tablicy. Użyj, [0]aby uzyskać dostęp do pierwszego znalezionego elementu.
Aminah Nuraini
Dziwny efekt uboczny ... ta metoda działała, dopasowując element do atrybutu danych, gdy .find("[data-attrib='value']")nie działał. Nie wiem, czy wartości to atrybuty danych zostały dodane przez jQuery czy nie ...
błąd
1
To nie jest dziwne, ponieważ dwie odpowiedzi robią 2 różne rzeczy. $.findkonkretnie znajduje potomków tego elementu, ale użycie składni filtru w ciągu selektora po prostu odfiltruje wyniki.
Phil
227

Podczas wyszukiwania za pomocą [data-x = ...] uważaj, nie działa z seter 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

Możesz użyć tego zamiast:

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

$('<b>').data('x', 1).filterByData('x', 1).length
> 1
psycho brm
źródło
1
$.fn.filterByDatajest znakomity; jest to jednak ostrzeżenie dla kopiujących-pasterów tam ... musisz tylko $('<b>').filterByData('x', 1)znaleźć <b>tagi data-x="1". jeśli skopiujesz i wkleisz .data(x, 1)część ... data-xprzed filtrowaniem ustawisz wartość „1”.
WEBjuju
39

Poprawiłem rozszerzenie filterByData od psycho brm do jQuery.

Tam, gdzie poprzednie rozszerzenie szukało pary klucz-wartość, za pomocą tego rozszerzenia można dodatkowo wyszukiwać obecność atrybutu danych, niezależnie od jego wartości.

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

Stosowanie:

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

Lub skrzypce: http://jsfiddle.net/PTqmE/46/

bPratik
źródło
34

Bez JQuery, ES6

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

Wiem, że pytanie dotyczy JQuery, ale czytelnicy mogą chcieć czystej metody JS.

rap-2-h
źródło
33

Napotkałem ten sam problem podczas pobierania elementów za pomocą jQuery i atrybutu data- *.

więc w celach informacyjnych najkrótszy kod znajduje się tutaj:

To jest mój kod HTML:

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

To jest mój selektor jQuery:

$('section[data-js="carousel"]');
// this will return array of the section elements which has data-js="carousel" attribute.
użytkownik1378423
źródło
19
$("ul").find("li[data-slide='" + current + "']");

Mam nadzieję, że to może działać lepiej

dzięki

Jomin George Paul
źródło
15

Ten selektor $("ul [data-slide='" + current +"']");będzie działał dla następującej struktury:

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

Chociaż $("ul[data-slide='" + current +"']");będzie to działać dla:

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

Matas Vaitkevicius
źródło
12

Wracając do pierwotnego pytania o to, jak to zrobić, nie znając z góry typu elementu, wykonuje następujące czynności:

$(ContainerNode).find(el.nodeName + "[data-slide='" + current + "']");
Bryan Garaventa
źródło