summaryrefslogtreecommitdiff
path: root/public/scrollbar.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/scrollbar.js')
-rw-r--r--public/scrollbar.js52
1 files changed, 52 insertions, 0 deletions
diff --git a/public/scrollbar.js b/public/scrollbar.js
new file mode 100644
index 0000000..da6aded
--- /dev/null
+++ b/public/scrollbar.js
@@ -0,0 +1,52 @@
+function initScrollbox(box) {
+ const area = box.querySelector("[data-scroll-area]");
+ const track = box.querySelector("[data-scroll-track]");
+ const thumb = box.querySelector("[data-scroll-thumb]");
+
+ const inset = () => parseFloat(getComputedStyle(thumb).left) || 0;
+
+ const update = () => {
+ const pad = inset();
+ const room = track.clientHeight - pad * 2;
+ const maxScroll = area.scrollHeight - area.clientHeight;
+ const ratio = Math.min(1, area.clientHeight / area.scrollHeight);
+ const height = Math.max(room * ratio, thumb.clientWidth);
+ const progress = maxScroll > 0 ? area.scrollTop / maxScroll : 0;
+ thumb.style.height = `${height}px`;
+ thumb.style.top = `${pad + progress * (room - height)}px`;
+ };
+
+ thumb.addEventListener("pointerdown", (e) => {
+ e.preventDefault();
+ thumb.setPointerCapture(e.pointerId);
+ const startY = e.clientY;
+ const startTop = parseFloat(thumb.style.top) || 0;
+
+ const move = (ev) => {
+ const pad = inset();
+ const room = track.clientHeight - pad * 2 - thumb.offsetHeight;
+ const top = Math.min(
+ Math.max(startTop - pad + ev.clientY - startY, 0),
+ room,
+ );
+ const progress = room > 0 ? top / room : 0;
+ area.scrollTop = progress * (area.scrollHeight - area.clientHeight);
+ };
+ const stop = () => {
+ thumb.removeEventListener("pointermove", move);
+ thumb.removeEventListener("pointerup", stop);
+ thumb.removeEventListener("pointercancel", stop);
+ };
+ thumb.addEventListener("pointermove", move);
+ thumb.addEventListener("pointerup", stop);
+ thumb.addEventListener("pointercancel", stop);
+ });
+
+ area.addEventListener("scroll", update, { passive: true });
+ const observer = new ResizeObserver(update);
+ observer.observe(area);
+ for (const child of area.children) observer.observe(child);
+ update();
+}
+
+document.querySelectorAll("[data-scrollbox]").forEach(initScrollbox);