Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When prepending data to vertically-scrolled document, how can I keep previous part visible?

This is a part of infinite scroll which also works when we scroll upwards:

<div id="sContainer">
    <div class="message0">Initial Content 111</div>
    <div class="message1">Initial Content 222</div>
    <div class="message2">Initial Content 333</div>
    <div class="message3">Initial Content 444</div>
    <div class="message4">Initial Content 555</div>
    <div class="message5">Initial Content 666</div>
    <div class="message6">Initial Content 777</div>
</div>

JS code :

var dataAbc = '<div class="message7">Focus Shifted Here</div>';
setTimeout(function(){  $(dataAbc).prependTo("#sContainer");},3000);
setTimeout(function(){  $(dataAbc).prependTo("#sContainer");},3000);
setTimeout(function(){  $(dataAbc).prependTo("#sContainer");},3000);
setTimeout(function(){  $(dataAbc).prependTo("#sContainer");},3000);

Js Fiddle: http://jsfiddle.net/LRLR/ocfLkxex/

Issue:

Whenever prependTo is called, the data is shifted downwards and new data is added at the top. The scrollbar seems to ignores this, and from the users' point of view, everything he was reading gets pushed down. After a few times, what user was reading gets pushed out of the visible area, and user must scroll down to continue reading.

Desired:

I want the user to be able to read long content without having to (re)scroll when new items are added at the top of the list. Ideally, if user scrolled so that i.e. "Initial Content 444" is at the top of the view, when new items are added, it should keep its visual position. New items should be added "above" it without visually moving the current contents.

Why doesn't the scrollbar keep those elements visible already?
How can I configure the scrollbar to behave like I want?

like image 929
chicharito Avatar asked Nov 30 '14 07:11

chicharito


1 Answers

This is an obvious behavior. You are adding new elements, which changes the height if the content. This leads to the change in body scrollTop value too.

What you can do is to calculate the total height of the added content (plus margins) and after appending new content you should reset body/html scrollTop with the old scrollTop + appended content height.

Your meta example then would be something like this:

setTimeout(function () {

    var top = $('body').scrollTop();

    top += $(dataAbc).prependTo("#sContainer").outerHeight() + 10;
    top += $(dataAbc).prependTo("#sContainer").outerHeight() + 10;
    top += $(dataAbc).prependTo("#sContainer").outerHeight() + 10;

    $('body, html').scrollTop(top);
}, 3000);

Demo: http://jsfiddle.net/ocfLkxex/1/

Note. I hardcoded magic number 10 for margin value, in your case you can use a constant or calculate it dynamically of course (preferred, e.g. .css('marginTop')).

like image 118
dfsq Avatar answered Oct 27 '22 12:10

dfsq