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/
Ответы
Ответ 1
У этой проблемы только сейчас - это ошибка Chrome, вы не должны манипулировать DOM в событии dragStart, иначе dragEnd запускается немедленно. Решение для меня оказалось - использовать setTimeout() и манипулировать DOM внутри функции timeout.
Ответ 2
Кажется, это ошибка Chrome: https://groups.google.com/a/chromium.org/forum/?fromgroups=#!msg/chromium-bugs/YHs3orFC8Dc/ryT25b7J-NwJ
Ответ 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 ...
}