Условное включение/выключение

В библиотеке Shopify Draggable управление возможностью перетаскивания элементов осуществляется не только на этапе инициализации, но и динамически во время работы приложения. Условное включение и выключение функционала Drag & Drop позволяет адаптировать интерфейс к различным состояниям страницы, ролям пользователя или конкретным операциям.

Методы enable() и disable()

Каждый экземпляр Draggable обладает методами:

  • draggable.enable() — активирует возможность перетаскивания для всех элементов, соответствующих селектору, указанному при инициализации.
  • draggable.disable() — полностью деактивирует перетаскивание. Все слушатели событий, связанные с drag, остаются, но действия перетаскивания не выполняются.

Пример:

const draggable = new Draggable.Sortable(document.querySelectorAll('.list'), {
  draggable: '.item'
});

// Временно отключить перетаскивание
draggable.disable();

// Позже снова включить
draggable.enable();

Условное управление на основе состояния элементов

В некоторых сценариях нужно разрешить перетаскивание только для определённых элементов. Для этого используется опция mirror и слушатели событий drag:start или sortable:sorted для проверки состояния:

const draggable = new Draggable.Sortable(document.querySelectorAll('.list'), {
  draggable: '.item'
});

draggable.on('drag:start', (event) => {
  if (event.source.dataset.locked === 'true') {
    event.cancel();
  }
});

Здесь условие event.source.dataset.locked === 'true' проверяет атрибут data-locked, и если элемент заблокирован, перетаскивание отменяется вызовом event.cancel(). Это эффективный способ условного ограничения без отключения всей сортируемой области.

Использование событий для динамического включения/выключения

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

  • drag:start — перед началом перетаскивания.
  • drag:move — во время движения элемента.
  • drag:stop — при завершении перетаскивания.
  • sortable:sorted — после сортировки элементов.

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

draggable.on('drag:start', (event) => {
  const container = event.source.closest('.list');
  if (!container.classList.contains('draggable-enabled')) {
    event.cancel();
  }
});

Здесь перетаскивание разрешается только для контейнеров с классом .draggable-enabled.

Комбинирование enable/disable с CSS-классами

Для визуального представления состояния элементов используют CSS-классы. Это позволяет одновременно контролировать доступность перетаскивания и изменять стиль:

.item.locked {
  opacity: 0.5;
  cursor: not-allowed;
}
const draggable = new Draggable.Sortable(document.querySelectorAll('.list'), {
  draggable: '.item:not(.locked)'
});

function toggleLock(item) {
  item.classList.toggle('locked');
  draggable.disable();
  draggable.enable(); // пересобираем доступные элементы
}

Метод enable() повторно инициирует обработку только доступных для перетаскивания элементов, игнорируя заблокированные через селектор.

Условное включение по внешним событиям

Иногда необходимо включать Drag & Drop на основе действий пользователя, например, при нажатии кнопки или смене вкладки:

document.querySelector('#activate-drag').addEventListener('click', () => {
  draggable.enable();
});

document.querySelector('#deactivate-drag').addEventListener('click', () => {
  draggable.disable();
});

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

Использование фильтров для частичной блокировки

Опция draggable поддерживает CSS-селекторы, что позволяет условно исключать элементы из перетаскивания:

const draggable = new Draggable.Sortable(document.querySelectorAll('.list'), {
  draggable: '.item:not(.no-drag)'
});

Элементы с классом .no-drag автоматически исключаются из всех операций Drag & Drop, что упрощает условное включение на уровне DOM.

Рекомендации по производительности

  • Избегать частого вызова disable() и enable() в циклах или при каждом движении мыши — это может снижать производительность.
  • Для динамического контроля лучше использовать селекторы и события drag:start, чтобы отменять действия только при необходимости.
  • Комбинировать CSS-классы и селекторы для визуального и функционального разделения элементов, обеспечивая прозрачность интерфейса.

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