我创建了一个演示:http://pastebin.me/584b9a86d715c9ba85b7bebf0375e237
当滚动条位于底部并拖动项目以对其进行排序时,会导致滚动条向上跳跃。它似乎在FF,Safari,Chrome和IE(至少IE8)中这样做。
在我的Mac上的Firefox中,当滚动条位于底部时,它会跳起来,但也会为整个列表添加一个漂亮的闪存。它只是在向上滚动整个列表时闪烁。我相信如果我弄清楚导致向上滚动的原因(如果我可以阻止它),闪烁也会停止。
我不喜欢它像那样跳起来b / c我发现它很刺耳和混乱。我知道这是一个有点角落的情况,但如果可以,我想解决它。
那么,有没有办法防止它向上滚动?或者,是什么导致它向上滚动?
由于
答案 0 :(得分:46)
问题很简单。
首先让我们设置场景。您有一个可排序元素列表,您的页面高于您的屏幕,因此它有一个滚动条,您的页面位于最底部,滚动条一直向下。
问题是,你去拖动一个元素,导致jQuery从dom中删除它然后添加一个占位符。让它慢下来,它首先删除元素,现在列表更短,导致页面更短,导致滚动条更短。然后将其添加占位符,现在页面较长,现在srollbar较长(但窗口犯规向后滚动下来,所以会出现在滚动条跳起来)。
我发现抵消这种情况的最好方法是确保可排序列表具有静态高度,因此删除元素不会导致它变短。这样做的一种方法是
create:function(){
jQuery(this).height(jQuery(this).height());
}
上面的内容将在创建可排序列表时调用,静态设置其高度为当前高度。
如果您在其中一个可排序元素中有图片,则除非您预先定义标记中的尺寸,否则上述代码将无效。原因是当调用和设置height()时,它在图像填写之前进行计算。没有尺寸,那么图像就没有空间。一旦图像加载,它就会占用空间。
这是一种必须定义尺寸的方法。每次检测到要加载的图像时,只需调整列表高度即可。
create:function(){
var list=this;
jQuery(list).find('img').load(function(){
jQuery(list).height(jQuery(list).height());
});
}
最终版本:
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;
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);
}
});
});
答案 1 :(得分:20)
我在使用div容器和div元素时遇到了同样的问题,并且设置容器高度对我没有帮助,但在包含div上显式设置overflow:auto css属性确实解决了问题。仅在Chrome中测试过。
答案 2 :(得分:13)
我也遇到过这个问题。当列表指示页面的长度时会发生这种情况。当您开始排序时,列表高度会瞬间变化,从而导致页面跳转。这是一个奇怪但非常实用的解决方案:
$('ul').height($('ul').height());
答案 3 :(得分:5)
添加到@Carl M. Gregory的答案,为了充分利用动态容器而不是将其设置在固定高度,我将编辑 jquery.ui.sortable.js 核心文件。
简单地回到第228行。this._createPlaceHolder...
第208行之前。this.helper.css("position", "absolute");
感谢jquery故障单门户网站上的 Honda 。我使用的是Sortable.js版本1.10.3。
答案 4 :(得分:5)
Carl M. Gregory完美地解释了这个问题,但我认为他的解决方案不必要地复杂化了。
将列表高度设置为固定值可以解决问题,但是在创建列表时这样做太早了。您可以使用.mousedown()
功能在排序开始之前设置高度。到目前为止,任何潜在的图像都已加载,因此无需检查其大小。
所以跳转并没有发生,但现在请考虑一下:你有多个连接的列表,它们是垂直排列的。现在发生这种情况:
auto
所以在某些时候,你应该回归它的'高度回到auto
。什么时候?在mouseup
上已经太晚了(请参阅https://jsfiddle.net/937vv4tx/1/),但没关系,在跳转不再是威胁之后,您几乎可以立即返回正确的值。使用start()
事件
更新但您仍然希望在auto
上将高度设置为.mouseup()
,因为如果您只是点击项目并且不开始拖动,它仍会设置固定高度,因为.mousedown()
已经发生。
$('.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');
}
});
这段代码非常适合我。
答案 5 :(得分:3)
感谢您提供出色的解决方案 但我建议使用以下代码:
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());
}
答案 6 :(得分:3)
所以,复杂!您所要做的就是将overflow: auto;
添加到父级(ul,#element,whatever_you_call_it),它应该可以正常工作。这样可以确保即使文档稍微改变高度,在调整大小时,溢出自动也会保留元素的高度。
答案 7 :(得分:2)
Carl M. Gregory正在解释为什么会发生这种情况'很清楚。
然而,固定高度似乎不够,因为当您调整窗口大小时内部内容会变得更高。
我希望能做什么:
实践中会发生什么:在我们捕获开始事件之前发生了跳转,因此无法使用
解决方法:监听可排序项目上的jquery mousedown和mouseup事件。这非常简单。
$(".sortable_item").mousedown(function(){
$(".sortable_container").height($(".sortable_container").height());
}).mouseup(function(){
$(".sortable_container").height('auto');
});
我建议你仍然考虑卡尔关于图像加载的观点。他的回答值得一读。
答案 8 :(得分:0)
我在Chrome中遇到过这个问题。所有可排序的div都有固定的高度。
问题出在这些div的css属性position: relative
中。当从DOM拖拽div时,由于相对位置,它的坐标计算错误。
Inherit
或absolute
定位应用于可排序元素。
答案 9 :(得分:0)
这就是我解决问题的方法。
$(".groups").sortable({
...
helper: function(event, ui){
lastScrollPosition = $("body").scrollTop();
},
start: function(e, ui){
// avoid scroll jump
$("body").scrollTop(lastScrollPosition);
},
});
答案 10 :(得分:0)
我正在将可排序的div VIA Ajax加载到具有自动高度的包装器中。
我没有尝试链接到可排序的事件,而是在加载和更改列表时将高度设置为自动,然后将其设置为静态高度。
Vit的解决方案类似,但我不想在每个mousedown
和mouseup
事件上添加不必要的开销。相反,我只是在列表更改负载或添加新元素时执行此操作(我使用slideDown
动画,并在完成时将高度设置为静态)。
$("#wrapper").load("list.php",function() {
$("#wrapper").css({ "height":"auto" });
$("#wrapper").css({ "height": $("#wrapper").height() });
}
当我重新加载数据时,其他解决方案对我不起作用,因为我只在页面加载期间对它们进行了一次排序。
我的列表/ div随着下拉列表的变化而变化,因此我可以选择不同的列表,并且我的包装器会相应调整大小而不会产生烦人的跳跃。
如果你需要添加元素或重新加载任何东西,只需将这两行代码抛出一个函数并调用该函数。
希望这有助于某人!
答案 11 :(得分:0)
这里是解决此问题的另一种简便方法。
当鼠标进入您的排序图标时,
$("body").css("overflow-y","hidden");
当鼠标离开排序图标时
$("body").css("overflow-y","scroll");