Ограничения и валидация

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


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

Основной способ ограничения перемещения элемента — использование опции containers и draggable при инициализации Draggable. Элементы можно перемещать только в пределах указанных контейнеров:

const draggable = new Draggable.Sortable(
  document.querySelectorAll('.container'),
  {
    draggable: '.item',
    mirror: {
      constrainDimensions: true,
    }
  }
);

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

  • draggable определяет селектор элементов, которые можно перетаскивать.
  • mirror.constrainDimensions фиксирует размеры элемента во время перетаскивания.
  • Контейнеры ограничивают область, где элемент может быть размещен.

Если необходимо ограничить перемещение строго по вертикали или горизонтали, используют событие drag:start для модификации стилей:

draggable.on('drag:move', (event) => {
  const axis = 'y'; // или 'x'
  if (axis === 'y') {
    event.data.dragEvent.deltaX = 0;
  } else {
    event.data.dragEvent.deltaY = 0;
  }
});

Это позволяет точно контролировать траекторию движения и предотвращает смещение в нежелательном направлении.


Ограничение на допустимые контейнеры

В Draggable можно указать контейнеры, куда элемент может быть перемещен, и запретить остальные. Для этого используется метод canMove или кастомные проверки внутри события drag:over:

draggable.on('drag:over', (event) => {
  const validContainers = ['#allowed-container1', '#allowed-container2'];
  if (!validContainers.includes(event.overContainer.id)) {
    event.cancel();
  }
});

Особенности работы:

  • event.overContainer указывает на контейнер, над которым находится элемент.
  • Метод cancel() прерывает текущую операцию перетаскивания.
  • Можно реализовать сложную логику, проверяя атрибуты контейнера или классы.

Валидация перетаскиваемых элементов

Валидация необходима для предотвращения ошибок интерфейса при неправильном размещении элементов. Основные подходы:

  1. Типовая проверка элемента: проверка класса или атрибута data-type:
draggable.on('drag:over', (event) => {
  if (event.dragEvent.source.dataset.type !== event.overContainer.dataset.accept) {
    event.cancel();
  }
});
  1. Ограничение по позиции: запрет перемещения в определённые индексы контейнера:
draggable.on('sortable:sort', (event) => {
  if (event.newIndex < 1) {
    event.cancel();
  }
});
  1. Комбинированные правила: проверка нескольких условий одновременно для реализации бизнес-логики интерфейса.

Валидация позволяет исключить конфликтные состояния и гарантировать правильное распределение элементов по контейнерам.


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

Draggable позволяет контролировать максимальное количество элементов в контейнере:

draggable.on('drag:over', (event) => {
  if (event.overContainer.children.length >= 5) {
    event.cancel();
  }
});

Это особенно полезно для списков с фиксированными слотами, таких как карточки товаров или элементы меню.


Ограничение движения при помощи CSS

Дополнительно к логике на JavaScript можно использовать CSS для визуального ограничения:

.container {
  overflow: hidden;
  max-height: 300px;
}
.item {
  cursor: grab;
}
  • overflow: hidden предотвращает визуальное выход за пределы контейнера.
  • Комбинация с Draggable обеспечивает согласованное поведение между визуальной и программной ограничениями.

События для контроля и ограничения

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

  • drag:start — можно задавать начальные условия для элемента.
  • drag:move — контроль траектории движения.
  • drag:over / drag:out — проверка допустимости контейнера.
  • sortable:sort — проверка и валидация новой позиции элемента.

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


Пример комплексного ограничения

Комбинируя все вышеописанные методы, можно создать систему с несколькими условиями:

draggable.on('drag:over', (event) => {
  const maxItems = 3;
  const allowedContainers = ['#container1', '#container2'];
  
  if (!allowedContainers.includes(event.overContainer.id)) {
    event.cancel();
  }

  if (event.overContainer.children.length >= maxItems) {
    event.cancel();
  }

  if (event.dragEvent.source.dataset.type !== event.overContainer.dataset.accept) {
    event.cancel();
  }
});

Такой подход позволяет полностью контролировать:

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

Итоговые рекомендации по ограничениям

  • Всегда комбинировать программные и визуальные ограничения.
  • Использовать события drag:over и sortable:sort для точной валидации.
  • Не ограничиваться одним условием: комплексная проверка предотвращает ошибки UX.
  • Для мобильных интерфейсов учитывать размеры контейнеров и сенсорные ограничения движения.

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