Я работаю над реализацией перетаскиваемых списков HTML5 и сталкиваюсь с проблемами.
По сути, всякий раз, когда я перетаскиваю элемент, я вставляю перетаскиваемый элемент непосредственно перед или после только что введенного элемента. Это означает, что когда вы перемещаете мышь, элемент продолжает перемещаться в положение под мышью. (Я установил visibility: hidden
для элемента, поэтому он отображается как пустое место.) Когда вы отбрасываете элемент, я затем отправляю вызов AJAX на сервер, описывающий позицию элемента, чтобы выполнить перемещение на сервере.
Проблема в том, что по какой-то причине событие drop никогда не срабатывает (точка останова в моем обработчике никогда не срабатывает), а изображение перетаскивания возвращается туда, где оно началось. (Конечно, элемент переместился на странице, поэтому он снова появляется в своем новом местоположении, но поскольку drop никогда не срабатывает, сервер никогда не уведомляется об изменении.) Кто-нибудь знает, что происходит? Обычный ответ: "вам нужно вызвать preventDefault()
в dragenter/dragover", но я уже это делаю.
Я использую jQuery 1.10.2 и вижу такое поведение как в Safari 7.0.1, так и в Firefox 26.0. Что бы это ни стоило, Rails 4.0.2 является моей основой для этого проекта, и я использую jquery_ujs и turbolinks.
Соответствующий код:
var draggingLI;
$('ol[data-passage-id]').find('li > a').attr('draggable', 'true')
.on('dragstart', function (ev) {
draggingLI = $(ev.target).closest("li")[0];
ev.originalEvent.dataTransfer.effectAllowed = 'move';
ev.originalEvent.dataTransfer.setData('text/plain', ev.target.href);
ev.originalEvent.dataTransfer.setData('text/uri-list', ev.target.href);
})
.on('dragenter', function (ev) {
ev.originalEvent.dataTransfer.dropEffect = 'move';
$(draggingLI).css('visibility', 'hidden');
if(canDropIn(ev.target)) {
var droppingLI = $(ev.target).closest("li")[0];
if(draggingLI == droppingLI) {
// do nothing
}
if(draggingLI.nextElementSibling == droppingLI) {
// We want to move the dragging element below this element.
$(droppingLI).after(draggingLI);
}
else {
// We want to move the dragging element above this element.
$(droppingLI).before(draggingLI);
}
ev.preventDefault();
ev.stopPropagation();
return false;
}
})
.on('dragover', function (ev) {
if(canDropIn(ev.target)) {
ev.preventDefault();
ev.stopPropagation();
return false;
}
})
.on('drop', function (ev) {
sendMovedItem(draggingLI);
ev.preventDefault();
ev.stopPropagation();
return false;
})
.on('dragend', function (ev) {
$(draggingLI).css('visibility', '');
});
canDropIn()
в настоящее время является заглушкой, которая всегда возвращает true
. sendMovedItem()
— это функция, которая выполняет вызов AJAX. В консоли ошибок нет.