Enhanced Faster Webpage Loading with Pjax

Preload subsequent pages, lazy load images and videos, and use Pjax for faster webpage loading with robust error handling and fallback navigation.

Verzia zo dňa 02.01.2025. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Enhanced Faster Webpage Loading with Pjax
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  Preload subsequent pages, lazy load images and videos, and use Pjax for faster webpage loading with robust error handling and fallback navigation.
// @author       Tae
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Lazy load images, videos, and multimedia
    document.addEventListener("DOMContentLoaded", () => {
        const lazyElements = Array.from(document.querySelectorAll("img.lazy, video.lazy, iframe.lazy"));

        function loadLazyElement(el) {
            const dataSrc = el.dataset.src;
            if (!dataSrc) return;

            el.src = dataSrc;
            if (el.tagName === "VIDEO") {
                el.load();
            }
            el.classList.remove("lazy");
        }

        if ("IntersectionObserver" in window) {
            const observer = new IntersectionObserver((entries, observer) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        loadLazyElement(entry.target);
                        observer.unobserve(entry.target);
                    }
                });
            });

            lazyElements.forEach(el => observer.observe(el));
        } else {
            const lazyLoadFallback = () => {
                lazyElements.forEach((el, index) => {
                    if (
                        el.getBoundingClientRect().top < window.innerHeight &&
                        el.getBoundingClientRect().bottom > 0 &&
                        getComputedStyle(el).display !== "none"
                    ) {
                        loadLazyElement(el);
                        lazyElements.splice(index, 1); // Remove loaded element
                    }
                });
                if (lazyElements.length === 0) {
                    document.removeEventListener("scroll", lazyLoadFallback);
                    window.removeEventListener("resize", lazyLoadFallback);
                    window.removeEventListener("orientationchange", lazyLoadFallback);
                }
            };
            document.addEventListener("scroll", lazyLoadFallback);
            window.addEventListener("resize", lazyLoadFallback);
            window.addEventListener("orientationchange", lazyLoadFallback);
        }
    });

    // Prefetch links
    document.addEventListener("mouseover", event => {
        const link = event.target.closest("a[href]");
        if (link && !link.target && !link.rel.includes("nofollow")) {
            const href = link.href;
            if (/^https?:\/\//.test(href) && !href.includes("#")) {
                const prefetch = document.createElement("link");
                prefetch.rel = "prefetch";
                prefetch.href = href;
                document.head.appendChild(prefetch);
            }
        }
    });

    // Initialize Pjax
    function initializePjax() {
        if (typeof Pjax === "undefined") {
            const script = document.createElement("script");
            script.src = "https://cdnjs.cloudflare.com/ajax/libs/pjax/0.2.8/pjax.min.js";
            script.onload = () => setupPjax();
            document.head.appendChild(script);
        } else {
            setupPjax();
        }
    }

    function setupPjax() {
        const pjax = new Pjax({
            elements: "a[href]:not([target]):not([data-pjax-disabled])", // Only internal links
            selectors: ["title", ".content"], // Elements to update
            cacheBust: true, // Force cache refresh
        });

        document.addEventListener("pjax:send", () => console.log("Pjax: Request sent"));
        document.addEventListener("pjax:complete", () => {
            console.log("Pjax: Request complete");
            reinitializeLazyLoading();
        });
        document.addEventListener("pjax:error", event => {
            console.error("Pjax: Error occurred", event);
            // Fallback to normal navigation
            window.location.href = event.request.responseURL || event.target.href;
        });
    }

    function reinitializeLazyLoading() {
        const newLazyElements = Array.from(document.querySelectorAll("img.lazy, video.lazy, iframe.lazy:not([src])"));
        if ("IntersectionObserver" in window) {
            const observer = new IntersectionObserver((entries, observer) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const el = entry.target;
                        el.src = el.dataset.src;
                        if (el.tagName === "VIDEO") el.load();
                        observer.unobserve(el);
                    }
                });
            });

            newLazyElements.forEach(el => observer.observe(el));
        }
    }

    // Initialize the script
    initializePjax();
})();