JSFiddle - React, Tailwind, and code Playground
by Tony Realovich
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drag & Drop</title>
</head>
<body>
<ul class="list">
<li class="item">
<div class="label">First</div>
</li>
<li class="item">
<div class="label">Second</div>
<ul class="sublist">
<li class="subitem"><div class="sublabel">SubFirst</div></li>
<li class="subitem"><div class="sublabel">SubSecond</div></li>
<li class="subitem"><div class="sublabel">SubThird</div></li>
<li class="subitem"><div class="sublabel">SubFourth</div></li>
</ul>
</li>
<li class="item">
<div class="label">Third</div>
</li>
<li class="item">
<div class="label">Fourth</div>
</li>
</ul>
</body>
</html>
CSS
.label {
padding: 8px;
border: 2px solid LightSteelBlue;
background-color: LightBlue;
border-radius: 8px;
color: SteelBlue;
font-weight: bold;
text-transform: uppercase;
}
.sublabel {
padding: 4px 8px;
border: 2px dotted BurlyWood;
background-color: Bisque;
border-radius: 4px;
color: Peru;
font-weight: bold;
}
li {
margin: 4px 0;
}
.selected {
opacity: .6;
}
JavaScript
const dndListElement = document.querySelector('.list');
const dndItemClass = 'item';
const dndSublistElement = document.querySelector('.sublist');
const dndSubitemClass = 'subitem';
const makeDraggable = (itemClass, listElement) => {
const items = document.querySelectorAll(`.${itemClass}`);
for (const dndItem of items) {
dndItem.draggable = true;
}
listElement.addEventListener('dragstart', (evt) => {
evt.target.classList.add('selected');
});
listElement.addEventListener('dragend', (evt) => {
evt.target.classList.remove('selected');
});
listElement.addEventListener('dragover', (evt) => {
evt.preventDefault();
const activeElement = listElement.querySelector('.selected');
const currentElement = evt.target;
const parentElement = currentElement.parentElement;
const isMoveable = activeElement !== parentElement && parentElement.classList.contains(`${itemClass}`);
if(!isMoveable) {
return;
}
const nextElement = (parentElement === activeElement.nextElementSibling) ? parentElement.nextElementSibling : parentElement;
listElement.insertBefore(activeElement, nextElement);
});
}
makeDraggable(dndItemClass, dndListElement);
makeDraggable(dndSubitemClass, dndSublistElement);