Drag Drop Nested Lists

by Muthuraman B

HTML

<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<div class="drag">
		<div class="above">
				<p>Col 1</p>
		</div>
		<div class="drop">
				<div class="drag">
						<div class="above">
								<p>Col 2</p>
						</div>
						<div class="drop">
								<div class="drag">
										<div class="above">
												<p>Col 3</p>
										</div>
										<div class="drop">
										</div>
								</div>
						</div>
						<div class="below">
								<p>Col 2</p>
						</div>
				</div>
		</div>
		<div class="below">
				<p>Col 1</p>
		</div>
</div>

CSS

* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
	position: relative;
	font-family: sans-serif;
}

.drag {
	border: 1px solid lightblue;
  border-right: none;
	margin-bottom: 15px;
}

.drag .drop {
	margin-left: 15px;
}

.above, .below {
	margin: 15px;
}

.marker {
  border: 1px dashed lightblue;
}

JavaScript

var dragZones = $(".drag");
dragZones.on('click', function(event) {
    var mouseY = event.pageY;
    var targetZone;
    var targetDist = Infinity;
    
		dragZones.each(function(index) {
    	// Calculate Distances
    	var zone    = {};
      zone.el     = $(this);
      zone.offset = zone.el.offset();
      zone.top    = zone.offset.top;
      zone.bottom = zone.top + zone.el.outerHeight();
      zone.distTop = Math.abs(mouseY - zone.top);
      zone.distBottom = Math.abs(mouseY - zone.bottom);
      
    	// Use Top Corner
      if(zone.distTop < targetDist)
      {
	      targetZone = zone;
        targetDist = zone.distTop;
      }
      
    	// Use Bottom Corner
      if (zone.distBottom < targetDist)
      {
	      targetZone = zone;
        targetDist = zone.distBottom;
      }
		});
		
    // Reset Marker
		$('.marker').remove();
    var marker = 
    `<div class="drag marker">
      <div class="above">
        <p>Col 4</p>
      </div>
      <div class="drop">
      </div>
    </div>`;
    
    // Inside Closest Element
    if (mouseY >= targetZone.top && mouseY <= targetZone.bottom)
    {
    	// Closest to Top Corner
      if (targetZone.distTop < targetZone.distBottom)
      {
        $(marker).prependTo(targetZone.el.children('.drop').first());
      }
    	// Closest to Bottom Corner
      else
      {
        $(marker).appendTo(targetZone.el.children('.drop').first());
      }
    }
    // Outside Closest Element
    else
    {
    	// Closest to Top Corner
      if (targetZone.distTop < targetZone.distBottom)
      {
        $(marker).insertBefore(targetZone.el);
      }
    	// Closest to Bottom Corner
      else
      {
        $(marker).insertAfter(targetZone.el);
      }
    }
		event.stopPropagation();
});