Dragula — это легковесная JavaScript-библиотека для реализации drag-and-drop интерфейсов. Её ключевое преимущество — простота настройки и минимальный код для работы с перетаскиванием элементов. В контексте множественного выбора элементов библиотека позволяет пользователю одновременно перемещать несколько элементов между контейнерами или внутри одного контейнера, при этом сохраняя интерактивность и гибкость интерфейса.
Для работы с множественным выбором элементов первым шагом является определение контейнеров. Контейнеры — это HTML-элементы, содержащие draggable-элементы.
const containers = [
document.getElementById('container1'),
document.getElementById('container2')
];
Dragula принимает массив контейнеров при инициализации. Это позволяет перемещать элементы между любыми из них без дополнительных сложных обработчиков событий.
const drake = dragula(containers, {
moves: (el, source, handle, sibling) => el.classList.contains('draggable'),
copy: false,
revertOnSpill: true
});
Ключевые моменты:
moves — функция, определяющая, можно ли перетаскивать
элемент. Часто используется для фильтрации draggable-элементов.copy — указывает, будет ли элемент копироваться при
перемещении. Для множественного выбора чаще используют
false.revertOnSpill — возвращает элементы на исходное место,
если они были сброшены вне контейнера.Множественный выбор элементов требует хранения состояния выбранных элементов. Чаще всего это реализуется через массив, который обновляется при клике на элемент.
let selectedElements = [];
document.querySelectorAll('.draggable').forEach(el => {
el.addEventListener('click', (e) => {
if (e.ctrlKey || e.metaKey) {
el.classList.toggle('selected');
updateSelection(el);
}
});
});
function updateSelection(el) {
if (el.classList.contains('selected')) {
selectedElements.push(el);
} else {
selectedElements = selectedElements.filter(item => item !== el);
}
}
Ключевые моменты:
ctrlKey или metaKey используется для
множественного выбора без снятия предыдущего выбора.selected позволяет визуально выделять выбранные
элементы.updateSelection управляет массивом выбранных
элементов.Dragula по умолчанию работает с одним элементом за раз. Для реализации перемещения нескольких элементов одновременно необходимо создавать обертку или использовать программное клонирование выбранных элементов на лету.
drake.on('drag', (el) => {
if (!el.classList.contains('selected')) return;
selectedElements.forEach(sel => {
if (sel !== el) {
sel.style.display = 'none'; // временно скрыть остальные элементы
}
});
});
drake.on('drop', (el, target, source, sibling) => {
selectedElements.forEach(sel => {
sel.style.display = 'block'; // вернуть элементы после перемещения
if (sel !== el) target.appendChild(sel);
});
selectedElements = [];
});
Ключевые моменты:
drag используется для модификации поведения
выбранных элементов во время перемещения.drop осуществляется фактическое перемещение всех
выбранных элементов в новый контейнер.Для более сложных интерфейсов часто требуется ограничивать
перемещения по контейнерам или по типу элементов. Dragula позволяет это
реализовать через опцию accepts.
const drake = dragula(containers, {
accepts: (el, target, source, sibling) => {
if (!el.classList.contains('selected')) return false;
return target.dataset.type === el.dataset.type;
}
});
Ключевые моменты:
accepts определяет, можно ли сбросить элемент в
конкретный контейнер.data-атрибутов упрощает фильтрацию по
типам элементов.Выделение выбранных элементов и визуальные подсказки при перемещении повышают удобство использования. Обычно применяют CSS-классы:
.draggable {
cursor: grab;
transition: transform 0.2s;
}
.selected {
border: 2px solid #007BFF;
background-color: #E0F0FF;
}
.gu-mirror {
opacity: 0.7;
border: 1px dashed #007BFF;
}
Ключевые моменты:
.gu-mirror — временный элемент, который Dragula создает
для визуализации перетаскивания.selected помогают пользователю видеть выбранные
элементы при множественном выделении.Dragula предоставляет набор событий, которые можно использовать для гибкой логики при множественном выборе:
drag — элемент начал перетаскиваться.drop — элемент сброшен в новый контейнер.over / out — курсор находится над
контейнером или покидает его.cancel — перетаскивание отменено.remove — элемент удален из контейнера.Использование этих событий позволяет интегрировать множественное перемещение с сохранением состояния, логикой undo/redo или анимациями.