使用 HTML5 Drag'n'Drop 进行列表排序 - 根据鼠标放置在上方或下方
Posted
技术标签:
【中文标题】使用 HTML5 Drag\'n\'Drop 进行列表排序 - 根据鼠标放置在上方或下方【英文标题】:List Sorting with HTML5 Drag'n'Drop - Drop Above or Below Depending on Mouse使用 HTML5 Drag'n'Drop 进行列表排序 - 根据鼠标放置在上方或下方 【发布时间】:2017-11-08 23:01:11 【问题描述】:背景
我正在处理一个可排序的列表,以避免在数据库中手动输入排序顺序号。它通过 html5 的拖放功能工作,即 javascript 中的新 drag*
事件。
我目前大部分时间都在工作。我可以单击并拖动,它会自行排序。
问题
据我所知,drop
以及 dragstart
和 dragend
事件只知道它们要进入的元素。他们无法判断鼠标是在放置区的上半部分还是下半部分。
我想要的是,当我将鼠标悬停在列表项的上半部分时,将拖动的内容放置在该项目的上方。然后,如果我将鼠标悬停在下半部分,则拖动的内容将放置在项目下方。
目前:
在下面的屏幕截图中,我展示了我的代码的一个工作(简化)示例。我在放置目标上使用border-bottom
来表明它是目标。请注意,当“项目 1”在“项目 2”上方时,“项目 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>
问题
有没有一种方法可以让它在上方或下方,而不是总是在下方,具体取决于拖动时的鼠标位置?
【问题讨论】:
【参考方案1】:回答
因此,命运的转折,对另一个问题的评论回复将我指向了这里的答案。 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>
【讨论】:
当你点击它时是否可以做到这一点:光标仍然出现,而不是箭头指针?我正在尝试做一些简单的事情,比如 jQuery UI 版本,但只有光标:move jqueryui.com/sortable/#default以上是关于使用 HTML5 Drag'n'Drop 进行列表排序 - 根据鼠标放置在上方或下方的主要内容,如果未能解决你的问题,请参考以下文章
HTML5 Drag & Drop 在拖动时更改光标(不要使用 UI)