JavaScript. Подробное руководство, 6-е издание, стр. 266
Пример 17.5. Список как приемник и источник
<b>/* Прикладной программный интерфейс механизма буксировки весьма сложен, его реализации</b><b>* в разных броузерах не являются полностью совместимыми. В своей основе этот пример</b><b>* реализован правильно, но все броузеры немного отличаются друг от друга,</b><b>* и каждый из них имеет свои уникальные особенности. В данном примере не делается</b><b>* попыток реализовать обходные решения, характерные для отдельных броузеров.</b><b>*/</b><b>whenReady(function() { // Вызовет эту функцию, когда документ будет загружен</b><b> // Отыскать все элементы <ul class='dnd> и вызвать функцию dnd() для них</b><b> var lists = document.getElementsByTagName("ul");</b><b> var regexp = /\bdnd\b/;</b><b> for(var і = 0; і < lists.length; i++)</b><b> if (regexp.test(lists[i].className)) dnd(lists[i]);</b><b> // Добавляет обработчики событий буксировки в элемент списка </b><b> function dnd(list) {</b><b> var original_class = list.className; // Сохранить начальный CSS-class</b><b> var entered =0; // Вход и выход за границы</b><b> // Этот обработчик вызывается, когда буксируемый объект оказывается над списком.</b><b> // Он проверяет, содержит ли буксируемый объект данные в поддерживаемом формате.</b><b> // и, если это так, отменяет событие, чтобы сообщить, что список готов</b><b> // принять объект. В этом случае он также подсвечивает элемент-приемник,</b><b> // чтобы показать пользователю, что готов к приему данных,</b><b> list.ondragenter = function(e) {</b><b> е = е И window.event; // Объект события, стандартный или IE</b><b> var from = е.relatedTarget;</b><b> // События dragenter и dragleave всплывают, из-за чего сложнее определить,</b><b> // когда следует подсвечивать элемент, а когда снимать подсветку в случаях,</b><b> // подобных этому, где элемент <ui> содержит дочерние элементы <li>.</b><b> // В броузерах, поддерживающих свойство relatedTarget, эту проблему можно решить.</b><b> // В других броузерах приходится считать пары событий входа/выхода.</b><b> // Если указатель мыши оказался над списком, переместившись из-за его пределов,</b><b> // или он оказался над списком впервые, необходимо выполнить некоторые операции </b><b> entered++;</b><b> if ((from && !ischild(from, list)) || entered == 1) {</b><b> // Вся информация о буксируемом объекте находится в объекте dataTransfer</b><b> var dt = е.dataTransfer;</b><b> // Объект dt.types содержит список типов, или форматов, в которых доступны</b><b> // буксируемые данные. Спецификация HTML5 требует, чтобы свойство types имело</b><b> // метод contains(). В некоторых броузерах это свойство является массивом</b><b> // с методом indexOf. В IE версии 8 и ниже оно просто отсутствует,</b><b> var types = dt.types; // В каких форматах доступны данные</b><b> // Если информация о типах отсутствует или данные доступны в простом</b><b> // текстовом формате, подсветить список, чтобы показать пользователю, что он</b><b> // готов принять данные, и вернуть false, чтобы известить о том же и броузер,</b><b> if (!types || //IE</b><b> (types.contains && types.contains("text/plain")) || //HTML5</b><b> (types.indexOf && types.indexOf("text/plain")!=-1)) //Webkit</b><b> {</b><b> list.className = original_class + " droppable";</b><b> return false;</b><b> }</b><b> // Если тип данных не поддерживается, мы не сможем принять их return;</b><b> // без отмены</b><b> }</b><b> return false; // Если это не первое вхождение, мы по-прежнему готовы</b><b> };</b><b> // Этот обработчик вызывается в ходе буксировки объекта над списком.</b><b> // Этот обработчик должен быть определен, и он должен возвращать false,</b><b> // иначе сброс объектов будет невозможен, </b><b> list.ondragover = function(e) { return false; };</b>