События множественного перетаскивания

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


Подключение и инициализация SortableJS

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

import Sortable from 'sortablejs';
import MultiDrag from 'sortablejs/plugins/MultiDrag';

Sortable.mount(new MultiDrag());

const sortable = new Sortable(document.getElementById('list'), {
    multiDrag: true,
    selectedClass: 'selected',
    animation: 150,
    fallbackTolerance: 3
});
  • multiDrag: активирует возможность выбора нескольких элементов одновременно.
  • selectedClass: CSS-класс, применяемый к выделенным элементам.
  • animation: длительность анимации перемещения.
  • fallbackTolerance: минимальное смещение курсора, чтобы начать перетаскивание.

Основные события для множественного перетаскивания

SortableJS предоставляет события, позволяющие отслеживать как одиночные, так и множественные перемещения:

onSelect и onDeselect

Вызываются при выборе или снятии выделения с элемента.

sortable.option("onSelect", function(evt) {
    console.log('Выбран элемент:', evt.item);
});

sortable.option("onDeselect", function(evt) {
    console.log('Снято выделение:', evt.item);
});
  • evt.item — DOM-элемент, который был выделен или снят с выделения.
  • Позволяют управлять визуальными эффектами выделения и синхронизировать состояние интерфейса.

onStart и onEnd

Отслеживают начало и окончание перетаскивания.

sortable.option("onStart", function(evt) {
    console.log('Начало перетаскивания:', evt.items);
});

sortable.option("onEnd", function(evt) {
    console.log('Окончание перетаскивания:', evt.items);
});
  • evt.items — массив всех элементов, участвующих в текущей операции множественного перетаскивания.
  • Используются для логики обновления данных или отправки изменений на сервер после завершения перетаскивания.

onAdd, onRemove и onUpdate

Эти события управляют изменениями структуры списка при перемещении элементов между контейнерами или внутри одного списка.

sortable.option("onAdd", function(evt) {
    console.log('Элементы добавлены в контейнер:', evt.items);
});

sortable.option("onRemove", function(evt) {
    console.log('Элементы удалены из контейнера:', evt.items);
});

sortable.option("onUpdate", function(evt) {
    console.log('Порядок элементов изменен:', evt.items);
});
  • onAdd — срабатывает, когда элементы перетаскиваются из другого списка.
  • onRemove — элементы удаляются из текущего списка.
  • onUpdate — перестановка элементов внутри одного контейнера.

При множественном перетаскивании evt.items всегда содержит массив выбранных элементов, что позволяет легко обрабатывать группы элементов одновременно.


Управление визуальным выделением

Для улучшения UX важно правильно стилизовать выбранные элементы:

.selected {
    border: 2px solid #007BFF;
    background-color: rgba(0, 123, 255, 0.1);
}
  • Выделение нескольких элементов визуально обозначает, какие объекты будут перемещаться вместе.
  • Можно добавить дополнительные эффекты, например, изменение прозрачности остальных элементов во время перетаскивания.

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

Выделение элементов можно контролировать через методы API:

// Выделить конкретный элемент
sortable.select(document.querySelector('#item1'));

// Снять выделение
sortable.deselect(document.querySelector('#item2'));

// Получить массив всех выделенных элементов
const selectedElements = sortable.getSelected();
console.log(selectedElements);

Эти методы особенно полезны при интеграции с интерфейсами, где пользователь может выбрать элементы через кнопки или чекбоксы, а не только кликами с зажатым Ctrl/Shift.


Работа с перетаскиванием нескольких списков

SortableJS поддерживает drag-and-drop между несколькими контейнерами с множественным выбором:

const listA = new Sortable(document.getElementById('listA'), {
    group: 'shared',
    multiDrag: true,
    selectedClass: 'selected'
});

const listB = new Sortable(document.getElementById('listB'), {
    group: 'shared',
    multiDrag: true,
    selectedClass: 'selected'
});
  • group: общий идентификатор группы контейнеров для обмена элементами.
  • При переносе элементов из listA в listB события onAdd и onRemove автоматически получают массив выбранных элементов.

Настройка поведения при перетаскивании

SortableJS позволяет задавать условия перетаскивания через функции filter и preventOnFilter:

const sortable = new Sortable(list, {
    multiDrag: true,
    filter: '.no-drag',
    preventOnFilter: false
});
  • filter — селектор элементов, которые не должны быть перетаскиваемыми.
  • preventOnFilter — определяет, отменять ли стандартное действие браузера при попытке перетащить фильтрованный элемент.

Эти настройки особенно полезны при работе с таблицами, списками с кнопками или интерактивными элементами.


Оптимизация для больших списков

При множественном перетаскивании больших наборов данных важно учитывать производительность:

  • Использовать requestAnimationFrame для обновления визуальных эффектов.
  • Минимизировать пересчет стилей и DOM-операции при каждом событии.
  • Применять animation: 0 для операций, где визуальные эффекты не критичны, чтобы ускорить обработку большого количества элементов.

Итоговая структура событий для множественного перетаскивания

Событие Описание Параметр evt
onSelect Выбор элемента evt.item
onDeselect Снятие выделения evt.item
onStart Начало перетаскивания evt.items
onEnd Завершение перетаскивания evt.items
onAdd Добавление элементов в контейнер evt.items
onRemove Удаление элементов из контейнера evt.items
onUpdate Перестановка элементов внутри одного контейнера evt.items

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