UNPKG

@stimulus-library/controllers

Version:

A library of useful controllers for Stimulus

69 lines (68 loc) 2.37 kB
import { BaseController, warn } from "@stimulus-library/utilities"; import { useEventListener } from "@stimulus-library/mixins"; export class PrefetchController extends BaseController { get _mode() { return this.hasModeValue ? this.modeValue : "mouseover"; } get _supportsPrefetch() { var _a, _b; const link = document.createElement("link"); return ((_a = link.relList) === null || _a === void 0 ? void 0 : _a.supports) && ((_b = link.relList) === null || _b === void 0 ? void 0 : _b.supports("prefetch")); } get _href() { return this.el.href; } get _existingPrefetch() { return (document.head.querySelectorAll(`link[rel="prefetch"][href="${this._href}"]`) || []).length > 0; } get _connectionSuitable() { const connection = navigator.connection; if (!connection) { return true; } if (connection) { if (connection.saveData) { warn(this, "Data Saving is enabled"); return false; } if (/2g/.test(connection.effectiveType)) { warn(this, "Network is too slow"); return false; } } return true; } connect() { if (!this._supportsPrefetch) { return; } switch (this._mode) { case "intersect": this._setupObserver(); break; case "mouseover": useEventListener(this, this.el, "mouseover", this.prefetch, { once: true }); break; default: throw new Error(`'${this._mode}' is not a supported prefetch mode`); } } _setupObserver() { const observer = new IntersectionObserver(([entry], observer) => { if (entry.isIntersecting) { this.prefetch(); observer.unobserve(entry.target); } }); observer.observe(this.element); } prefetch() { if (this._existingPrefetch || !this._connectionSuitable) { return; } const link = document.createElement("link"); Object.assign(link, { rel: "prefetch", href: this._href, as: "document" }); document.head.appendChild(link); } } PrefetchController.values = { mode: String };