Wybieranie elementu według atrybutu danych

1019

Czy istnieje prosta i prosta metoda wybierania elementów na podstawie ich dataatrybutów? Na przykład wybierz wszystkie kotwice, które mają nazwany atrybut danych o customerIDwartości 22.

Waham się przed użyciem rellub innymi atrybutami do przechowywania takich informacji, ale znacznie trudniej jest mi wybrać element na podstawie tego, jakie dane są w nim przechowywane.

Hazem Salama
źródło
2
Zobacz także stackoverflow.com/q/4191386/292060
goodeye,
To, co pomogło mi wybrać wszystkie atrybuty danych (niezależnie od wartości): $('*[data-customerID]')Można go używać z np$('*[data-customerID]').each( function() { ... });
Kai Noack

Odpowiedzi:

1467
$('*[data-customerID="22"]');

Powinieneś być w stanie pominąć *, ale jeśli dobrze pamiętam, w zależności od używanej wersji jQuery, może to dawać błędne wyniki.

Należy pamiętać, że w celu zapewnienia zgodności z interfejsem API selektorów ( document.querySelector{,all}), cytaty wokół wartości atrybutu ( 22) mogą nie zostać w tym przypadku pominięte .

Ponadto, jeśli często pracujesz z atrybutami danych w skryptach jQuery, możesz rozważyć użycie wtyczki niestandardowych atrybutów danych HTML5 . Pozwala to na pisanie jeszcze bardziej czytelnego kodu przy użyciu .dataAttr('foo')i powoduje zmniejszenie rozmiaru pliku po zmniejszeniu (w porównaniu do użycia .attr('data-foo')).

Mathias Bynens
źródło
69
Tylko uwaga, że ​​.data („foo”) działa, aby uzyskać wartość atrybutu „data-foo” od jQuery 1.4.3. Ponadto, ponieważ jQuery 1.6: .data („fooBar”) otrzymuje atrybut „data-foo-bar”.
James McCormack
4
@Zootius: Tak, plik Readme wtyczki zawiera notatkę: „Od wersji jQuery 1.4.3 domyślnie .data()mapuje się na niestandardowe data-*atrybuty, co powoduje, że ta wtyczka jest zbędna. Nadal jednak można go używać w starszych wersjach jQuery. ”
Mathias Bynens
Jak więc jeden post jQuery 1.4.3 wybiera obiekt według wartości jego obiektu danych? Czy w tym przykładzie chciałem wybrać dowolny obiekt o danych dla ID klienta równych 22?
Wycieczka
54
Również jeśli jesteś zainteresowany tylko obecnością określonego atrybutu danych, możesz to zrobić:$('[data-customerID]')
Darkside
7
To nie działa, jeśli pole danych zostało ustawione przez jquery (using .data()), prawda?
Martin R.
329

Dla osób korzystających z Google i chcących bardziej ogólnych zasad dotyczących wybierania za pomocą atrybutów danych:

$("[data-test]")wybierze dowolny element, który ma tylko atrybut danych (bez względu na wartość atrybutu). Włącznie z:

<div data-test=value>attributes with values</div>
<div data-test>attributes without values</div>

$('[data-test~="foo"]')wybierze dowolny element, w którym atrybut danych zawiera, foo ale nie musi być dokładny, taki jak:

<div data-test="foo">Exact Matches</div>
<div data-test="this has the word foo">Where the Attribute merely contains "foo"</div>

$('[data-test="the_exact_value"]')wybierze dowolny element, w którym dokładna wartość atrybutu danych to the_exact_value, na przykład:

<div data-test="the_exact_value">Exact Matches</div>

ale nie

<div data-test="the_exact_value foo">This won't match</div>
JTG
źródło
21
Dobrze. Zauważ, że ~=pasuje do słów oddzielonych spacjami, natomiast *=pasuje do dowolnego podłańcucha.
Sam
Co z ^postacią?
kuba44,
1
@ kuba44 rzeczywiście możesz również użyć ^, ponieważ $('[data-test^=foo]')w takim przypadku wybierasz wszystko zaczynające się od foo, takie jak <div data-test="foo_exact_value">lub <div data-test="food">nie<div data-test="seafoo">
JDuarteDJ
Wyczerpująca lista selektorów atrybutów: drafts.csswg.org/selectors-3/#attribute-selectors
1460043
142

Używanie $('[data-whatever="myvalue"]')wybierze wszystko z atrybutami html, ale w nowszych jQueries wydaje się, że jeśli użyjesz $(...).data(...)do dołączenia danych, używa jakiejś magicznej przeglądarki i nie wpływa na html, dlatego nie jest wykrywane przez, .findjak wskazano w poprzedniej odpowiedzi .

Weryfikacja (testowana w wersji 1.7.2+) (patrz także skrzypce ): (zaktualizowano, aby była bardziej kompletna)

var $container = $('<div><div id="item1"/><div id="item2"/></div>');

// add html attribute
var $item1 = $('#item1').attr('data-generated', true);

// add as data
var $item2 = $('#item2').data('generated', true);

// create item, add data attribute via jquery
var $item3 = $('<div />', {id: 'item3', data: { generated: 'true' }, text: 'Item 3' });
$container.append($item3);

// create item, "manually" add data attribute
var $item4 = $('<div id="item4" data-generated="true">Item 4</div>');
$container.append($item4);

// only returns $item1 and $item4
var $result = $container.find('[data-generated="true"]');
drzaus
źródło
1
aha - okazuje się, że ktoś inny wskazuje to na stackoverflow.com/questions/4191386/...
drzaus
4
i oferuje rozwiązanie .filter tutaj
drzaus
22
używa magicznej przeglądarki i nie wpływa na HTML : nie ma czegoś takiego jak magia;) learningjquery.com/2011/09/using-jquerys-data-apis
Tom Sarduy
1
Jeśli dodajesz atrybut danych, który musisz później znaleźć, użyj$item.attr('data-id', 10);
Pedro Moreira
77

Nie widziałem odpowiedzi JavaScript bez jQuery. Mam nadzieję, że to komuś pomaga.

var elements = document.querySelectorAll('[data-customerID="22"]');

elements[0].innerHTML = 'it worked!';
<a data-customerID='22'>test</a>

Informacje:

Sjoerd Pottuit
źródło
1
Dzięki za to. Miło widzieć rozwiązania niebędące kwaskami.
Chuck
68

Aby wybrać wszystkie kotwice z atrybutem danych data-customerID==22, należy uwzględnić opcję aograniczenia zakresu wyszukiwania tylko do tego typu elementu. Przeszukiwanie atrybutów danych w dużej pętli lub z dużą częstotliwością, gdy na stronie znajduje się wiele elementów, może powodować problemy z wydajnością.

$('a[data-customerID="22"]');
Travis J
źródło
27

Przykłady natywnych JS

Uzyskaj NodeList elementów

var elem = document.querySelectorAll('[data-id="container"]')

HTML: <div data-id="container"></div>

Zdobądź pierwszy element

var firstElem = document.querySelector('[id="container"]')

HTML: <div id="container"></div>

Kieruj na zbiór węzłów, który zwraca listę węzłów

document.getElementById('footer').querySelectorAll('[data-id]')

HTML:

<div class="footer">
    <div data-id="12"></div>
    <div data-id="22"></div>
</div>

Uzyskaj elementy w oparciu o wiele wartości danych (OR)

document.querySelectorAll('[data-section="12"],[data-selection="20"]')

HTML:

<div data-selection="20"></div>
<div data-section="12"></div>

Uzyskaj elementy na podstawie połączonych (I) wartości danych

document.querySelectorAll('[data-prop1="12"][data-prop2="20"]')

HTML:

<div data-prop1="12" data-prop2="20"></div>

Zdobądź przedmioty, od których zaczyna się wartość

document.querySelectorAll('[href^="https://"]')
etoksyna
źródło
Selektor „pobierz pierwszy element” jest poprawny, ale niespójny z innymi przykładami - wydaje mi się, że brakuje w nim „danych-”.
GuyPaddock
15

za pomocą metody Jquery filter ():

http://jsfiddle.net/9n4e1agn/1/

HTML:

<button   data-id='1'>One</button>
<button   data-id='2'>Two</button>

JavaScript:

$(function() {    
    $('button').filter(function(){
        return $(this).data("id")   == 2}).css({background:'red'});  
     });
Razan Paul
źródło
Próbowałeś skrzypce? Metoda FIlter to kolejne podejście do osiągnięcia tego samego. Może być przydatny, gdy masz już zestaw obiektów Jquery i musisz filtrować na podstawie atrybutu danych lub czegokolwiek innego.
Razan Paul
Przepraszam, @Blizzard. Skomentowałem złą odpowiedź. Wkleiłem go teraz we właściwy sposób. #AlwaysALongDayAtWork
Peter Bishop
15

Taka konstrukcja: $('[data-XXX=111]')nie działa w przeglądarce Safari 8.0 .

Jeśli ustawisz atrybut danych w ten sposób: $('div').data('XXX', 111)działa to tylko wtedy, gdy ustawisz atrybut danych bezpośrednio w DOM w następujący sposób:$('div').attr('data-XXX', 111) .

Myślę, że dzieje się tak, ponieważ zespół jQuery zoptymalizował moduł wyrzucania elementów bezużytecznych, aby zapobiec wyciekom pamięci i ciężkim operacjom odbudowywania DOM przy każdym atrybucie zmiany danych.

Anton Danilchenko
źródło
To bardzo mi pomogło - jeśli użyłem metod danych lub prop, to wybór za pomocą $ ('... [data-x = "y"]') nie działał - zamiast tego użyłem attr (przesuwa zmianę atrybutu na DOM). Thx
Jarda
13

Aby działało to w Chrome, wartość nie może zawierać innej pary cudzysłowów.

Działa tylko na przykład tak:

$('a[data-customerID=22]');
użytkownik55318
źródło
4
To wydaje się niepoprawne. Przynajmniej teraz nie jest poprawne. Właśnie użyłem $ ('[data-action = "setStatus"]'). RemoveClass ('disabled'); w Chrome i działa idealnie.
Peter Bishop
$('[data-action=setStatus]').removeClass('disabled')
Wydaje mi się
6

Czasami pożądane jest filtrowanie elementów na podstawie tego, czy mają one dołączone do nich elementy danych programowo (inaczej nie poprzez atrybuty dom):

$el.filter(function(i, x) { return $(x).data('foo-bar'); }).doSomething();

Powyższe działa, ale nie jest bardzo czytelne. Lepszym podejściem jest użycie pseudoselektora do testowania tego rodzaju rzeczy:

$.expr[":"].hasData = $.expr.createPseudo(function (arg) {
    return function (domEl) {
        var $el = $(domEl);
        return $el.is("[" + ((arg.startsWith("data-") ? "" : "data-") + arg) + "]") || typeof ($el.data(arg)) !== "undefined";
    };
});

Teraz możemy zmienić oryginalne stwierdzenie na coś bardziej płynnego i czytelnego:

$el.filter(":hasData('foo-bar')").doSomething();
XDS
źródło
1
W pierwszym rozwiązaniu brakuje instrukcji return, musi to być: $ el.filter (function (i, x) {return $ (x) .data ('foo-bar');}). DoSomething ();
Salma Gomaa,
3

Aby uzupełnić wszystkie odpowiedzi pewnymi funkcjami „standardu życia” - do tej pory (w erze HTML5) można to zrobić bez bibliotek innych firm:

  • pure / plain JS with querySelector (używa selektorów CSS):
    • wybierz pierwszy w DOM: document.querySelector('[data-answer="42"],[type="submit"]')
    • zaznacz wszystko w DOM: document.querySelectorAll('[data-answer="42"],[type="submit"]')
  • czysty / zwykły CSS
    • niektóre określone tagi: [data-answer="42"],[type="submit"]
    • wszystkie tagi z określonym atrybutem: [data-answer]lubinput[type]
Sven
źródło