JavaScript. Подробное руководство, 6-е издание, стр. 266

Пример 17.5. Список как приемник и источник

<b>/* Прикладной программный интерфейс механизма буксировки весьма сложен, его реализации</b>

<b>* в разных броузерах не являются полностью совместимыми. В своей основе этот пример</b>

<b>* реализован правильно, но все броузеры немного отличаются друг от друга,</b>

<b>* и каждый из них имеет свои уникальные особенности. В данном примере не делается</b>

<b>* попыток реализовать обходные решения, характерные для отдельных броузеров.</b>

<b>*/</b>

<b>whenReady(function() { // Вызовет эту функцию, когда документ будет загружен</b>

<b>  // Отыскать все элементы &lt;ul class='dnd&gt; и вызвать функцию dnd() для них</b>

<b>  var lists = document.getElementsByTagName(&quot;ul&quot;);</b>

<b>  var regexp = /\bdnd\b/;</b>

<b>  for(var і = 0; і &lt; 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>      // подобных этому, где элемент &lt;ui&gt; содержит дочерние элементы &lt;li&gt;.</b>

<b>      // В броузерах, поддерживающих свойство relatedTarget, эту проблему можно решить.</b>

<b>      // В других броузерах приходится считать пары событий входа/выхода.</b>

<b>      // Если указатель мыши оказался над списком, переместившись из-за его пределов,</b>

<b>      // или он оказался над списком впервые, необходимо выполнить некоторые операции </b>

<b>      entered++;</b>

<b>      if ((from &amp;&amp; !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 &amp;&amp; types.contains(&quot;text/plain&quot;)) || //HTML5</b>

<b>             (types.indexOf &amp;&amp; types.indexOf(&quot;text/plain&quot;)!=-1)) //Webkit</b>

<b>        {</b>

<b>          list.className = original_class + &quot; droppable&quot;;</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>