Dubrowsky
Хроники одного дупла
Блогово  →  WebDev  → 

Фильтрация в jQuery - $.find() и $.filter()

14 Июня 2012 года

Всем известно, что в jQuery есть метод .find(selector), позволяющий найти потомков по селектору. Также есть менее известный, но не менее полезный метод .filter(selector), находящий в коллекции узлы, соответствующие селектору (т.е. фильтрующий коллекцию по селектору). Обычно эти методы используются в разных случаях и проблем не возникает. Но бывают исключения.

Бывает, что надо найти что-то в куске дерева, но мы не знаем, расположено ли это искомое в глубине, или является узлом контекста.

В xPath для такой ситуации существует ось descendant-or-self, используя которую, мы можем проверить на соответствие условию и узел контекста, и его потомков.

Кстати, в jQuery проблема усугубляется еще и тем, что "узла контекста" как такового не существует, в качестве контекста используется коллекция, которая может содержать и несколько узлов.

Я сейчас работаю над задачкой, где с этим приходится сталкиваться все время. Официального встроенного решения я не нашел, а делать каждый раз две проверки - очень лень. Поэтому предлагаю вашему вниманию костыль в виде метода .descendant_or_self(selector), делающего ровно то, что мы хотим.

Вот пример. Тут есть 3 коллекции, в каждой мы ищем тег с классом needle тремя способами. Надеюсь, понятно.

var collections = {
   shallow: $('<div class="needle">ololo</div>'),
   deep: $('<div class="haystack"><div class="needle">oo</div></div>'),
   combi: $('<div class="needle"><div class="needle">oo</div></div>'+
                 '<div class="needle">o</div>')
}

// определяем наш костыль!
// эти три строчки можно копипастить
$.fn.descendant_or_self = function(selector) {
   return this.find(selector).add( this.filter(selector));
};

var message = '';
$.each(collections, function(coll_name, coll) {
   message += '---'+coll_name+"---\n";
   message += '.find() - '+coll.find('.needle').length+', ';
   message += '.filter() - '+coll.filter('.needle').length+', ';
   message += '.descendant_or_self() - '+
                       coll.descendant_or_self('.needle').length+'\n\n';
});

alert(message);

Как видите, последний способ находит все .needle, где бы они ни были. Финт слишком простой, чтобы заворачивать его в "плагин" :) Так что, если кому надо, можете просто скопипастить :)

Если вы днем и ночью думаете лишь о том, как стать богаче - учите JavaScript и jQuery, не пропадете, я гарантирую это!

Камменты

secit04.05.2014, 07:00#
Спасибо, как раз то что искал...

Написать коммент: памятка постеру

 

Крутые посты wtf??? →

02.10.2012 · 91 каммент · рейтинг 18.61
28.04.2008 · 44 каммента · рейтинг 9.51
06.03.2008 · 29 камментов · рейтинг 7.66
30.01.2013 · 13 камментов · рейтинг 7.27
19.01.2008 · 20 камментов · рейтинг 6.32

Последне камменты

14.12.2017  БраузерНовый Яндекс.Браузер - браузер "Yandex" (отзыв / обзор): Я предпочитаю использовать яндекс браузер
18.11.2017  JohnКак закрыть окно Skype / свернуть нафиг в трэй: Спасибо, добрый человек! Неимоверно раздражало.
10.11.2017  NikПочему не работает form.submit(): Автор, спасибо за статью 5-летней давности. Подари...
27.10.2017  ДенисОбработка кликов и цели в Яндекс.Метрике, улучшенный вариант: Блин. А для не в зуб ногой - можно код целиком выл...
17.10.2017  ДубрDenwer - настройка алиасов (ServerAlias): Ахуенно не это, ахуенно то что кто-то пользуется Д...

Статсы