26

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

如果这很重要,我正在使用最新的 Chrome (v23)。

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('<div class="empty-drop-target"></div>');
  console.log('drop spaces added');
}

function removeDropSpaces(){
  $('.empty-drop-target').remove();
  console.log('drop spaces removed');
}

这是HTML:

<div class="question-item" draggable="true">Box 1: Milk was a bad choice.</div>
<div class="question-item" draggable="true">Box 2: I'm Ron Burgundy?</div>
<div class="question-item" draggable="true">Box 3: You ate the entire wheel of cheese?</div>
<div class="question-item" draggable="true">Box 4: Scotch scotch scotch</div>

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

4

6 回答 6

34

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

于 2013-12-22T20:42:08.930 回答
10

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

于 2013-01-07T21:15:49.743 回答
6

不确定这是否是一个错误,但我认为当您在 dragstart 处理程序中更改 DOM 时问题就出现了。我认为第一个框起作用的原因与它的位置在 DOM 中的其他框之前以及当您更改 DOM 时,第一个框的位置(?)不受影响和拖放事件有关可靠地点火。

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

于 2013-10-29T15:52:36.547 回答
0

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

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

允许排序。编码:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>jQuery UI Draggable + Sortable</title>
    <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
    <script src="http://code.jquery.com/jquery-1.8.3.js"></script>
    <script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
    <link rel="stylesheet" href="/resources/demos/style.css" />
    <style>
    ul { list-style-type: none; margin: 0; padding: 0; margin-bottom: 10px; }
    li { margin: 5px; padding: 5px; width: 150px; }
    </style>
    <script>
    $(function() {
        $( "#sortable" ).sortable({
            revert: true
        });
        $( "#draggable" ).draggable({
            connectToSortable: "#sortable",
            helper: "clone",
            revert: "invalid"
        });
        $( "ul, li" ).disableSelection();
    });
    </script>
</head>
<body> 
<ul>
    <li id="draggable" class="ui-state-highlight">Drag me down</li>
</ul>

<ul id="sortable">
    <li class="ui-state-default">Item 1</li>
    <li class="ui-state-default">Item 2</li>
    <li class="ui-state-default">Item 3</li>
    <li class="ui-state-default">Item 4</li>
    <li class="ui-state-default">Item 5</li>
</ul>

</body>
</html> 

另见: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); 

等只是为了看看效果?

于 2013-01-07T21:21:10.230 回答
-1

您需要防止“事件”冒泡,以免引发其他事件。请参阅https://developer.mozilla.org/en-US/docs/DOM/event.stopPropagation

对于 startDrag、toggleDropStyles、removeDropSpaces 函数,你可以这样写:

function startDrag(ev) {
   ev.stopPropagation();
   ... your code here ...
}
于 2013-01-07T21:21:26.923 回答
-1

改变这个功能

function addDropSpaces()
{
  $(this).after('<div class="empty-drop-target"></div>');
}

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

于 2013-01-07T20:57:45.787 回答