jquery - keep window from changing scroll position while prepending items to a list?

前端 未结 6 923
误落风尘
误落风尘 2020-11-29 23:10

I have a page that displays messages and I want it to work just like Facebook, but without the lazy loader. Messages are displayed in chronological order, most recent last.<

相关标签:
6条回答
  • 2020-11-29 23:26

    You could also keep the scroll position based on the offset to the bottom of the page/element.

    var ScrollFromBottom = $(document).height() - $(window).scrollTop();
    
    //ajax - add messages -- geenrate html code then add to dom
    
    //set scroll position
    $(window).scrollTop($(document).height() - ScrollFromBottom);
    
    0 讨论(0)
  • 2020-11-29 23:27

    I just ran across a variation of this. i detached a large number of elements, processed them and then attached them again. this doesn't complete synchronously in Chrome so i could not set $el.scrollTop(oldval) reliably. I found this solution worked for me.

    // get old scroll top of '#sub_elem'
    var oldScrollTop = $('#sub_elem').scrollTop();
    
    // detach
    var $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);
    }
    
    0 讨论(0)
  • 2020-11-29 23:32

    Some folks coming here may just want to add content without the current focus jumping around. Modifying Jeff B's demo above to use the click event target makes this idiom more portable:

    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/ (variant of Jeff B's demo above but with the [add more] button at an arbitrary point in the page).

    0 讨论(0)
  • 2020-11-29 23:36

    No need for jQuery here, just check for changes in the elements scrollHeight and adjust the scrollTop accordingly, ie:

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

    Demo

    http://jsfiddle.net/fkqqv28e/

    jQuery

    To access the native DOM node from a jQuery collection, use array access; ie:

    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 讨论(0)
  • 2020-11-29 23:37

    Store a reference to the first message before you prepend new messages, and after you prepend, set the scroll to the offset of that message:

    $(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);
        }
    });
    

    Demo: http://jsfiddle.net/GRnQY/

    Edit: I noticed you wanted it with a button. You might have to do a little more math:

    $(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);
    });
    

    Demo: http://jsfiddle.net/GRnQY/5/

    0 讨论(0)
  • 2020-11-29 23:44

    Here's a simple trick that worked for me:

    // divWithTheScroll.prependElement...
    divWithTheScroll.scrollTop += newlyPrependedElement.scrollHeight;
    
    0 讨论(0)
提交回复
热议问题