I have a page and script like this:
I want to scroll to each listitem
pause for a sec then scroll to next listitem
and continue till the end of the list.
My attempted code looks like this:
const sleep = (time) => new Promise(res => setTimeout(res, time, "done sleeping"));
let elm = document.querySelector('#pane-side');
let listitems = elm.children[0].children[0].children
for (let index = 0; index < listitems.length; index++) {
const y = listitems[index].getBoundingClientRect().top + window.scrollY;
elm.scroll({
top: y,
behavior: 'smooth'
});
sleep(1000).then(msg => console.log(msg));
}
<div id="pane-side">
<div>
<div>
<div>
<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
</div>
</div>
</div>
</div>
It only scrolls once to the first listitem
and then does nothing.
Another variant that I tries was replacing elm.scroll({..})
with listitems[index].scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
which didnt even scroll once.
2
Answers
You need some more CSS to do this
And why not use interval?
Here is a version that uses your original scroll and does not move the page. I had to tweak the offsetTop to handle margins and padding
Change the counting to
const listItem = listitems[cnt % len];
and add cnt++ to the end of the function to loop around
One way to achieve this would be to use a function which you call recursively via
setTimeout()
, incrementing the index with each call. Note that you can use the modulo operator to make sure the index never goes out of bounds.Here’s working example: https://jsfiddle.net/6srbtvjz/.
Note that I had to place it in a jsFiddle as the scrolling caused issues with the SO layout when using a snippet.