jquery - удерживать окно от изменения позиции прокрутки при добавлении элементов в список? - PullRequest
30 голосов
/ 23 марта 2012

У меня есть страница, которая отображает сообщения, и я хочу, чтобы она работала так же, как Facebook, но без ленивого загрузчика.Сообщения отображаются в хронологическом порядке, самые последние из них последние.

Мой список сообщений изначально заполнен x числом самых последних сообщений, и окно прокручивается вниз.Когда пользователь начинает читать поток, он читает снизу вверх.Если они доберутся до вершины, они смогут загружать больше сообщений ... Я заставляю их нажимать на кнопку ... У Facebook есть ленивый загрузчик.Новые сообщения добавляются в список.

Проблема: По мере добавления новых сообщений существующие сообщения выталкиваются вниз, в результате чего пользователь теряет свое место «просмотра».Как сохранить текущую позицию просмотра пользователя при добавлении новых сообщений?Например, откройте длинную ветку сообщений в Facebook, прокрутите вверх, вызывая добавление новых сообщений ... ваше местоположение просмотра не меняется, даже если позиция прокрутки меняется.

Ответы [ 6 ]

51 голосов
/ 23 марта 2012

Сохраните ссылку на первое сообщение перед тем, как добавлять новые сообщения, а после добавления установите прокрутку на смещение этого сообщения:

$(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/

7 голосов
/ 25 ноября 2015

Здесь нет необходимости в 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

Чтобы получить доступ к собственному узлу DOM из коллекции jQuery, используйте доступ к массиву;т.е.:

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;
3 голосов
/ 14 мая 2016

Некоторые люди, которые приходят сюда, могут просто захотеть добавить контент, не обращая внимания на текущий фокус. Изменение вышеприведенной демонстрации Джеффа Б для использования цели события click делает эту идиому более переносимой:

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/ (вариант демонстрации Джеффа Б. выше, но с кнопкой [добавить еще] в произвольной точке на странице).

1 голос
/ 09 сентября 2018

Вот простой трюк, который сработал для меня:

// divWithTheScroll.prependElement...
divWithTheScroll.scrollTop += newlyPrependedElement.scrollHeight;
0 голосов
/ 13 сентября 2016

Вы также можете сохранить положение прокрутки на основе смещения к нижней части страницы / элемента.

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 голосов
/ 20 февраля 2016

Я только что наткнулся на вариант этого. Я отсоединил большое количество элементов, обработал их, а затем снова прикрепил их. это не завершается синхронно в Chrome, поэтому я не могу установить $ el.scrollTop (oldval) надежно. Я обнаружил, что это решение работает для меня.

// 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);
}
...