Клавиатурная навигация

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

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

Здесь containers — массив элементов DOM, между которыми будет возможна перетаскиваемая сортировка. После инициализации экземпляра, drake автоматически добавляет слушатели событий мыши для всех элементов контейнеров.

Настройка параметров

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

const drake = dragula(containers, {
  moves: (el, source, handle, sibling) => handle.classList.contains('handle'),
  accepts: (el, target, source, sibling) => !target.classList.contains('disabled'),
  copy: false,
  revertOnSpill: true
});
  • moves — функция, определяющая, можно ли начать перетаскивание конкретного элемента. Возвращает true или false.
  • accepts — функция, контролирующая, можно ли поместить элемент в конкретный контейнер.
  • copy — если true, элементы при перетаскивании копируются вместо перемещения.
  • revertOnSpill — возвращает элемент на исходную позицию при некорректном отпускании.

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

События Dragula

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

  • drag — срабатывает при начале перетаскивания элемента.
  • dragend — срабатывает после завершения перетаскивания, когда элемент отпущен.
  • drop — срабатывает при успешном отпускании элемента в контейнере.
  • over / out — фиксируют наведение или выход элемента над контейнером.
  • cloned — срабатывает при клонировании элемента (если включён режим копирования).

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

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

События позволяют интегрировать Dragula с backend-логикой, обновлять данные в базе и анимацию интерфейса.

Клавиатурная навигация и доступность

Стандартная реализация Dragula ориентирована на мышь и сенсорные устройства, однако в современных веб-приложениях важна поддержка клавиатурной навигации. Для этого необходимо:

  1. Сделать элементы фокусируемыми, используя tabindex="0".
  2. Отслеживать события клавиатуры, например keydown.
  3. Реализовать логику перемещения с помощью стрелок и Enter/Space.

Пример расширения Dragula для клавиатурного управления:

document.querySelectorAll('.draggable').forEach(item => {
  item.setAttribute('tabindex', '0');

  item.addEventListener('keydown', (e) => {
    const parent = item.parentElement;
    if (e.key === 'ArrowUp' && item.previousElementSibling) {
      parent.insertBefore(item, item.previousElementSibling);
    }
    if (e.key === 'ArrowDown' && item.nextElementSibling) {
      parent.insertBefore(item.nextElementSibling, item);
    }
    if (e.key === 'Enter') {
      console.log(`Выбран элемент: ${item.textContent}`);
    }
  });
});

Особенности реализации:

  • Поддержка focus позволяет пользователю перемещаться между элементами с клавиатуры.
  • ArrowUp / ArrowDown реализуют перемещение вверх и вниз в пределах контейнера.
  • Enter / Space можно использовать для имитации «подъёма» элемента, аналогично началу drag.

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

Работа с динамическими элементами

Dragula автоматически не отслеживает новые элементы, добавленные в DOM после инициализации. Для динамических списков необходимо:

  • Повторно добавлять элементы в контейнеры через метод drake.containers.push(newContainer) при создании нового контейнера.
  • Подключать фокус и события клавиатуры для новых элементов.

Пример динамического добавления:

const newItem = document.createElement('div');
newItem.className = 'draggable';
newItem.textContent = 'Новый элемент';
document.getElementById('left').appendChild(newItem);

// Сделать элемент фокусируемым и добавить обработчик клавиатуры
newItem.setAttribute('tabindex', '0');
newItem.addEventListener('keydown', handleKeyboardNavigation);

Это обеспечивает согласованное поведение интерфейса и предотвращает потерю доступности при добавлении новых элементов.

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

Dragula легко интегрируется с React, Vue и Angular:

  • React: управление контейнерами через ref, события Dragula синхронизировать с состоянием компонентов.
  • Vue: использовать v-for для рендеринга элементов, привязывать контейнеры через ref и управлять событиями через методы компонента.
  • Angular: подключать Dragula через сервис или сторонний пакет ng2-dragula, используя директивы для контейнеров и элементов.

Клавиатурная навигация при этом реализуется аналогично — фокусируемые элементы и обработчики клавиатуры работают вне зависимости от фреймворка.

Важные рекомендации

  • Для полной доступности необходимо сочетать Dragula с ARIA-атрибутами (role="list", role="listitem").
  • Реализовать визуальные индикаторы фокуса, чтобы пользователь видел, какой элемент выбран.
  • Тестировать работу стрелок, Enter и Space в разных браузерах для стабильного поведения.

Подход, основанный на клавиатурной навигации, позволяет Dragula быть не только мощной библиотекой для drag-and-drop, но и полностью соответствовать современным стандартам доступности.