Сохранение и восстановление фильтров

Isotope — это мощная библиотека для динамической фильтрации, сортировки и расположения элементов на веб-странице. Одной из ключевых задач при работе с интерактивными интерфейсами является сохранение текущего состояния фильтров и их восстановление при повторной загрузке страницы или переходе между вкладками. Это обеспечивает пользователю плавный и предсказуемый опыт взаимодействия с контентом.


Сохранение фильтров через localStorage

Для хранения текущего фильтра удобно использовать localStorage, который позволяет сохранять данные между сессиями браузера. Пример подхода:

// Инициализация Isotope
var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  layoutMode: 'fitRows'
});

// Функция применения фильтра
function applyFilter(filterValue) {
  iso.arrange({ filter: filterValue });
  // Сохраняем текущий фильтр
  localStorage.setItem('currentFilter', filterValue);
}

// Восстановление фильтра при загрузке страницы
var savedFilter = localStorage.getItem('currentFilter');
if (savedFilter) {
  applyFilter(savedFilter);
}

Ключевой момент: метод arrange({ filter: ... }) не только применяет фильтр к элементам, но и обеспечивает корректную анимацию расположения.


Работа с несколькими фильтрами

Когда требуется поддержка нескольких фильтров одновременно, например фильтр по категории и по тегу, можно хранить состояние в виде объекта JSON:

var filterState = {
  category: '*',
  tag: '*'
};

// Обновление фильтра
function updateFilter(type, value) {
  filterState[type] = value;
  var filterString = concatFilters(filterState);
  iso.arrange({ filter: filterString });
  localStorage.setItem('filterState', JSON.stringify(filterState));
}

// Конкатенация фильтров
function concatFilters(state) {
  var filters = [];
  if(state.category !== '*') filters.push('.' + state.category);
  if(state.tag !== '*') filters.push('.' + state.tag);
  return filters.length ? filters.join('') : '*';
}

// Восстановление при загрузке
var savedState = JSON.parse(localStorage.getItem('filterState'));
if(savedState) {
  filterState = savedState;
  iso.arrange({ filter: concatFilters(filterState) });
}

Выделение важного: правильное формирование строки фильтров критично для корректного отображения. Isotope поддерживает объединение классов через конкатенацию (например, .category-tag), поэтому генерация строки должна учитывать все активные фильтры.


Сохранение сортировки и порядка элементов

Помимо фильтров, часто важно восстановить и сортировку:

// Сортировка элементов по атрибуту data-name
function sortItems(sortBy) {
  iso.arrange({ sortBy: sortBy });
  localStorage.setItem('sortBy', sortBy);
}

// Восстановление сортировки
var savedSort = localStorage.getItem('sortBy');
if(savedSort) {
  iso.arrange({ sortBy: savedSort });
}

Isotope поддерживает несколько критериев сортировки одновременно, используя объект sortAscending:

iso.arrange({
  sortBy: ['name', 'price'],
  sortAscending: { name: true, price: false }
});

Для сохранения такого сложного состояния также удобно использовать JSON.


Использование URL-параметров для сохранения фильтров

Иногда требуется, чтобы состояние фильтров было доступно по ссылке. Для этого можно использовать URL-параметры:

function setFilterInURL(filterValue) {
  var url = new URL(window.location);
  url.searchParams.set('filter', filterValue);
  window.history.replaceState({}, '', url);
}

function getFilterFromURL() {
  var urlParams = new URLSearchParams(window.location.search);
  return urlParams.get('filter') || '*';
}

var initialFilter = getFilterFromURL();
iso.arrange({ filter: initialFilter });

Преимущество этого подхода — возможность делиться ссылкой с конкретным состоянием фильтров.


Автоматическое восстановление при взаимодействии с интерфейсом

Для кнопок фильтров удобно добавлять обработчик клика, который автоматически обновляет как Isotope, так и сохранённое состояние:

var filterButtons = document.querySelectorAll('.filter-button');

filterButtons.forEach(function(button) {
  button.addEventListener('click', function() {
    var filterValue = button.getAttribute('data-filter');
    applyFilter(filterValue);
    updateActiveButton(button);
  });
});

function updateActiveButton(activeButton) {
  filterButtons.forEach(btn => btn.classList.remove('is-active'));
  activeButton.classList.add('is-active');
}

Важно: синхронизация состояния кнопок с сохранёнными фильтрами позволяет визуально отобразить активный фильтр после перезагрузки страницы.


Работа с динамическим контентом

Если элементы на странице добавляются динамически, Isotope требует вызова метода appended или reloadItems перед применением фильтров:

// Добавление новых элементов
var newElements = document.querySelectorAll('.grid .new-item');
iso.appended(newElements);
iso.arrange({ filter: concatFilters(filterState) });

Это гарантирует, что все новые элементы корректно попадут под текущие фильтры.


Резюме основных принципов

  1. localStorage и URL-параметры — основные способы сохранения состояния фильтров.
  2. Состояние фильтров можно хранить как простую строку для одного фильтра, или как объект JSON для множественных фильтров.
  3. Для восстановления фильтров при загрузке страницы необходимо корректно формировать строку фильтров и применять её через arrange().
  4. Синхронизация интерфейса и состояния фильтров обеспечивает предсказуемость и удобство для пользователя.
  5. При работе с динамическим контентом важно использовать методы appended и reloadItems для интеграции новых элементов с текущим состоянием.

Хотите, я подготовлю отдельный подробный блок с примерами для комбинирования фильтров и сортировки вместе с динамическим сохранением состояния, который можно вставлять прямо в учебник? Это будет логическое продолжение этой главы.