I created a demo: http://pastebin.me/584b9a86d715c9ba85b7bebf0375e237
When the scroll bar is at the bottom and you drag items to sort them, it causes the scroll bar
I have experienced this issue as well. It happens when the list dictates the length of your page. When you start sorting, the list height changes for a split second, causing the page to jump. Here is an odd, but very functional solution to this problem:
$('ul').height($('ul').height());
Lol, looks like this still isn't patched 4 years later. Here's the ticket.
Adding onto @Carl M. Gregory's answer, to fully take advantage of a dynamic container instead of setting it on a fixed height, i would edit the jquery.ui.sortable.js core file.
Simply move back line 228. this._createPlaceHolder...
before line 208. this.helper.css("position", "absolute");
Thanks to Honda on the jquery ticket portal. Am using Sortable.js version 1.10.3.
Carl M. Gregory explains the issue perfectly, but I think his solution is unnecessarily complicated.
Setting list height to fixed value fixes the issue, but doing so at the moment of creating the list is way too early. You can use .mousedown()
function to set the height right before the sorting starts. By this time any potential images are already loaded, so there is no need in checking their sizes.
So the jump doesn't occur, but now please consider this: You have multiple connected list and they are arranged vertically. Now this happens:
auto
So at some point, you should return its' height back to auto
. When? On mouseup
is too late (see https://jsfiddle.net/937vv4tx/1/), but it's okay, you can return the correct value almost immediately after the jump is no more a threat. Using the start()
event
Update: But you still want to set height to auto
on .mouseup()
because if you just click on item and don't start dragging, it still sets fixed height because the .mousedown()
has already happened.
$('.sortable').mousedown(function() {
// set fixed height to prevent scroll jump
// when dragging from bottom
$(this).height($(this).height());
}).mouseup(function () {
// set height back to auto
// when user just clicked on item
$(this).height('auto');
}).sortable({
connectWith: '.sortable',
placeholder: 'placeholder',
start: function() {
// dragging is happening
// and scroll jump was prevented,
// we can set it back to auto
$(this).height('auto');
}
});
This code works perfectly for me.
Seems like jQuery UI 1.9.2 solved the issue.
If you are unable to change the library, there's a workaround including a simple scroll bar operation. The idea is simple:
Here you go;
var lastScrollPosition = 0; //variables defined in upper scope
var tempScrollPosition = 0;
window.onscroll = function () { // Up to you requirement you may change it to another elemnet e.g $("#YourPanel").onscroll
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function () {
tempScrollPosition = lastScrollPosition; // Scrolls don't change from position a to b. They cover some numbers between a and b during the change to create a smooth sliding visual. That's why we pick the previous scroll position with a timer of 250ms.
}, 250));
lastScrollPosition = $(document).scrollTop(); // Up to you requirement you may change it to another elemnet e.g $("#YourPanel").onscroll
};
$("#YourSortablePanel").sortable({
start: function (event, ui) {
$(document).scrollTop(tempScrollPosition);
}
});
Thanks for the great solution but I recommend using the following instead:
create:function(){
var list=this;
resize=function(){
jQuery(list).css("min-height","0");
jQuery(list).height(jQuery(list).height());
};
jQuery(list).css('min-height', jQuery(list).height());
}
This is how i solve the issue.
$(".groups").sortable({
...
helper: function(event, ui){
lastScrollPosition = $("body").scrollTop();
},
start: function(e, ui){
// avoid scroll jump
$("body").scrollTop(lastScrollPosition);
},
});