Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
17mie32
GitHub Repository: 17mie32/17mie32.github.io
Path: blob/main/libs/instantpage/instantpage.js
1320 views
1
/*! instant.page v2.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license */
2
3
let urlToPreload
4
let mouseoverTimer
5
let lastTouchTimestamp
6
7
const prefetcher = document.createElement('link')
8
const isSupported = prefetcher.relList && prefetcher.relList.supports && prefetcher.relList.supports('prefetch')
9
const isDataSaverEnabled = navigator.connection && navigator.connection.saveData
10
const allowQueryString = 'instantAllowQueryString' in document.body.dataset
11
const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset
12
const useWhitelist = 'instantWhitelist' in document.body.dataset
13
14
let delayOnHover = 65
15
let useMousedown = false
16
let useMousedownOnly = false
17
if ('instantIntensity' in document.body.dataset) {
18
if (document.body.dataset.instantIntensity.substr(0, 'mousedown'.length) == 'mousedown') {
19
useMousedown = true
20
if (document.body.dataset.instantIntensity == 'mousedown-only') {
21
useMousedownOnly = true
22
}
23
} else {
24
const milliseconds = parseInt(document.body.dataset.instantIntensity)
25
if (!isNaN(milliseconds)) {
26
delayOnHover = milliseconds
27
}
28
}
29
}
30
31
if (isSupported && !isDataSaverEnabled) {
32
prefetcher.rel = 'prefetch'
33
document.head.appendChild(prefetcher)
34
35
const eventListenersOptions = {
36
capture: true,
37
passive: true,
38
}
39
40
if (!useMousedownOnly) {
41
document.addEventListener('touchstart', touchstartListener, eventListenersOptions)
42
}
43
44
if (!useMousedown) {
45
document.addEventListener('mouseover', mouseoverListener, eventListenersOptions)
46
} else {
47
document.addEventListener('mousedown', mousedownListener, eventListenersOptions)
48
}
49
}
50
51
function touchstartListener(event) {
52
/* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp`
53
* must be assigned on touchstart to be measured on mouseover. */
54
lastTouchTimestamp = performance.now()
55
56
const linkElement = event.target.closest('a')
57
58
if (!isPreloadable(linkElement)) {
59
return
60
}
61
62
linkElement.addEventListener('touchcancel', touchendAndTouchcancelListener, {
63
passive: true
64
})
65
linkElement.addEventListener('touchend', touchendAndTouchcancelListener, {
66
passive: true
67
})
68
69
urlToPreload = linkElement.href
70
preload(linkElement.href)
71
}
72
73
function touchendAndTouchcancelListener() {
74
urlToPreload = undefined
75
stopPreloading()
76
}
77
78
function mouseoverListener(event) {
79
if (performance.now() - lastTouchTimestamp < 1100) {
80
return
81
}
82
83
const linkElement = event.target.closest('a')
84
85
if (!isPreloadable(linkElement)) {
86
return
87
}
88
89
linkElement.addEventListener('mouseout', mouseoutListener, {
90
passive: true
91
})
92
93
urlToPreload = linkElement.href
94
95
mouseoverTimer = setTimeout(() => {
96
preload(linkElement.href)
97
mouseoverTimer = undefined
98
}, delayOnHover)
99
}
100
101
function mousedownListener(event) {
102
const linkElement = event.target.closest('a')
103
104
if (!isPreloadable(linkElement)) {
105
return
106
}
107
108
linkElement.addEventListener('mouseout', mouseoutListener, {
109
passive: true
110
})
111
112
urlToPreload = linkElement.href
113
114
preload(linkElement.href)
115
}
116
117
function mouseoutListener(event) {
118
if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) {
119
return
120
}
121
122
if (mouseoverTimer) {
123
clearTimeout(mouseoverTimer)
124
mouseoverTimer = undefined
125
}
126
127
urlToPreload = undefined
128
129
stopPreloading()
130
}
131
132
function isPreloadable(linkElement) {
133
if (!linkElement || !linkElement.href) {
134
return
135
}
136
137
if (urlToPreload == linkElement.href) {
138
return
139
}
140
141
if (useWhitelist && !('instant' in linkElement.dataset)) {
142
return
143
}
144
145
if (!allowExternalLinks && linkElement.origin != location.origin && !('instant' in linkElement.dataset)) {
146
return
147
}
148
149
if (!['http:', 'https:'].includes(linkElement.protocol)) {
150
return
151
}
152
153
if (linkElement.protocol == 'http:' && location.protocol == 'https:') {
154
return
155
}
156
157
if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) {
158
return
159
}
160
161
if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) {
162
return
163
}
164
165
if ('noInstant' in linkElement.dataset) {
166
return
167
}
168
169
return true
170
}
171
172
function preload(url) {
173
prefetcher.href = url
174
}
175
176
function stopPreloading() {
177
prefetcher.removeAttribute('href')
178
}
179
180