sortable:sorted и sortable:stop

Библиотека Shopify Draggable предоставляет мощный API для реализации перетаскиваемых элементов (drag & drop) в веб-приложениях. Среди ключевых событий, связанных с сортировкой элементов, выделяются sortable:sorted и sortable:stop, которые позволяют отслеживать изменения порядка и завершение операций перетаскивания.


sortable:sorted

Событие sortable:sorted вызывается в момент, когда элемент был перемещён и помещён на новую позицию внутри контейнера. Оно возникает после того, как DOM обновляется, но до завершения всей операции сортировки.

Основные параметры события

draggable.on('sortable:sorted', (event) => {
  console.log(event.oldIndex); // Индекс элемента до перемещения
  console.log(event.newIndex); // Новый индекс после перемещения
  console.log(event.item);     // DOM-элемент, который был перемещён
  console.log(event.source);   // Контейнер, из которого элемент переместили
  console.log(event.over);     // Контейнер, в который элемент помещён
});

Ключевые свойства объекта события:

  • item — перетаскиваемый DOM-элемент.
  • source — исходный контейнер, из которого элемент был перемещён.
  • over — целевой контейнер, в который элемент помещён (в случае drag между несколькими контейнерами).
  • oldIndex — индекс элемента до перемещения.
  • newIndex — индекс элемента после перемещения.

Применение sortable:sorted

  • Обновление данных на клиенте: синхронизация массива элементов с новым порядком.
  • Отправка изменений на сервер: можно делать AJAX-запросы для сохранения позиции элементов.
  • Анимации и визуальная обратная связь: добавление эффекта подсветки или плавного перемещения.

Пример обновления массива:

const items = ['A', 'B', 'C', 'D'];

draggable.on('sortable:sorted', (event) => {
  const movedItem = items.splice(event.oldIndex, 1)[0];
  items.splice(event.newIndex, 0, movedItem);
  console.log(items); // ['A', 'C', 'B', 'D'] если B перемещён с индекса 1 на 2
});

sortable:stop

Событие sortable:stop срабатывает после завершения всей операции drag & drop, когда пользователь отпустил элемент и нет никаких активных перемещений. В отличие от sortable:sorted, оно не срабатывает на каждом изменении позиции, а только один раз в конце сортировки.

Основные параметры события

draggable.on('sortable:stop', (event) => {
  console.log(event.oldIndex); // Индекс элемента до начала перетаскивания
  console.log(event.newIndex); // Индекс элемента после завершения перетаскивания
  console.log(event.item);     // DOM-элемент, который завершил перетаскивание
  console.log(event.source);   // Контейнер, из которого элемент переместили
});

Отличительные особенности:

  • sortable:stop может срабатывать даже если порядок элементов не изменился, но drag был инициирован.
  • Идеально подходит для финальной синхронизации состояния, например, отправки окончательного порядка на сервер.
  • Используется для очистки временных стилей, добавленных во время drag: классы dragging, mirror и т.п.

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

draggable.on('sortable:stop', (event) => {
  const updatedOrder = Array.from(event.source.children).map(el => el.dataset.id);
  
  fetch('/update-order', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ order: updatedOrder })
  });
});

Различие между sortable:sorted и sortable:stop

Параметр sortable:sorted sortable:stop
Когда вызывается После изменения позиции элемента После завершения drag & drop
Частота срабатывания Каждый раз при изменении позиции Один раз после окончания перемещения
Использование Мгновенное обновление порядка, визуальные эффекты Финальная синхронизация, очистка стилей
Доступные свойства item, source, over, oldIndex, newIndex item, source, oldIndex, newIndex

Практические рекомендации

  1. Комбинирование событий: часто используют оба события — sortable:sorted для обновления интерфейса и sortable:stop для окончательного сохранения данных.
  2. Обновление массива элементов: работать с oldIndex и newIndex необходимо аккуратно, чтобы не нарушить порядок элементов при нескольких последовательных перемещениях.
  3. Стилизация элементов: добавление класса draggable--moving на sortable:sorted и его удаление на sortable:stop позволяет визуально показать активный drag.
  4. Мультиконтейнерный drag: sortable:sorted предоставляет over контейнер, что важно при перемещении элементов между списками.

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

const draggable = new Draggable.Sortable(document.querySelectorAll('.list'), {
  draggable: '.item'
});

draggable.on('sortable:sorted', (event) => {
  const movedItem = event.item;
  movedItem.classList.add('highlight');
});

draggable.on('sortable:stop', (event) => {
  Array.from(event.source.children).forEach(el => el.classList.remove('highlight'));

  const newOrder = Array.from(event.source.children).map(el => el.dataset.id);
  console.log('Окончательный порядок:', newOrder);
});

В этом примере элемент подсвечивается в процессе перемещения и возвращается к нормальному виду после завершения drag. Окончательный порядок элементов фиксируется и может быть отправлен на сервер.


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