aboutsummaryrefslogtreecommitdiff
path: root/public/js/app.js
diff options
context:
space:
mode:
authorThedro Neely <thedroneely@gmail.com>2019-11-09 03:00:33 -0500
committerThedro Neely <thedroneely@gmail.com>2019-11-09 03:00:33 -0500
commitc5255a0249489f44c83a95cd57b5643b8e03f31e (patch)
tree45fda90bc822a1e5fe0a8d105667e152980085f1 /public/js/app.js
parentb7b84be10bf6a7bf094d67b67f91304b4f0477f9 (diff)
downloadthedroneely.com-c5255a0249489f44c83a95cd57b5643b8e03f31e.tar.gz
thedroneely.com-c5255a0249489f44c83a95cd57b5643b8e03f31e.tar.bz2
thedroneely.com-c5255a0249489f44c83a95cd57b5643b8e03f31e.zip
public/js/app: Add instant page
Diffstat (limited to 'public/js/app.js')
-rw-r--r--public/js/app.js206
1 files changed, 206 insertions, 0 deletions
diff --git a/public/js/app.js b/public/js/app.js
index 5804fab..ddfdc3e 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -608,3 +608,209 @@ window.onscroll = function() {
imageZoom = mediumZoom('[data-image-zoom]');
imageZoom.on('open', function(event) { addClass(navbar, 'navbar__headroom'); });
imageZoom.on('close', function(event) { remClass(navbar, 'navbar__headroom'); });
+
+
+/**
+ * instant.page v3.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license
+ */
+
+let mouseoverTimer
+let lastTouchTimestamp
+const prefetches = new Set()
+const prefetchElement = document.createElement('link')
+const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports('prefetch')
+ && window.IntersectionObserver && 'isIntersecting' in IntersectionObserverEntry.prototype
+const allowQueryString = 'instantAllowQueryString' in document.body.dataset
+const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset
+const useWhitelist = 'instantWhitelist' in document.body.dataset
+
+let delayOnHover = 65
+let useMousedown = false
+let useMousedownOnly = false
+let useViewport = false
+if ('instantIntensity' in document.body.dataset) {
+ const intensity = document.body.dataset.instantIntensity
+
+ if (intensity.substr(0, 'mousedown'.length) == 'mousedown') {
+ useMousedown = true
+ if (intensity == 'mousedown-only') {
+ useMousedownOnly = true
+ }
+ }
+ else if (intensity.substr(0, 'viewport'.length) == 'viewport') {
+ if (!(navigator.connection && (navigator.connection.saveData || navigator.connection.effectiveType.includes('2g')))) {
+ if (intensity == "viewport") {
+ /* Biggest iPhone resolution (which we want): 414 × 896 = 370944
+ * Small 7" tablet resolution (which we don’t want): 600 × 1024 = 614400
+ * Note that the viewport (which we check here) is smaller than the resolution due to the UI’s chrome */
+ if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) {
+ useViewport = true
+ }
+ }
+ else if (intensity == "viewport-all") {
+ useViewport = true
+ }
+ }
+ }
+ else {
+ const milliseconds = parseInt(intensity)
+ if (!isNaN(milliseconds)) {
+ delayOnHover = milliseconds
+ }
+ }
+}
+
+if (isSupported) {
+ const eventListenersOptions = {
+ capture: true,
+ passive: true,
+ }
+
+ if (!useMousedownOnly) {
+ document.addEventListener('touchstart', touchstartListener, eventListenersOptions)
+ }
+
+ if (!useMousedown) {
+ document.addEventListener('mouseover', mouseoverListener, eventListenersOptions)
+ }
+ else {
+ document.addEventListener('mousedown', mousedownListener, eventListenersOptions)
+ }
+
+ if (useViewport) {
+ let triggeringFunction
+ if (window.requestIdleCallback) {
+ triggeringFunction = (callback) => {
+ requestIdleCallback(callback, {
+ timeout: 1500,
+ })
+ }
+ }
+ else {
+ triggeringFunction = (callback) => {
+ callback()
+ }
+ }
+
+ triggeringFunction(() => {
+ const intersectionObserver = new IntersectionObserver((entries) => {
+ entries.forEach((entry) => {
+ if (entry.isIntersecting) {
+ const linkElement = entry.target
+ intersectionObserver.unobserve(linkElement)
+ preload(linkElement.href)
+ }
+ })
+ })
+
+ document.querySelectorAll('a').forEach((linkElement) => {
+ if (isPreloadable(linkElement)) {
+ intersectionObserver.observe(linkElement)
+ }
+ })
+ })
+ }
+}
+
+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('a')
+
+ if (!isPreloadable(linkElement)) {
+ return
+ }
+
+ preload(linkElement.href)
+}
+
+function mouseoverListener(event) {
+ if (performance.now() - lastTouchTimestamp < 1100) {
+ return
+ }
+
+ const linkElement = event.target.closest('a')
+
+ if (!isPreloadable(linkElement)) {
+ return
+ }
+
+ linkElement.addEventListener('mouseout', mouseoutListener, {passive: true})
+
+ mouseoverTimer = setTimeout(() => {
+ preload(linkElement.href)
+ mouseoverTimer = undefined
+ }, delayOnHover)
+}
+
+function mousedownListener(event) {
+ const linkElement = event.target.closest('a')
+
+ if (!isPreloadable(linkElement)) {
+ return
+ }
+
+ preload(linkElement.href)
+}
+
+function mouseoutListener(event) {
+ if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) {
+ return
+ }
+
+ if (mouseoverTimer) {
+ clearTimeout(mouseoverTimer)
+ mouseoverTimer = undefined
+ }
+}
+
+function isPreloadable(linkElement) {
+ if (!linkElement || !linkElement.href) {
+ return
+ }
+
+ if (useWhitelist && !('instant' in linkElement.dataset)) {
+ return
+ }
+
+ if (!allowExternalLinks && linkElement.origin != location.origin && !('instant' in linkElement.dataset)) {
+ return
+ }
+
+ if (!['http:', 'https:'].includes(linkElement.protocol)) {
+ return
+ }
+
+ if (linkElement.protocol == 'http:' && location.protocol == 'https:') {
+ return
+ }
+
+ if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) {
+ return
+ }
+
+ if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) {
+ return
+ }
+
+ if ('noInstant' in linkElement.dataset) {
+ return
+ }
+
+ return true
+}
+
+function preload(url) {
+ if (prefetches.has(url)) {
+ return
+ }
+
+ const prefetcher = document.createElement('link')
+ prefetcher.rel = 'prefetch'
+ prefetcher.href = url
+ document.head.appendChild(prefetcher)
+
+ prefetches.add(url)
+}