Element filtrujący oparty na kluczu / wartości .data ()

116

Powiedzmy, że mam 4 elementy div z klasą .navlink, które po kliknięciu służą .data()do ustawiania wywoływanego klucza 'selected'na wartość true:

$('.navlink')click(function() { $(this).data('selected', true); })

Za każdym razem, gdy .navlinkkliknięto nowy , chciałbym zapisać poprzednio wybrany navlinkdo późniejszej manipulacji. Czy istnieje szybki i łatwy sposób na wybranie elementu na podstawie tego, co zostało zapisane przy użyciu .data()?

Wygląda na to, że nie ma żadnych filtrów jQuery : pasujących do rachunku i próbowałem wykonać następujące czynności (w ramach tego samego zdarzenia kliknięcia), ale z jakiegoś powodu to nie działa:

var $previous = $('.navlink').filter( 
    function() { $(this).data("selected") == true }
);

Wiem, że są inne sposoby, aby to osiągnąć, ale w tej chwili jestem po prostu ciekawy, czy można to zrobić za pomocą .data().

user113716
źródło

Odpowiedzi:

192

twój filtr zadziałałby, ale musisz zwrócić true na pasujących obiektach w funkcji przekazanej do filtra, aby je przechwycił.

var $previous = $('.navlink').filter(function() { 
  return $(this).data("selected") == true 
});
BarokowyBobcat
źródło
6
Należy pamiętać, że nie jest to już jedyny sposób, aby to zrobić, StefanoP zapewnił alternatywę
Nathan Koop
3
@NathanKoop, niezupełnie. Zobacz mój komentarz do jego odpowiedzi.
Bryan Downing,
Dla tych, którzy używają atrybutu danych, aby znaleźć inny niemożliwy do znalezienia element (id less divs itp., Do którego z dowolnego powodu trzeba mieć dostęp) w dowolnym miejscu w dokumencie:$("*").filter(function() { return $(this).data("DATA IDENTIFIER HERE") == DATA VALUE HERE; });
Tschallacka
to nie jest „niechlujny” - jest to jedyny bezpieczny sposób filtrowania według dowolnych terminów bez konieczności „ucieczki” od tych wartości, aby upewnić się, że połączenie wyszukiwanego hasła z pozostałą częścią selektora nie utworzy niedozwolonego selektora.
Alnitak
145

Tylko dla porządku, to można filtrować dane z jQuery (to pytanie jest dość stary i jQuery ewoluowała od tego czasu, więc jest to prawo do pisania tego rozwiązania, jak również):

$('.navlink[data-selected="true"]');

lub lepiej (dla wydajności):

$('.navlink').filter('[data-selected="true"]');

lub jeśli chcesz otrzymać wszystkie elementy z data-selectedset:

$('[data-selected]')

Zauważ, że ta metoda będzie działać tylko z danymi, które zostały ustawione za pomocą atrybutów html. Jeśli ustawisz lub zmienisz dane za pomocą .data()wywołania, ta metoda nie będzie już działać.

StefanoP
źródło
9
jeśli niska liczba głosów na tę odpowiedź Cię przeraża - jest to zaakceptowana odpowiedź z ponad 100 głosami na praktycznie identyczne pytanie stackoverflow.com/questions/4146502
Simon_Weaver
48
-1 To nie działa, gdy dane są ustawiane za pomocą .data()metody zamiast data-atrybutu. Zobacz to skrzypce: jsfiddle.net/bryandowning/tySWC - również .find()metoda wyszukuje elementy podrzędne poprzedniego selektora. W podanym przykładzie data-selectedjest atrybutem .navlink, a nie dzieckiem .navlink. Ponadto $('div p')i $('div').find('p')są zasadniczo równoważne. Używanie .find()wydaje się być wolniejsze ze względu na dodatkowe wywołanie funkcji (chociaż nie jestem co do tego przekonany). Proszę mnie poprawić, jeśli się mylę w którymkolwiek z tych punktów (naprawdę chciałbym, żeby ta metoda zadziałała).
Bryan Downing,
3
kilka rzeczy: 1) masz rację, że to nie działa, jeśli ustawisz dane za pomocą .data(), ponieważ jQuery przeszukuje DOM, wysłałem go dla tych (takich jak ja), którzy dostali się do tego pytania z innych powodów; 2) poprawne, .find()przeszukuje dzieci, więc w tym przykładzie jest źle; 3) mylisz się, nie są one równoważne, ponieważ jQuery wyszukuje od prawej do lewej, patrz jonraasch.com/blog/…
StefanoP
2
Głosowanie w górę $('[data-selected]')pomogło mi w czymś takim jak$('ul.categories a[data-categories_id]').click(......);
Luke Cousins
Wydaje się również, że jeśli zaktualizujesz atrybut danych za pomocą .attr, jeśli pobierzesz go za pomocą .data, wartość nie zostanie zaktualizowana - więc zachowaj ostrożność podczas mieszania obu
Fabio Lolli
13

Możemy łatwo stworzyć wtyczkę:

$.fn.filterData = function(key, value) {
    return this.filter(function() {
        return $(this).data(key) == value;
    });
};

Użycie (sprawdzanie przycisku radiowego):

$('input[name=location_id]').filterData('my-data','data-val').prop('checked',true);
mpen
źródło
Masz na myśli metodę wtyczki, w przeciwnym razie jest to to samo, co zaakceptowana odpowiedź ...
jave.web
@ jave.web Rzeczywiście. Ale nie każdy wie, jak przekształcić go w wtyczkę. Zaktualizowana słówka.
mpen
nie zrozum mnie źle, twoja odpowiedź jest świetna, jednak słowa tutaj są bardzo ważne, dziękuję za aktualizację :)
jave.web
8

Zauważyłem dwie rzeczy (mogą to być jednak błędy z czasu, gdy to zapisałeś).

  1. W pierwszym przykładzie przegapiłeś kropkę ( $('.navlink').click)
  2. Aby filtr działał, musisz zwrócić wartość ( return $(this).data("selected")==true)
Tomasz
źródło
-1

Brzmi jak więcej pracy niż jej wartość.

1) Dlaczego nie mieć tylko jednej zmiennej JavaScript, która przechowuje odniesienie do aktualnie wybranego elementu \ jQuery obiektu.

2) Dlaczego nie dodać klasy do aktualnie wybranego elementu. Następnie możesz zapytać DOM o klasę „.active” lub coś w tym stylu.

Bryan Migliorisi
źródło
Tak, ale jak powiedziałem, wiedziałem, że są inne sposoby na osiągnięcie tego. Po prostu utknąłem na tym, czy można go przefiltrować przez data () i dlaczego filter () nie działa dla mnie. W każdym razie dzięki.
user113716
Przepraszam. Brakowało mi tej części twojego pytania.
Bryan Migliorisi