Drag menu editor

by Alon Rotem

HTML

<ul class="drag-sort-enable">
  <li>item 1
    <ul>
      <li class="sub">sub-item1</li>
    </ul>
  </li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

CSS

ul {
  margin: 0;
  padding: 0;
}

li {
  margin: 5px 0;
  padding: 0 20px;
  /*height: 40px;*/
  line-height: 40px;
  border-radius: 3px;
  background: #136a8a;
/*background: -webkit-linear-gradient(to right, #267871, #136a8a);
background: linear-gradient(to right, #267871, #136a8a);*/
  color: #fff;
  list-style: none;
}

.sub{
  background-color: yellow;
}

li.drag-sort-active {
  background: transparent;
  color: transparent;
  border: 1px solid #4ca1af;
}

span.drag-sort-active {
  background: transparent;
  color: transparent;
}

JavaScript

//see: https://codepen.io/fitri/pen/VbrZQm


function enableDragSort(listClass) {
  const sortableLists = document.getElementsByClassName(listClass);
  Array.prototype.map.call(sortableLists, (list) => {enableDragList(list)});
}

function enableDragList(list) {
  Array.prototype.map.call(list.children, (item) => {enableDragItem(item)});
}

function enableDragItem(item) {
  item.setAttribute('draggable', true)
  item.ondrag = handleDrag;
  item.ondragend = handleDrop;
}

function handleDrag(item) {
  const selectedItem = item.target,
        list = selectedItem.parentNode,
        x = event.clientX,
        y = event.clientY;
  
  selectedItem.classList.add('drag-sort-active');
  let swapItem = document.elementFromPoint(x, y) === null ? selectedItem : document.elementFromPoint(x, y);
  
  if (list === swapItem.parentNode) {
    swapItem = swapItem !== selectedItem.nextSibling ? swapItem : swapItem.nextSibling;
    list.insertBefore(selectedItem, swapItem);
  }
}

function handleDrop(item) {
  item.target.classList.remove('drag-sort-active');
}

(()=> {enableDragSort('drag-sort-enable')})();