Dragula — это легковесная библиотека для реализации функционала drag-and-drop в веб-приложениях на JavaScript. Она ориентирована на простоту использования, минимальный код для интеграции и автоматическое управление перемещением элементов между контейнерами. Ключевой особенностью Dragula является система событий, которая позволяет отслеживать весь жизненный цикл перетаскивания элемента: от начала захвата до его размещения в новом контейнере.
Для начала работы создается экземпляр Dragula, которому передается массив контейнеров:
const drake = dragula([container1, container2]);
После инициализации все элементы внутри указанных контейнеров становятся перетаскиваемыми. По умолчанию Dragula использует простую логику: любой элемент внутри контейнера можно перетащить, а любой контейнер может принять любой элемент.
Dragula предоставляет набор событий, отражающих последовательность действий пользователя. Понимание порядка их срабатывания критично для правильного управления состоянием интерфейса.
dragСрабатывает при начале перетаскивания элемента. На
этом этапе создается внутреннее представление перетаскиваемого элемента
(mirror), которое следует за курсором. Основные параметры
события:
el — перетаскиваемый элемент.source — контейнер, из которого был взят элемент.Пример использования:
drake.on('drag', (el, source) => {
el.style.opacity = '0.5';
});
dragendПроисходит по завершении перетаскивания, когда элемент отпущен, но еще не вставлен в новый контейнер. Этот этап позволяет восстановить исходное состояние перетаскиваемого элемента и удалить временное зеркало.
drake.on('dragend', (el) => {
el.style.opacity = '';
});
over и outЭти события фиксируют вход и выход элемента из контейнера во время перемещения:
over — элемент находится над контейнером и потенциально
может быть туда вставлен.out — элемент покидает контейнер без вставки.Параметры:
el — перемещаемый элемент.container — контейнер, над которым или из которого
происходит событие.source — исходный контейнер (для over и
out совпадает с container).drake.on('over', (el, container) => {
container.classList.add('highlight');
});
drake.on('out', (el, container) => {
container.classList.remove('highlight');
});
dropОсновное событие, которое срабатывает когда элемент успешно вставлен в контейнер. На этом этапе можно обновлять данные модели или выполнять дополнительную логику, например, синхронизацию с сервером.
drake.on('drop', (el, target, source, sibling) => {
console.log(`Элемент перемещен из ${source.id} в ${target.id}`);
});
Параметры:
el — перемещаемый элемент.target — контейнер, куда элемент вставлен.source — исходный контейнер.sibling — элемент, перед которым был вставлен
el. Может быть null при вставке в конец.cancelСрабатывает, если перетаскивание было отменено, например, если элемент отпущен за пределами допустимого контейнера. Позволяет откатить визуальные изменения.
drake.on('cancel', (el, container, source) => {
console.log('Перетаскивание отменено');
});
removeПроисходит, когда элемент удаляется из контейнера, если Dragula
настроен на удаление при выходе за пределы контейнера
(removeOnSpill: true). Параметры идентичны
drop.
Важно понимать последовательность, в которой Dragula вызывает события:
drag — пользователь начал
перетаскивать элемент. Создано зеркало (mirror), исходный
элемент полупрозрачный.over — элемент наведен на
контейнер.out — элемент покидает контейнер, не
вставляясь.over /
out при перемещении между контейнерами.drop — элемент вставлен в целевой
контейнер. Если вставки не произошло, событие не вызывается.dragend — перетаскивание завершено,
зеркало удалено, элемент вернул исходное состояние.cancel — если вставка невозможна и
элемент возвращен в исходный контейнер.remove — если элемент удаляется из
контейнера при настройке removeOnSpill.Этот порядок позволяет строить согласованную логику интерфейса, отслеживать визуальные состояния элементов и правильно синхронизировать данные модели с пользовательским действием.
Dragula позволяет изменять порядок или условия срабатывания событий через конфигурацию:
moves(el, source, handle, sibling) — управляет, можно
ли перетаскивать конкретный элемент.accepts(el, target, source, sibling) — проверяет, может
ли элемент быть вставлен в конкретный контейнер.invalid(el, handle) — запрещает перетаскивание для
определенных элементов.copy(el, source) — создает копию элемента вместо
перемещения.removeOnSpill — удаляет элемент, если он отпущен за
пределами контейнера.Применение этих опций позволяет точно управлять логикой drag-and-drop без вмешательства в внутренние события Dragula.
Для сложных интерфейсов часто используется комбинация событий:
drake.on('drag', (el) => el.classList.add('dragging'));
drake.on('over', (el, container) => container.classList.add('hovered'));
drake.on('out', (el, container) => container.classList.remove('hovered'));
drake.on('drop', (el, target) => target.classList.remove('hovered'));
drake.on('dragend', (el) => el.classList.remove('dragging'));
Такой подход обеспечивает плавный визуальный отклик на действия пользователя и строгий контроль состояния элементов.
Эта схема событий Dragula позволяет создавать сложные интерфейсы с перемещением элементов, сохраняя предсказуемость поведения и удобство управления состоянием. Правильная организация событий обеспечивает минимальное количество ошибок и максимально чистую синхронизацию между DOM и логикой приложения.