Page Progess counter for Weebcentral

Shows "current page/total pages" on the bottom-left of the window for reading websites.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         Page Progess counter for Weebcentral
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Shows "current page/total pages" on the bottom-left of the window for reading websites.
// @author       Nirmal Bhasarkar
// @license      MIT
// @match        https://weebcentral.com/chapters/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    const config = {
        // --- POSITIONING ---
        counterPosition: {
            bottom: '5px', // Modify this two values to move the box location
            left: '5px'
        },
    };
    // --- End of Configuration ---

    let pageCounterElement;
    let cachedTotalPages = null;
    let observer;

    function debounce(func, delay) {
        let debounceTimer;
        return function(...args) {
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(() => func.apply(this, args), delay);
        };
    }

    function createCounterElement() {
        if (document.getElementById('page-counter-userscript')) return;

        pageCounterElement = document.createElement('div');
        pageCounterElement.id = 'page-counter-userscript';

        // Custom styling for the counter box
        Object.assign(pageCounterElement.style, {
            position: 'fixed',
            bottom: config.counterPosition.bottom,
            left: config.counterPosition.left,
            padding: '5px 7px',
            borderRadius: '0px',
            color: 'rgba(255, 255, 255, 0.5)',          //Adjust 0.X to increase or decrease text brightness
            border: '0.3px solid rgba(1, 1, 12, 1.0)',  //Set 1.0 to 0.0 to hide the border
            backgroundColor: 'rgba(73, 83, 89, 1.0)',   //Set 1.0 to 0.0 to hide the background
            zIndex: '99999',
            fontSize: '17px',
            fontFamily: 'Inter, sans-serif',
            fontWeight: '525',
            pointerEvents: 'none',
        });
        document.body.appendChild(pageCounterElement);
    }

    /**
     * Adjusts the counter's scale to counteract browser zoom, keeping its size constant.
     */
    function adjustForZoom() {
        if (!pageCounterElement) return;
        const zoomLevel = window.devicePixelRatio || 1;
        const scale = 1 / zoomLevel;
        pageCounterElement.style.transform = `scale(${scale})`;
        pageCounterElement.style.transformOrigin = 'bottom left';
    }


    /**
     * Finds the total number of pages ONCE by reading the hidden input field.
     */
    function findAndCacheTotalPages() {
        if (cachedTotalPages !== null) return;
        try {
            const maxPageInput = document.getElementById('max_page');
            if (maxPageInput && maxPageInput.value) {
                cachedTotalPages = parseInt(maxPageInput.value, 10);
            }
        } catch (e) {
            console.error("[Page Counter] Error reading total pages.", e);
        }
    }

    /**
     * Finds the current page number by reading the visible page button.
     */
    function getCurrentPage() {
        try {
            const pageButton = document.querySelector("button[x-text=\"'Page ' + page\"]");
            if (pageButton && pageButton.textContent) {
                const match = pageButton.textContent.match(/(\d+)/);
                if (match && match[1]) {
                    return parseInt(match[1], 10);
                }
            }
        } catch(e) {
            console.error("[Page Counter] Error reading current page.", e);
        }
        return null;
    }

    /**
     * Updates the counter display.
     */
    function updatePageCount() {
        if (!pageCounterElement) return;

        const current = getCurrentPage();
        const total = cachedTotalPages;

        if (current !== null || total !== null) {
            const currentStr = current !== null ? current : '?';
            const totalStr = total !== null ? total : '?';
            pageCounterElement.textContent = `${currentStr}/${totalStr}`;
            pageCounterElement.style.opacity = '1';
        } else {
             pageCounterElement.style.opacity = '0';
        }
    }

    const debouncedUpdate = debounce(updatePageCount, 50);

    function init() {
        createCounterElement();
        adjustForZoom(); // Set the initial scale
        findAndCacheTotalPages();

        const observerTarget = document.querySelector("button[x-text=\"'Page ' + page\"]");
        if (!observerTarget) {
            console.error("[Page Counter] Could not find target page button for observation.");
            updatePageCount(); // Try to update once
            return;
        }

        observer = new MutationObserver(() => {
            debouncedUpdate();
        });

        observer.observe(observerTarget, {
            childList: true,
            subtree: true
        });

        // Listen for resize/zoom events to keep the counter size consistent
        window.addEventListener('resize', debounce(adjustForZoom, 100));

        updatePageCount();
    }

    if (document.readyState === 'complete') {
        init();
    } else {
        window.addEventListener('load', init);
    }
})();