Path: blob/main/libs/instantpage/instantpage.js
1320 views
/*! instant.page v2.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license */12let urlToPreload3let mouseoverTimer4let lastTouchTimestamp56const prefetcher = document.createElement('link')7const isSupported = prefetcher.relList && prefetcher.relList.supports && prefetcher.relList.supports('prefetch')8const isDataSaverEnabled = navigator.connection && navigator.connection.saveData9const allowQueryString = 'instantAllowQueryString' in document.body.dataset10const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset11const useWhitelist = 'instantWhitelist' in document.body.dataset1213let delayOnHover = 6514let useMousedown = false15let useMousedownOnly = false16if ('instantIntensity' in document.body.dataset) {17if (document.body.dataset.instantIntensity.substr(0, 'mousedown'.length) == 'mousedown') {18useMousedown = true19if (document.body.dataset.instantIntensity == 'mousedown-only') {20useMousedownOnly = true21}22} else {23const milliseconds = parseInt(document.body.dataset.instantIntensity)24if (!isNaN(milliseconds)) {25delayOnHover = milliseconds26}27}28}2930if (isSupported && !isDataSaverEnabled) {31prefetcher.rel = 'prefetch'32document.head.appendChild(prefetcher)3334const eventListenersOptions = {35capture: true,36passive: true,37}3839if (!useMousedownOnly) {40document.addEventListener('touchstart', touchstartListener, eventListenersOptions)41}4243if (!useMousedown) {44document.addEventListener('mouseover', mouseoverListener, eventListenersOptions)45} else {46document.addEventListener('mousedown', mousedownListener, eventListenersOptions)47}48}4950function touchstartListener(event) {51/* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp`52* must be assigned on touchstart to be measured on mouseover. */53lastTouchTimestamp = performance.now()5455const linkElement = event.target.closest('a')5657if (!isPreloadable(linkElement)) {58return59}6061linkElement.addEventListener('touchcancel', touchendAndTouchcancelListener, {62passive: true63})64linkElement.addEventListener('touchend', touchendAndTouchcancelListener, {65passive: true66})6768urlToPreload = linkElement.href69preload(linkElement.href)70}7172function touchendAndTouchcancelListener() {73urlToPreload = undefined74stopPreloading()75}7677function mouseoverListener(event) {78if (performance.now() - lastTouchTimestamp < 1100) {79return80}8182const linkElement = event.target.closest('a')8384if (!isPreloadable(linkElement)) {85return86}8788linkElement.addEventListener('mouseout', mouseoutListener, {89passive: true90})9192urlToPreload = linkElement.href9394mouseoverTimer = setTimeout(() => {95preload(linkElement.href)96mouseoverTimer = undefined97}, delayOnHover)98}99100function mousedownListener(event) {101const linkElement = event.target.closest('a')102103if (!isPreloadable(linkElement)) {104return105}106107linkElement.addEventListener('mouseout', mouseoutListener, {108passive: true109})110111urlToPreload = linkElement.href112113preload(linkElement.href)114}115116function mouseoutListener(event) {117if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) {118return119}120121if (mouseoverTimer) {122clearTimeout(mouseoverTimer)123mouseoverTimer = undefined124}125126urlToPreload = undefined127128stopPreloading()129}130131function isPreloadable(linkElement) {132if (!linkElement || !linkElement.href) {133return134}135136if (urlToPreload == linkElement.href) {137return138}139140if (useWhitelist && !('instant' in linkElement.dataset)) {141return142}143144if (!allowExternalLinks && linkElement.origin != location.origin && !('instant' in linkElement.dataset)) {145return146}147148if (!['http:', 'https:'].includes(linkElement.protocol)) {149return150}151152if (linkElement.protocol == 'http:' && location.protocol == 'https:') {153return154}155156if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) {157return158}159160if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) {161return162}163164if ('noInstant' in linkElement.dataset) {165return166}167168return true169}170171function preload(url) {172prefetcher.href = url173}174175function stopPreloading() {176prefetcher.removeAttribute('href')177}178179180