Полифиллы для старых браузеров

Dragula — это легковесная библиотека для реализации drag-and-drop интерфейсов на JavaScript без необходимости подключения больших фреймворков. Она предоставляет простое API для перетаскивания элементов между контейнерами с поддержкой визуальных эффектов и коллизий. Установка производится через npm или CDN:

npm install dragula

или подключение через <script>:

<script src="https://unpkg.com/dragula/dist/dragula.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/dragula/dist/dragula.min.css">

После подключения библиотека готова к использованию на любых DOM-элементах.


Инициализация и базовые методы

Создание экземпляра Dragula осуществляется вызовом функции dragula() с массивом контейнеров:

const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers);

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

  • drake.on(event, callback) — подписка на события: drag, drop, over, out, cancel.
  • drake.destroy() — полное удаление всех слушателей и очистка состояния.
  • drake.containers — массив текущих контейнеров для перетаскивания.

Настройки поведения

Dragula поддерживает конфигурацию через объект опций:

const drake = dragula(containers, {
    moves: (el, source, handle, sibling) => handle.classList.contains('handle'),
    accepts: (el, target, source, sibling) => !target.classList.contains('forbidden'),
    copy: true,
    revertOnSpill: true,
});

Основные опции:

  • moves — функция, определяющая, можно ли перетаскивать конкретный элемент.
  • accepts — функция для ограничения контейнеров, в которые разрешено помещать элемент.
  • copy — при значении true элементы копируются, вместо перемещения.
  • revertOnSpill — возвращает элемент в исходное место, если он был «выброшен» за пределы контейнеров.

События Dragula

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

  • drag(el, source) — элемент начал перетаскиваться.
  • drop(el, target, source, sibling) — элемент отпущен в контейнер.
  • over(el, container, source) — элемент наведен на контейнер.
  • out(el, container, source) — элемент покинул контейнер.
  • cancel(el, container, source) — перетаскивание было отменено.

Пример использования:

drake.on('drop', (el, target, source, sibling) => {
    console.log(`Элемент ${el.textContent} перемещен из ${source.id} в ${target.id}`);
});

Поддержка старых браузеров

Dragula использует стандартные события drag и drop браузера и не требует дополнительных полифиллов для современных версий Chrome, Firefox, Edge или Safari. Для IE11 и ниже могут возникать проблемы с:

  • Методами classList на SVG-элементах.
  • Событиями CustomEvent.
  • Функциями Array.prototype.find, forEach на NodeList.

Полифиллы для Dragula:

  1. classList
<script src="https://cdn.jsdelivr.net/npm/classlist-polyfill@1.2.0/index.min.js"></script>
  1. CustomEvent
(function () {
    if ( typeof window.CustomEvent === "function" ) return false;
    function CustomEvent ( event, params ) {
        params = params || { bubbles: false, cancelable: false, detail: null };
        var evt = document.createEvent( 'CustomEvent' );
        evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
        return evt;
    }
    CustomEvent.prototype = window.Event.prototype;
    window.CustomEvent = CustomEvent;
})();
  1. Array.prototype.find
if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this == null) throw new TypeError('Array.prototype.find called on null or undefined');
    if (typeof predicate !== 'function') throw new TypeError('predicate must be a function');
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    for (var i = 0; i < length; i++) {
      var value = list[i];
      if (predicate.call(thisArg, value, i, list)) return value;
    }
    return undefined;
  };
}
  1. NodeList.forEach
if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
}

Стилизация перетаскивания

Dragula добавляет класс gu-transit элементу во время перемещения. Остальные классы:

  • gu-mirror — копия элемента, следящая за курсором.
  • gu-hide — скрывает исходный элемент, если включен режим копирования.
  • gu-unselectable — предотвращает выделение текста.

Стилизация может быть выполнена через CSS:

.gu-mirror {
    background: rgba(0, 150, 255, 0.2);
    border: 2px dashed #0096ff;
    box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.gu-transit {
    opacity: 0.5;
}

Интеграция с фреймворками

Dragula легко интегрируется с React, Vue и Angular, так как работает напрямую с DOM. Основные рекомендации:

  • React: использовать useEffect для инициализации и удаления экземпляра Dragula.
  • Vue: создавать экземпляр в mounted() и уничтожать в beforeDestroy().
  • Angular: инициализация в ngAfterViewInit и очистка в ngOnDestroy.

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

Dragula подходит для:

  • Панелей управления с перемещаемыми виджетами.
  • Списков задач с drag-and-drop сортировкой.
  • Таблиц и досок типа Kanban.
  • Динамических форм, где элементы можно добавлять и перемещать.

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