jQuery Sortable List - scroll bar jumps up when sorting
The problem is very simple.
First let's set up the scenario. You have a list of sortable elements, your page is higher than your screen so it has a scrollbar, your page is at the very bottom, the scroll bar all the way down.
The issue, you go to drag an element which causes jQuery to remove it from the dom then add in a placeholder. Let’s slow it down, it removes the element first, now the list is shorter causing the page to be shorter, causing the scrollbar to be shorter. Then it adds the placeholder, now the page is longer, now the srollbar is longer (but the window doesnt scroll back down, so it appears the scroll bar jumped up).
Best way I found to counteract this would be to ensure the sortable list has a static height, so removing an element doesn't cause it to go shorter. One method of doing this would be
create:function(){
jQuery(this).height(jQuery(this).height());
}
The above will be called upon the creation of the sortable list, staticly setting its height to it's current height.
If you have pictures in one of the sortable elements, the above code will not work unless you pre-define the dimensions in the tag. Reason is that when the height() is called and set, it's calculating before the image is filled out. No dimension, then the image accounts for no space. Once the image loads, then will it take up space.
Here is a way around having to define dimensions. Simply resize the list height every time an image within is detected to be loaded.
create:function(){
var list=this;
jQuery(list).find('img').load(function(){
jQuery(list).height(jQuery(list).height());
});
}
Final version:
jQuery(document).ready(function(){
jQuery("div#todoList").sortable({
handle:'img.moveHandle',
opacity: 0.6,
cursor: 'move',
tolerance: 'pointer',
forcePlaceholderSize: true,
update:function(){
jQuery("body").css('cursor','progress');
var order = jQuery(this).sortable('serialize');
jQuery.post("/ajax.php?do=sort&"+order,function(data){jQuery("body").css('cursor','default');});
},
create:function(){
var list=this;
var resize=function(){
jQuery(list).css("height","auto");
jQuery(list).height(jQuery(list).height());
};
jQuery(list).height(jQuery(list).height());
jQuery(list).find('img').load(resize).error(resize);
}
});
});
I had the same issue when using a div container and div elements and setting the container height didn't help me, but explicitly setting overflow:auto css property on the containing div did fix the issue. Only tested in Chrome though.