Восстановление порядка

SortableJS — это легковесная библиотека на JavaScript, предназначенная для реализации интерактивного перетаскивания элементов списка с сохранением их порядка. Основная цель библиотеки — предоставить разработчику гибкий инструмент для создания drag-and-drop интерфейсов, поддерживающих работу с DOM-элементами без необходимости глубокого взаимодействия с низкоуровневыми событиями мыши или тачскрина.

Ключевые возможности:

  • Drag-and-drop элементов с любого места списка.
  • Поддержка вложенных списков и групп элементов.
  • Обработка событий на старте, движении, окончании перетаскивания.
  • Сортировка на лету с визуальными эффектами и плавными анимациями.
  • Поддержка сенсорных экранов и кроссбраузерная совместимость.

Инициализация и базовое использование

Для начала работы достаточно подключить библиотеку и вызвать конструктор Sortable для контейнера элементов:

import Sortable from 'sortablejs';

const list = document.getElementById('my-list');

const sortable = Sortable.create(list, {
    animation: 150,
    ghostClass: 'sortable-ghost',
    chosenClass: 'sortable-chosen'
});

Пояснения к параметрам:

  • animation — продолжительность анимации в миллисекундах при перемещении элементов.
  • ghostClass — CSS-класс, применяемый к элементу, который перемещается.
  • chosenClass — класс для выбранного элемента до завершения перетаскивания.

Управление порядком элементов

SortableJS позволяет не только менять визуальный порядок элементов, но и отслеживать и сохранять порядок в данных. Основной механизм — события onEnd и методы toArray, sort:

sortable.option("onEnd", function(evt) {
    const order = sortable.toArray(); // Получение текущего порядка элементов
    console.log(order);
});
  • evt.oldIndex — исходная позиция элемента.
  • evt.newIndex — новая позиция после перетаскивания.

Метод toArray() возвращает массив идентификаторов элементов, что удобно для синхронизации с сервером или локальным хранилищем.


Восстановление порядка

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

const initialOrder = sortable.toArray();

// Функция для восстановления порядка
function restoreOrder() {
    const items = sortable.el.children;
    initialOrder.forEach(id => {
        const item = document.getElementById(id);
        sortable.el.appendChild(item);
    });
}

Особенности метода:

  • Элементы перемещаются обратно в соответствии с initialOrder.
  • Порядок в DOM полностью восстанавливается, что сохраняет правильную работу событий и стилей.
  • Метод работает для списков любого размера и структуры, включая вложенные контейнеры, если обрабатывать их рекурсивно.

Группы и взаимная сортировка

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

const sortableA = Sortable.create(listA, { group: 'shared' });
const sortableB = Sortable.create(listB, { group: 'shared' });

const initialOrderA = sortableA.toArray();
const initialOrderB = sortableB.toArray();

function restoreAll() {
    initialOrderA.forEach(id => listA.appendChild(document.getElementById(id)));
    initialOrderB.forEach(id => listB.appendChild(document.getElementById(id)));
}

Использование групп обеспечивает:

  • Перетаскивание элементов между списками без потери идентификаторов.
  • Гибкую логику восстановления порядка, применяемую к каждому списку индивидуально.

Настройка анимации при восстановлении

Чтобы визуально подчеркнуть возвращение элементов в исходный порядок, можно включить анимацию SortableJS при изменении DOM:

sortable.option("animation", 300);
restoreOrder();
  • animation работает как при пользовательском перетаскивании, так и при программном перемещении элементов.
  • Для улучшенной визуализации можно комбинировать с классами chosenClass и ghostClass.

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

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

function addItem(text) {
    const li = document.createElement('li');
    li.id = `item-${Date.now()}`;
    li.textContent = text;
    sortable.el.appendChild(li);
    initialOrder.push(li.id);
}
  • Каждому новому элементу присваивается уникальный id.
  • initialOrder синхронизируется с добавленными элементами.

События и контроль состояния

Для сложных интерфейсов полезно использовать полный набор событий SortableJS:

  • onStart — момент начала перетаскивания.
  • onEnd — завершение перемещения элемента.
  • onAdd — добавление элемента из другого списка.
  • onUpdate — изменение порядка внутри списка.
  • onRemove — удаление элемента из списка.

С помощью этих событий можно:

  • Поддерживать историю изменений.
  • Сохранять порядок в базе данных или localStorage.
  • Реализовать откат к исходному состоянию в любой момент.

Практические советы

  • Всегда присваивать уникальные id элементам, если требуется восстановление порядка.
  • Для больших списков использовать requestAnimationFrame при массовом восстановлении DOM, чтобы избежать «подвисания» интерфейса.
  • При работе с несколькими списками лучше хранить отдельные массивы порядка для каждого, чтобы избежать конфликтов.
  • Использовать CSS-классы ghostClass и chosenClass для визуального контроля состояния элементов.