2012-03-23 102 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); 
相關問題