【问题标题】:Multiple drop events in HTML5HTML5 中的多个放置事件
【发布时间】:2011-07-16 14:00:45
【问题描述】:

我正在尝试在 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>

【问题讨论】:

    标签: javascript html drag-and-drop


    【解决方案1】:

    这就是为什么在循环中定义函数(例如回调函数)通常是个坏主意。您在循环中分配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 现在似乎对我有用。更多解释见here

    【讨论】:

    • 谢谢!这是有道理的,那么为什么最后一个 id 总是出现。 MDN 链接很有帮助;看来我对闭包有点了解。
    猜你喜欢
    • 1970-01-01
    • 2011-07-28
    • 2011-09-04
    • 2012-12-25
    • 2015-12-17
    • 2012-06-08
    • 1970-01-01
    • 2020-05-27
    • 2023-03-24
    相关资源
    最近更新 更多