背景
我正在处理一个可排序的列表,以避免必须在数据库中手动输入排序顺序号。它通过 HTML5 的拖放功能工作,即 Javascript 中新的 drag*
事件。
我目前大部分时间都在使用它。我可以点击并拖动,它会自行排序。
问题
据我所知,drop
以及 dragstart
和 dragend
事件只知道它们要去的元素进入。他们无法判断鼠标是在拖放区的上半部分还是下半部分。
我想要的是,当我将鼠标悬停在列表项的上半部分时,拖动的内容将放置在该项目的上方。然后,如果我将鼠标悬停在下半部分,则将拖动的内容放置在项目下方。
目前:
在下面的屏幕截图中,我展示了我的代码的一个工作(简化)示例。我在放置目标上使用 border-bottom
来表明它就是目标。请注意,当“Item 1”位于“Item 2”上方时,“Item 2”在底部会亮起,无论我将鼠标悬停在上半部分还是下半部分。
代码
var dragging = null;
document.addEventListener('dragstart', function(event) {
dragging = event.target;
event.dataTransfer.setData('text/html', dragging);
});
document.addEventListener('dragover', function(event) {
event.preventDefault();
});
document.addEventListener('dragenter', function(event) {
event.target.style['border-bottom'] = 'solid 4px blue';
});
document.addEventListener('dragleave', function(event) {
event.target.style['border-bottom'] = '';
});
document.addEventListener('drop', function(event) {
event.preventDefault();
event.target.style['border-bottom'] = '';
event.target.parentNode.insertBefore(dragging, event.target.nextSibling);
});
ul {
margin:0;
padding:0
}
li {
cursor:move;
display:block;
padding:20px 10px;
background:white;
border-bottom:solid 1px gray;
}
<ul>
<li draggable="true" class="sortable-bulk">List Item 1</li>
<li draggable="true" class="sortable-bulk">List Item 2</li>
<li draggable="true" class="sortable-bulk">List Item 3</li>
<li draggable="true" class="sortable-bulk">List Item 4</li>
<li draggable="true" class="sortable-bulk">List Item 5</li>
<li draggable="true" class="sortable-bulk">List Item 6</li>
<li draggable="true" class="sortable-bulk">List Item 7</li>
<li draggable="true" class="sortable-bulk">List Item 8</li>
<li draggable="true" class="sortable-bulk">List Item 9</li>
<li draggable="true" class="sortable-bulk">List Item 10</li>
</ul>
问题
有没有办法让它落在上方或下方,而不总是下方,具体取决于拖动时鼠标的位置?
最佳答案
回答
所以在命运的转折中,对另一个问题的评论回复将我指向了这里的答案。 wolf-war值得称赞的是pointing me到正确的事件和方法。
无论如何,开始回答。解决方案在于使用 dragover
事件,而不是使用 dragenter
事件。 dragover
在您悬停时一直开火。
问题代码的代码更改
我们摆脱了 dragenter
代码:
document.addEventListener('dragenter', function(event) {
event.target.style['border-bottom'] = 'solid 4px blue';
});
替换为:
document.addEventListener('dragover', function(event) {
event.preventDefault();
var bounding = event.target.getBoundingClientRect()
var offset = bounding.y + (bounding.height/2);
if ( event.clientY - offset > 0 ) {
event.target.style['border-bottom'] = 'solid 4px blue';
event.target.style['border-top'] = '';
} else {
event.target.style['border-top'] = 'solid 4px blue';
event.target.style['border-bottom'] = '';
}
});
然后在 drop
部分,我们检查放置目标的边框,并使用它在上方或下方插入拖动的内容。
完整的工作代码:
var dragging = null;
document.addEventListener('dragstart', function(event) {
var target = getLI( event.target );
dragging = target;
event.dataTransfer.setData('text/plain', null);
event.dataTransfer.setDragImage(self.dragging,0,0);
});
document.addEventListener('dragover', function(event) {
event.preventDefault();
var target = getLI( event.target );
var bounding = target.getBoundingClientRect()
var offset = bounding.y + (bounding.height/2);
if ( event.clientY - offset > 0 ) {
target.style['border-bottom'] = 'solid 4px blue';
target.style['border-top'] = '';
} else {
target.style['border-top'] = 'solid 4px blue';
target.style['border-bottom'] = '';
}
});
document.addEventListener('dragleave', function(event) {
var target = getLI( event.target );
target.style['border-bottom'] = '';
target.style['border-top'] = '';
});
document.addEventListener('drop', function(event) {
event.preventDefault();
var target = getLI( event.target );
if ( target.style['border-bottom'] !== '' ) {
target.style['border-bottom'] = '';
target.parentNode.insertBefore(dragging, event.target.nextSibling);
} else {
target.style['border-top'] = '';
target.parentNode.insertBefore(dragging, event.target);
}
});
function getLI( target ) {
while ( target.nodeName.toLowerCase() != 'li' && target.nodeName.toLowerCase() != 'body' ) {
target = target.parentNode;
}
if ( target.nodeName.toLowerCase() == 'body' ) {
return false;
} else {
return target;
}
}
ul {
margin:0;
padding:0
}
li {
cursor:move;
display:block;
padding:20px 10px;
background:white;
border-bottom:solid 1px gray;
}
<ul>
<li draggable="true">List Item 1</li>
<li draggable="true">List Item 2</li>
<li draggable="true">List Item 3</li>
<li draggable="true">List Item 4</li>
<li draggable="true">List Item 5</li>
<li draggable="true">List Item 6</li>
<li draggable="true">List Item 7</li>
<li draggable="true">List Item 8</li>
<li draggable="true">List Item 9</li>
<li draggable="true">List Item 10</li>
</ul>
关于javascript - 使用 HTML5 Drag'n'Drop 进行列表排序 - 根据鼠标拖放到上方或下方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44415228/