/** * AKSRT Instant Page * * Lightweight page prefetch on hover/focus. * Preloads pages when the user hovers over a link, so navigation feels instant. * No external dependencies — pure vanilla JS. * * Based on the instant.page concept (MIT license). * * @package AKSRT */ (function () { 'use strict'; // Only prefetch on desktop (no touch-only devices) with good connection if ('connection' in navigator) { var conn = navigator.connection; if (conn.saveData || (conn.effectiveType && conn.effectiveType.indexOf('2g') !== -1)) return; } // Don't run on touch-only devices (they don't benefit from hover prefetch) var hasHoverSupport = window.matchMedia('(hover: hover) and (pointer: fine)').matches; if (!hasHoverSupport) return; var prefetcher = document.createElement('link'); var isPrefetched = {}; var timer = null; var DELAY = 65; // ms to wait before prefetching var MAX_PREFETCH = 3; // max concurrent prefetches var prefetchedCount = 0; if (!prefetcher.relList || !prefetcher.relList.supports || !prefetcher.relList.supports('prefetch')) return; function prefetch(url) { if (isPrefetched[url] || prefetchedCount >= MAX_PREFETCH) return; // Don't prefetch URLs with hash (same page navigation) if (url.indexOf('#') !== -1) return; // Only prefetch same-origin URLs try { var link = new URL(url, window.location.origin); if (link.origin !== window.location.origin) return; // Don't prefetch the current page if (link.pathname === window.location.pathname && link.search === window.location.search) return; } catch (e) { return; } // Don't prefetch files/downloads if (/\.(pdf|zip|rar|7z|tar|gz|exe|dmg|apk|mp[34]|avi|mov|wmv|flv|webm|ogg|wav|bmp|gif|ico|svg|woff2?|ttf|eot)(\?|$)/i.test(url)) return; isPrefetched[url] = true; prefetchedCount++; var linkEl = document.createElement('link'); linkEl.rel = 'prefetch'; linkEl.href = url; linkEl.as = 'document'; document.head.appendChild(linkEl); } function onHoverStart(e) { var link = e.target.closest('a'); if (!link || !link.href) return; if (link.target === '_blank') return; if (link.hasAttribute('download')) return; if (link.getAttribute('rel') === 'nofollow') return; if (link.closest('.no-prefetch,[data-no-prefetch]')) return; clearTimeout(timer); timer = setTimeout(function () { prefetch(link.href); }, DELAY); } function onHoverEnd() { clearTimeout(timer); } document.addEventListener('mouseover', onHoverStart, { passive: true, capture: true }); document.addEventListener('mouseout', onHoverEnd, { passive: true, capture: true }); // Also prefetch on focus for keyboard navigation document.addEventListener('focusin', function (e) { var link = e.target.closest('a'); if (link && link.href) { prefetch(link.href); } }, { passive: true, capture: true }); // Cleanup after page hides (bfcache) window.addEventListener('pagehide', function () { isPrefetched = {}; prefetchedCount = 0; }); })();