我很难用语言来总结这个错误。所以我为这个bug做了video。 基本上,当调用dragEnd时,元素动画就像转到原始位置一样。如何停止默认行为?我也为此制作了fiddle和codepen。
我的示例有两个列表,在释放鼠标按钮后调用dragEnd。来自一个列表的元素将动画转到其原始位置列表而不是它将要到达的位置。
JS代码:
'use strict';
var source = null; var heightWidth = null; var lastDragOverElementId = null; var dragImageSource = null;
function listItemDragStartHandler(event) {
source = event.currentTarget;
heightWidth = [];
heightWidth.push(source.offsetHeight);
heightWidth.push(source.offsetWidth);
event.dataTransfer.setData('text/html', event.currentTarget.innerHTML);
event.dataTransfer.effectAllowed = 'move';
// Drag image logic
dragImageSource = source.cloneNode(true);
dragImageSource.style.position = 'absolute';
// Don't show the element
dragImageSource.style.top = '0px';
dragImageSource.style.left = '-' + String(window.innerWidth) + 'px';
// dragImageSource.style.left = '-100px';
var toTiltElement = dragImageSource.getElementsByClassName('item-list-element')[0];
toTiltElement.style.transform = 'rotate(5deg)';
document.body.append(dragImageSource);
event.dataTransfer.setDragImage(dragImageSource, heightWidth[1]/2, heightWidth[0]/2); }
function dragoverHandler(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
source.style.display = 'none';
var currentElement = event.currentTarget;
var listContainer = currentElement.parentNode;
if (lastDragOverElementId != currentElement.getAttribute('id')) {
lastDragOverElementId = currentElement.getAttribute('id');
if(document.getElementById('grayed-empty-node') !== null) {
if(currentElement.getAttribute('id') !== 'grayed-empty-node') {
document.getElementById('grayed-empty-node').remove();
}
}
var isGrayEmptyNodeThere = document.getElementById('grayed-empty-node'); //
if(isGrayEmptyNodeThere === null) {
var emptyNode = document.getElementById('empty-node').cloneNode(true);
emptyNode.removeAttribute('id');
emptyNode.setAttribute('id', 'grayed-empty-node');
emptyNode.setAttribute('class', 'fade-in');
emptyNode.style.height = String(heightWidth[0]) + 'px';
emptyNode.style.width = String(heightWidth[1]) + 'px';
listContainer.insertBefore(emptyNode, currentElement);
}
} }
function dragLeaveHandler(event) {
event.preventDefault();
var currentElement = event.currentTarget;
var listContainer = currentElement.parentNode;
var elementList = listContainer.getElementsByClassName('item-template-container');
var visibleElementList = [];
var i = 0;
for (i=0; i<elementList.length; i++) {
if (elementList[i].style.display !== 'none') {
visibleElementList.push(elementList[i]);
}
}
// Last element ondragleave handler should be delayed, otherwise it
// would spin off chain reaction.
var lastVisibleElement = visibleElementList[visibleElementList.length - 1];
// Basically last element
if (currentElement.id === lastVisibleElement.getAttribute('id')) {
lastVisibleElement.removeAttribute('ondragleave');
if(document.getElementById('grayed-empty-node') !== null) {
document.getElementById('grayed-empty-node').remove();
}
var isGrayEmptyNodeThere = document.getElementById('grayed-empty-node');
if(isGrayEmptyNodeThere === null) {
var listContainer = currentElement.parentNode;
var emptyNode = document.getElementById('empty-node').cloneNode(true);
emptyNode.removeAttribute('id');
emptyNode.setAttribute('id', 'grayed-empty-node');
emptyNode.setAttribute('class', 'fade-in');
emptyNode.style.height = String(heightWidth[0]) + 'px';
emptyNode.style.width = String(heightWidth[1]) + 'px';
listContainer.insertBefore(emptyNode, null);
}
// This delayed the chain reaction
setTimeout(function() {
visibleElementList[visibleElementList.length - 1].setAttribute('ondragleave', 'dragLeaveHandler(event);');
}, 500);
// When event is on last element set the lastDragOverElementId to null
// then dragover to lastVisibleElement(second last element) can be handled
// otherwise dragover to second last element won't show placeholder.
lastDragOverElementId = null;
} }
function dragEndHandler(event) {
event.preventDefault();
// Check the dropEffect
dragImageSource.remove();
var listElement = document.getElementById('grayed-empty-node')
var listContainer = listElement.parentNode;
if (event.dataTransfer.dropEffect === 'none') {
var grayEmptyNode = document.getElementById('grayed-empty-node');
// When grayEmptyNode is null, that will append at the end.
listContainer.insertBefore(source, grayEmptyNode);
source.style.display = '';
if(document.getElementById('grayed-empty-node') !== null) {
document.getElementById('grayed-empty-node').remove();
}
} else if (event.dataTransfer.dropEffect === 'move') {
var grayEmptyNode = document.getElementById('grayed-empty-node');
// When grayEmptyNode is null, that will append at the end.
listContainer.insertBefore(source, grayEmptyNode);
source.style.display = '';
if(document.getElementById('grayed-empty-node') !== null) {
document.getElementById('grayed-empty-node').remove();
}
} }
function delete_item(event) {
var currentElement = event.currentTarget;
var grandParentOfDelete = currentElement.parentNode.parentNode;
grandParentOfDelete.remove(); }
function add_item() {
var item_text_node = document.getElementsByName('add-item-text')[0]
var item_text = item_text_node.value;
if (item_text.length > 0) {
var item_template = document.getElementById('item-template-container');
var item_clone = item_template.cloneNode(true);
item_clone.removeAttribute('id');
var random_id = (new Date().getTime() +
parseInt(Math.random(0, 1000) * 1000))
item_clone.setAttribute('id', random_id);
var clone_text = item_clone.getElementsByClassName('item-text')[0];
clone_text.textContent = item_text;
// reset the value
item_text_node.value = '';
var item_list = document.getElementById('item-list');
item_list.appendChild(item_clone);
} else {
alert('No text?? Add some text!');
} }
function add_item_2() {
var item_text_node = document.getElementsByName('add-item-text-2')[0]
var item_text = item_text_node.value;
if (item_text.length > 0) {
var item_template = document.getElementById('item-template-container');
var item_clone = item_template.cloneNode(true);
item_clone.removeAttribute('id');
var random_id = (new Date().getTime() +
parseInt(Math.random(0, 1000) * 1000))
item_clone.setAttribute('id', random_id);
var clone_text = item_clone.getElementsByClassName('item-text')[0];
clone_text.textContent = item_text;
// reset the value
item_text_node.value = '';
var item_list = document.getElementById('item-list-2');
item_list.appendChild(item_clone);
} else {
alert('No text?? Add some text!');
} }
function onEnterInInput() {
var e = e || window.event;
if (e.keyCode == 13) {
add_item()
} }
function sample_data() {
for(var i=0;i<10;i++){
var item_text_node = document.getElementsByName('add-item-text')[0]
item_text_node.value = i;
var item_text_node_2 = document.getElementsByName('add-item-text-2')[0]
item_text_node_2.value = i;
add_item();
add_item_2();
} }
window.onload = function () {
sample_data(); }
HTML code:
<!DOCTYPE html>
<html>
<head>
<title>List task</title>
<script type="text/javascript" src="list-task.js"></script>
<link rel="stylesheet" type="text/css" href="list-task.css">
<script>
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
':35729/livereload.js?snipver=1"></' + 'script>')
</script>
</head>
<body>
<div id="container">
<div id="list-1">
<div id="add-item-div">
<input type="text" name="add-item-text" onkeypress="onEnterInInput(event);">
<button id="add-item" onclick="add_item(event)">Add Item</button>
</div>
<div id="item-list">
</div>
</div>
<div id="list-2">
<div id="add-item-div-2">
<input type="text" name="add-item-text-2" onkeypress="onEnterInInput(event);">
<button id="add-item-2" onclick="add_item_2(event)">Add Item</button>
</div>
<div id="item-list-2">
</div>
</div>
<div id="item-template-container" class="item-template-container" draggable="true" ondragstart="listItemDragStartHandler(event);" ondragover="dragoverHandler(event);" ondragend="dragEndHandler(event);" ondragleave="dragLeaveHandler(event);" ondrop="onDropHandler(event);">
<div class="item-list-element">
<div class="item-text"></div>
<div class="delete-item-div">
<button class="delete-item" onclick="delete_item(event);">Delete</button>
</div>
</div>
</div>
<div id="empty-node"> </div>
</div>
</body>
</html>
描述错误的视频:https://www.youtube.com/watch?v=Uz_ukKdg1O0&feature=youtu.be
注意:我观察了Mac上的行为,不确定Linux和Windows。
答案 0 :(得分:0)
在dragend事件处理程序中,您需要检测鼠标是否在要放入的列表中的灰盒子上。注意您需要编写逻辑来查询元素grayBoxInOtherList
但是这就是你需要做的事情:
if ($(grayBoxInOtherList).parent().find(":hover")) {
listContainer.insertBefore(source, grayEmptyNode);
}
只有当您将鼠标悬停在grayBoxInOtherList上时才能执行此操作:listContainer.insertBefore(source, grayEmptyNode);