-
Notifications
You must be signed in to change notification settings - Fork 0
/
scroll-region.js
67 lines (58 loc) · 1.81 KB
/
scroll-region.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"use strict";
defer(() => {
Array.from(document.getElementsByClassName("scroll-region")).map(
(node) => new ScrollRegion(node)
);
});
class ScrollRegion {
constructor(domNode) {
this.domNode = domNode;
this.scrollNode = domNode.children[0];
this.items = domNode.querySelectorAll(".scroll-region__item");
(this.scrollToNextButton = domNode.querySelector(
".scroll-region__next"
)).addEventListener("click", () => this.scrollToNext());
(this.scrollToPreviousButton = domNode.querySelector(
".scroll-region__previous"
)).addEventListener("click", () => this.scrollToPrevious());
}
scrollToNext() {
const index = this.getCurrentScrollIndex() + 1;
if (this.items[index]) this.scrollToIndex(index);
}
scrollToPrevious() {
const index = this.getCurrentScrollIndex() - 1;
if (this.items[index]) this.scrollToIndex(index);
}
scrollToIndex(index) {
this.items[index].scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "start",
});
}
getCurrentScrollIndex() {
// NOTE: this doesn't yet support RTL, where scrollX is negative as
// scrolling occurs, and we should consult offsetRight, not offsetLeft.
const scrollPadding = parseInt(
getComputedStyle(this.items[0].parentNode).paddingInlineStart
);
// Return the index of the smallest absolute difference between left offset
// and left scroll
return Array.from(this.items)
.map((note, index) => ({
index,
value: Math.abs(
note.offsetLeft - (this.scrollNode.scrollLeft - scrollPadding)
),
}))
.sort((a, b) => {
if (a.value > b.value) return 1;
if (a.value < b.value) return -1;
return 0;
})[0].index;
}
}
function defer(callbackFn) {
setTimeout(callbackFn, 0);
}