Двустороннее связывание

SortableJS — это мощная библиотека JavaScript, обеспечивающая интерактивное перетаскивание элементов в списках и сетках с поддержкой событий и гибкой настройки. Она позволяет создавать динамичные пользовательские интерфейсы, где элементы могут изменять порядок без сложного манипулирования DOM.

Библиотека поддерживает drag-and-drop в различных режимах, включая односторонние и двусторонние списки. Особенностью является высокая производительность и минимальная зависимость от внешних библиотек.

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

Для использования SortableJS необходимо подключить библиотеку через CDN или npm:

<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

Инициализация осуществляется простым вызовом конструктора:

const sortable = new Sortable(document.getElementById('my-list'), {
    animation: 150,
    ghostClass: 'sortable-ghost'
});

Параметры и их значения:

  • animation — скорость анимации перемещения элементов в миллисекундах.
  • ghostClass — CSS-класс, который применяется к перетаскиваемому элементу для визуального эффекта.
  • handle — CSS-селектор для элемента, за который можно тянуть.

Двустороннее связывание списков

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

const listA = document.getElementById('list-a');
const listB = document.getElementById('list-b');

new Sortable(listA, {
    group: 'shared',
    animation: 150
});

new Sortable(listB, {
    group: 'shared',
    animation: 150
});

Ключевые моменты двустороннего связывания:

  • group — имя группы, элементы которой могут перемещаться между списками.
  • Все списки с одинаковым значением group автоматически поддерживают обмен элементами.
  • Можно задавать дополнительные параметры для контроля поведения: pull, put.
new Sortable(listA, {
    group: {
        name: 'shared',
        pull: 'clone', // позволяет клонировать элементы при перетаскивании
        put: false     // запрет вставки из других списков
    },
    animation: 150
});

Различия между pull и put:

  • pull контролирует, можно ли забирать элементы из списка.
  • put контролирует, можно ли вставлять элементы в список.

Работа с событиями

SortableJS предоставляет обширный набор событий для управления поведением элементов:

  • onStart — начинается перетаскивание.
  • onEnd — завершено перетаскивание.
  • onAdd — элемент добавлен в новый список.
  • onUpdate — элемент изменил позицию внутри текущего списка.
  • onRemove — элемент удалён из списка.

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

new Sortable(listB, {
    group: 'shared',
    animation: 150,
    onAdd: function (evt) {
        console.log('Элемент перемещен из другого списка:', evt.item);
    }
});

evt.item содержит DOM-элемент, который был перемещён, а evt.from и evt.to дают ссылки на исходный и целевой список.

Кастомизация визуальных эффектов

Для улучшения интерфейса часто применяются следующие параметры:

  • ghostClass — стиль для перетаскиваемого элемента.
  • chosenClass — стиль выбранного элемента.
  • dragClass — стиль элемента во время перетаскивания.
  • fallbackOnBody — позволяет использовать body в качестве контейнера для временного элемента при сложной верстке.

Пример:

new Sortable(listA, {
    group: 'shared',
    animation: 200,
    ghostClass: 'ghost',
    chosenClass: 'chosen',
    dragClass: 'dragging',
    fallbackOnBody: true
});

Ограничение типов элементов

Для двустороннего связывания важно иногда разрешать перемещение только определённых элементов. Это достигается с помощью filter и draggable:

new Sortable(listA, {
    group: 'shared',
    animation: 150,
    draggable: '.draggable', // только элементы с этим классом можно перемещать
    filter: '.non-draggable', // элементы с этим классом нельзя тянуть
    onMove: function(evt) {
        return !evt.related.classList.contains('non-draggable');
    }
});

onMove позволяет контролировать динамически, разрешать ли перемещение конкретного элемента в данный момент.

Работа с массивами данных

SortableJS может синхронизироваться с массивами JavaScript, что упрощает работу с динамическими данными. Для этого используют метод toArray и событие onEnd:

const items = ['Элемент 1', 'Элемент 2', 'Элемент 3'];

new Sortable(listA, {
    group: 'shared',
    animation: 150,
    onEnd: function(evt) {
        const newOrder = sortable.toArray();
        console.log('Новый порядок элементов:', newOrder);
    }
});

С помощью метода sort() можно программно изменять порядок элементов, а fromArray() позволяет восстановить порядок из массива.

Работа с вложенными и комплексными структурами

SortableJS поддерживает вложенные списки, таблицы и сетки. Для комплексных структур используют параметр swapThreshold, invertSwap и fallbackTolerance, чтобы контролировать чувствительность перетаскивания и замену элементов.

Пример для вложенного списка:

new Sortable(nestedList, {
    group: 'nested',
    animation: 150,
    fallbackTolerance: 5, // минимальное смещение для срабатывания drag
    swapThreshold: 0.65  // процент перекрытия для обмена
});

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

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

SortableJS оптимизирован под сенсорные экраны, но для корректной работы на мобильных устройствах полезно включать touchStartThreshold и проверять поддержку pointer events:

new Sortable(listA, {
    group: 'shared',
    animation: 150,
    touchStartThreshold: 10
});

touchStartThreshold определяет минимальное движение пальца для начала перетаскивания, что снижает ложные срабатывания при прокрутке.


Если требуется, могу подготовить отдельный блок с примерами двустороннего связывания с сохранением порядка в массиве и интеграцией с backend — это будет полезно для учебника. Хотите, чтобы я это сделал?