JSFiddle - React, Tailwind, and code Playground

by Ben Schnell

HTML

<div id="dropzone">
  <div id="record-id-1" class="node" draggable="true">One</div>
  <div id="record-id-2" class="node" draggable="true">Two</div>
  <div id="record-id-3" class="node" draggable="true">Three</div>
  <div id="record-id-4" class="node" draggable="true">Four</div>
  <div id="record-id-5" class="node" draggable="true">Five</div>
  <div id="record-id-6" class="node" draggable="true">Six</div>
  <div id="record-id-7" class="node" draggable="true">Seven</div>
  <div id="record-id-8" class="node" draggable="true">Eight</div>
</div>

CSS

#dropzone {
	background-color: powderblue;
  margin: 0.5em;
  padding: 0.4em;
  min-height: 100vh;
  font-size: 1.4em;
}

.node {
	background-color: cornsilk;
  margin: 0.5em;
  padding: 0.4em;
  border: 3px skyblue solid;
}

JavaScript

var dropzone = document.getElementById('dropzone');
var nodes = document.getElementsByClassName('node');
var selectedNode = '';
var selectedNodePos = 0;

for (var i = 0; i < nodes.length; i++) {
	nodes[i].addEventListener('mousedown', (e) => {
  	for (var i = 0; i < nodes.length; i++) {
    	nodes[i].style.backgroundColor = 'cornsilk';
    }
  	document.getElementById(e.target.id).style.backgroundColor = 'tomato';
    document.getElementById(e.target.id).style.transition = '0s';
  })
  nodes[i].addEventListener('dragstart', (e) => {
  	e.dataTransfer.setData('text', e.target.id);
  	
    selectedNode = document.getElementById(e.target.id);
    setTimeout(() => {
    	dropzone.removeChild(selectedNode);
    }, 0)
  })
}

dropzone.addEventListener('dragover', (e) => {
	e.preventDefault();
  whereAmI(e.clientY);
})

dropzone.addEventListener('drop', (e) => {
	e.preventDefault();
  
  dropzone.insertBefore(selectedNode, dropzone.children[selectedNodePos]);
  resetNodes();
  setTimeout(() => {
  	selectedNode.style.backgroundColor = 'cornsilk';
  	selectedNode.style.transition = '2s';
  }, 200);
})

function establishNodePositions() {
	for (var i = 0; i < nodes.length; i++) {
  	var element = document.getElementById(nodes[i]['id']);
    var position = element.getBoundingClientRect();
    var yTop = position.top;
    var yBottom = position.bottom;
    nodes[i]['yPos'] = yTop + ((yBottom - yTop)/2); 
  }
}

function resetNodes() {
	for (var i = 0; i < nodes.length; i++) {
  	document.getElementById(nodes[i]['id']).style.marginTop = '0.5em';
  }
}

function whereAmI(currentYPos) {
	establishNodePositions();
  for (var i = 0; i < nodes.length; i++) {
  	if (nodes[i]['yPos']<currentYPos) {
    	var nodeAbove = document.getElementById(nodes[i]['id']);
      selectedNodePos = i +1;
    } else {
    	if (!nodeBelow) {
    		var nodeBelow = document.getElementById(nodes[i]['id']);
    	}
    }
  }
  if (typeof nodeAbove == 'undefined') {
  	selectedNodePos = 0;
  }
 ...