Все це drag’n’drop, Підручник HTML5

У стандарт HTML5 поведінка drag'n'drop включено спочатку. Реалізується воно новим атрибутом draggable та рядом подій на кожен етап дій щодо переміщення об'єктів. Усього їх сім:

- dragstart - подія початку перетягування об'єкта;

- drag - переміщення об'єкта;

- dragenter - подія викликається, коли об'єкт, що перетягується, потрапляє на об'єкт-приймач;

- dragleave - об'єкт-приймач, що перетягується, залишає;

- dragover - подія викликається під час переміщення об'єкта, що перетягується над об'єктом-приймачем;

- drop - подія викликається, коли об'єкт, що переміщається, потрапляє на об'єкт-приймач і користувач відпускає кнопку миші;

- dragend – користувач перестає перетягувати об'єкт.

Це все, але давайте з цим набором спробуємо створити щось корисне.

Насамперед нам потрібні візуальні об'єкти, а значить, html-розмітка та зіставлені їй стилі. Створимо об'єкти:

Результат можна побачити на рис. 78.

Наше завдання – забезпечити можливість переміщати квадратики з цифрами всередину великого прямокутника у довільному порядку (можливо, це буде щось на зразок гри або головоломки). Почнемо з того, що забезпечимо саму можливість перетягувати об'єкти мишкою (тут і далі ми будемо використовувати javascript - фреймворк jQuery - знову виключно для скорочення обсягу коду):

Такий самий ефект дасть

Мал. 78. Все готове до drag-n-drop

Мал. 79. Починаємо перетягування

Не зупинятимемося на досягнутому — рухатимемося до мети, використовуючи вищеописану модель подій. Спочатку займемося початком переміщення:

Це. add EventListener('dragstart', handleDragStart, false); >);

Поки що просто зробимооб'єкт, що переміщається, напівпрозорим:

Тепер позначимо цільову область переміщення. У нас це div з id "tr". Забезпечимо його обробником подій наDragenter і onDagleave:

Це. addEventListener('dragenter', handleDragEnter, false); це. addEventListener('dragleave', handleDragLeave, false); >);

Тепер створимо клас over, що визначає цільову область в момент знаходження над нею об'єкта, що перетягується (її необхідно «підсвітити» просто для зручності):

Border: 2px dashed #000:

Дуже проста: var inCont = 0; function handleDragEnter(e) < $(this).addClass('over'); return false; inCont = 1;

Тепер переміщення візуально оформлене (мал. 80), але поки що від цього не дуже багато користі, потрібне реальне переміщення.

Мал. 80. Позначимо цільову область

Тут нам на допомогу прийде новий об'єкт dataTransfer, який зберігає дані від об'єкта, що перетягується. Для його використання трохи модифікуємо handleDragStar:

E. DataTransfer. effectAllowed = 'move'; e. dataTransfer. setData('text/html', this. outerHTML); це. стиль. opacity = '0.4'; return false:

Тепер у dataTransfer у нас зберігається код об'єкта, що перетягується. Зараз потрібно обробити подію:

Це. addEventListener('drop', handleDrop, false); >);

Var obj = e. dataTransfer. getData('text/html'); $(this).append(obj);

І додамо обробку закінчення перетягування:

Це. add EventListener('dragstart', handleDragStart, false); це. addEventListener('dragend', handleDragEnd, false);

E. srcElement. стиль. opacity = '1.0'; if(inCont == 1)

$(e. srcElement).remove(); inCont = 0;

Власне все. Щоправда, швидше за все, нічого не працює, але це ми зараз виправимо. Справа в тому, що здебільшогобраузерів реалізовано поведінку при припиненні перетягування об'єкта за умовчанням (наприклад, картинка, перетягнута з робочого столу, розкриється, а div draggable повернеться на колишнє місце). Виправимо це, використовуючи preventDefault():

Це. addEventListener('dragover', handleDragOver, false); це. addEventListener('drop', handleDrop, false);

E. DataTransfer. dropEffect = 'move';

Тепер об'єкти переміщаються (рис. 81), саме час запитати себе: навіщо взагалі все це, якщо з jQuery, MooTools або ExtJs все набагато простіше і красивіше?

Мал. 81. Drag'n'drop у дії

Справа в тому, що drag'n'drop, здійснюваний засобами атрибутів style і position DOM-елемента (а саме його використовують перелічені бібліотеки), і щойно реалізована нами поведінка мають принципову різницю. Те, що ми зробили, — це справжнє переміщення із залученням буфера обміну, а не імітація його за допомогою стилів. Щоб переконатись у цьому, проведемо невелике випробування. Спочатку трохи змінимо handleDragEnd:

E. srcElement. стиль. opacity = '1.0'; if((inCont == 1) (e. x '].join(»);

Document. get ElementById('gallery').insert Before(span, null);

Тепер можна вантажити зображення мишкою (рис. 83, я прибрав плашки та додав клас icon та div id="gallery"). Цей скрипт легко модифікувати для мультизавантаження, але це я залишу читачеві як домашнє завдання. Зробимо ще одну дію — додамо завантаження цих зображень на сервер (інакше наша галерея зникне з натисканням кнопки F5):

Alert'Oira! "); return 0;

Xhr. open("POST", "/upload. php"); var boundary="testest";

Xhr. setRequestHeader("Content-Type", "multipart/form-data, boundary=" + boundary);

Var body = "-" + boundary + "rn";

Body+= "Content-Disposition: form-data; name='myFile'; filename='" + file. name + "'rn";

Мал. 83. Перетягуємо картинки з провідника Windows

Body += "Content-Type: application/octet-streamrnrn"; body + = reader. result + "rn"; body += "-" + boundary + "-"; xhr. send(body);

Цю функцію викликаємо, наприклад, тут:

Files = e. dataTransfer. files; if(upload(file[0])

Ну а як продати upload. php, я думаю, пояснювати немає потреби.

Все — візуальний завантажувач готовий, а ми продовжимо наші мандри HTML5 в наступному розділі.