From e5ef253333bcc3641581c9ebccd282cd31a7d477 Mon Sep 17 00:00:00 2001 From: Gijo Varghese Date: Fri, 13 Sep 2019 19:37:30 +0530 Subject: [PATCH] prefetching on mobile using 'touchstart' --- flying-pages.js | 23 ++++++++++++++--------- flying-pages.min.js | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/flying-pages.js b/flying-pages.js index 0e418c8..f75c969 100644 --- a/flying-pages.js +++ b/flying-pages.js @@ -102,6 +102,13 @@ const mouseOverListener = event => { } }; +// Preload on touchstart on mobile +const touchStartListener = event => { + const elm = event.target.closest("a"); + if (elm && elm.href && !alreadyPrefetched.has(elm.href)) + addUrlToQueue(elm.href, true); +}; + // Clear timeout on mouse out if not already preloaded const mouseOutListener = event => { const elm = event.target.closest("a"); @@ -133,9 +140,10 @@ const stopPreloading = () => { // Clear pending links in queue toPrefetch.clear(); - // Remove event listeners for mouse hover + // Remove event listeners for mouse hover and mobile touch document.removeEventListener("mouseover", mouseOverListener, true); document.removeEventListener("mouseout", mouseOutListener, true); + document.removeEventListener("touchstart", touchStartListener, true); }; function flyingPages(options = {}) { @@ -164,12 +172,9 @@ function flyingPages(options = {}) { ) ); - // Add event listeners to detect mouse hover - const eventListenerOptions = { capture: true, passive: true }; - document.addEventListener( - "mouseover", - mouseOverListener, - eventListenerOptions - ); - document.addEventListener("mouseout", mouseOutListener, eventListenerOptions); + // Add event listeners to detect mouse hover and mobile touch + const listenerOptions = { capture: true, passive: true }; + document.addEventListener("mouseover", mouseOverListener, listenerOptions); + document.addEventListener("mouseout", mouseOutListener, listenerOptions); + document.addEventListener("touchstart", touchStartListener, listenerOptions); } diff --git a/flying-pages.min.js b/flying-pages.min.js index 29c5635..3d7107d 100644 --- a/flying-pages.min.js +++ b/flying-pages.min.js @@ -1 +1 @@ -const toPrefetch=new Set,alreadyPrefetched=new Set,prefetcher=document.createElement("link"),isNativePrefetchSupported=prefetcher.relList&&prefetcher.relList.supports&&prefetcher.relList.supports("prefetch"),isSlowConnection=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),prefetch=e=>isNativePrefetchSupported?new Promise((t,r)=>{const o=document.createElement("link");o.rel="prefetch",o.href=e,o.onload=t,o.onerror=r,document.head.appendChild(o)}):new Promise((t,r)=>{const o=new XMLHttpRequest;o.open("GET",e,o.withCredentials=!0),o.onload=(()=>{200===o.status?t():r()}),o.send()}),prefetchWithTimeout=e=>{const t=setTimeout(()=>stopPreloading(),5e3);prefetch(e).catch(()=>stopPreloading()).finally(()=>clearTimeout(t))},addUrlToQueue=(e,t=!1)=>{if(alreadyPrefetched.has(e)||toPrefetch.has(e))return;const r=window.location.origin;if(e.substring(0,r.length)===r&&window.location.href!==e){for(let t=0;t{e.forEach(e=>{if(e.isIntersecting){const t=e.target.href;addUrlToQueue(t,!window.FPConfig.maxRPS)}})}),startQueue=()=>setInterval(()=>{Array.from(toPrefetch).slice(0,window.FPConfig.maxRPS).forEach(e=>{prefetchWithTimeout(e),alreadyPrefetched.add(e),toPrefetch.delete(e)})},1e3);let hoverTimer=null;const mouseOverListener=e=>{const t=e.target.closest("a");t&&t.href&&!alreadyPrefetched.has(t.href)&&(hoverTimer=setTimeout(()=>{addUrlToQueue(t.href,!0)},window.FPConfig.hoverDelay))},mouseOutListener=e=>{const t=e.target.closest("a");t&&t.href&&!alreadyPrefetched.has(t.href)&&clearTimeout(hoverTimer)},requestIdleCallback=window.requestIdleCallback||function(e){const t=Date.now();return setTimeout(function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})},1)},stopPreloading=()=>{document.querySelectorAll("a").forEach(e=>observer.unobserve(e)),toPrefetch.clear(),document.removeEventListener("mouseover",mouseOverListener,!0),document.removeEventListener("mouseout",mouseOutListener,!0)};function flyingPages(e={}){if(isSlowConnection)return;window.FPConfig=Object.assign({delay:0,ignoreKeywords:[],maxRPS:3,hoverDelay:50},e),startQueue(),requestIdleCallback(()=>setTimeout(()=>document.querySelectorAll("a").forEach(e=>observer.observe(e)),1e3*window.FPConfig.delay));const t={capture:!0,passive:!0};document.addEventListener("mouseover",mouseOverListener,t),document.addEventListener("mouseout",mouseOutListener,t)} +const toPrefetch=new Set,alreadyPrefetched=new Set,prefetcher=document.createElement("link"),isNativePrefetchSupported=prefetcher.relList&&prefetcher.relList.supports&&prefetcher.relList.supports("prefetch"),isSlowConnection=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),prefetch=e=>isNativePrefetchSupported?new Promise((t,r)=>{const o=document.createElement("link");o.rel="prefetch",o.href=e,o.onload=t,o.onerror=r,document.head.appendChild(o)}):new Promise((t,r)=>{const o=new XMLHttpRequest;o.open("GET",e,o.withCredentials=!0),o.onload=(()=>{200===o.status?t():r()}),o.send()}),prefetchWithTimeout=e=>{const t=setTimeout(()=>stopPreloading(),5e3);prefetch(e).catch(()=>stopPreloading()).finally(()=>clearTimeout(t))},addUrlToQueue=(e,t=!1)=>{if(alreadyPrefetched.has(e)||toPrefetch.has(e))return;const r=window.location.origin;if(e.substring(0,r.length)===r&&window.location.href!==e){for(let t=0;t{e.forEach(e=>{if(e.isIntersecting){const t=e.target.href;addUrlToQueue(t,!window.FPConfig.maxRPS)}})}),startQueue=()=>setInterval(()=>{Array.from(toPrefetch).slice(0,window.FPConfig.maxRPS).forEach(e=>{prefetchWithTimeout(e),alreadyPrefetched.add(e),toPrefetch.delete(e)})},1e3);let hoverTimer=null;const mouseOverListener=e=>{const t=e.target.closest("a");t&&t.href&&!alreadyPrefetched.has(t.href)&&(hoverTimer=setTimeout(()=>{addUrlToQueue(t.href,!0)},window.FPConfig.hoverDelay))},touchStartListener=e=>{const t=e.target.closest("a");t&&t.href&&!alreadyPrefetched.has(t.href)&&addUrlToQueue(t.href,!0)},mouseOutListener=e=>{const t=e.target.closest("a");t&&t.href&&!alreadyPrefetched.has(t.href)&&clearTimeout(hoverTimer)},requestIdleCallback=window.requestIdleCallback||function(e){const t=Date.now();return setTimeout(function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})},1)},stopPreloading=()=>{document.querySelectorAll("a").forEach(e=>observer.unobserve(e)),toPrefetch.clear(),document.removeEventListener("mouseover",mouseOverListener,!0),document.removeEventListener("mouseout",mouseOutListener,!0),document.removeEventListener("touchstart",touchStartListener,!0)};function flyingPages(e={}){if(isSlowConnection)return;window.FPConfig=Object.assign({delay:0,ignoreKeywords:[],maxRPS:3,hoverDelay:50},e),startQueue(),requestIdleCallback(()=>setTimeout(()=>document.querySelectorAll("a").forEach(e=>observer.observe(e)),1e3*window.FPConfig.delay));const t={capture:!0,passive:!0};document.addEventListener("mouseover",mouseOverListener,t),document.addEventListener("mouseout",mouseOutListener,t),document.addEventListener("touchstart",touchStartListener,t)}