Сортировка по атрибутам

Библиотека Muuri предоставляет мощный механизм для динамического управления сеткой элементов. Одной из ключевых возможностей является сортировка элементов по их атрибутам, что позволяет организовать контент в зависимости от данных, хранящихся в элементах.

Настройка элементов с атрибутами

Элементы, которые необходимо сортировать, должны содержать пользовательские атрибуты, например:

<div class="grid">
  <div class="item" data-name="Яблоко" data-price="50"></div>
  <div class="item" data-name="Банан" data-price="30"></div>
  <div class="item" data-name="Виноград" data-price="70"></div>
</div>

Здесь используется два атрибута: data-name и data-price. Эти атрибуты станут основой для сортировки по различным критериям.

Инициализация Muuri

Сетка создаётся следующим образом:

const grid = new Muuri('.grid', {
  dragEnabled: true,
  layout: {
    rounding: false
  }
});

Опция dragEnabled позволяет перетаскивать элементы, а layout.rounding контролирует округление координат при перестроении сетки.

Использование функции сортировки

Метод sort() позволяет определить порядок элементов. Для сортировки по атрибуту необходимо передать функцию:

grid.sort((itemA, itemB) => {
  const priceA = parseInt(itemA.getElement().dataset.price, 10);
  const priceB = parseInt(itemB.getElement().dataset.price, 10);
  return priceA - priceB;
});

Пояснение:

  • itemA.getElement() — возвращает DOM-элемент элемента сетки.
  • dataset.price — получает значение атрибута data-price.
  • parseInt(..., 10) — преобразует строку в число.
  • Функция возвращает отрицательное, нулевое или положительное значение, определяющее порядок элементов.

Сортировка по алфавиту

Для сортировки по строковым атрибутам, например data-name, используется стандартное сравнение строк:

grid.sort((itemA, itemB) => {
  const nameA = itemA.getElement().dataset.name.toLowerCase();
  const nameB = itemB.getElement().dataset.name.toLowerCase();
  if (nameA < nameB) return -1;
  if (nameA > nameB) return 1;
  return 0;
});

Использование toLowerCase() обеспечивает регистронезависимую сортировку, что особенно важно при работе с текстовыми данными.

Комбинированная сортировка

Можно сортировать по нескольким атрибутам одновременно. Например, сначала по цене, а затем по имени:

grid.sort((itemA, itemB) => {
  const priceA = parseInt(itemA.getElement().dataset.price, 10);
  const priceB = parseInt(itemB.getElement().dataset.price, 10);

  if (priceA !== priceB) {
    return priceA - priceB;
  }

  const nameA = itemA.getElement().dataset.name.toLowerCase();
  const nameB = itemB.getElement().dataset.name.toLowerCase();

  if (nameA < nameB) return -1;
  if (nameA > nameB) return 1;
  return 0;
});

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

Динамическая перестройка сетки

После изменения атрибутов элементов можно заново отсортировать сетку:

itemElement.dataset.price = "45";
grid.refreshItems().sort((a, b) => parseInt(a.getElement().dataset.price, 10) - parseInt(b.getElement().dataset.price, 10));

Метод refreshItems() обновляет внутренние данные Muuri, что гарантирует корректную сортировку после изменения атрибутов.

Плавная анимация при сортировке

Muuri обеспечивает анимацию при перестановке элементов. Для тонкой настройки можно использовать параметры layout:

grid.sort(...).layout({
  duration: 400,
  easing: 'ease-in-out'
});
  • duration — время анимации в миллисекундах.
  • easing — функция плавности перехода (linear, ease-in, ease-out, ease-in-out).

Сортировка с фильтрацией

Для комбинирования сортировки и фильтрации можно использовать filter() и sort() совместно:

grid.filter(item => parseInt(item.getElement().dataset.price, 10) > 40)
    .sort((a, b) => parseInt(a.getElement().dataset.price, 10) - parseInt(b.getElement().dataset.price, 10));

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

Поддержка обратного порядка

Для сортировки в обратном порядке достаточно изменить направление сравнения:

grid.sort((itemA, itemB) => {
  const priceA = parseInt(itemA.getElement().dataset.price, 10);
  const priceB = parseInt(itemB.getElement().dataset.price, 10);
  return priceB - priceA;
});

Это удобно для реализации функций «от дорогого к дешевому» или «от Z до A».

Советы по оптимизации

  • Для больших сеток рекомендуется использовать предварительную обработку данных перед сортировкой, чтобы избежать многократного обращения к DOM.
  • Использование dataset вместо getAttribute() ускоряет доступ к атрибутам.
  • В комбинации с dragEnabled сортировка может быть интегрирована с перетаскиванием для создания интерактивного опыта.