Dragula — это лёгкая JavaScript-библиотека для организации перетаскивания элементов между контейнерами и внутри одного контейнера. Её основной принцип построен на простоте: минимальная конфигурация и возможность быстрого внедрения функционала drag-and-drop без обширного кода.
Для начала работы создаются контейнеры, которые будут участвовать в перетаскивании:
const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers);
dragula(containers) принимает массив DOM-элементов,
которые будут взаимодействовать между собой. По умолчанию библиотека
разрешает перемещение всех элементов между этими
контейнерами.
Dragula предоставляет настройки через объект опций. Основные параметры:
moves(el, source, handle, sibling) — функция,
возвращающая true или false, определяет, можно
ли начать перетаскивание конкретного элемента.accepts(el, target, source, sibling) — функция,
определяющая, разрешено ли помещать элемент в конкретный контейнер.copy — булевый параметр, если true,
элемент копируется при перетаскивании.revertOnSpill — если true, элемент
возвращается на исходную позицию при отпускании вне контейнера.Пример использования:
const drake = dragula(containers, {
moves: (el, source, handle, sibling) => handle.classList.contains('handle'),
accepts: (el, target, source, sibling) => !target.classList.contains('no-drop'),
copy: false,
revertOnSpill: true
});
Dragula генерирует несколько ключевых событий, которые позволяют полностью контролировать процесс перетаскивания:
drag — элемент начал перетаскиваться.drop — элемент был помещён в контейнер.over — элемент перемещён над контейнером.out — элемент покинул контейнер.cancel — перетаскивание было отменено.cloned — событие срабатывает, если элемент был
скопирован.Пример подписки на события:
drake.on('drag', el => {
el.style.opacity = '0.5';
});
drake.on('drop', (el, target, source, sibling) => {
el.style.opacity = '1';
console.log(`Элемент перемещён из ${source.id} в ${target.id}`);
});
drake.on('over', (el, container) => {
container.style.background = '#f0f0f0';
});
drake.on('out', (el, container) => {
container.style.background = '';
});
Эмуляция событий полезна для тестирования интерфейсов или автоматизации действий без физического участия пользователя. Dragula позволяет программно инициировать перемещение элементов через методы библиотеки и события DOM.
Эмуляция перетаскивания сводится к вызову методов Dragula и события DOM в правильной последовательности:
function simulateDragAndDrop(el, target) {
const eventDragStart = new Event('dragstart', { bubbles: true, cancelable: true });
el.dispatchEvent(eventDragStart);
const eventDragEnter = new Event('dragenter', { bubbles: true });
target.dispatchEvent(eventDragEnter);
const eventDragOver = new Event('dragover', { bubbles: true });
target.dispatchEvent(eventDragOver);
const eventDrop = new Event('drop', { bubbles: true, cancelable: true });
target.dispatchEvent(eventDrop);
const eventDragEnd = new Event('dragend', { bubbles: true, cancelable: true });
el.dispatchEvent(eventDragEnd);
}
В сочетании с Dragula можно использовать метод
drake.start() для начала перетаскивания элемента:
drake.start(el); // Неофициальный способ, зависит от версии библиотеки
drake.end(); // Завершение перетаскивания
Для корректной эмуляции важно учитывать логическую проверку
функций moves и accepts, чтобы
элемент не был заблокирован настройками Dragula:
if (drake.moves(el) && drake.accepts(el, target, el.parentNode)) {
simulateDragAndDrop(el, target);
}
Dragula автоматически добавляет и удаляет CSS-классы при перетаскивании:
gu-transit — элемент находится в состоянии
перемещения.gu-mirror — создаётся копия элемента для визуального
эффекта перемещения.gu-hide — скрывает оригинальный элемент во время
перетаскивания.Эти классы позволяют создавать сложные анимации и стили, контролируя внешний вид процесса drag-and-drop.
.gu-mirror {
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
opacity: 0.8;
}
.gu-transit {
opacity: 0.5;
}
Dragula поддерживает добавление новых контейнеров после инициализации:
const newContainer = document.createElement('div');
document.body.appendChild(newContainer);
drake.containers.push(newContainer);
После добавления нового контейнера элементы можно перемещать туда без переинициализации всей библиотеки.
moves и accepts для
минимизации лишних проверок на каждом событии.revertOnSpill только при
необходимости, чтобы избежать лишних DOM-операций.copy и
событие cloned, чтобы избежать утечек памяти при
динамических контейнерах.Эти методы обеспечивают гибкое управление перетаскиванием и позволяют создавать сложные интерфейсы с минимальными усилиями.