Filterelement basierend auf .data () Schlüssel / Wert

115

Angenommen, ich habe 4 div-Elemente mit Klasse .navlink, mit denen beim Klicken .data()ein Schlüssel namens 'selected'auf den Wert gesetzt wird true:

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

Jedes Mal, wenn auf ein neues .navlinkgeklickt wird, möchte ich das zuvor ausgewählte navlinkfür eine spätere Bearbeitung speichern . Gibt es eine schnelle und einfache Möglichkeit, ein Element basierend auf dem, was mit gespeichert wurde, auszuwählen .data()?

Es scheint keine jQuery : -Filter zu geben , die zur Rechnung passen, und ich habe Folgendes versucht (innerhalb desselben Klickereignisses), aber aus irgendeinem Grund funktioniert es nicht:

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

Ich weiß, dass es andere Möglichkeiten gibt, dies zu erreichen, aber im Moment bin ich meistens nur neugierig, ob dies über möglich ist .data().

user113716
quelle

Antworten:

191

Ihr Filter würde funktionieren, aber Sie müssen true für übereinstimmende Objekte in der an den Filter übergebenen Funktion zurückgeben, damit er sie abruft.

var $previous = $('.navlink').filter(function() { 
  return $(this).data("selected") == true 
});
BarockBobcat
quelle
6
Bitte beachten Sie, dass dies nicht mehr der einzige Weg ist, dies zu tun. StefanoP hat Alternativen bereitgestellt
Nathan Koop
3
@ NathanKoop, nicht ganz. Siehe meinen Kommentar zu seiner Antwort.
Bryan Downing
Für diejenigen, die ein Datenattribut verwenden, um ein ansonsten nicht auffindbares Element (ID weniger Divs usw.) zu finden, auf das Sie aus irgendeinem Grund zugreifen müssen, an einer beliebigen Stelle im Dokument:$("*").filter(function() { return $(this).data("DATA IDENTIFIER HERE") == DATA VALUE HERE; });
Tschallacka
Dies ist nicht "chaotisch" - dies ist die einzig sichere Methode zum Filtern nach beliebigen Begriffen, ohne dass Sie diesen Werten "entkommen" müssen, um sicherzustellen, dass durch die Verkettung des Suchbegriffs mit dem Rest des Selektors kein unzulässiger Selektor erstellt wird.
Alnitak
145

Nur zur Veranschaulichung : Sie können Daten mit jquery filtern (diese Frage ist ziemlich alt und jQuery hat sich seitdem weiterentwickelt, daher ist es richtig, auch diese Lösung zu schreiben):

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

oder besser (für die Leistung):

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

oder, wenn Sie alle Elemente mit data-selectedset erhalten möchten :

$('[data-selected]')

Beachten Sie, dass diese Methode nur mit Daten funktioniert, die über HTML-Attribute festgelegt wurden. Wenn Sie mit dem .data()Aufruf Daten festlegen oder ändern , funktioniert diese Methode nicht mehr.

StefanoP
quelle
9
Wenn Ihnen die niedrige Stimmenzahl für diese Antwort Angst macht, ist dies die akzeptierte Antwort mit mehr als 100 Stimmen für eine praktisch identische Frage. stackoverflow.com/questions/4146502
Simon_Weaver
47
-1 Dies funktioniert nicht, wenn Daten mit der .data()Methode anstelle eines data-Attributs festgelegt werden. Siehe diese Geige: jsfiddle.net/bryandowning/tySWC - Außerdem .find()sucht die Methode nach untergeordneten Elementen des vorhergehenden Selektors. In dem angegebenen Beispiel data-selectedist ein Attribut von .navlink, kein Kind von .navlink. Auch $('div p')und $('div').find('p')sind im Wesentlichen gleichwertig. Die Verwendung .find()scheint aufgrund des zusätzlichen Funktionsaufrufs langsamer zu sein (obwohl ich diesbezüglich nicht sicher bin). Bitte korrigieren Sie mich, wenn ich in irgendetwas falsch liege (ich wünschte wirklich, diese Methode würde funktionieren).
Bryan Downing
3
ein paar Dinge: 1) Sie haben Recht, dass dies nicht funktioniert, wenn Sie Daten mit festlegen .data(). Da jQuery das DOM durchsucht, habe ich es für diejenigen (wie mich) gepostet, die aus anderen Gründen zu dieser Frage gekommen sind. 2) richtig, .find()durchsucht die Kinder, so dass es in diesem Beispiel falsch ist; 3) Sie liegen falsch, sie sind nicht gleichwertig, da jQuery von rechts nach links sucht, siehe jonraasch.com/blog/…
StefanoP
2
Die Abstimmung dafür $('[data-selected]')half mir für so etwas wie$('ul.categories a[data-categories_id]').click(......);
Luke Cousins
Es scheint auch so, als ob Sie das Datenattribut mit .attr aktualisieren. Wenn Sie es mit .data abrufen, wird der Wert nicht aktualisiert. Seien Sie also vorsichtig, wenn Sie die beiden mischen
Fabio Lolli
13

Wir können ziemlich einfach ein Plugin erstellen:

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

Verwendung (Aktivieren eines Optionsfelds):

$('input[name=location_id]').filterData('my-data','data-val').prop('checked',true);
mpen
quelle
Du meinst Plugin-Methode, sonst ist dies die gleiche wie die akzeptierte Antwort ...
jave.web
@ jave.web In der Tat. Aber nicht jeder weiß, wie man daraus ein Plugin macht. Aktualisierte Sprache.
Mpen
Versteh
8

Zwei Dinge sind mir aufgefallen (es können jedoch Fehler sein, als Sie es aufgeschrieben haben).

  1. Sie haben im ersten Beispiel einen Punkt verpasst ( $('.navlink').click)
  2. Damit der Filter funktioniert, müssen Sie einen Wert ( return $(this).data("selected")==true) zurückgeben.
Thomas
quelle
-1

Klingt nach mehr Arbeit als es wert ist.

1) Warum nicht einfach eine einzige JavaScript-Variable haben, die einen Verweis auf das aktuell ausgewählte Element \ jQuery-Objekt speichert.

2) Fügen Sie dem aktuell ausgewählten Element eine Klasse hinzu. Dann könnten Sie das DOM nach der Klasse ".active" abfragen oder so.

Bryan Migliorisi
quelle
Ja, aber wie gesagt, ich wusste, dass es andere Möglichkeiten gibt, dies zu erreichen. Ich war nur festgefahren, ob es über data () gefiltert werden kann und warum filter () bei mir nicht funktioniert. Trotzdem danke.
user113716
Es tut uns leid. Ich habe diesen Teil Ihrer Frage verpasst.
Bryan Migliorisi