Кастомные обработчики

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


Настройка Dragula с кастомными опциями

Для инициализации Dragula используется функция dragula(containers, options), где containers — массив DOM-элементов, а options — объект с параметрами. Основные опции, связанные с кастомизацией:

  • moves — функция, определяющая, можно ли перемещать элемент.

    moves: function (el, source, handle, sibling) {
        return handle.classList.contains('handle');
    }

    В этом примере элемент можно перемещать только за специфический дочерний узел с классом handle.

  • accepts — функция, контролирующая, разрешён ли перенос элемента в конкретный контейнер.

    accepts: function (el, target, source, sibling) {
        return !target.classList.contains('no-drop');
    }

    Здесь запрещён перенос в контейнер с классом no-drop.

  • invalid — функция, определяющая элементы, которые не могут быть перетащены.

    invalid: function (el, handle) {
        return el.classList.contains('fixed');
    }
  • copy — позволяет указать, будет ли элемент копироваться или перемещаться. Может быть функцией для динамического контроля.

    copy: function(el, source) {
        return source.id === 'source-list';
    }

Кастомные обработчики событий

Dragula предоставляет богатый набор событий, на которые можно навесить кастомные функции:

  • drag — срабатывает при начале перетаскивания. Позволяет изменять стиль элемента:

    drake.on('drag', function(el) {
        el.style.opacity = '0.5';
    });
  • dragend — вызывается при завершении перетаскивания, полезно для очистки временных стилей:

    drake.on('dragend', function(el) {
        el.style.opacity = '';
    });
  • drop — срабатывает при успешной установке элемента в новый контейнер. Здесь можно реализовать логику сортировки или синхронизации данных:

    drake.on('drop', function(el, target, source, sibling) {
        console.log(`Элемент ${el.textContent} перемещён в ${target.id}`);
    });
  • over / out — позволяют реализовать визуальные подсказки при наведении на контейнеры:

    drake.on('over', function(el, container) {
        container.classList.add('highlight');
    });
    drake.on('out', function(el, container) {
        container.classList.remove('highlight');
    });
  • cancel — можно использовать для отмены переноса на определённых условиях.

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


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

Dragula позволяет не только перемещать элементы, но и динамически управлять ими в процессе drag&drop:

  • Создание элементов “на лету”: можно клонировать элемент и помещать его в другой контейнер при событии drag:

    drake.on('drag', function(el) {
        const clone = el.cloneNode(true);
        clone.classList.add('clone');
        document.querySelector('#clone-container').appendChild(clone);
    });
  • Изменение порядка: можно программно перемещать элементы, взаимодействуя с sibling в событии drop:

    drake.on('drop', function(el, target, source, sibling) {
        if(sibling) {
            target.insertBefore(el, sibling);
        } else {
            target.appendChild(el);
        }
    });
  • Ограничения на перенос по типам элементов: комбинируя moves и accepts, можно реализовать строгие правила, например, запрещать перемещение заголовков между списками или разрешать только определённые категории элементов.


Динамическое включение и отключение Dragula

Можно создавать и удалять обработчики Dragula в зависимости от состояния интерфейса:

  • Отключение Dragula на контейнере:

    drake.remove(); // полностью удаляет слушатели и контейнеры
  • Временное блокирование перемещения:

    drake.options.moves = function() { return false; };
  • Повторная активация с новыми опциями:

    drake.options.moves = function(el, source, handle) {
        return handle.classList.contains('draggable');
    };

Расширенные техники кастомизации

  • Использование CSS-классов для визуальной обратной связи: Создание динамических классов dragging, over, invalid для плавного интерфейса.

  • Асинхронная проверка: функции accepts или moves могут использовать асинхронные данные (например, с сервера) для решения, можно ли перемещать элемент. В этом случае часто применяется временная блокировка визуального перетаскивания до получения ответа.

  • Комбинирование с другими библиотеками: Dragula может интегрироваться с фреймворками типа React или Vue через кастомные события и состояние компонентов.


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

  • Всегда определять кастомные обработчики через функции, а не статические значения, чтобы логика была гибкой.
  • Использовать drag и dragend для управления визуальными эффектами и предотвращения мерцаний при перемещении.
  • Разделять логику accepts и moves, чтобы избежать конфликтов при сложных правилах перетаскивания.
  • Создавать отдельные контейнеры для элементов-заполнителей и клонов, чтобы основной DOM оставался чистым.