Элемент фильтра на основе ключа / значения .data ()

116

Скажем, у меня есть 4 элемента div с классом .navlink, которые при нажатии используются .data()для установки вызываемого ключа 'selected'на значение true:

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

Каждый раз, когда .navlinkнажимается новое , я хотел бы сохранить ранее выбранное navlinkдля последующих манипуляций. Есть ли быстрый и простой способ выбрать элемент на основе того, что было сохранено с использованием .data()?

Кажется, нет никаких фильтров jQuery :, которые подходят под все требования, и я попробовал следующее (в том же событии щелчка), но по какой-то причине это не работает:

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

Я знаю, что есть другие способы сделать это, но сейчас мне просто любопытно, можно ли это сделать с помощью .data().

user113716
источник

Ответы:

192

ваш фильтр будет работать, но вам нужно вернуть true для совпадающих объектов в функции, переданной фильтру, чтобы он их захватил.

var $previous = $('.navlink').filter(function() { 
  return $(this).data("selected") == true 
});
BaroqueBobcat
источник
6
Обратите внимание, что это больше не единственный способ сделать это, StefanoP предоставил альтернативы
Натан Куп
3
@NathanKoop, не совсем так. Смотрите мой комментарий к его ответу.
Брайан Даунинг,
Для тех, кто использует атрибут данных, чтобы найти элемент, который иначе невозможно найти (id без div и т. Д., К которому вам необходимо иметь доступ по какой-либо причине) в любом месте документа:$("*").filter(function() { return $(this).data("DATA IDENTIFIER HERE") == DATA VALUE HERE; });
Tschallacka
это не «беспорядочный» - это единственный безопасный способ фильтрации по произвольным терминам без необходимости «экранировать» эти значения, чтобы гарантировать, что объединение поискового запроса с остальной частью селектора не приведет к созданию недопустимого селектора.
Alnitak
145

Просто для записи вы можете фильтровать данные с помощью jquery (этот вопрос довольно старый, и с тех пор jQuery эволюционировал, поэтому также правильно написать это решение):

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

или лучше (по производительности):

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

или, если вы хотите получить все элементы с помощью data-selectedset:

$('[data-selected]')

Обратите внимание, что этот метод будет работать только с данными, которые были установлены через атрибуты html. Если вы установите или измените данные с помощью .data()вызова, этот метод больше не будет работать.

StefanoP
источник
9
если низкое количество голосов за этот ответ пугает вас - это принятый ответ с более чем 100 голосами за практически идентичный вопрос. stackoverflow.com/questions/4146502
Simon_Weaver
48
-1 Это не работает, когда данные устанавливаются .data()методом вместо data-атрибута. См. Эту скрипку: jsfiddle.net/bryandowning/tySWC - Кроме того, .find()метод выполняет поиск дочерних элементов предыдущего селектора. В приведенном примере data-selectedявляется атрибутом .navlink, а не дочерним элементом .navlink. Также $('div p')и $('div').find('p')по сути эквивалентны. Использование .find()кажется , что это может быть медленнее из - за вызов дополнительной функции (хотя я не уверен по этому поводу). Пожалуйста, поправьте меня, если я ошибаюсь в этом (я действительно хочу, чтобы этот метод работал).
Брайан Даунинг,
3
пара вещей: 1) вы правы, что это не работает, если вы устанавливаете данные с помощью .data(), поскольку jQuery выполняет поиск в DOM, я опубликовал его для тех (таких как я), кто попал в этот вопрос по другим причинам; 2) правильно, .find()перебирает дочерние элементы, поэтому в данном примере это неправильно; 3) Вы ошибаетесь, они не эквивалентны, так как jQuery выполняет поиск справа налево, см. Jonraasch.com/blog/…
StefanoP
2
Голосование за $('[data-selected]')это помогло мне в чем-то вроде$('ul.categories a[data-categories_id]').click(......);
Люк Казинс,
Кроме того, похоже, что если вы обновите атрибут данных с помощью .attr, если вы получите его с помощью .data, значение не будет обновлено - так что будьте осторожны при смешивании двух
Фабио Лолли
13

Мы можем довольно легко сделать плагин:

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

Использование (установка переключателя):

$('input[name=location_id]').filterData('my-data','data-val').prop('checked',true);
mpen
источник
Вы имеете в виду метод плагина, иначе это то же самое, что и принятый ответ ...
jave.web
@ jave.web Действительно. Но не все знают, как превратить его в плагин. Обновленное словоблудие.
mpen
не поймите меня неправильно, ваш ответ отличный, однако слова здесь очень важны, спасибо за обновление :)
jave.web
8

Я заметил две вещи (хотя они могут быть ошибками, когда вы это записали).

  1. Вы пропустили точку в первом примере ( $('.navlink').click)
  2. Чтобы фильтр работал, вы должны вернуть значение ( return $(this).data("selected")==true)
Томас
источник
-1

Похоже, работы больше, чем ее стоит.

1) Почему бы просто не иметь единственную переменную JavaScript, которая хранит ссылку на текущий выбранный объект element \ jQuery.

2) Почему бы не добавить класс к текущему выбранному элементу. Затем вы можете запросить в DOM класс «.active» или что-то в этом роде.

Брайан Миглиориси
источник
Да, но, как я уже сказал, я знал, что есть другие способы добиться этого. Я просто зациклился на том, можно ли его отфильтровать с помощью data () и почему filter () у меня не работает. Спасибо хоть.
user113716
Сожалею. Я пропустил эту часть вашего вопроса.
Брайан Миглиориси