JSFiddle - React, Tailwind, and code Playground
by Znarkus
HTML
<ul>
<li><div></div><div></div><div></div></li>
<li><div></div></li>
<li><div></div><div></div><div></div><div></div><div></div></li>
<li><div></div><div></div><div></div></li>
<li><div></div><div></div><div></div><div></div><div></div><div></div><div></div></li>
<li><div></div></li>
</ul>
CSS
div {
background: #fed;
width: 50px;
height: 50px;
float: left;
margin: 0 10px 10px 0;
}
li {
overflow: hidden;
padding: 10px 10px 0;
border: 1px dotted #000;
margin: 10px;
min-height: 60px;
}
li.empty {
background: #eee;
}
.ui-sortable-placeholder {
visibility: visible !important;
background: none;
outline: 1px dotted #ccc;
}
JavaScript
var $items = $('ul li'), mouse_move_timer;
function real_children($li) {
return $li.children(':not(.ui-sortable-placeholder,.ui-sortable-helper)');
}
function mouse_move(e) {
var $li;
$items.each(function () {
$li = $(this);
if (Math.abs($li.offset().top + $li.outerHeight() - e.pageY) < 20) {
if ($li.next('.empty').length == 0
&& real_children($li).length > 0
&& ($li.next().length == 0 || real_children($li.next()).length > 0)) {
$li.siblings('.empty').remove();
$li.after('<li class="empty"></li>');
attach_sortable($li.next('.empty'));
$items.sortable('refresh');
}
}
});
$li = $items.first();
if (Math.abs($li.offset().top - e.pageY) < 20) {
if (real_children($li).length > 0) {
$li.siblings('.empty').remove();
$li.before('<li class="empty"></li>');
attach_sortable($li.prev('.empty'));
$items.sortable('refresh');
}
}
}
function attach_sortable($e) {
$e.sortable({
connectWith: 'ul li',
sort: function (e, ui) {
clearTimeout(mouse_move_timer);
mouse_move_timer = setTimeout(function () {
mouse_move(e);
}, 150);
},
stop: function (e, ui) {
ui.item.parent().siblings('.empty').add(ui.item.parent('.empty')).each(function () {
var $empty = $(this);
if ($empty.children().length == 0) {
$empty.remove();
} else {
$items = $items.add($empty.removeClass('empty'));
}
});
$items.filter(':empty').remove();
}
});
}
attach_sortable($items);