drag - начало перетаскивания

Dragula — это легковесная JavaScript-библиотека для организации перетаскивания элементов между контейнерами и внутри одного контейнера. Основной принцип работы Dragula заключается в создании «драгул» объектов, которые управляют состоянием перетаскивания и событиями.

Для начала работы необходимо подключить библиотеку через npm, CDN или локальный файл. После подключения создаётся объект Dragula с указанием контейнеров, между которыми будет происходить перемещение:

const drake = dragula([document.querySelector('#container1'), document.querySelector('#container2')]);

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


Настройка допустимых перетаскиваний

Dragula предоставляет возможность тонкой настройки правил перетаскивания через опции при создании объекта. Наиболее важные опции:

  • moves — функция, определяющая, можно ли перетаскивать конкретный элемент:
const drake = dragula([container], {
  moves: function (el, source, handle, sibling) {
    return handle.classList.contains('handle');
  }
});

Здесь элемент можно перетаскивать только если инициатор перетаскивания содержит класс handle.

  • accepts — функция, задающая, можно ли помещать элемент в конкретный контейнер:
const drake = dragula([container1, container2], {
  accepts: function (el, target, source, sibling) {
    return target.id !== 'container2' || el.dataset.type === 'allowed';
  }
});

Эта опция предотвращает перемещение элементов в запрещённые зоны, обеспечивая контроль бизнес-логики интерфейса.

  • copy — определяет, будет ли элемент копироваться или перемещаться:
const drake = dragula([container1, container2], {
  copy: true
});

При включённой опции copy исходный элемент остаётся на месте, а в целевом контейнере создаётся его копия.


События начала перетаскивания

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

  • drag — срабатывает в момент, когда элемент начинает двигаться:
drake.on('drag', function(el, source) {
  console.log('Начато перетаскивание элемента:', el, 'из контейнера:', source);
});
  • cloned — срабатывает при создании копии элемента, если включена опция copy:
drake.on('cloned', function(clone, original, type) {
  console.log('Создан клон элемента:', clone, 'исходный элемент:', original);
});
  • cancel — срабатывает, если перемещение отменяется по какой-либо причине:
drake.on('cancel', function(el, container, source) {
  console.log('Перетаскивание отменено для элемента:', el);
});

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


Визуальные эффекты и манипуляции с DOM

Dragula автоматически управляет положением перетаскиваемого элемента и вставкой его в целевой контейнер. Для улучшения UX можно использовать CSS-классы и слушатели событий:

  • Класс gu-transit добавляется к элементу в момент перетаскивания.
  • Класс gu-mirror создаёт визуальную копию, которая следует за курсором.

Пример кастомизации стиля при начале перетаскивания:

drake.on('drag', function(el) {
  el.style.opacity = '0.5';
});

drake.on('dragend', function(el) {
  el.style.opacity = '';
});

Сочетание событий Dragula и CSS позволяет полностью контролировать визуальную составляющую перемещения элементов без вмешательства в логику библиотеки.


Ограничение начала перетаскивания

Для предотвращения случайных перемещений используется функция moves, которая проверяет инициатор перетаскивания. Часто задают правило: перетаскивание возможно только по «ручке» внутри элемента. Это предотвращает нежелательные срабатывания при клике на контент элемента.

Пример с ручкой:

<div class="item">
  <div class="handle">☰</div>
  <div class="content">Текст элемента</div>
</div>
const drake = dragula([container], {
  moves: function(el, source, handle) {
    return handle.classList.contains('handle');
  }
});

Такой подход делает интерфейс более предсказуемым и удобным для пользователя, а код остаётся чистым и управляемым.


Поддержка нескольких контейнеров

Dragula позволяет сразу задавать несколько контейнеров, между которыми элементы могут перемещаться. При этом каждое перемещение можно контролировать через события drag и drop, а правила accepts и moves позволяют индивидуально конфигурировать поведение для каждого контейнера.

const drake = dragula([container1, container2, container3], {
  accepts: function(el, target) {
    return target.dataset.allowed === 'true';
  }
});

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