Обзор системы событий

Dragula — это легковесная библиотека для перетаскивания элементов в веб-интерфейсах. Основная концепция строится на drag and drop без необходимости написания большого количества кода для отслеживания событий и управления DOM. Библиотека минимизирует работу с низкоуровневыми событиями mousedown, mousemove и mouseup, предоставляя высокоуровневый API с удобными хуками.

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


Инициализация Dragula

Для создания экземпляра используется функция dragula, которой передается массив контейнеров:

const containers = [document.querySelector('#left'), document.querySelector('#right')];
const drake = dragula(containers);

После этого все элементы внутри контейнеров становятся перетаскиваемыми. Можно передавать конфигурационный объект для тонкой настройки поведения.

Основные опции:

  • moves(el, source, handle, sibling) — функция, возвращающая true, если элемент можно перетаскивать.
  • accepts(el, target, source, sibling) — функция, определяющая, можно ли перемещать элемент в определенный контейнер.
  • copy — логическое значение или функция; определяет, будет ли элемент копироваться при перетаскивании.
  • revertOnSpill — возвращает элемент в исходное место, если он был сброшен вне контейнера.
  • removeOnSpill — удаляет элемент при сбросе вне контейнера.

Пример с использованием опций:

const drake = dragula(containers, {
    moves: (el, source, handle) => handle.classList.contains('handle'),
    accepts: (el, target) => !target.classList.contains('forbidden'),
    copy: false,
    revertOnSpill: true
});

Система событий Dragula

Dragula предоставляет мощный механизм событий, которые позволяют управлять поведением перетаскивания на каждом этапе. События привязываются через метод .on и имеют следующие ключевые моменты:

1. drag

Срабатывает, когда элемент начинает перетаскиваться.

drake.on('drag', (el, source) => {
    el.classList.add('is-dragging');
});

Параметры:

  • el — элемент, который перетаскивается.
  • source — контейнер, из которого берется элемент.

2. dragend

Срабатывает после завершения перетаскивания, когда элемент отпущен.

drake.on('dragend', (el) => {
    el.classList.remove('is-dragging');
});

3. drop

Происходит при успешном размещении элемента в новом контейнере.

drake.on('drop', (el, target, source, sibling) => {
    console.log('Элемент перемещен из', source.id, 'в', target.id);
});

Параметры:

  • target — контейнер, куда помещается элемент.
  • sibling — элемент, перед которым вставляется перетаскиваемый элемент (null, если вставка в конец).

4. over и out

Эти события связаны с наведением на контейнер во время перетаскивания:

  • over(el, container, source) — элемент находится над контейнером.
  • out(el, container, source) — элемент покидает контейнер.

5. cancel

Вызывается, когда перетаскивание отменяется. Может произойти при использовании метода drake.cancel() или других условий.

6. cloned

Срабатывает при копировании элемента, если включена опция copy.

drake.on('cloned', (clone, original, type) => {
    clone.classList.add('clone');
});

Параметры:

  • clone — новый элемент.
  • original — исходный элемент.
  • type — тип операции (copy или mirror).

Взаимодействие с DOM и порядок элементов

Dragula автоматически обновляет порядок элементов при перемещении, что делает его удобным для списков и колонок. Параметр sibling в событиях drop, over и out позволяет вставлять элемент перед конкретным элементом в контейнере. Это упрощает синхронизацию состояния интерфейса с данными.

Для сохранения порядка элементов после перемещения можно использовать простой цикл по container.children и формировать массив идентификаторов:

drake.on('drop', (el, target) => {
    const order = Array.from(target.children).map(child => child.dataset.id);
    console.log('Новый порядок:', order);
});

Программное управление Dragula

Dragula позволяет управлять поведением через методы экземпляра:

  • drake.start(el) — программно инициирует перетаскивание элемента.
  • drake.end() — завершает текущее перетаскивание.
  • drake.cancel() — отменяет текущее перемещение.
  • drake.remove() — удаляет элемент из DOM, если опция removeOnSpill активна.
  • drake.destroy() — удаляет все обработчики событий и очищает экземпляр.

Применение этих методов полезно при динамическом изменении интерфейса или интеграции с другими библиотеками.


Особенности работы с динамическими элементами

Dragula корректно обрабатывает элементы, добавленные в контейнер после инициализации. Для этого достаточно убедиться, что новый элемент попадает под правила moves и accepts. Дополнительно можно использовать метод drake.containers.push(newContainer) для добавления новых областей перетаскивания на лету.


Советы по оптимизации

  • Для сложных интерфейсов с большим количеством элементов рекомендуется использовать фильтры в moves и accepts, чтобы снизить нагрузку на проверку элементов.
  • Избегать вложенных контейнеров с одинаковыми экземплярами Dragula, чтобы события не конфликтовали.
  • Использовать CSS-классы для визуального отображения состояний dragging, over и clone, что упрощает отладку и улучшает UX.

Система событий Dragula обеспечивает полный контроль над процессом перетаскивания, позволяет интегрировать сложную логику и поддерживает синхронизацию интерфейса с данными без прямой работы с низкоуровневыми событиями браузера.