Использование Drag and drop в HTML5

Долгое время для создания Drag&Drop интерфейсов использовались реализации на JavaScript, но браузеры не имели встроенной поддержки Drag&Drop. С приходом HTML5 современные браузеры позволяют легко создавать drag and drop интерфейсы. В этой статье мы рассмотрим основные принципы создания Drag&Drop интерфейсов.

Поддержка

Прежде чем начать: Drag&Drop поддерживают все основные современные браузеры, но не все >мобильные браузеры имеют полную поддержку.

События Drag and drop

На каждом шаге выполнения операции перетаскивания активируются разные события, таким образом браузер знает какой именно JavaScript код выполнять, события следующие:

  • dragStart: срабатывает, когда пользователь начинает перетаскивать объект.
  • dragEnter: срабатывает, когда перетаскиваемый объект попадает в целевую зону.
  • dragOver: срабатывает, когда курсор оказывается поверх элемента во время перетаскивания.
  • dragLeave: срабатывает, когда курсор оказывается вне элемента во время перетаскивания.
  • drag: срабатывает при движении мыши во время перетаскивания.
  • drop: срабатывает, когда объект отпустили в целевой позиции (происходит drop).
  • dragEnd: срабатывает, когда пользователь отпускает перетаскиваемый объект.

Все эти события помогают осуществлять полный контроль вашего Drag&Drop интерфейса.

Объект dataTransfer

Вся магия происходит здесь, этот объект содержит всю информацию о перетаскивании. Основные свойства и методы объекта:

  • dataTransfer.effectAllowed=value: возвращает тип действия, допустимые значения: none, copy, copyLink, copyMove, link, linkMove, move, all и uninitialized.
  • dataTransfer.setData(format, data): добавляет переданные данные и их формат.
  • dataTransfer.clearData( format ): удаляет все данные заданного формата.
  • dataTransfer.setDragImage(element, x, y): устанавливает изображение, которое вы хотите перетаскивать и положение курсора (0, 0 — верхний левый угол).
  • data = dataTransfer.getData(format): возвращает данные, соответствующие формату.

Пример

Создадим небольшой пример Drag&Drop интерфейса.

Перетаскивание объекта

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

Код
<div id="boxA" draggable="true"></div>

После нам потребуется функция JavaScript, которая будет вызвана при перетаскивании объекта:

Код
function dragStart(ev) {
    ev.dataTransfer.effectAllowed = 'move';
    ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));
    ev.dataTransfer.setDragImage(ev.target, 100, 100);
    return true;
}

Этот код устанавливает тип допустимого эффекта — move, во второй строке мы устанавливаем данные для операции — тип — Text и значение — ID перетаскиваемого элемента. После используется метод setDragImage для установки того, что мы будем перетаскивать и, так как мы будем тащить квадраты размера 200 на 200px, курсор будет установлен в центр. И, наконец, функция возвращает true.

Drop объекта

Код
<div id="big" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)"></div>

Для того, чтобы объект можно было полноценно перетаскивать, необходимо отслеживать 3 разных события: dragEnter, dragOver и drop:

Код
function dragEnter(ev) {
    ev.preventDefault();
    return true;
}
 
function dragOver(ev) {
    ev.preventDefault();
}

Теперь необходимо написать соответствующие функции, начнем с событий dragenter и dragover:

В первой функции мы определяем поведение объекта, который мы перетаскиваем, когда он достигает целевого элемента. В нашем примере мы предотвращаем стандартное действие браузера, но вы можете совершать любые действия: сменить фон или добавить текста, что бы пользователь понимал, что тащит объект туда, куда нужно, а с помощью события dragleave вы можете отменить сделанные изменения. В функции dragOver просто предотвращается стандартное действие браузера. Далее объявляем функцию, которая вызывается непосредственно, когда происходит drop объекта в нужном месте:

Код
function dragDrop(ev) {
    var data = ev.dataTransfer.getData("Text");
    ev.target.appendChild(document.getElementById(data));
    ev.stopPropagation();
    return false;
}

В этой функции мы получаем все данные типа текст (это и будет объект, который мы тащим) и добавляем эти данные к целевому элементу. И, наконец, останавливаем всплытие (bubbling) события к родительским элементам и возвращаем false.

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

Этого будет достаточно, чтобы квадраты можно было вернуть на место.

Код
<section id="section" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)">

На этом всё!

1190