JSFiddle - React, Tailwind, and code Playground
HTML
<div id="parent" class="parent">
<button id="button1" class="button">Drag me 1</button>
<button id="button2" class="button">Drag me 2</button>
<button id="button3" class="button">Drag me 3</button>
<button id="button3" class="button">Drag me 3</button>
<button id="button3" class="button">Drag me 3</button>
</div>
<div id="log1"></div>
<div id="log2"></div>
<div id="log3"></div>
<div id="log4"></div>
<button id="clickme">
CLICK ME FOR MORE
</button>
CSS
.parent {
position: relative;
display: block;
padding: 20px 5px 20px 5px;
margin: 20px;
width: 150px;
border: 1px solid black;
overflow: auto;
height:300px;
}
.button {
position: relative;
top: 0;
display: table;
margin-bottom: 2px;
width: 80%;
height: 80px;
clear: both;
margin: 2px auto;
}
.button:hover { cursor: pointer; }
.button.drag { z-index: 99; color: red; }
JavaScript
$(function() {
$("#clickme").click(function(){
var elemnew = $("<button id='button1' class='button'>NEWLY ADDED</button>");
elemnew.insertBefore("#button1");
elemnew.height(elemnew.width());
});
$(".button").height($(".button").width());
$('.button').mousedown(function(e) {
if(e.which===1) {
var button = $(this);
var button_id = button.attr('id');
var parent_height = button.parent().innerHeight();
var top = parseInt(button.css('top'));
var original_ypos = button.position().top; //original ypos
var drag_min_ypos = 0-original_ypos;
var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
var drag_start_ypos = e.clientY;
var my_ypos = original_ypos;
//Set current order for all
$('.button').each(function(i) { $(this).attr('data-order',(i+1)); });
var prev_button = button.prev('.button'); var next_button = button.next('.button');
var prev_button_ypos = prev_button.length>0 ? prev_button.position().top : '';
var next_button_ypos = next_button.length>0 ? next_button.position().top : '';
$('#log1').text('mousedown '+button_id+' original_ypos: '+original_ypos);
$('#log2').text('');
$('#log3').text('');
$(window).on('mousemove',function(e) {
//Move and constrain
button.addClass('drag');
var direction = my_ypos>button.position().top ? 'up' : 'down';
var new_top = top+(e.clientY-drag_start_ypos);
my_ypos = button.position().top;
button.css({top:new_top+'px'});
if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
$('#log2').text('mousemove new_top: '+new_top+', my_ypos: '+my_ypos+', direction:...