Работа с URL и history API

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


Настройка фильтрации через URL

Isotope позволяет использовать параметры в URL для задания фильтров. Чаще всего применяется query-параметр filter, где передаётся CSS-селектор соответствующих элементов.

var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  layoutMode: 'fitRows'
});

// Функция для применения фильтра из URL
function applyFilterFromURL() {
  var urlParams = new URLSearchParams(window.location.search);
  var filterValue = urlParams.get('filter') || '*';
  iso.arrange({ filter: filterValue });
}

// Применение фильтра при загрузке страницы
applyFilterFromURL();

Ключевой момент: использование URLSearchParams позволяет безопасно получать параметры фильтров и предотвращает ошибки при отсутствии параметра.


Синхронизация фильтров с History API

Для того чтобы фильтры сетки отражались в URL и можно было использовать кнопки «назад» и «вперед», применяется history.pushState и history.replaceState.

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

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

    // Добавление состояния в историю
    var newUrl = new URL(window.location.href);
    newUrl.searchParams.set('filter', filterValue);
    history.pushState({ filter: filterValue }, '', newUrl);
  });
});

Важное замечание: pushState создаёт новую запись в истории, а replaceState заменяет текущую. Для динамической фильтрации, без создания лишних шагов назад, удобно использовать replaceState.


Обработка события popstate

Событие popstate срабатывает при использовании кнопок навигации браузера. Это позволяет возвращать сетку к состоянию, соответствующему URL.

window.addEventListener('popstate', function(event) {
  var filterValue = '*';
  if (event.state && event.state.filter) {
    filterValue = event.state.filter;
  }
  iso.arrange({ filter: filterValue });
});

Ключевой момент: при первом открытии страницы popstate не вызывается, поэтому начальное состояние следует применять отдельно через проверку URL.


Интеграция сортировки с URL

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

var sortButtons = document.querySelectorAll('.sort-button-group button');

sortButtons.forEach(function(button) {
  button.addEventListener('click', function() {
    var sortValue = button.getAttribute('data-sort-by');
    iso.arrange({ sortBy: sortValue });

    var newUrl = new URL(window.location.href);
    newUrl.searchParams.set('sortBy', sortValue);
    history.pushState({ sortBy: sortValue }, '', newUrl);
  });
});

При обработке popstate необходимо учитывать оба параметра: фильтр и сортировку.

window.addEventListener('popstate', function(event) {
  var filterValue = '*';
  var sortValue = 'original-order';
  
  if (event.state) {
    if (event.state.filter) filterValue = event.state.filter;
    if (event.state.sortBy) sortValue = event.state.sortBy;
  }
  
  iso.arrange({
    filter: filterValue,
    sortBy: sortValue
  });
});

Управление параметрами URL без перезагрузки

Для динамического изменения URL при взаимодействии с Isotope удобно комбинировать History API с URLSearchParams. Это позволяет создавать чистые и читабельные URL.

function updateURL(params) {
  var url = new URL(window.location);
  Object.keys(params).forEach(key => {
    if (params[key] === null) {
      url.searchParams.delete(key);
    } else {
      url.searchParams.set(key, params[key]);
    }
  });
  history.replaceState(params, '', url);
}

Применение:

filterButtons.forEach(button => {
  button.addEventListener('click', function() {
    var filterValue = button.dataset.filter;
    iso.arrange({ filter: filterValue });
    updateURL({ filter: filterValue });
  });
});

Преимущество: при использовании replaceState URL обновляется без создания новых шагов в истории, что важно для фильтров, которые пользователь переключает часто.


Поддержка нескольких фильтров через URL

Isotope поддерживает комбинацию фильтров с помощью CSS-классов. Для передачи нескольких фильтров через URL удобно использовать разделитель, например ,.

var urlParams = new URLSearchParams(window.location.search);
var filtersParam = urlParams.get('filter');
var filters = filtersParam ? filtersParam.split(',') : ['*'];
var filterString = filters.join('');
iso.arrange({ filter: filterString });

Рекомендация: использовать уникальные CSS-классы и однозначный синтаксис разделителей, чтобы избежать конфликтов при декодировании параметров URL.


Динамическая загрузка элементов и URL

При загрузке новых элементов через Ajax необходимо обновлять состояние сетки и URL одновременно. Isotope предоставляет методы appended и layout для интеграции с History API.

fetch('/api/load-more')
  .then(response => response.json())
  .then(data => {
    var elems = data.map(itemHTML => {
      var div = document.createElement('div');
      div.className = 'grid-item';
      div.innerHTML = itemHTML;
      return div;
    });
    grid.append(...elems);
    iso.appended(elems);
    iso.layout();
  });

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


Резюме ключевых практик

  • Использовать URLSearchParams для безопасного извлечения параметров фильтров и сортировки.
  • Применять history.pushState для создания записей истории при значимых действиях и history.replaceState для частых динамических обновлений.
  • Обрабатывать событие popstate для синхронизации состояния сетки с URL при навигации.
  • Обеспечивать поддержку нескольких фильтров через понятный разделитель.
  • Обновлять URL при динамической загрузке элементов, чтобы состояние оставалось консистентным.

Эти методы позволяют создать интерактивную сетку с полным контролем через URL и History API, обеспечивая удобство навигации и корректное поведение при обновлении страницы.