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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/*! instant.page v1.2.2 - (C) 2019 Alexandre Dieulot - https://instant.page/license */
let urlToPreload;
let mouseoverTimer;
let lastTouchTimestamp;
const prefetcher = document.createElement("link");
const isSupported = prefetcher.relList && prefetcher.relList.supports && prefetcher.relList.supports("prefetch");
const isDataSaverEnabled = navigator.connection && navigator.connection.saveData;
const allowQueryString = "instantAllowQueryString" in document.body.dataset;
const allowExternalLinks = "instantAllowExternalLinks" in document.body.dataset;
if (isSupported && !isDataSaverEnabled) {
prefetcher.rel = "prefetch";
document.head.appendChild(prefetcher);
const eventListenersOptions = {
capture: true,
passive: true,
};
document.addEventListener("touchstart", touchstartListener, eventListenersOptions);
document.addEventListener("mouseover", mouseoverListener, eventListenersOptions)
}
function touchstartListener(event) {
/* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp`
* must be assigned on touchstart to be measured on mouseover. */
lastTouchTimestamp = performance.now();
const linkElement = event.target.closest("tr[data-href]");
if (!isPreloadable(linkElement)) {
return
}
linkElement.addEventListener("touchcancel", touchendAndTouchcancelListener, {passive: true});
linkElement.addEventListener("touchend", touchendAndTouchcancelListener, {passive: true});
urlToPreload = window.location.href + linkElement.getAttribute("data-href");
preload(urlToPreload)
}
function touchendAndTouchcancelListener() {
urlToPreload = undefined;
stopPreloading()
}
function mouseoverListener(event) {
if (performance.now() - lastTouchTimestamp < 1100) {
return
}
const linkElement = event.target.closest("tr[data-href]");
if (!isPreloadable(linkElement)) {
return
}
linkElement.addEventListener("mouseout", mouseoutListener, {passive: true});
urlToPreload = window.location.href + linkElement.getAttribute("data-href");
mouseoverTimer = setTimeout(() => {
preload(urlToPreload);
mouseoverTimer = undefined
}, 65)
}
function mouseoutListener(event) {
if (event.relatedTarget && event.target.closest("tr[data-href]") === event.relatedTarget.closest("tr[data-href]")) {
return
}
if (mouseoverTimer) {
clearTimeout(mouseoverTimer);
mouseoverTimer = undefined
} else {
urlToPreload = undefined;
stopPreloading()
}
}
function isPreloadable(linkElement) {
if (!linkElement || !(window.location.href + linkElement.getAttribute("data-href"))) {
return
}
if (urlToPreload === window.location.href + linkElement.getAttribute("data-href")) {
return
}
const preloadLocation = new URL(window.location.href + linkElement.getAttribute("data-href"));
if (!allowExternalLinks && preloadLocation.origin !== location.origin && !("instant" in linkElement.dataset)) {
return
}
if (!["http:", "https:"].includes(preloadLocation.protocol)) {
return
}
if (preloadLocation.protocol === "http:" && location.protocol === "https:") {
return
}
if (!allowQueryString && preloadLocation.search && !("instant" in linkElement.dataset)) {
return
}
if (preloadLocation.hash && preloadLocation.pathname + preloadLocation.search === location.pathname + location.search) {
return
}
if ("noInstant" in linkElement.dataset) {
return
}
return true
}
function preload(url) {
prefetcher.href = url
}
function stopPreloading() {
prefetcher.removeAttribute("href")
}
|