I'm using the scrollspy of Bootstrap-5.2 to update the displayed text whithin the scrollBox
, when reaching the top or bottom part (pre-reload-item
/post-reload-item
).
The funktion for the bottom shiftContentDown
works fine, but for shiftContentUp
it works the first time only. After that the scrollspy doesn't activate the reload-top
element anymore unless I scroll down to the post-reload-item
(->reload-bottom
activates -> shiftContentDown
fires) and then up again.
I suspect it has something to do with the line document.getElementById('scrollBox').scrollBy(0, count * 24)
. Without it the new content of the pre-reload-item
would be in fokus and the reload-top
element stays active. With it the previous content of the pre-reload-item
now part of the mid-reload-item
stays visible and the reload-top
element is no longer active. I'd expect it to activate again if I scroll up now, but for some reason it doesn't.
let nextIndex = 0;
let allContent = [];
let displayed = [0, 0]
let eof = false;
let pre = document.getElementById('pre-reload-item');
let mid = document.getElementById('mid-reload-item');
let post = document.getElementById('post-reload-item');
document.getElementById('scrollBox').addEventListener('activate.bs.scrollspy', () => {
let current = document.querySelector('#indexBox > a.active');
if (current === document.getElementById('reload-bottom')) {
shiftContentDown()
} else if (current === document.getElementById('reload-top')) {
shiftContentUp()
}
});
function shiftContentDown(count = 100, buffer = 0.5) {
let shift = allContent.length - displayed[1];
if (!eof && shift < count) {
getMoreContent(nextIndex);
} else {
let addition = allContent.slice(displayed[1], displayed[1] + count);
addition.forEach(l => {
if (pre.childElementCount >= (count * buffer)) {
pre.removeChild(pre.childNodes[0]);
displayed[0]++;
}
if (mid.childElementCount >= (count * (1 + 2*buffer)))
pre.appendChild(mid.childNodes[0]);
if (post.childElementCount >= (count * buffer) || post.childNodes.length > mid.childNodes.length)
mid.appendChild(post.childNodes[0]);
post.appendChild(l);
displayed[1]++;
});
}
}
function shiftContentUp(count = 100) {
let addition = allContent.slice(Math.max(displayed[0] - count, 0), displayed[0]);
addition.reverse().forEach(l => {
pre.insertBefore(l, pre.childNodes[0]);
displayed[0]--;
mid.insertBefore(pre.childNodes[pre.childElementCount - 1], mid.childNodes[0]);
post.insertBefore(mid.childNodes[mid.childElementCount - 1], post.childNodes[0]);
post.removeChild(post.childNodes[post.childElementCount - 1]);
displayed[1]--;
});
document.getElementById('scrollBox').scrollBy(0, count * 24);
}
function getMoreContent(index, chunkSize=100, last=1000) {
for (let i=0; i < chunkSize; i++) {
if (nextIndex < last) {
let newLineNode = document.createElement('div');
newLineNode.innerHTML = '----- ' + (nextIndex++) + ' -----';
allContent.push(newLineNode);
} else {
eof = true;
}
}
shiftContentDown();
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<div id="indexBox" class="list-group" style="display: none">
<a id="reload-bottom" class="list-group-item list-group-item-action" href="#post-reload-item">reload bottom</a>
<a id="reload-top" class="list-group-item list-group-item-action" href="#pre-reload-item">reload top</a>
</div>
<div id="scrollBox" data-bs-spy="scroll" data-bs-target="#indexBox" data-bs-smooth-scroll="true" data-bs-offset="0" class="scrollspy-example" tabindex="0" style="height: 300px; overflow-y: scroll">
<div id="pre-reload-item" class="text-bg-danger" style="white-space: pre-line"></div>
<div id="mid-reload-item" class="text-bg-info" style="white-space: pre-line"></div>
<div id="post-reload-item" class="text-bg-danger" style="white-space: pre-line"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>