JSFiddle - React, Tailwind, and code Playground
by Alon Rotem
HTML
<div class='menueditor'>
<ul>
<li id="d" class="topmenuitem" draggable='true'>Item 1
<ul>
<li class="submenu-placeholder" draggable='true'>Placeholder</li>
</ul>
</li>
<li class="topmenuitem" draggable='true'>Item 2
<ul>
<li class="submenu" draggable='true'>menu 2.1</li>
<li class="submenu" draggable='true'>menu 2.2</li>
</ul>
</li>
<li class="topmenuitem" draggable='true'>Item 3
<ul>
<li class="submenu" draggable='true'>menu 3.1</li>
</ul>
</li>
</ul>
<div id="messag">Nothing is happening</div>
<!--
<span style='background-color:red; color: white; padding: 5px; ' draggable='true'>SPAN</span>
<span style='background-color:green; color: white; padding: 5px; position:absolute;'>SPAN</span>
</div>
-->
CSS
.menueditor
{
height:140px;
/*background-color:yellow;*/
/*width:40%;*/
}
.topmenuitem
{
list-style-type: none;
background-color: red;
padding: 10px;
color: white;
border: 1px solid black;
}
.submenu
{
list-style-type: none;
background-color: teal;
padding: 10px;
border: 1px solid black;
}
.submenu-placeholder
{
list-style-type: none;
background-color: yellow;
color: black;
padding: 10px;
border: 1px solid black;
}
li.drag-sort-active {
background: transparent;
color: transparent;
border: 1px solid #4ca1af;
}
li.drag-sort-active li {
background: transparent;
color: transparent;
border: 0;
}
JavaScript
(() => {
var sortableLists = document.getElementsByClassName("topmenuitem");
Array.prototype.map.call(sortableLists, (item) => {
// Array.prototype.map.call(list.children, (item) => {
item.ondrag = handleDrag;
item.ondragend = handleDrop;
});
/*
document.onmousemove = function(event){
x = event.clientX;
y = event.clientY;
showMessage(x + ", " + y);
document.getElementById("d").style.position="absolute";
document.getElementById("d").style.top = y +"px";
document.getElementById("d").style.left = x +"px";
};*/
// });
})();
/*
✓ Draggin top menu to another top menu.
Draggin top menu into another submenu (if it has no sub of itself)
Draggin submenu into top menu.
Draggin submenu items among themselves
*/
function handleDrag(item) {
const selectedItem = item.target,
list = selectedItem.parentNode,
x = event.clientX,
y = event.clientY;
var itemtype = selectedItem.classList.contains("topmenuitem") ?
"top item" :
"submenu";
selectedItem.classList.add('drag-sort-active');
let swapItem = document.elementFromPoint(x, y) === null ?
selectedItem :
document.elementFromPoint(x, y);
var swapitemtype = selectedItem.classList.contains("topmenuitem") ?
"top item" :
"submenu";
showMessage("dragging " + itemtype + " onto "+swapitemtype+"...");
if (list === swapItem.parentNode) {
swapItem = swapItem !== selectedItem.nextSibling ?
swapItem :
swapItem.nextSibling;
list.insertBefore(selectedItem, swapItem);
}
}
function handleDrop(item) {
showMessage("dropped.");
item.target.classList.remove('drag-sort-active');
}
function showMessage(text) {
var container = document.getElementById("messag");
if (text && container) {
container.textContent = text;
}
}