javascript - Lock scroll as new content is added above and below - Stack Overflow

I have a meteor.js app that functions as a news feed, with threads being posted and people menting on t

I have a meteor.js app that functions as a news feed, with threads being posted and people menting on the threads in realtime. This means that while you are looking at a post, there will be new ments being added to posts above and below and new threads will be added above. This will push the post you are focusing on down and out of the viewport, which is never expected (unless you're already scrolled to the top).

What is the best way to update the scrolling to maintain the same visual center as new content is added?

I have a meteor.js app that functions as a news feed, with threads being posted and people menting on the threads in realtime. This means that while you are looking at a post, there will be new ments being added to posts above and below and new threads will be added above. This will push the post you are focusing on down and out of the viewport, which is never expected (unless you're already scrolled to the top).

What is the best way to update the scrolling to maintain the same visual center as new content is added?

Share Improve this question asked Dec 21, 2015 at 22:07 JacobPariseauJacobPariseau 1951 silver badge13 bronze badges 1
  • i'd suggest you don't update the post ments until you scroll them into view: that way the user actually sees that there has been an update and it's being loaded as s/he goes by it. Otherwise it'd be quite difficult to know which ones are new and which ones are old, and which ones the user may have already read. This is not the answer to your question but I think it would lead to a better user experience. – MrE Commented Jan 6, 2016 at 18:50
Add a ment  | 

3 Answers 3

Reset to default 3 +50

You could try this approach:

  1. save the scrollTop value;
  2. prepend the content (i.e., add a new post above the one that's focused);
  3. add the height of the new content to the value saved in step 1;
  4. scroll to the new value.

Here's an example:

function randomString() {
  return Math.random().toString(36).substring(7);
}

$('#addAbove').on('click', function(e){
  var newDiv = $('<li class="post">' + randomString() + '</li>');
  var savedScrollTop = $('#content').scrollTop();
  $('#content').prepend(newDiv);
  $('#content').scrollTop(savedScrollTop + newDiv.height());
});

$('#addBelow').on('click', function(e){
  var newDiv = $('<li class="post">' + randomString() + '</li>');
  $('#content').append(newDiv);
});
#content {
  height: 100px;
  overflow-y: scroll;
}
.post {
  height: 40px;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="content">
  <li class="post">u9tv190be29</li>
  <li class="post">dgdr8gp66rp</li>
  <li class="post">93vfntdquxr</li>
</ul>
<button id="addAbove">Add Above</button>
<button id="addBelow">Add Below</button>

Appending content below the current viewport shouldn't require adjustment.

Here's a blog post describing a similar approach, and a similar SO question.

I suggest you do like so, when a new item is to be added you check if you are at the top, if so, then just add the new item.

If not, you get the existing top/height of your item container, add the new item, get the item containers height a second time and then update the scroll top.

Here is a simple sample of how one can do, adding at both top and bottom (btw, at bottom don't need scroll pensation).

function addItem (totop) {
  var msgdiv = document.getElementById('items');
  var attop = scrollAtTop(msgdiv);
  var prevtop = parseInt(msgdiv.scrollHeight - msgdiv.scrollTop);

  if (totop) {
    msgdiv.innerHTML = 'Long long content ' + (tempCounter++) + '!<br/>' + msgdiv.innerHTML;

    if (!attop) {
      updateScroll(msgdiv, parseInt(msgdiv.scrollHeight) - prevtop);
    }
  } else {
    msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
  }
}

var tempCounter = 10;
function updateScroll(el, top){
  el.scrollTop = top;
}
function scrollAtTop(el){
  return (el.scrollTop == 0);
}
html, body { height:100%; margin:0; padding:0; }

.items{
  display: inline-block;
  width: 300px;
  height: 220px;
  border: 1px solid black;
  overflow: auto;
}


button { width: 15%; height: 44px; margin: 20px; vertical-align: top; }
<div class="items" id="items">
  Long long content 9!<br/>
  Long long content 8!<br/>
  Long long content 7!<br/>
  Long long content 6!<br/>
  Long long content 5!<br/>
  Long long content 4!<br/>
  Long long content 3!<br/>
  Long long content 2!<br/>
  Long long content 1!<br/>
</div>
<button onclick="addItem(true);">Add 2 top</button><button onclick="addItem(false);">Add 2 bottom</button>

You can use package animated-each meteor add mizzao:animated-each, to solve the problem.

It would be certainly better than implementing custom jquery. And if package does not solve exact problem, then you can use it as an example on how to hook into rendering and create solution the meteor way. Probably by utilising meteor-ui-hooks

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745085240a4610366.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信