От автора: существует множество отличных библиотек JavaScript для добавления функции перетаскивания элементов в приложение. Но вы можете не знать, что HTML имеет встроенный API для создания перетаскиваемых элементов в DOM. Здесь мы рассмотрим создание функции перетаскивания с использованием HTML Drag and Drop API с небольшим количеством JavaScript для настройки обработчиков событий.
Обзор
HTML Drag and Drop API использует модель событий DOM для получения информации о том, что перетаскивается, и для обновления этого элемента при перетаскивании. С помощью всего лишь нескольких обработчиков событий вы можете превратить любой элемент в перетаскиваемый элемент или в зону сброса.
Drag and Drop API предоставляет множество параметров для настройки действий, помимо перетаскивания. Например, вы можете обновить CSS-стиль перетаскиваемых элементов. Кроме того, вместо того, чтобы просто перемещать элемент, вы можете скопировать перетаскиваемый элемент, чтобы он воспроизводился в другом месте.
Здесь мы сосредоточимся на основах создания JavaScript-функций перетаскивания для непосредственного обновления DOM.
Делаем HTML-элементы перетаскиваемыми
Давайте начнем с того, что мы хотим перетащить. Допустим, у нас есть контейнер с двумя типами дочерних элементов: дочерние элементы, которые могут быть перемещены, и дочерние элементы, в которые могут быть перемещены другие элементы. Например, если бы у нас был список дел, мы могли бы перетаскивать задачи в область «готово». (Мы вернемся к этому примеру списка дел в конце.)
Для простоты давайте будем называть перемещаемые элементы перетаскиваемыми элементами, а целевые элементы — «зоной сброса».
<div class='parent'> <span id='draggableSpan'> draggable </span> <span> dropzone </span> </div>
Наш первый пример по умолчанию, и потомки не перетаскиваются. Итак, давайте начнем с того, что явно сделаем перетаскиваемый элемент действительно перетаскиваемым. Для этого нам нужно использовать атрибут draggable:
<div class='parent'> <span id='draggableSpan' draggable='true'> draggable </span> <span> dropzone </span> </div>
Теперь, если вы попытаетесь переместить перетаскиваемый элемент с помощью мыши (извините, мобильные посетители!), вы должны увидеть более светлую версию элемента, перемещаемую с помощью курсора при перетаскивании.
Без установки для атрибута draggable значения true, значение по умолчанию — auto. Это означает, что возможность перетаскивания элемента будет определяться настройками вашего браузера по умолчанию. Например, ссылки (<a>) обычно являются перетаскиваемыми по умолчанию. А в то же время span — нет.
Создание обработчиков событий перетаскивания
В настоящее время, если мы отпустим мышь при перетаскивании элемента, ничего не произойдет. Это бесполезно! Чтобы фактически вызвать действие при перетаскивании, нам нужно применить Drag and Drop API минимум для трех событий:
ondragstart: Устанавливает идентификатор перетаскиваемого элемента и вносит любые другие изменения, которые мы хотим применить в состоянии перетаскивания.
ondragover: Браузеры по умолчанию не запускают действия при перетаскивании элемента. Мы должны вмешаться и позволить произойти действиям сброса!
ondrop: Все, что должно произойти при сбросе, будет выполнено здесь. Часто перетаскиваемый элемент перемещается в новый родительский элемент в DOM.
Обработчики событий ondragstart, ondragover, ondrop — это только начало. Всего их восемь: ondrag, ondragend, ondragenter, ondragexit, ondragleave, ondragover, ondragstart и ondrop.
Интерфейс DataTransfer
Интерфейс DataTransfer будет отслеживать информацию, связанную с текущим перетаскиванием. Чтобы обновить элемент при перетаскивании, нам нужен прямой доступ к объекту DataTransfer. Для этого мы можем выбрать свойство dataTransfer из события DOM.
Интерфейс DataTransfer (или объект) может технически отслеживать информацию для нескольких элементов, перетаскиваемых одновременно. В нашем примере мы сосредоточимся на перетаскивании только одного элемента.
Обновление элемента при перетаскивании
На следующем шаге мы настроим функцию ondragstart. В функции ondragstart мы можем вносить любые изменения, которые хотели бы видеть после начала перетаскивания. Вы можете обновить CSS перетаскиваемого элемента, сделать перетаскиваемую версию временным изображением, и все остальное, о чем вы можете подумать, может быть доступно через событие DOM.
Свойство dataTransfer объекта setData можно использовать для установки информации о состоянии перетаскивания для текущего перетаскиваемого элемента. Он принимает два параметра: строку, которая объявляет формат второго параметра и фактические передаваемые данные.
Наша цель — переместить перетаскиваемый элемент к новому родителю, поэтому нам нужно иметь возможность выбрать перетаскиваемый элемент с уникальным идентификатором. Мы можем установить идентификатор перетаскиваемого элемента с помощью свойства setData, чтобы его можно было использовать позже так:
function onDragStart(event) { event .dataTransfer .setData('text/plain', event.target.id); }
Чтобы обновить CSS-стиль перетаскиваемого элемента, мы можем снова получить доступ к его стилям, используя событие DOM и установив любые стили, которые хотим для currentTarget:
function onDragStart(event) { event .dataTransfer .setData('text/plain', event.target.id); event .currentTarget .style .backgroundColor = 'yellow'; }
Примечание. Любые стили, которые вы изменяете, нужно будет снова обновлять вручную, если вы хотите, чтобы стили применялись только при перетаскивании. Таким образом, если вы измените что-либо при перетаскивании, перетаскиваемый элемент сохранит этот новый стиль, если вы не измените его обратно.
Теперь, когда у нас есть функция JavaScript для начала перетаскивания, мы можем передать ее атрибуту ondragstart перетаскиваемого элемента:
<div class='parent'> <span id='draggableSpan' draggable='true' ondragstart='onDragStart(event);'> draggable </span> <span> dropzone </span> </div>
Вот как будет выглядеть перетаскивание, если у вас нет мыши, чтобы попробовать его самостоятельно.
Если вы попытаетесь перетащить элемент сейчас, будет применен объявленный стиль ondragstart, но ничего при этом не произойдет. Давайте перейдем к обработчикам событий dropzone.
Сбрасывание элементов
После ondragstart далее нам нужно заняться функцией ondragover. Как уже упоминалось, по умолчанию браузер предотвращает действия сброса, поэтому мы должны запретить браузеру предотвращать наши действия сброса. Запретить запрещение — это значит разрешить, верно?
function onDragOver(event) { event.preventDefault(); }
Все, что нам нужно сделать, это остановить браузер от вмешательства в действие сброса. Теперь мы можем добавить это для зоны сброса, чтобы она могла стать гостеприимным родителем для любых перетаскиваемых элементов.
<div class='parent'> <span id='draggableSpan' draggable='true' ondragstart='onDragStart(event);'> draggable </span> <span ondragover='onDragOver(event);'> dropzone </span> </div>
Несмотря на то, что теперь зона сброса может принимать перетаскиваемые элементы, мы до сих пор не сказали, что должно произойти, когда мышь отпущена.
Что делать при сбросе
Теперь мы можем представить нашу третью и последнюю функцию: ondrop. Наши действия для этой функции будут следующими:
Помните данные, которые мы установили в setData? Теперь нам нужно получить эти данные с помощью объекта dataTransfer свойства getData. Данные, которые мы установили, были идентификатором, они будут нам возвращены.
Выбираем перетаскиваемый элемент с помощью идентификатора, который мы получили на первом этапе.
Выбираем элемент dropzone.
Добавляем перетаскиваемый элемент в dropzone.
Сбрасываем объект dataTransfer.
function onDrop(event) { const id = event .dataTransfer .getData('text'); const draggableElement = document.getElementById(id); const dropzone = event.target; dropzone.appendChild(draggableElement); event .dataTransfer .clearData(); }
Поскольку это наша третья и последняя функция, нам просто нужно передать ее в атрибут ondrop dropzone. Когда это будет сделано, у нас готова функция перетаскивания!
<div class='parent'> <span id='draggableSpan' draggable='true' ondragstart='onDragStart(event);'> draggable </span> <span ondragover='onDragOver(event);' ondrop='onDrop(event);'> dropzone </span> </div>
Наш пример предельно прост, он показывает, как сделать что-либо на странице перетаскиваемым или сбрасываемым. У вас может быть несколько перетаскиваемых элементов, несколько зон сброса, и они все могут быть настроены с помощью обработчиков событий Drag and Drop API.
Вот еще один пример того, как вы можете использовать этот API: простой список дел, упомянутый в начале.
Повторюсь, просто добавьте больше перетаскиваемых элементов, как мы делали выше. Просто убедитесь, что у вас идентификаторы всегда уникальны!
Дополнительные ресурсы
Чтобы узнать больше обо всем, что вы можете добавить с помощью Drag and Drop API, ознакомьтесь с документацией MDN.
Автор: Jess Mitchell
Источник: https://alligator.io
Редакция: Команда webformyself.