Живой поиск по тексту — jQuery

Недавно у меня появилась необходимость реализовать живой поиск по тексту. Но работать он должен не просто как стандартный браузерный поиск через ctrl+f, выделяя найденные фрагменты, а скрывая элементы, в которых не найдено ни одного совпадения. При этом задача усложнялась еще и тем, что если в секции нет элементов, в которых есть хоть одно совпадение, то должна скрываться и вся секция. Давайте попробуем реализовать это.
Поиск готовых плагинов увы, результатов не дал. Был найден похожий по функционалу плагин под названием jcOnPageFilter, но он сыроват, поэтому среди его возможностей содержит и некоторые ошибки. Давайте разберемся, что он умеет.
Плагин имеет несколько настроек - это очень здорово. Давайте рассмотрим некоторые из них:
- Важная функция - возможность скрывать элементы, в которых нет совпадений (из-за нее и был взят этот плагин)
- Можно указать родительский элемент (который будет скрыт, если ничего не найдено) и дочерний элемент (в котором будет осуществляться поиск) - здесь была найдена существенная недоработка - если дочерний элемент содержит вложенную структуру из тегов с классами, то поиск осуществляется и по названиям классов тоже - что нередко ломает верстку
- Настраивается и как скрывать и отображать найденное - мгновенно или с плавной анимацией - здесь тоже есть нюанс - при старте поиска скрывается все и отображаются лишь элементы, в которых есть совпадения - поэтому при использовании варианта с анимацией получается эффект мигания
- Можно задать, чтобы поиск осуществлялся только по первому слову в дочерних элементах (мне эта функция пока не пригодилась)
- Легко настраивается цвет выделения и цвет текста в выделенном фрагменте - приятная мелочь
- Дополнительно можно задать установку фокуса в поле поиска при загрузке страницы
Теперь подробнее остановимся на минусах. Самое главное чего не хватало - это удаление с экрана секции, если в содержащихся внутри нее элементах не найдено ни одно совпадение. Это необходимо если у нас есть несколько списков с заголовками. И получается, что в списке нет совпадений, а заголовок списка остался торчать. Неплохо было бы его тоже убирать.
Второе по очереди, но не менее важное - это поиск по названию классов. Это, к сожалению, побороть не удалось - открыт к предложениям. Выход только один - указывать дочерний класс элементам, внутри которых только текст без разметки.
И еще одно важное замечание - в плагине есть зависимость, что дочерний элемент (в котором проводится поиск) должен быть в первом уровне вложенности от родителя. Плагин просто перестает работать при сложной верстке (если внутри элемента большая вложенность, а искать нужно по нескольким параметрам).
С автором этого плагина связаться не удалось, поэтому пришлось допилить "на коленке" его творение под свои нужны.
Из плюсов (которые покрывают описанные выше минусы):
- Возможность указание секции для удаления с экрана (parentSectionClass), если внутри нее не найдено совпадений ни в одном из элементов
- Возможность сложной верстки (с неограниченной вложенностью)
- Возможность поиска по нескольким параметрам внутри одного элемента (ищет во всех элементах childBlockClass), если совпадений не найдено - скрывает родителя (parentLookupClass)
- Если все родители скрыты, скрывает секцию (parentSectionClass)
Чтобы активировать плагин, достаточно его инициализировать, предварительно добавив строке поиска нужный класс (в моем случае - search-input):
$('.search-input').jcOnPageFilter({ parentSectionClass:'section', parentLookupClass:'row', childBlockClass:'searchable', });
Для понимания, о чем речь - подготовил демо, где видно, как важно иногда иметь возможность скрывать секцию. Всем успехов!
Еще одна версия доработанного "на коленке" плагина
Сделал новую настройку - parentSearchClass - если нужно указать область поиска. Бывает полезна, если на одной странице планируется сделать более одной строки поиска, которые должны искать в разных местах. Если такой необходимости нет, то можно использовать прошлую версию. Новое демо и архив:
3 версия плагина поиска по тексту
Теперь строке с найденным содержимым - элементам, в которых непосредственно и осуществляется поиск, добавляется класс search-results. Для этого должна быть включена опция: addClassElems:true.
4 версия - добавление класса секции
В 4 версии плагина добавил возможность задать настройку addClassSection:true, которая добавляет класс search-results секции, если в ней найдено хоть одно совпадение. Поясню для чего это нужно. Например, у вас есть список групп. Каждая группа имеет заголовок и список товаров. Вы осуществляете поиск по товарам, но так же и по названию группы. Получается, что если среди товаров совпадений нет - то вся группа скрывается (независимо есть ли совпадение в заголовке). Поэтому можно через стили, используя как раз класс search-results принудительно отобразить группу и все товары, если совпадение по поиску найдено только в заголовке.
5 версия - добавление класса родителю
В предыдущей версии мне показалось, что получится обойтись без этой настройки. Увы, не получилось. Поэтому, впилил еще одну настройку: addClassParent:true,, при которой класс search-results назначается всем родительским элементам, внутри которых есть совпадения по поиску. Важный нюанс: если добавление класса элементам в 3 версии скрипта работает только при включенной опции hideNegatives:true, (включена по-умолчанию - скрывает элементы, в которых ничего не найдено), то добавление класса родительским элементам и секциям работает всегда (если, конечно, они включены).