Page Progess counter for Weebcentral

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

Устаревшая версия за 09.10.2025. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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);
    }
})();