Условное перетаскивание

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

Ограничение перетаскиваемых элементов

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

const list = document.getElementById('items');

Sortable.create(list, {
  filter: '.non-draggable',
  onMove: function (evt, originalEvent) {
    return !evt.related.classList.contains('non-draggable');
  }
});

Пояснение:

  • .non-draggable — CSS-класс элементов, которые не могут быть перетащены.
  • onMove — функция обратного вызова, вызываемая при попытке перемещения. Возврат false блокирует перемещение.

Динамическое управление возможностью перетаскивания

Иногда необходимо менять условие перетаскивания динамически в зависимости от состояния приложения. Для этого используют функцию в filter или проверку в onMove.

Sortable.create(list, {
  onMove: function (evt) {
    // Разрешить перемещение только элементов с data-draggable="true"
    return evt.dragged.dataset.draggable === 'true';
  }
});

Здесь каждый элемент может иметь атрибут data-draggable, и его значение определяет возможность перемещения.

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

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

Sortable.create(listA, {
  group: {
    name: 'shared',
    pull: 'clone', // Разрешить копирование элементов при перетаскивании
    put: function (to) {
      // Разрешить добавление элементов только в пустые списки
      return to.el.children.length === 0;
    }
  }
});

Ключевые моменты:

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

Перетаскивание только по условию пользователя

Иногда требуется дать пользователю возможность выбирать элементы для перетаскивания вручную. Для этого применяют событие start и проверку кастомного условия.

Sortable.create(list, {
  onStart: function (evt) {
    if (!evt.item.classList.contains('active')) {
      evt.preventDefault(); // Блокировка начала перетаскивания
    }
  }
});

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

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

Sortables поддерживает ограничение направления перемещения через опцию direction и области перетаскивания через событие dragover или проверку в onMove.

Sortable.create(list, {
  direction: 'vertical', // Перетаскивание только по вертикали
  onMove: function (evt) {
    const rect = evt.related.getBoundingClientRect();
    // Запретить перемещение, если элемент находится в верхней половине контейнера
    return evt.clientY > rect.top + rect.height / 2;
  }
});

Такой подход позволяет создавать сложные правила взаимодействия с элементами списка.

Сочетание фильтров и событий

Для полноценного условного перетаскивания обычно комбинируют:

  • filter для статических ограничений;
  • onMove для динамических условий;
  • onStart для проверки возможности начала перетаскивания.

Пример комплексной реализации:

Sortable.create(list, {
  filter: '.non-draggable',
  onStart: function (evt) {
    if (!evt.item.dataset.enabled) evt.preventDefault();
  },
  onMove: function (evt) {
    return evt.dragged.dataset.priority === 'high';
  }
});

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

Практические рекомендации

  • Использовать data-атрибуты для хранения условий перетаскивания: это упрощает логику и улучшает читаемость кода.
  • Комбинировать статические (filter) и динамические (onMove, onStart) проверки.
  • Тестировать поведение при быстром перетаскивании и на мобильных устройствах, так как события touch могут вести себя иначе.