Обработка успешного drop

В Shopify Draggable событие drop является ключевым для управления логикой после перемещения элемента. Оно срабатывает, когда draggable-элемент успешно был перемещён и отпущен над допустимой зоной (drop zone). Для корректной работы важно понимать структуру объекта события и методы, доступные внутри обработчика.


Основные свойства объекта события drop

Объект события drop содержит несколько критически важных свойств:

  • source – DOM-элемент, который был перемещён.
  • mirror – визуальная копия элемента, используемая для drag-and-drop. Она создаётся автоматически Draggable и удаляется после завершения операции.
  • container – контейнер, в котором находился исходный элемент.
  • droppable – целевой drop zone, на который был произведён drop. Может быть null, если элемент был отпущен вне зоны.
  • originalEvent – нативное событие браузера (MouseEvent или TouchEvent), связанное с действием пользователя.

Пример базового обработчика drop:

draggable.on('droppable:drop', (event) => {
  const draggedElement = event.source;
  const dropZone = event.droppable;

  if (dropZone) {
    dropZone.appendChild(draggedElement);
    console.log('Элемент успешно перемещён:', draggedElement);
  }
});

Разделение логики на события: droppable:over, droppable:out, droppable:drop

Draggable использует систему событий, которая позволяет отделять стадии drag-and-drop:

  • droppable:over – элемент находится над drop zone.
  • droppable:out – элемент покинул drop zone.
  • droppable:drop – элемент был отпущен в drop zone.

Для успешной обработки drop важно учитывать состояние предыдущих событий. Например, можно изменить стиль drop zone при наведении и вернуть его при уходе элемента:

draggable.on('droppable:over', (event) => {
  event.droppable.classList.add('highlight');
});

draggable.on('droppable:out', (event) => {
  event.droppable.classList.remove('highlight');
});

draggable.on('droppable:drop', (event) => {
  event.droppable.classList.remove('highlight');
  event.droppable.appendChild(event.source);
});

Использование cancel() и stop() в drop-обработчиках

Иногда необходимо предотвратить выполнение стандартного поведения при drop или остановить дальнейшее распространение события. Draggable предоставляет два метода:

  • event.cancel() – отменяет стандартное поведение drop, элемент возвращается на исходное место.
  • event.stop() – прекращает дальнейшую обработку события другими подписчиками.

Пример с проверкой условий:

draggable.on('droppable:drop', (event) => {
  if (!event.droppable.classList.contains('active')) {
    event.cancel();
    console.log('Drop запрещён для этой зоны');
  } else {
    console.log('Drop разрешён');
  }
});

Анимация и плавная интеграция элементов после drop

Для создания визуальной плавности рекомендуется работать с CSS-трансформациями и анимацией добавляемого элемента. После drop можно:

  • Изменить позицию с помощью transform для плавного перемещения.
  • Добавить класс для CSS-анимации.
  • Использовать requestAnimationFrame для синхронизации с браузером.

Пример анимации перемещения:

draggable.on('droppable:drop', (event) => {
  const el = event.source;
  const dropZone = event.droppable;

  dropZone.appendChild(el);
  el.style.transition = 'transform 0.3s ease';
  el.style.transform = 'translate(0, 0)';

  el.addEventListener('transitionend', () => {
    el.style.transition = '';
    el.style.transform = '';
  }, { once: true });
});

Работа с множественными drop zones

Draggable поддерживает несколько drop zone одновременно. При этом обработка drop может включать определение приоритетной зоны и динамическое создание логики:

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

draggable.on('droppable:drop', (event) => {
  if (event.droppable.dataset.type === 'primary') {
    console.log('Основная зона:', event.droppable);
  } else {
    console.log('Второстепенная зона:', event.droppable);
  }
});

Сохранение состояния после drop

Для интеграции с backend часто требуется сохранять порядок элементов после перемещения. На drop можно получить индекс и идентификатор элемента:

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

Таким образом, объект события drop предоставляет полный контроль над перемещением элементов, их визуальной интеграцией и синхронизацией с серверной логикой. Правильная обработка этих событий позволяет создавать динамичные, отзывчивые интерфейсы с точной и безопасной логикой drag-and-drop.