JSFiddle - React, Tailwind, and code Playground
by Mike Pol
HTML
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ul>
CSS
ul {
margin: 0;
padding: 0;
list-style: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
li {
cursor: move;
margin: 1px;
padding: 5px 20px;
font-size: 20px;
background-color: #ccc;
}
.ghost {
opacity: .4;
}
}
JavaScript
function sortable(rootEl, onUpdate){
var dragEl;
// Делаем всех детей перетаскиваемыми
[].slice.call(rootEl.children).forEach(function (itemEl){
itemEl.draggable = true;
});
// Фнукция отвечающая за сортировку
function _onDragOver(evt){
evt.preventDefault();
evt.dataTransfer.dropEffect = 'move';
var target = evt.target;
if( target && target !== dragEl && target.nodeName == 'LI' ){
// Сортируем
rootEl.insertBefore(dragEl, target.nextSibling || target);
}
}
// Окончание сортировки
function _onDragEnd(evt){
evt.preventDefault();
dragEl.classList.remove('ghost');
rootEl.removeEventListener('dragover', _onDragOver, false);
rootEl.removeEventListener('dragend', _onDragEnd, false);
// Сообщаем об окончании сортировки
onUpdate(dragEl);
}
// Начало сортировки
rootEl.addEventListener('dragstart', function (evt){
dragEl = evt.target; // Запоминаем элемент который будет перемещать
// Ограничиваем тип перетаскивания
evt.dataTransfer.effectAllowed = 'move';
evt.dataTransfer.setData('Text', dragEl.textContent);
// Пописываемся на события при dnd
rootEl.addEventListener('dragover', _onDragOver, false);
rootEl.addEventListener('dragend', _onDragEnd, false);
setTimeout(function (){
// Если выполнить данное действие без setTimeout, то
// перетаскиваемый объект, будет иметь этот класс.
dragEl.classList.add('ghost');
}, 0)
}, false);
}
// Используем
sortable( document.getElementById('list'), function (item){
console.log(item);
});