2012-03-23 38 views
22

我有一个页面显示消息,我希望它像Facebook一样工作,但没有懒惰的加载程序。消息按时间顺序显示,最近一次显示。jquery - 保持窗口改变滚动位置,同时预先将项目列表?

我的消息列表最初被填充了x个最近的消息,并且窗口滚动到底部。当用户开始读取线程时,他们从下到上阅读。如果他们到达顶端,他们可以加载更多的消息...我让他们点击一个按钮... Facebook有一个懒惰的加载程序。新消息被列在名单前。

问题:由于新消息被预先占用,现有消息被压低,导致用户失去“查看”位置。我添加新消息时如何保持用户当前的视图位置?例如,在Facebook中打开一个长消息线程,滚动到顶部导致添加新消息...即使滚动位置确实,您的视图位置也不会改变。

回答

41

商店,你在前面加上新的消息之前,你在前面加上后,设置滚动到该消息的偏移的第一条消息的引用:

$(document).on('scroll', function() { 
    var scroll = $(document).scrollTop(); 
    if (scroll < 1) { 
     // Store eference to first message 
     var firstMsg = $('.message:first'); 

     // Prepend new message here (I'm just cloning...) 
     $('body').prepend(firstMsg.clone()); 

     // After adding new message(s), set scroll to position of 
     // what was the first message 
     $(document).scrollTop(firstMsg.offset().top); 
    } 
}); 

演示:http://jsfiddle.net/GRnQY/

编辑:我注意到你想用一个按钮。您可能需要做一些更多的数学:

$(document).on('click', '#loadMore', function() { 
    var firstMsg = $('.message:first'); 

    // Where the page is currently: 
    var curOffset = firstMsg.offset().top - $(document).scrollTop(); 

    // Prepend 
    firstMsg.before(firstMsg.clone()); 

    // Offset to previous first message minus original offset/scroll 
    $(document).scrollTop(firstMsg.offset().top-curOffset); 
}); 

演示:http://jsfiddle.net/GRnQY/5/

+6

第二种解决方案非常棒 - 非常感谢您,这对于实现Facebook反向信息的“反向无限滚动”非常有帮助。 – 2012-10-22 19:48:44

+0

如果您使用的是ajax,请在滚动的ajax'success'属性上添加'$(selector).scrollTop(firstMsg.offset()。top-curOffset);'以便正常工作 – user3284463 2015-11-27 18:02:58

+0

太棒了!谢谢杰夫! – Can 2016-01-07 08:05:19

5

无需jQuery的这里,只是检查中的元素scrollHeight属性的变化,并相应地调整scrollTop的,即:

var lastScrollHeight = el.scrollHeight; 
for(var n=0; n<10; n++){ 
    // Prepend here... 
} 
var scrollDiff = el.scrollHeight - lastScrollHeight; 
el.scrollTop += scrollDiff; 

演示

http://jsfiddle.net/fkqqv28e/

的jQuery

要从一个jQuery集合访问本地DOM节点上,使用数组访问;即:

var lastScrollHeight = $('#myElement')[0].scrollHeight; 
for(var n=0; n<10; n++){ 
    $('#myElement').prepend('<div>prepended '+Math.random()+'</div>'); 
} 
var scrollDiff = $('#myElement')[0].scrollHeight - lastScrollHeight; 
$('#myElement')[0].scrollTop += scrollDiff; 
0

我只是碰到了这个变化。我分离了大量的元素,对它们进行处理,然后再将它们连接起来。这不会在Chrome中同步完成,因此我无法可靠地设置$ el.scrollTop(oldval)。我发现这个解决方案为我工作。

// get old scroll top of '#sub_elem' 
oldScrollTop = $('#sub_elem).scrollTop(); 

// detach 
$els = $('#sub_elem').detach(); 

// complex processing on #sub_elem 
// goes here 

// attach 
$('#main_el').attach($els); 

// problem- always scrolls #sub_elem back to the top 
// attempt #1: $('#sub_elem').scrollTop(oldScrollTop); // fails on mac Chrome 
// attempt #2: use instant animation. this works on mac Chrome 
if (oldScrollTop) { 
    $('#sub_elem').animate({ 
     scrollTop: oldScrollTop 
    }, 0); 
} 
1

有些人来到这里可能只是想添加内容,而没有当前焦点跳来跳去。修改上面Jeff B的演示以使用点击事件目标使得该成语更便携:

someButton.on('click', function() { 
    var curOffset = $(this).offset().top - $(document).scrollTop(); 
    // add content to your heart's content. 
    $(document).scrollTop($(this).offset().top-curOffset); 
}); 

c.f. http://jsfiddle.net/bwz8uLvt/1/(以上Jeff B演示的变体,但在页面中的任意点添加[添加更多]按钮)。

0

您还可以根据页面/元素底部的偏移量来保持滚动位置。

var ScrollFromBottom = $(document).height() - $(window).scrollTop(); 

//ajax - add messages -- geenrate html code then add to dom 

//set scroll position 
$(window).scrollTop($(document).height() - ScrollFromBottom); 
相关问题