moves - контроль возможности перетаскивания

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


Синтаксис и назначение moves

Опция moves является функцией, которая вызывается каждый раз, когда пользователь пытается начать перетаскивание элемента. Функция имеет следующую сигнатуру:

function moves(el, source, handle, sibling) {
    // возвращает true или false
}
  • el — сам элемент, который пользователь пытается перетащить.
  • source — контейнер, из которого элемент берётся.
  • handle — элемент, с которого был инициирован drag. Это может быть сам el или его потомок, с которого пользователь начал перетаскивать.
  • sibling — элемент, перед которым будет вставлен перетаскиваемый элемент при текущем положении курсора (в момент начала перетаскивания).

Функция должна возвращать логическое значение: true, если перетаскивание разрешено, и false, если запрещено.


Простейший пример использования

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

dragula([document.querySelector('#container')], {
    moves: function(el, source, handle, sibling) {
        // Только элементы с классом 'draggable' можно перемещать
        return el.classList.contains('draggable');
    }
});

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


Контроль через “ручку” (handle)

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

dragula([document.querySelector('#tasks')], {
    moves: function(el, source, handle, sibling) {
        // Разрешаем перетаскивание только через элемент с классом 'handle'
        return handle.classList.contains('handle');
    }
});

Таким образом, элемент не станет draggable при клике на любую другую область.


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

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

dragula([container1, container2], {
    moves: function(el, source, handle, sibling) {
        if (source.id === 'locked-container') {
            return false; // полностью запрещаем перетаскивание из контейнера с id 'locked-container'
        }
        return true;
    }
});

Здесь элементы из locked-container не могут быть перемещены, а из остальных контейнеров — могут.


Динамическая проверка состояния элемента

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

dragula([document.querySelector('#list')], {
    moves: function(el, source, handle, sibling) {
        // Проверка пользовательского атрибута data-lock
        return el.getAttribute('data-lock') !== 'true';
    }
});

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


Комбинирование условий

Часто требуется учитывать одновременно несколько критериев: класс, контейнер, состояние элемента и ручку. В этом случае условия объединяются через логические операторы:

dragula([containerA, containerB], {
    moves: function(el, source, handle, sibling) {
        const isHandleCorrect = handle.classList.contains('drag-handle');
        const isNotLocked = el.getAttribute('data-locked') !== 'true';
        const allowedContainer = source.id !== 'forbidden';
        return isHandleCorrect && isNotLocked && allowedContainer;
    }
});

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


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

  • Использовать классы или атрибуты для идентификации draggable элементов, это повышает читаемость кода.
  • Всегда учитывать handle, чтобы избежать случайного перетаскивания при клике на контент элемента.
  • Объединять условия через && и ||, чтобы правила были гибкими и масштабируемыми.
  • Не использовать глобальные селекторы, если есть несколько контейнеров, так как это может привести к конфликтам в логике drag-and-drop.

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