drake.cancel() - отмена операции

Метод drake.cancel() предназначен для программной отмены текущей операции перетаскивания элементов. Он относится к объекту Drake, который создаётся при инициализации Dragula и управляет всей логикой перетаскивания. Важно понимать, что вызов cancel() не удаляет элемент из DOM и не возвращает его в исходное состояние визуально без соответствующих действий Dragula — он отменяет только внутреннюю логику перемещения и события.


Синтаксис и использование

drake.cancel([el]);
  • el — необязательный параметр. Если передан элемент DOM, отменяется перемещение именно этого элемента. Если параметр отсутствует, отменяется текущая операция перетаскивания, которая в данный момент активна.

Пример:

const drake = dragula([container1, container2]);

drake.on('drag', (el) => {
  if (el.classList.contains('locked')) {
    drake.cancel(el);
  }
});

В этом примере попытка перетащить элемент с классом locked сразу же отменяется.


Механизм действия

Метод cancel() выполняет несколько ключевых действий:

  1. Возврат элемента Если элемент был перемещён в новый контейнер, он возвращается в исходное положение в DOM. Dragula сохраняет исходное местоположение и индекс элемента, что позволяет корректно восстановить порядок элементов.

  2. Сброс внутренних состояний Dragula использует объект drake для отслеживания текущего состояния перетаскивания (dragging, mirror, source, moves). Вызов cancel() сбрасывает эти состояния, предотвращая выполнение событий drop или remove.

  3. Вызов событий Метод инициирует событие cancel, которое можно использовать для дополнительной логики:

drake.on('cancel', (el, container, source) => {
  console.log(`Перетаскивание элемента ${el.textContent} отменено`);
});

Отличие от drake.remove()

Метод drake.cancel() отличается от drake.remove() принципиально:

  • cancel() отменяет перемещение, возвращая элемент на исходную позицию.
  • remove() удаляет элемент из DOM контейнера назначения.

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


Применение в условиях

Метод особенно полезен при условных ограничениях перетаскивания:

  1. Блокировка определённых элементов
drake.on('drag', (el) => {
  if (el.dataset.locked === 'true') {
    drake.cancel(el);
  }
});
  1. Ограничение по контейнерам
drake.on('over', (el, container, source) => {
  if (!container.classList.contains('allowed')) {
    drake.cancel(el);
  }
});
  1. Проверка пользовательских условий
drake.on('drag', (el) => {
  if (!userCanMove(el)) {
    drake.cancel(el);
  }
});

Взаимодействие с зеркалом (mirror)

Dragula создаёт зеркальный элемент (mirror) при перетаскивании, который визуально перемещается вместе с курсором. При вызове cancel():

  • Зеркало удаляется из DOM.
  • Исходный элемент возвращается в контейнер.
  • Визуальные эффекты перетаскивания сбрасываются.

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


Ограничения и особенности

  • cancel() работает только в момент активного перетаскивания. Если вызвать его после завершения drop, эффект будет отсутствовать.
  • Метод не вызывает drop события. Любая логика, привязанная к drop, не выполняется.
  • Если в контейнере много элементов с одинаковыми данными, Dragula использует позицию DOM, а не содержимое, для возврата элемента.

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

  • Использовать drake.cancel(el) для блокировки элементов с динамическими условиями.
  • Привязывать обработчики к событиям drag или over, чтобы вовремя реагировать на попытки перемещения.
  • Для комплексных интерфейсов с множественными контейнерами отслеживать source и container при отмене, чтобы избежать некорректного возвращения элементов.

Метод drake.cancel() является мощным инструментом для контроля перетаскивания, обеспечивая безопасное управление элементами без нарушения структуры DOM и без удаления данных. Его правильное использование позволяет строить сложные интерфейсы с гибкой логикой блокировок и условий перемещения.