Here is the part from jQuery UI documentation for the tolerance
option:
This is the way the reordering behaves during drag. Possible valu
I have unevenly sized sortable items and this makes things event worse. I've modified dioslaska's code to change the order once the bottom of the handler passes the bottom of the child (when moving down) and the same for the tops ...
sort: function (event, ui) {
var that = $(this),
draggedHeight = ui.helper.outerHeight(),
originalTop = ui.originalPosition.top,
draggedTop = ui.helper.position().top,
draggedBottom = draggedTop + draggedHeight;
that.children().each(function () {
if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) {
return true;
}
var childTop = $(this).position().top,
childHeight = $(this).outerHeight(),
childBottom = childTop + childHeight,
isChildAfter = originalTop < childTop,
largeTop,largeBottom,smallTop,smallBottom;
if (childHeight > draggedHeight) {
largeTop = childTop;
largeBottom = childTop + childHeight;
smallTop = draggedTop;
smallBottom = draggedBottom;
} else {
smallTop = childTop;
smallBottom = childTop + childHeight;
largeTop = draggedTop;
largeBottom = draggedBottom;
}
if (smallBottom > largeTop || smallTop < largeBottom) {
if (isChildAfter && draggedBottom >= childBottom) {
$('.ui-sortable-placeholder', that).insertAfter($(this));
} else if (!isChildAfter && draggedTop <= childTop) {
$('.ui-sortable-placeholder', that).insertBefore($(this));
return false;
}
}
});
}
You can see the overlap detection is a little trickier than before as you may be dragging a large item over a small item or vice versa.
It's not perfect, but it is a huge improvement over the default functionality.