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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
function observeScrolling(elements, callback) {
if (!Array.isArray(elements))
elements = [elements];
var lastChangedFrame = 0;
var lastLeft = new Map();
var lastTop = new Map();
elements.forEach((element) => {
lastLeft.set(element, element.scrollLeft);
lastTop.set(element, element.scrollTop);
});
function tick(frames) {
// We requestAnimationFrame either for 500 frames or until 20 frames with
// no change have been observed.
if (frames >= 500 || frames - lastChangedFrame > 20) {
callback(true);
} else {
var scrollHappened = elements.some((element) => {
return element.scrollLeft != lastLeft.get(element) || element.scrollTop != lastTop.get(element);
});
if (scrollHappened) {
lastChangedFrame = frames;
elements.forEach((element) => {
lastLeft.set(element, element.scrollLeft);
lastTop.set(element, element.scrollTop);
});
callback(false);
}
requestAnimationFrame(tick.bind(null, frames + 1));
}
}
tick(0);
}
function waitForScrollEnd(elements) {
return new Promise((resolve) => {
observeScrolling(elements, (done) => {
if (done)
resolve();
});
});
}
function resetScroll(scrollingElement) {
// Try various methods to ensure the element position is reset immediately.
scrollingElement.scrollLeft = 0;
scrollingElement.scrollTop = 0;
scrollingElement.scroll({left: 0, top: 0, behavior: "instant"});
}
function resetScrollForWindow(scrollingWindow) {
// Try various methods to ensure the element position is reset immediately.
scrollingWindow.document.scrollingElement.scrollLeft = 0;
scrollingWindow.document.scrollingElement.scrollTop = 0;
scrollingWindow.scroll({left: 0, top: 0, behavior: "instant"});
}
function setScrollBehavior(styledElement, className) {
styledElement.classList.remove("autoBehavior", "smoothBehavior");
styledElement.classList.add(className);
}
function scrollNode(scrollingElement, scrollFunction, behavior, elementToRevealLeft, elementToRevealTop) {
var args = {};
if (behavior)
args.behavior = behavior;
switch (scrollFunction) {
case "scrollIntoView":
args.inline = "start";
args.block = "start";
elementToReveal.scrollIntoView(args);
break;
default:
args.left = elementToRevealLeft;
args.top = elementToRevealTop;
scrollingElement[scrollFunction](args);
break;
}
}
function scrollWindow(scrollingWindow, scrollFunction, behavior, elementToRevealLeft, elementToRevealTop) {
var args = {};
if (behavior)
args.behavior = behavior;
args.left = elementToRevealLeft;
args.top = elementToRevealTop;
scrollingWindow[scrollFunction](args);
}
|