简体   繁体   中英

How to auto-scroll to the bottom of a div perpetually?

I have a <div> with scrolling. Through JavaScript I add elements to the <div> with element.scrollTop = element.scrollHeight . Works great except I have to do that every time an element is added to the <div> . Is there a way to auto-scroll (without using setInterval and repeatedly scrolling over and over) and keep the <div> 's scrollbar pegged to the bottom?

My <div> :

<div class="messages" style="height: 7em; overflow: scroll">
  <div>Anonymous: Hello</div>
  <div>John: Hi</div>
</div>

Is there a <div> event for when the content changes?

UPDATE : I don't have easy access to JavaScript code after the <div> is added. That's why I'd love to add an event listener or some other mechanism to keep the scroll bar pegged to the bottom.

Create a variable var index = 0 . Add tabIndex attribute to the dynamically created element with index set as .value of tabIndex attribute. Call .focus() on dynamically created element after appending element to parent element.

var index = 0;

var div = document.createElement("div");
div.setAttribute("tabIndex", index);
document.querySelector(".messages").appendChild(div);
div.focus();
++index; 

 window.onload = function() { var messages = document.querySelector(".messages"); var index = 0; setInterval(function() { var div = document.createElement("div"); div.setAttribute("tabIndex", index); div.innerHTML = "abc"; messages.appendChild(div); div.focus(); ++index; }, 2000) } 
 <div class="messages" style="height: 7em; overflow: scroll"> <div>Anonymous: Hello</div> <div>John: Hi</div> </div> 

plnkr https://plnkr.co/edit/34QUtpGNVfho2fmYIlUI?p=preview

You could overwrite the addChild method of the target element or you can use the MutationOvserver to observe the DOM.

given HTML:

<div id="messages-out" class="messages" style="height: 7em; overflow: scroll">
  <div>Anonymous: Hello</div>
  <div>John: Hi</div>
</div>
<input id="txtMessage" type="text" autofocus>

overwritten method approach:

document.addEventListener('DOMContentLoaded', function(ev)
{
  var msgs = document.getElementById('messages-out');
  msgs.appendChild = function(childNode)
  {
    Element.prototype.appendChild.call(msgs, childNode);
    msgs.scrollTop = msgs.scrollHeight;
  }

  document.getElementById('txtMessage').addEventListener('keypress', function(ev)
  {
    if(13 === ev.which)
    {
      var div = document.createElement('div');
      div.innerHTML = '<em>nick: </em>' + ev.target.value;
      msgs.appendChild(div);
      ev.target.value = '';
    }
  });
})

MutationObserver approach:

document.addEventListener('DOMContentLoaded', function(ev) {
  var
    msgs     = document.getElementById('messages-out'),
    observer = new MutationObserver(function (mutations)
    {
      var added = false;

      mutations.forEach(function (mutation) {
        if ('childList' === mutation.type && 0 < mutation.addedNodes.length)
          added = true;
      });

      if (added)
        msgs.scrollTop = msgs.scrollHeight;
    })
  ;

  observer.observe(msgs, {childList: true});

  document.getElementById('txtMessage').addEventListener('keypress', function(ev)
  {
    if(13 === ev.which)
    {
      var div = document.createElement('div');
      div.innerHTML = '<em>nick: </em>' + ev.target.value;
      msgs.appendChild(div);
      ev.target.value = '';
    }
  });

});

Note: It is not sure that the element.appendChild method is used to add a message, eg a child could be appended as in in the line Element.prototype.appendChild.call(msgs, childNode); or by insertBefore . So the second approach is more the "catch all" one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM