Подтвердить что ты не робот

Dragend, dragenter и dragleave, стреляя сразу же, когда я перетаскиваю

Я пытаюсь создать список элементов, которые можно переместить с помощью перетаскивания. Первый элемент, 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/

4b9b3361

Ответ 1

У этой проблемы только сейчас - это ошибка Chrome, вы не должны манипулировать DOM в событии dragStart, иначе dragEnd запускается немедленно. Решение для меня оказалось - использовать setTimeout() и манипулировать DOM внутри функции timeout.

Ответ 3

Не уверен, что это ошибка или нет, но я думаю, что проблема возникает, когда вы меняете DOM в обработчике dragstart. Причина, по которой я полагаю, что первое поле работает, связано с тем, что его позиция находится перед другими блоками в DOM, и когда вы меняете DOM, позиция (?) Первого не затрагивается и события dragdrop пожар надежно.

Вам нужно будет немного переработать ваш код и добавить dropSpaces в обработчик события dragenter. Вам нужно будет изменить метод addDropSpaces, чтобы учитывать тот факт, что он будет вызываться несколько раз.

Ответ 4

Жизнь проще с 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); 

и т.д.. просто увидеть эффект?

Ответ 5

изменить эту функцию

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

в вашей версии вы добавляете div после каждого из $questionItems.

Ответ 6

Вам нужно предотвратить "событие" от пузырьков, чтобы он не запускал другие события. См. https://developer.mozilla.org/en-US/docs/DOM/event.stopPropagation

Для функций startDrag, toggleDropStyles, removeDropSpaces вы должны написать что-то вроде этого:

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