Фильтрация и сортировка элементов на javascript

Фильтрация и сортировка элементов на javascript

Всем привет, сегодня поговорим о том, какие способы сортировки и фильтрации элементов (например, товары в интернет магазине) существуют. Сильные и слабые стороны различных реализаций.

В этой статье мы напишем на javascript фильтр товаров и их сортировку без перезагрузки страницы.

Так же я покажу некоторые подводные камни, возникающие при организации фильтрации элементов.

Содержание статьи:

Давайте определимся с некоторыми терминами:

Фильтрация - это выборка каких-либо элементов из базы данных по определенным параметрам. При этом элементы не подходящие под заданные параметры будут скрыты.

Сортировка - это расположение элементов на странице в определенном порядке, например, по возрастанию цены. В этом случае, в начале списка будут показаны самые дешевые товары, а уже ниже будут товары подороже.

Когда-то давным давно

Когда-то давным давно, когда javascript использовался только для анимаций и слайдеров, все манипуляции с данными производили на стороне сервера.

Например, для того, чтобы отфильтровать товары человек заполнял фильтр, который представлял из себя форму с несколькими полями и нажимал кнопку “Показать”. Далее страница перезагружалась и мы видели товары, попадающие в рамки фильтра.

Принцип работы фильтра в этом случае заключался в следующем:

  • При нажатии на кнопку “Показать” на сервер уходил POST или GET запрос, содержащий критерии фильтра.
  • Серверный скрипт, обрабатывающий этот запрос, анализировал его и отправлял запрос в базу данных.
  • Получив ответ от базы данных, скрипт отправлял пользователя на специальную страницу или перезагружал существующую, на которой и выводился результат поиска.

Примерно по такому же принципу происходила и сортировка товаров, например, по возрастанию или убыванию цены. Только нас не перекидывали на новую страницу, а перезагружали существующую. При этом показывая все товары просто в определенном порядке.

У такого подхода есть большой минус - для каждой фильтрации или сортировки нужно было перезагружать страницу. А при медленном интернете каждая новая перезагрузка вызывает у пользователя только раздражение.

Фильтр товаров на javascript

С развитием веб технологий был придуман способ организации фильтра товаров на javascript c помощью Ajax.

Внешне фильтр все так же выглядит в виде формы с несколькими полями и кнопкой применения фильтра. Немного изменилась лишь логика его работы:

  • Пользователь заполняет поля фильтра и нажимает кнопку “Применить”.
  • Скрипт, написанный уже на javascript срабатывает по событию нажатия кнопки и отправляет Ajax запрос на сервер, показывая при этом индикатор загрузки (спинер).
  • Серверный скрипт обрабатывает запрос и на его основе делает запрос к базе данных с товарами.
  • Далее сервер отправляет ответ, в котором содержится список товаров, попадающих в рамки фильтра.
  • Javascript скрывает спиннер и на основе ответа от сервера показывает полученные товары.

Используя этот способ нет необходимости перезагружать страницу. С сервера приходят данные и на сайте мы перерисовываем только список товаров. Это не только экономит трафик, но и ускоряет работу сайта.

Можно обойтись и без Ajax. В этом случае все товары должны быть загружены на страницу и фильтрация производится только среди них. Логика получается совсем простая - товары не подходящие под фильтр мы просто скрываем. Единственное, у такого подхода могут быть проблемы с версткой:

See the Pen Filter red blocks by Alexandr (@login2030) on CodePen.

В данном примере отфильтруйте элементы, оставив только красные блоки. Как видите, верстка, в этом случае, “плывет”. Это происходит из-за того, что блоки перестроились лишь визуально, а в DOM дереве их положение не изменилось.

Решений у этой проблемы несколько:

  • Перестраивать DOM дерево, чтобы блоки подходящие под фильтр перемещались в начало DOM дерева.
  • Воспользоваться скриптом, который организует сетку для товаров самостоятельно.
  • Переписать верстку на Flexbox.

Давайте разберем все способы по порядку

Перестраивание DOM дерева

В интернете можно найти множество способов, как отсортировать элементы в DOM дереве. Я же предпочитаю пользоваться миниатюрным jQuery плагином sortElements

See the Pen Sort DOM for filter red blocks by Alexandr (@login2030) on CodePen.

Скрипт для организации сетки

Таких скриптов я знаю два - Masonry и Isotope. Эти скрипты очень актуальны в том случае, если фильтруемые блоки имеют разную высоту. Вот пример использования Masonry:

See the Pen Masonry filter red blocks by Alexandr (@login2030) on CodePen.

Обратите внимание на 2 новых блока внутри row:

html
1
2
<div class="grid-sizer"></div>
<div class="gutter-sizer"></div>

grid-sizer необходимо задать такую же ширину, как и нашим блокам item.
gutter-sizer необходимо задать ширину, равную расстоянию между нашими блоками, т.е. 25px.

А при нажатии на кнопку фильтрации, Masonry необходимо обновить:

javascript
1
row.masonry();

Переписать верстку на Flexbox

See the Pen Flexbox filter red blocks by Alexandr (@login2030) on CodePen.

Как Вы можете заметить, верстка при фильтрации не ломается. Но если в нижнем ряду будет 2 элемента, то они будут поровну делить все пространство родителя. А если останется только один элемент, то он разместиться в центре родительского блока.

Сортировка товаров на javascript

Как мы уже знаем из определения, сортировка - это расположение элементов в определенном порядке. В нашем случае сортировать мы будем разноцветные товары. Результатом нашей сортировки будет перемещение всех красных товаров в начало списка. При этом никакие блоки мы теперь скрывать не будем

Сортировка товаров возможна как на стороне сервера, так и на стороне клиента. В данном случае мы рассмотрим сортировку на клиенте, т.е. на javascript.

  • Сортировка товаров по цене, с помощью изменения DOM дерева:

See the Pen Sort elements by Alexandr (@login2030) on CodePen.

Как видно из примера, мы воспользовались тем же плагином sortElements для организации сортировки.

  • Сортировка товаров по цене с помощью Isotope:

See the Pen Isotope sort elements by Alexandr (@login2030) on CodePen.

Как видите, сортировка с помощью Isotope производится с приятной анимацией.

Давайте разберем этот пример более детально. Верстка практически не отличается от остальных примеров, за исключением того, что цена теперь помещена в специальный тег p с классом number:

html
1
2
3
<div class="item">
<p class="number">250р</p>
</div>

Стили перекочевали полностью из примера с Masonry, единственное, что добавились правила для нашего параграфа с ценой:

stylus
1
2
3
.number
reset()
line-height 100px

И наконец сам скрипт:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let row = $('.row'),
item = $('.item');
let isotope = row.isotope({
itemSelector: '.item',
masonry: {
columnWidth: '.grid-sizer',
gutter: '.gutter-sizer'
},
getSortData: {
number: '.number parseInt',
}
});
$('#descending').on('click', ()=> {
isotope.isotope({
sortBy: 'number',
sortAscending: false
})
});
$('#аscending').on('click', ()=> {
isotope.isotope({
sortBy: 'number',
sortAscending: true
});
});

В Isotope masonry является одним из вариантов лейоута, поэтому указываем его в настройке

javascript
1
2
3
4
masonry: {
columnWidth: '.grid-sizer',
gutter: '.gutter-sizer'
}

Далее идет настройка:

javascript
1
2
3
getSortData: {
number: '.number parseInt',
}

В которой мы указываем скрипту, по какому значению будем сортировать список товаров. Сортировать мы будем по тому, что находится внутри класса number, а так же, мы приведем это к числу с помощью parseInt.

Далее идут обработчики кликов на кнопки. Стоит отметить, что поле sortAscending отвечает непосредственно за порядок сортировки. По умолчанию оно установлено в true и сортирует в порядке 1,2,3,4,5, а если поставить его в false, то сортировка будет в обратном направлении. Только не забудьте указать параметр sortAscending в обоих случаях, так как автоматически он не переключается.

Более подробную информацию Вы найдете в [ Документации ]

Заключение

В этой статье я рассказал каким образом можно фильтровать и сортировать элементы на стороне клиента.

Если Вам понравилась статья, то можете поделиться ей в социальных сетях.

Если что-то не поняли или есть какие-то вопросы, то пишите комментарии, я постараюсь помочь.

Важно помнить, что все примеры в статье являются демонстрационными и не претендуют быть самыми лучшими =)