Несколько событий отбрасывания в HTML5 - PullRequest
0 голосов
/ 16 июля 2011

Я пытаюсь создать функцию перетаскивания в HTML5, где я могу перетаскивать из одного списка в другой.У меня есть один список с перетаскиваемыми элементами и другой список с элементами, к которым добавлены события перетаскивания.Проблема в том, что независимо от того, на какой элемент я добавляю, вызывается последнее добавленное событие.

Спасибо за любую помощь или предложения.

Я включил мой код ниже:

<!DOCTYPE html>

<head>
<title>List Conversion Test</title>

<style type="text/css">

#list, #cart {
  display: inline;
  float: left;
  border: 1px solid #444;
  margin: 25px;
  padding: 10px;
}

#list p {
  background-color: #036;
  color: #fff;
}
#cart p {
  background-color: #363;
  color: #fff;
}

.listitem {

}

.listitem_done {
  text-decoration: line-through;
}

.product {
  background-color: #CCC;
}

.product_over {
  background-color: #363;
}

</style>


<script type="text/javascript" src="http://html5demos.com/js/h5utils.js"></script>

</head>

<body>

<article>
  <div id="list">
    <p>On My List</p>
    <ul>
      <li class="listitem" id="L001">Shopping List Item #1</li>
      <li class="listitem" id="L002">Shopping List Item #2</li>
    </ul>
    <div id="done">
      <p>In My Cart</p>
      <ul></ul>
    </div>
  </div>

  <div id="cart">
    <p>Cart</p>
    <ul>
      <li class="product" id="P001">Product #1</li>
      <li class="product" id="P002">Product #2</li>
    </ul>
  </div>

</article>
<script>

  // make list items draggable
  var list = document.querySelectorAll('li.listitem'), thisItem = null;
  for (var i = 0; i < list.length; i++) {
    thisItem = list[i];

    thisItem.setAttribute('draggable', 'true');

    addEvent(thisItem, 'dragstart', function (e) {
      e.dataTransfer.effectAllowed = 'copy';
      e.dataTransfer.setData('Text', this.id);
    });
  }


  // give products drop events
  var products = document.querySelectorAll('li.product'), thisProduct = null;
  for (var i = 0; i < products.length; i++) {
    thisProduct = products[i];

    addEvent(thisProduct, 'dragover', function (e) {
      if (e.preventDefault) e.preventDefault();
      this.className = 'product_over';
      e.dataTransfer.dropEffect = 'copy';
      return false;
    });

    addEvent(thisProduct, 'dragleave', function () {
     this.className = 'product';
    });

    addEvent(thisProduct, 'drop', function (e) {
      //alert(thisProduct.id);
      if (e.stopPropagation) e.stopPropagation();
      var thisItem = document.getElementById(e.dataTransfer.getData('Text'));
      thisItem.parentNode.removeChild(thisItem);
      thisProduct.className = 'product';
      handleDrop(thisItem, thisProduct);
      return false;
    });

  }

  // handle the drop
  function handleDrop(i, p) {
    alert(i.id + ' to ' + p.id);
    var done = document.querySelector('#done > ul');
    done.appendChild(i);
    i.className = 'listitem_done';
  } 


</script>

</body>
</html>

1 Ответ

1 голос
/ 16 июля 2011

Вот почему часто плохая идея определять функции (такие как функции обратного вызова) внутри цикла. Вы присваиваете thisProduct внутри цикла, но он будет переназначен для следующей итерации цикла. При настройке замыканий каждый обратный вызов привязывается к одной и той же переменной thisProduct и будет использовать последнее значение.

Одним из возможных исправлений является создание нового замыкания, где требуется thisProduct, например

(function(thisProduct) {
    addEvent(thisProduct, 'drop', function (e) {
      //alert(thisProduct.id);
      if (e.stopPropagation) e.stopPropagation();
      var thisItem = document.getElementById(e.dataTransfer.getData('Text'));
      thisItem.parentNode.removeChild(thisItem);
      thisProduct.className = 'product';
      handleDrop(thisItem, thisProduct);
      return false;
    });
}(thisProduct));

Этот jsFiddle , кажется, теперь работает для меня. См. здесь для более подробного объяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...