I am working on a sortable list, to avoid having to manually type in sorting order numbers in a database. It works via HTML5\'s drag\'n\'drop functionality,
So in a twist of fate, a comment response on another question pointed me to the answer here. wolf-war deserves credit here for pointing me to the right event and method.
Anyway, on to the answer. The solution lies in using the dragover
event, rather than using the dragenter
event. dragover
keeps firing as long as you are hovering.
We get rid of the dragenter
code:
document.addEventListener('dragenter', function(event) {
event.target.style['border-bottom'] = 'solid 4px blue';
});
Replace it with:
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'] = '';
}
});
Then in the drop
section, we check to see which border the drop target has, and use that to insert the dragged content either above or below.
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>