0

There already is an answer for autoscrolling, but that has a problem. If the user has manually scrolled it up to read old logs, that code keeps auto-scrolling, interfering the user's reading. So, I want it to auto-scroll only when it is showing the last line (i.e., either the user has never scrolled it up, or scrolled it up and then scrolled down to the bottom). How can I determine that?

var output;
var i = 0;

function onLoad() {
  output = document.getElementById("output");
  onTimeout();
}

function onTimeout() {
  i++;
  var line = document.createElement("div");
  line.innerText = "Log " + i;
  output.appendChild(line);
  var isShowingTheLastLine = true;
  if (isShowingTheLastLine) {
    output.scrollTop = output.scrollHeight;
  }
  setTimeout(onTimeout, 1000);
}
<body onload="onLoad()">
  <div id="output" style="overflow-y:scroll; height:200px; width:300px; background:yellow"></div>
</body>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135

2 Answers2

0

Here is my suggestion

Click the output and it stops. Click the scrollbar and scroll up and you can read as long as you hold the mouse down

I also use eventListeners instead of inline events

let output;
let cnt = 0;
let tId;
let pause;
const onTimeout = () => {
  var line = document.createElement("div");
  line.innerText = `Log ${++cnt}`;
  output.appendChild(line);
  if (!pause) {
    output.scrollTop = output.scrollHeight;
    tId = setTimeout(onTimeout, 1000);    
  }
};
window.addEventListener("DOMContentLoaded", () => {
  output = document.getElementById("output");
  onTimeout();
  output.addEventListener("mousedown", () => {
    pause = true;
  });
  document.addEventListener("mouseup", () => {
    if (pause) {
      pause = false;
      onTimeout();
    }
  })
})
<div id="output" style="overflow-y:scroll; height:200px; width:300px; background:yellow"></div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

You can use the offsetHeight property in this case. output.scrollHeight - output.offsetHeight will be equal to output.scrollTop if the div is scrolled to the bottom. Sometimes the difference may not be that accurate. So you can keep a minimum amount check in the condition.

if(Math.floor(output.scrollHeight - output.offsetHeight) - Math.floor(output.scrollTop) < 5)
{
    // the div is currently at the bottom
}

Full code:

  var output;
  var i = 0;

  function onLoad() {
    output = document.getElementById("output");
    onTimeout();
  }

  function onTimeout() {
    i++;
    var line = document.createElement("div");
    line.innerText = "Log " + i;
    
    if (
      Math.floor(output.scrollHeight - output.offsetHeight) -
        Math.floor(output.scrollTop) < 5
    ) {
      // the div is currently at the bottom
      output.appendChild(line);
      output.scrollTop = output.scrollHeight;
    } else {
      output.appendChild(line);
    }

    setTimeout(onTimeout, 1000);
  }

  onLoad();
<div id="output" style="overflow-y:scroll; height:200px; width:300px; background:yellow"></div>
Zakaria Ahmed
  • 54
  • 2
  • 7
  • It's close but it has a bug. On my system, after launching the page and not touching anything, "Log 11" is partially printed above the bottom edge (scroll bar appeared, and the upper portion of "Log11" was visible, and the bottom portion of it was not visible), and auto-scrolling down does not work. When I manually scrolled down to the bottom, after that, then it began to auto-scroll. – Damn Vegetables Nov 03 '22 at 08:27