Home > other >  How to auto-scroll to end of div only when it is already showing the last line?
How to auto-scroll to end of div only when it is already showing the last line?

Time:11-03

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 onl oad() {
  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 onl oad="onLoad()">
  <div id="output" style="overflow-y:scroll; height:200px; width:300px; background:yellow"></div>
</body>

CodePudding user response:

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 onl oad() {
    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);
  }

  onl oad();
<div id="output" style="overflow-y:scroll; height:200px; width:300px; background:yellow"></div>

CodePudding user response:

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>

  • Related