Фильтрация блоков на jQuery | Блог веб-разработчика MaxGraph

Фильтрация блоков на jQuery

Привет! Рассмотрим сегодня, как сделать фильтрацию элементов по классу. Допустим, Вы имеете каталог товаров, и нужно по клику на фильтр вывести только определенную группу товаров. Вот это как раз об этом) Поехали!

Общее (Фильтрация блоков на jQuery)

Пример подобной фичи можно посмотреть тут. Как раз есть каталог, а сверху него выборка по полу, форме кроватки и т.д. Очень удобно. Ну а теперь непосредственно к тому, как такое реализовать.

Разметка

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
<div class="filter">
  <div class="filter__nav">
    <ul class="filter__nav-group" data-filter-group="group">
      <li><a href="#" class="button" data-filter=".group1">Группа1</a></li>
      <li><a href="#" class="button" data-filter=".group2">Группа2</a></li>
      <li><a href="#" class="button" data-filter=".group3">Группа3</a></li>
    </ul>
    <ul class="filter__nav-group" data-filter-group="season">
      <li><a href="#" class="button" data-filter=".winter">Зима</a></li>
      <li><a href="#" class="button" data-filter=".summer">Лето</a></li>
    </ul>
    <ul>
      <li>
        <a href="#" class="reset">Сбросить</a>
      </li>
    </ul>
  </div>
  
  <div class="filter__content">
    <div class="nothing">Ничего нет</div>
    <div class="filter__content-item group1 winter">Зима</div>
    <div class="filter__content-item group2 winter">Зима</div>
    <div class="filter__content-item group1 summer">Лето</div>
    <div class="filter__content-item group2 summer">Лето</div>
  </div>
</div>
<div class="filter">
  <div class="filter__nav">
    <ul class="filter__nav-group" data-filter-group="group">
      <li><a href="#" class="button" data-filter=".group1">Группа1</a></li>
      <li><a href="#" class="button" data-filter=".group2">Группа2</a></li>
      <li><a href="#" class="button" data-filter=".group3">Группа3</a></li>
    </ul>
    <ul class="filter__nav-group" data-filter-group="season">
      <li><a href="#" class="button" data-filter=".winter">Зима</a></li>
      <li><a href="#" class="button" data-filter=".summer">Лето</a></li>
    </ul>
    <ul>
      <li>
        <a href="#" class="reset">Сбросить</a>
      </li>
    </ul>
  </div>
  
  <div class="filter__content">
    <div class="nothing">Ничего нет</div>
    <div class="filter__content-item group1 winter">Зима</div>
    <div class="filter__content-item group2 winter">Зима</div>
    <div class="filter__content-item group1 summer">Лето</div>
    <div class="filter__content-item group2 summer">Лето</div>
  </div>
</div>

Собственно, что нам здесь нужно. Мы имеем два главных блока — filter__nav и filter__content, которые отвечают соответственно за навигацию (фильтрацию) и контент, который будет фильтроваться. Очень важны так называемые «триггеры» — data-filter-group=»» и data-filter=»», т.к. с помощью них и работает «магия». Первый отвечает за связь нескольких групп (иначе говоря мы можем сортировать сразу по нескольким признакам, и в таком случае они у нас будут складываться), а второй непосредственно за класс. Ну и в filter__content мы видим несколько элементов, которые имеют классы group1, winter и т.д. По этим классам как раз и идет фильтр.

Так же у нас есть кнопка «сбросить» для сброса всех фильтров. Ну, и как мы видим, для усложнения примера я как раз и добавил две группы, чтобы показать, как именно происходит выборка блоков по двум разным признакам.

CSS

Сюда не стал вставлять этот код, т.к. он на работу никак не влияет, но в конце статьи будет ссылка на codepen, сможете потыкать.

jQuery

Тут давайте пойдем по частям кода:

concatValues

1
2
3
4
5
6
7
function concatValues(obj) {
  var value = '';
  for ( var prop in obj ) {
    value += obj[ prop ];
  }
  return value;
}
function concatValues(obj) {
  var value = '';
  for ( var prop in obj ) {
    value += obj[ prop ];
  }
  return value;
}

Первая функция concatValues. Сейчас она из себя по сути ничего не представляет, но по названию можно понять, что же она делает, а именно берет значение фильтра и складывает его с другим, именно таким образом (судя по нашему html-коду будет фильтрация происходить одновременно по полю group и по полю season).

Переменные

1
2
3
4
5
6
let $grid = $('.filter__content'),
$item = $grid.find('.filter__content-item'),
filterButtons = $('.filter__nav'),
filters = {},
filterValue = '',
filtered = '';
let $grid = $('.filter__content'),
$item = $grid.find('.filter__content-item'),
filterButtons = $('.filter__nav'),
filters = {},
filterValue = '',
filtered = '';

Задаем переменные. $grid — для определения контейнера фильтруемых блоков, $item — один из этих блоков, $filterButtons — контейнер для кнопок фильтрации, а так же три пустых пока переменных, filters — объект с данными фильтрации, filterValue — строка со складываемыми значениями фильтра (в нашем случае это может быть, к примеру, .group1.winter),и filtered — псевдомассив с хранящимися отфильтрованными блоками.

Обработчик  $(‘.filter__nav-group’)

1
2
3
4
5
6
7
8
9
$('.filter__nav-group').each(function(i, buttonGroup) {
  var $buttonGroup = $(buttonGroup);
  $buttonGroup.on('click', '.button', function(event) {
  $('.all-button').removeClass('active');
    $buttonGroup.find('.active').removeClass('active');
    var $button = $(event.currentTarget);
    $button.addClass('active');
  });
});
$('.filter__nav-group').each(function(i, buttonGroup) {
  var $buttonGroup = $(buttonGroup);
  $buttonGroup.on('click', '.button', function(event) {
  $('.all-button').removeClass('active');
    $buttonGroup.find('.active').removeClass('active');
    var $button = $(event.currentTarget);
    $button.addClass('active');
  });
});

Первая функция довольно простая — она смотрит на все группы фильтрации и при клике на кнопки дает класс active одному элементу из группы (по которому нажали естественно).

Обработчик filterButtons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
filterButtons.on('click','.button', function(e){
  e.preventDefault();
  let $button = $(e.currentTarget);
  let $buttonGroup = $button.parents('.filter__nav-group');
  let filterGroup = $buttonGroup.attr('data-filter-group');
  filters[filterGroup] = $button.attr('data-filter');
  filterValue = concatValues(filters);
  filtered = $item.filter(filterValue);
  let length = filtered.length;
  if (length == 0) {
    $('.nothing').show();
    $('.nothing').css('display','flex');
  } else {
    $('.nothing').hide();
  }
  $item.hide();
  filtered.show();
});
filterButtons.on('click','.button', function(e){
  e.preventDefault();
  let $button = $(e.currentTarget);
  let $buttonGroup = $button.parents('.filter__nav-group');
  let filterGroup = $buttonGroup.attr('data-filter-group');
  filters[filterGroup] = $button.attr('data-filter');
  filterValue = concatValues(filters);
  filtered = $item.filter(filterValue);
  let length = filtered.length;
  if (length == 0) {
    $('.nothing').show();
    $('.nothing').css('display','flex');
  } else {
    $('.nothing').hide();
  }
  $item.hide();
  filtered.show();
});

А вот тут наконец самая главная и сложная магия.

При клике на кнопку определяем переменную для группы фильтрации. Затем, через запись filters[filterGroup] = $button.attr(‘data-filter’); заносим в объект filters значение фильтра (взятое из дата-атрибута кнопки).

Ну а дальше, при помощи filterValue = concatValues(filters); filtered = $item.filter(filterValue); сперва в filterValue получаем как раз таки строку со всеми фильтруемыми классами, а затем через метод filter получаем в переменную filtered псевдомассив с нужными блоками.

Остается одно — скрыть сперва ВСЕ блоки, а затем показать только filtered. Что мы и делаем.

Плюс видим что есть еще переменная length и некое условие. Тут как раз и проверяется, если length (кол-во фильтруемых блоков) равно нулю — блоки не покажутся, а вместо них покажется блок .nothing, в котором написано, что ничего не найдено. Это удобно в плане user friendly.

reset

1
2
3
4
5
6
7
$('.reset').click(function(e){
  e.preventDefault();
  filters = {};
  $item.show();
  $('.button').removeClass('active');
  $('.nothing').hide();
});
$('.reset').click(function(e){
  e.preventDefault();
  filters = {};
  $item.show();
  $('.button').removeClass('active');
  $('.nothing').hide();
});

Ну и сброс. Тоже удобная фича. Здесь просто сбрасываем все к начальным значениям (снова делаем объект filters пустым, показываем все блоки, удаляем класс active у кнопок и скрываем .nothing).

codepen — пример

Ну и чтобы Вам было совсем удобно — вот рабочий пример.

 

Надеюсь, Вам было интересно и познавательно. А главное — полезно в работе :) До скорых встреч!

Метки: , , ,

Понравилось? Оцени!
12345 (Пока оценок нет)
Загрузка...

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *