Dragula — это библиотека для перетаскивания элементов (drag-and-drop) в веб-приложениях на JavaScript. Она обеспечивает простое API для организации сортировки элементов в контейнерах. Для начала работы необходимо подключить саму библиотеку и её CSS-стили:
<link rel="stylesheet" href="https://unpkg.com/dragula/dist/dragula.min.css">
<script src="https://unpkg.com/dragula/dist/dragula.min.js"></script>
После подключения можно создавать контейнеры и инициировать Dragula:
const containers = [document.getElementById('list1'), document.getElementById('list2')];
const drake = dragula(containers);
Dragula управляет двумя ключевыми аспектами:
Важно понимать, что Dragula не изменяет исходные данные автоматически. Для сохранения порядка необходимо самостоятельно синхронизировать изменения с внутренними структурами данных (например, массивами или объектами).
Dragula предоставляет богатый набор событий:
drag — срабатывает в момент начала перетаскивания.
Позволяет, например, добавлять визуальные эффекты.drop — срабатывает при отпускании элемента в
контейнере. Здесь можно фиксировать новый порядок элементов.over / out — события при наведении на
контейнер или уходе из него, полезны для подсветки зоны назначения.cancel — срабатывает, если перетаскивание
отменено.Для сохранения порядка ключевое событие — drop:
drake.on('drop', (el, target, source, sibling) => {
const order = Array.from(target.children).map(child => child.dataset.id);
console.log('Новый порядок элементов:', order);
});
Здесь el — перемещаемый элемент, target —
контейнер, в который был помещен элемент, source — исходный
контейнер, sibling — элемент перед которым вставлен
el. dataset.id — атрибут элемента,
используемый для идентификации.
Для синхронизации DOM и массива данных порядок элементов в массиве
нужно обновлять при событии drop. Пример с массивом
объектов:
let items = [
{id: '1', name: 'Элемент 1'},
{id: '2', name: 'Элемент 2'},
{id: '3', name: 'Элемент 3'}
];
function updateOrder(container) {
const newOrder = Array.from(container.children).map(child => child.dataset.id);
items.sort((a, b) => newOrder.indexOf(a.id) - newOrder.indexOf(b.id));
console.log(items);
}
drake.on('drop', (el, target) => {
updateOrder(target);
});
Такой подход обеспечивает согласованность интерфейса и данных.
Dragula позволяет ограничивать перемещение элементов по различным правилам:
moves — функция, определяющая, можно ли перемещать
конкретный элемент. Например:const drake = dragula(containers, {
moves: (el, source, handle) => handle.classList.contains('handle')
});
accepts — функция, задающая правила вставки элемента в
контейнер:const drake = dragula(containers, {
accepts: (el, target) => !target.classList.contains('no-drop')
});
Эти механизмы помогают контролировать порядок элементов и предотвращают случайные перемещения.
Чтобы порядок элементов сохранялся после перезагрузки страницы,
используется локальное хранилище (localStorage) или
серверные запросы. Пример с localStorage:
drake.on('drop', (el, target) => {
const order = Array.from(target.children).map(child => child.dataset.id);
localStorage.setItem('itemOrder', JSON.stringify(order));
});
// Восстановление порядка при загрузке
const savedOrder = JSON.parse(localStorage.getItem('itemOrder') || '[]');
if (savedOrder.length) {
const container = document.getElementById('list1');
savedOrder.forEach(id => {
const el = container.querySelector(`[data-id="${id}"]`);
if (el) container.appendChild(el);
});
}
Такой подход гарантирует, что пользовательский порядок элементов будет сохранен между сессиями и корректно восстановлен.
Dragula автоматически отслеживает новые элементы в контейнере, однако важно повторно вызывать синхронизацию массива данных после добавления или удаления:
function addItem(container, item) {
const el = document.createElement('div');
el.textContent = item.name;
el.dataset.id = item.id;
container.appendChild(el);
updateOrder(container);
}
Удаление элемента:
function removeItem(container, id) {
const el = container.querySelector(`[data-id="${id}"]`);
if (el) el.remove();
updateOrder(container);
}
Dragula поддерживает работу с несколькими контейнерами одновременно. Перетаскивание между ними также обновляет порядок элементов в соответствующих массивах данных:
const drake = dragula([document.getElementById('list1'), document.getElementById('list2')]);
drake.on('drop', (el, target, source) => {
updateOrder(source);
updateOrder(target);
});
Таким образом сохраняется точная последовательность элементов в каждом контейнере.
Для удобства пользователя часто добавляются стили при перетаскивании:
.gu-mirror {
opacity: 0.7;
background-color: #f0f0f0;
border: 1px dashed #999;
}
.gu-transit {
opacity: 0.5;
}
Эти классы автоматически применяются Dragula к перетаскиваемым
элементам и зеркальной копии (mirror), создавая плавный
визуальный эффект.
При использовании Dragula в адаптивном дизайне важно учитывать:
moves.Это позволяет сохранять порядок элементов независимо от устройства и разрешения экрана.