Сортировка по пользовательским критериям

В библиотеке Muuri сортировка элементов осуществляется с помощью метода sort(), который позволяет управлять порядком отображения элементов в сетке на основе различных критериев. Основное преимущество Muuri — возможность создавать динамические и кастомные правила сортировки, используя свойства элементов, атрибуты HTML или даже внешние данные.

grid.sort((itemA, itemB) => {
    return itemA.getElement().dataset.value - itemB.getElement().dataset.value;
});

В этом примере элементы сортируются по числовому значению, хранящемуся в data-value. Метод getElement() возвращает DOM-элемент, связанный с объектом Muuri Item, что позволяет обращаться к любым его атрибутам или содержимому.


Использование предопределённых критериев

Muuri предоставляет несколько встроенных критериев сортировки:

  • 'original-order' — возвращает элементы в исходный порядок DOM.
  • 'desc' — сортировка по убыванию.
  • 'asc' — сортировка по возрастанию.
  • 'random' — случайная перестановка элементов.

Пример использования встроенного критерия:

grid.sort('asc'); // Сортирует элементы по их индексу в DOM
grid.sort('random'); // Перемешивает элементы случайным образом

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


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

Для сложных сценариев используется пользовательская функция сортировки, передаваемая в sort() вместо строки. Такая функция получает два объекта Item и должна вернуть числовое значение:

  • отрицательное числоitemA будет перед itemB
  • положительное числоitemB будет перед itemA
  • ноль — порядок элементов не изменится

Пример сортировки по алфавиту текста внутри элемента:

grid.sort((itemA, itemB) => {
    const textA = itemA.getElement().textContent.trim().toLowerCase();
    const textB = itemB.getElement().textContent.trim().toLowerCase();
    return textA.localeCompare(textB);
});

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

grid.sort((itemA, itemB) => {
    const valueA = parseInt(itemA.getElement().dataset.value, 10);
    const valueB = parseInt(itemB.getElement().dataset.value, 10);
    if (valueA !== valueB) return valueA - valueB;

    const nameA = itemA.getElement().textContent.trim();
    const nameB = itemB.getElement().textContent.trim();
    return nameA.localeCompare(nameB);
});

Здесь сначала сортировка выполняется по числовому значению, а при равных значениях — по тексту.


Асинхронная сортировка и обновление сетки

В случае, если данные для сортировки поступают асинхронно, можно динамически пересортировать элементы после получения данных.

fetch('/api/items')
    .then(res => res.json())
    .then(data => {
        grid.getItems().forEach(item => {
            const element = item.getElement();
            const newValue = data[element.dataset.id];
            element.dataset.value = newValue;
        });
        grid.sort((a, b) => a.getElement().dataset.value - b.getElement().dataset.value);
    });

Метод sort() автоматически анимирует переходы элементов в новое положение. Поскольку Muuri использует CSS трансформации, перестановка выглядит плавной без необходимости дополнительных библиотек анимации.


Сортировка с сохранением групп

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

const groupItems = grid.getItems().filter(item => item.getElement().dataset.group === 'featured');
grid.sort((a, b) => groupItems.indexOf(a) - groupItems.indexOf(b));

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


Интеграция с пользовательскими данными

Muuri позволяет использовать внешние объекты и массивы данных для контроля порядка элементов. Например, если есть массив приоритетов:

const priorityOrder = ['high', 'medium', 'low'];
grid.sort((itemA, itemB) => {
    const priorityA = itemA.getElement().dataset.priority;
    const priorityB = itemB.getElement().dataset.priority;
    return priorityOrder.indexOf(priorityA) - priorityOrder.indexOf(priorityB);
});

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


Адаптивная сортировка

Muuri поддерживает динамическое пересортирование при изменении содержимого элементов или их атрибутов. Для этого используется событие on('layoutEnd') или вызов refreshItems() перед сортировкой:

grid.refreshItems().sort((a, b) => {
    return parseInt(a.getElement().dataset.value) - parseInt(b.getElement().dataset.value);
});

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


Основные рекомендации

  • Использовать getElement() для доступа к DOM и атрибутам элементов.
  • Для числовой сортировки применять parseInt() или parseFloat().
  • Для текстовой сортировки использовать localeCompare() для корректной работы с разными языками.
  • Сортировку можно комбинировать с фильтрацией, чтобы контролировать подмножества элементов.
  • Асинхронные данные можно интегрировать, изменяя dataset элементов перед вызовом sort().

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