当我拖动时,dragend,dragenter和dragleave立即开火

我正在尝试制作一个可以通过拖放重新定位的元素列表。 第一个元素Box 1在100%的时间内都能正常工作。 有时第二个框可以工作,但其他框都没有按预期工作。 一旦开始拖动它们,它们似乎立即触发所有拖动事件。

如果重要的话,我正在使用最新的Chrome(第23版)。

var $questionItems = $('.question-item'); $questionItems .on('dragstart', startDrag) .on('dragend', removeDropSpaces) .on('dragenter', toggleDropStyles) .on('dragleave', toggleDropStyles); function startDrag(){ console.log('dragging...'); addDropSpaces(); } function toggleDropStyles(){ $(this).toggleClass('drag-over'); console.log(this); } function addDropSpaces(){ $questionItems.after('
'); console.log('drop spaces added'); } function removeDropSpaces(){ $('.empty-drop-target').remove(); console.log('drop spaces removed'); }

这是HTML:

 
Box 1: Milk was a bad choice.
Box 2: I'm Ron Burgundy?
Box 3: You ate the entire wheel of cheese?
Box 4: Scotch scotch scotch

这是我的代码的jsFiddle: http : //jsfiddle.net/zGSpP/5/

刚出现这个问题 – 这是一个Chrome bug,你不能在dragStart事件中操纵DOM,否则dragEnd会立即触发。 我的解决方案原来是 – 使用setTimeout()并在你超时的函数内操作DOM。

它似乎是一个Chrome错误: https : //groups.google.com/a/chromium.org/forum/?fromgroups =#! msg / chromium-bugs / YHs3orFC8Dc / rtT25b7J-NwJ

不确定它是否是一个bug,但我认为当你在dragstart处理程序中更改DOM时会出现问题。 我认为第一个盒子工作的原因与它的位置在DOM中的其他盒子之前的事实有关,当你改变DOM时,第一个盒子的位置(?)不受影响,并且拖拉事件火力可靠。

您需要稍微重构一下代码,并在dragenter事件处理程序中添加dropSpaces。 您需要更改addDropSpaces方法以适应它将被多次调用的事实。

jQuery让生活更轻松。 这正是您所描述的,使用jQueryUI。

http://jqueryui.com/draggable/#sortable

这允许排序。 代码:

     jQuery UI Draggable + Sortable         
  • Drag me down
  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5

另见: http : //jqueryui.com/sortable/

尝试手动添加事件,很长一段时间,例如:

 $questionItems[0].on('dragstart', startDrag); $questionItems[0].on('dragend', removeDropSpaces) $questionItems[0].on('dragenter', toggleDropStyles) $questionItems[0].on('dragleave', toggleDropStyles); $questionItems[1].on('dragstart', startDrag); $questionItems[1].on('dragend', removeDropSpaces) $questionItems[1].on('dragenter', toggleDropStyles) $questionItems[1].on('dragleave', toggleDropStyles); 

等只是为了看效果?

改变这个function

 function addDropSpaces() { $(this).after('
'); }

在您的版本中,您将在每个$ questionItem之后添加该div。

你需要防止“事件”冒泡,这样它就不会启动其他事件。 请参阅https://developer.mozilla.org/en-US/docs/DOM/event.stopPropagation

对于startDrag,toggleDropStyles,removeDropSpaces函数,你会写这样的东西:

 function startDrag(ev) { ev.stopPropagation(); ... your code here ... }