Drag & Drop (перетаскивание) — краткий справочник.

API Drag & Drop (Перетаскивание) предоставляет специальные события, методы и свойства, помогающие строить приложения с поддержкой перетаскивания элементов.

События

dragstart
Событие срабатывает на источнике, когда операция перетаскивания начинается. Обработчик этого события при необходимости может предотвратить перетаскивание, вызвав метод preventDefault() объекта события. Для управления возможностью копирования, создания ссылки или перемещения перетаскиваемого объекта необходимо задать свойство effectAllowed. Выделенный текст, изображения и ссылки по умолчанию помещаются в буфер обмена, но для жеста перетаскивания можно задать разные данные с помощью свойства dataTransfer объекта события.
drag
Событие срабатывает на источнике во время выполнения операции перетаскивания.
dragend
Событие срабатывает на источнике, когда операция перетаскивания завершается: либо перетаскиваемый элемент успешно попадает на зону приема, либо перетаскивание отменяется.
dragenter
Событие срабатывает на целевом элементе, когда указатель мыши с перетаскиваемым элементом оказывается над ним. Данное событие всегда необходимо отменять методом preventDefault().
Если изменить какие-либо из свойств объекта dataTransfer в обработчике события dragenter, эти изменения будут отменены следующим же событием dragover. С другой стороны, между событиями dragenter и первым событием dragover, которое может заставить курсор мигать, если заданы разные свойства, существует небольшая задержка. Часто для обоих событий может использоваться один и тот же обработчик.
dragover
Событие срабатывает на целевом элементе, когда указатель мыши с перетаскиваемым элементом находится над ним. Обработчик этого события должен задавать свойство dataTransfer.dropEffect для указания действия, которое необходимо выполнить по окончании перетаскивания: копирование, создание ссылки или перемещение. Данное событие всегда необходимо отменять методом preventDefault()..
drop
Событие срабатывает на целевом элементе, когда пользователь отпускает на нем перетаскиваемый элемент. Данное событие всегда необходимо отменять методом preventDefault().
dragleave
Событие срабатывает на целевом элементе, когда указатель мыши с перетаскиваемым элементом покидает данную зону.

Поддерживаемые HTML-теги

Все HTML-элементы

Совместимость с браузерами

4,09,03,56,012,0

Методы и свойства

Здесь приведен список наиболее важных методов и свойств.

setData()

Метод применяется для подготовки данных, которые будут отправлены при срабатывании события dragstart.

event.dataTransfer.setData(type, data)
type
В качестве значения можно передавать название любого обычного типа данных (таких, как text/plain, text/html, text/uri-list, image/x-vnd.adobe.air.bitmap и application/x-vnd.adobe.air.file-list), специальных типов (таких, как URL и Text) и даже персонализированных типов.
data
Указывается строка данных (значение атрибутов href, id, ...).
Наприммер: event.target.href, event.target.id
dataTransfer
Свойство/объект DataTransfer – это то самое место, где реализуется перетаскивание. Оно содержит часть данных, отправляемых при выполнении этого действия. Объект dataTransfer устанавливается в событии dragstart, а считывается и обрабатывается в событии drop.

Метод возвращает true в случае успеха и false в противном случае.

getData()

Метод возвращает строку, которая содержит данные указанного типа. Используется после того, как срабатывает событие drop.

event.dataTransfer.getData(type)
type
Тип отправленных элементом-источником данные.
clearData()

Метод удаляет данные указанного типа

event.dataTransfer.clearData([type])
type
Тип для удаления данных. Если тип не задан, то удаляются все типы.
setDragImage()

Метод заменяет эскиз по умолчанию, создаваемый браузером, указанным изображением, а также устанавливает его позицию относительно указателя мыши.

event.dataTransfer.setDragImage(element, x, y)
element
ссылка на новый эскиз.
x, y
мыши.

Метод setDragImage() может быть вызван только в ответ на событие dragstart.

types

Свойство возвращает массив, содержащий все типы, определенные в событии dragstart.

event.dataTransfer.types
files

Свойство возвращает массив с информацией о перетаскиваемых файлах.

event.dataTransfer.files
effectAllowed

Свойство возвращает допустимые типы операций. Также с помощью него можно менять список допустимых операций.

event.dataTransfer.effectAllowed = [ value ]
value: "none" | "copy" | "link" | "move" "copyLink" | "copyMove" | "linkMove" | "all"
  • none - Операция перетаскивания запрещена.
  • copy - Данные копируются в целевой элемент, оригинал остается на месте.
  • link - Данные совместно используются исходным и целевым элементами, для чего применяется ссылка на оригинал.
  • move - Данные копируются в целевое место и удаляются из исходного.
  • copyLink - Данные можно копировать или создавать ссылку на них.
  • copyMove - Данные можно открывать или перемещать.
  • linkMove - Данные можно перемещать или создавать на них ссылку.
  • all - Данные можно копировать, перемещать или создавать на них ссылку. Эффект All выставляется автоматически, если отменяется поведение по умолчанию.
dropEffect

Свойство возвращает тип выбранной в данный момент операции. Его также можно использовать для смены выбранной операции.

event.dataTransfer.dropEffect = [  "none" |"copy" | "move" | "link" ] 

Как правило, объект-приемник устанавливает это свойство в обработчике события dragenter или dragover. Значение этого свойства может также зависеть от клавиш модификаторов, удерживаемых пользователем в процессе буксировки, но это во многом зависит от платформы.

Примеры

Пример 1

<style type="text/css">
#div1, #div2
{float:left; width:100px; height:35px; margin:10px;padding:10px;border:1px solid #aaaaaa;}
</style>
<p>Перетащите «Домик» вперед и назад между двумя прямоугольниками:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img src="images/home1.png" draggable="true" ondragstart="drag(event)" id="drag1" />
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<script type="text/javascript">
function allowDrop(event) { event.preventDefault(); }

function drag(event) 
   { event.dataTransfer.setData("Text",event.target.id); }

function drop(event)
  { event.preventDefault();
    var data=event.dataTransfer.getData("Text");
    event.target.appendChild(document.getElementById(data));
  }
</script>


Пример 2

<style> #dst { 
  width: 450px; height: 30px; font-size: 14px;
  margin: 15px;  padding: 10px; border: 1px solid #aaaaaa; }
</style>
<a id=src href="help.htm" ondragstart="initDrag(event)">
ссылка на Справку</a>

<P id=dst ondragover="over(event)" ondrop="finishDrag(event)" onmouseout="mouseout()">
Бросьте ссылку сюда dst.</P>

<script>
var src = document.getElementById("src"), dst = document.getElementById("dst");

function mouseout() { dst.innerHTML = 'Бросьте ссылку сюда'; }

function initDrag(event) { // Сообщаем источнику, что объект нужно передать как URL.
  event.dataTransfer.effectAllowed = 'copy'; 
  event.dataTransfer.setData("URL", src.href); }

function over(event) {event.preventDefault();}

function finishDrag(event) { // Сообщаем приемнику, что объект нужно принять как URL.
 event.stopPropagation();
 event.preventDefault();
 dst.innerHTML = event.dataTransfer.getData("URL"); 
 return false;             }
</script>


Пример 3

<style>
.droptarget {
    float: left; width: 150px; height: 40px;
    margin: 15px;  padding: 10px; border: 1px solid #aaaaaa; }
</style>
<p>Перетащите элемент p вперед и назад между двумя прямоугольниками:</p>

<div class="droptarget">
  <p draggable="true" id="dragtarget">Перетащите меня!</p>
</div>

<div class="droptarget"></div>

<p id="demo" style="clear:both;"></p>

<script>
document.addEventListener("dragstart", function(event) {
    event.dataTransfer.setData("Text", event.target.id);

    document.getElementById("demo").innerHTML = "Началось перетаскивание элемента «p».";

    event.target.style.opacity = "0.4";
});

document.addEventListener("drag", function(event) {
    document.getElementById("demo").style.color = "red";
});

document.addEventListener("dragend", function(event) {
    document.getElementById("demo").innerHTML = "Закончено перетаскивание элемента «p».";
    event.target.style.opacity = "1";
});

document.addEventListener("dragenter", function(event) {
    if ( event.target.className == "droptarget" ) {
        event.target.style.border = "3px dotted red";
    }
});

document.addEventListener("dragover", function(event) {
    event.preventDefault();
});

document.addEventListener("dragleave", function(event) {
    if ( event.target.className == "droptarget" ) {
        event.target.style.border = "";
    }
});

document.addEventListener("drop", function(event) {
    event.preventDefault();
    if ( event.target.className == "droptarget" ) {
        document.getElementById("demo").style.color = "";
        event.target.style.border = "";
        var data = event.dataTransfer.getData("Text");
        event.target.appendChild(document.getElementById(data));
    }
});
</script>


Пример 4

<style type="text/css">
.binB { background: url("../example/images/computer-smile.png") top left no-repeat;}
.binA { background: url("../example/images/computer.png") top left no-repeat; }
#bin { height: 98px; width: 93px; margin-left: 100px;}
</style>

<div style="height:64px">
 <img src="../example/images/chrome.png"  id="i1">
 <img src="../example/images/ie.png"      id="i2">
 <img src="../example/images/firefox.png" id="i3">
 <img src="../example/images/safari.png"  id="i4">
 <img src="../example/images/opera.png"   id="i5">
</div>

<p>Браузеры переносить сюда:</p>
<div id="bin" class="binA"></div>
<script>
var links = document.images, el = null;
for (var i = 0; i < links.length; i++)
 { el = links[i]; 
   el.setAttribute('draggable', 'true');
   el.ondragstart = function (e) {
      e.dataTransfer.effectAllowed = 'copy'; 
      e.dataTransfer.setData('Text', this.id); }
  }

var bin = document.querySelector('#bin');
  bin.ondragover = function (e) {  e.preventDefault(); }
  bin.ondragenter = function (e) {  e.preventDefault(); return true;}
  bin.ondrop = function (e) {
    e.stopPropagation(); 
    e.preventDefault(); e.target.innerHTML=""; 
    var el = document.getElementById(e.dataTransfer.getData('Text'));
    
    el.parentNode.removeChild(el);
    bin.className='binB';
    setTimeout(function() { bin.className='binA'; }, 300);
    return false;
   }
</script>