mike's lib

快速處理畫面操作

Този скрипт не може да бъде инсталиран директно. Това е библиотека за други скриптове и може да бъде използвана с мета-директива // @require https://update.greasyfork.org/scripts/570074/1869594/mike%27s%20lib.js

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

Advertisement:

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

Advertisement:

// ==UserScript==
// @name         mike's lib
// @namespace    小說
// @version      2026.07.07
// @description  工具函式庫
// @author       mike
// @match        http*://*/*
// @grant        none
// ==/UserScript==

(function (global) {
    'use strict';

    // 等待物件 func
    const waitElement = (selector, callback) => {
        const interval = setInterval(() => {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(interval);
                callback(element);
            }
        }, 100);
    };

    // 移除物件
    const removeElement = (baseObj, removeTarget) => {
        let beRemoveObj = baseObj.querySelector(removeTarget);
        if (beRemoveObj) {
            beRemoveObj.remove();
        }
    };
    
    // 等並刪除
    const waitAndKillElement = (selector) => {
        waitElement(selector, () => {
            removeElement(document, selector);
        });
    };

    // 重置寬高
    const resetMarginPadding = (element) => {
        element.style.margin = '0px';
        element.style.padding = '0px';
    };
    
    // 取得 平台名稱
    const getPlatform = (platformList) => {
        const pathname = window.location.pathname // 用網址查
        const findPlatform = platformList.find(item => {
            const [key, value] = Object.entries(item)[0];
            return pathname.includes(key);
        });
        return Object.values(findPlatform)[0]
    }

    // 取得 平台名稱
    const getPlatformByHostname = (platformList) => {
        const hostname = window.location.hostname // 用網域查
        const findPlatform = platformList.find(item => {
            const [key, value] = Object.entries(item)[0];
            return hostname.includes(key);
        });
        if (!findPlatform) return '';
        return Object.values(findPlatform)[0];
    }

    // 製作快速跳轉浮窗
    // initChapterNavigator({selectors: ['.entry-content', 'p'], chapterStartsWith: ['[', '【']});
    const initChapterNavigator = ({
        selectors,
        chapterStartsWith
    }) => {

        if (
            !Array.isArray(selectors) ||
            selectors.length === 0 ||
            selectors.some(s => typeof s !== 'string' || !s.trim())
        ) {
            console.log('[ChapterNavigator] selectors 必須為非空字串陣列');
            return;
        }

        if (
            !Array.isArray(chapterStartsWith) ||
            chapterStartsWith.length === 0 ||
            chapterStartsWith.some(s => typeof s !== 'string' || !s)
        ) {
            console.log('[ChapterNavigator] chapterStartsWith 必須為非空字串陣列');
            return;
        }

        const queryBySelectors = () => {
            let current = document;

            for (let i = 0; i < selectors.length; i++) {
                if (!current) return [];

                if (i === selectors.length - 1) {
                    return Array.from(current.querySelectorAll(selectors[i]));
                }

                current = current.querySelector(selectors[i]);
            }

            return [];
        };

        const areaKeyList = () => {
            return queryBySelectors().filter(el => {
                const text = el.textContent.trim();
                return chapterStartsWith.some(prefix =>
                    text.startsWith(prefix)
                );
            });
        };

        const gotoText = (findText) => {
            areaKeyList().forEach(el => {
                if (el.textContent.includes(findText)) {
                    el.scrollIntoView({
                        behavior: 'smooth',
                        block: 'start'
                    });
                }
            });
        };

        const getChapterList = () =>
            areaKeyList().map(el => el.textContent);

        const createFloatingBox = (chapterList) => {
            if (document.getElementById('floatingBox')) {
                return;
            }

            const floatingBox = document.createElement('div');
            floatingBox.id = 'floatingBox';

            Object.assign(floatingBox.style, {
                position: 'fixed',
                right: '10px',
                bottom: '10px',
                width: '150px',
                height: '450px',
                overflow: 'auto',
                padding: '10px',
                backgroundColor: '#333',
                color: 'white',
                borderRadius: '8px',
                zIndex: '1000'
            });

            chapterList.forEach(text => {
                const btn = document.createElement('button');

                Object.assign(btn.style, {
                    width: '100%',
                    margin: '2px 0',
                    padding: '10px 5px',
                    backgroundColor: '#f44336',
                    color: 'white',
                    border: 'none',
                    borderRadius: '4px',
                    cursor: 'pointer'
                });

                btn.textContent = text;
                btn.onclick = () => gotoText(text);

                floatingBox.appendChild(btn);
            });

            document.body.appendChild(floatingBox);
        };

        const chapterList = getChapterList();

        if (!chapterList.length) {
            console.log('[ChapterNavigator] 未找到任何符合規則的章節');
            return;
        }

        createFloatingBox(chapterList);
    };

    // 處理 遊俠
    const process_ali213 = () => {
        // 移除
        let needRemoveElement;
        needRemoveElement = [".ns_t1", ".ns_t2", ".ns_t3", ".glzjfoot"];
        needRemoveElement.map((element) => {
            mikeLib.removeElement(document, element);
        });

        // 主要內容
        let main = document.querySelector(".main");
        mikeLib.resetMarginPadding(main);
        main.style.width = "100%";
        needRemoveElement = [".glzj_tj", "#ali_gl_detail_top_ad"];
        needRemoveElement.map((element) => {
            mikeLib.removeElement(main, element);
        });

        // 標題
        let gltitle = main.querySelector(".gltitle");
        mikeLib.resetMarginPadding(gltitle);
        gltitle.style.width = "initial";
        gltitle.querySelector(".tit").style.width = "initial";
        needRemoveElement = [".weizhi", ".showtag"];
        needRemoveElement.map((element) => {
            mikeLib.removeElement(main, element);
        });

        // 章節選項
        let dh = main.querySelector(".dh");
        mikeLib.resetMarginPadding(dh);
        dh.style.width = "initial";
        let changtiaodaohang = dh.querySelector(".changtiaodaohang");
        mikeLib.resetMarginPadding(changtiaodaohang);
        changtiaodaohang.style.width = "initial";
        changtiaodaohang.style.left = 0;

        // 內容
        let content = main.querySelector(".content");
        mikeLib.resetMarginPadding(content);
        content.style.width = "90%";
        needRemoveElement = [".gl_r"];
        needRemoveElement.map((element) => {
            mikeLib.removeElement(content, element);
        });

        let gl_l = content.querySelector(".gl_l");
        gl_l.style.width = "100%";
        needRemoveElement = [
            ".share-container",
            ".go-lb",
            ".glrelated",
            ".downrelated",
            "#newsbbs",
            ".gamecard_pc",
        ];
        needRemoveElement.map((element) => {
            mikeLib.removeElement(gl_l, element);
        });

        // let page = gl_l.querySelector('.page')
        // needRemoveElement = ['.n_show_b']
        // needRemoveElement.map((element) => {
        //     waitAndKillElement(page, element)
        // })
    };

    // 處理 娛樂計程車
    const process_entertainment14 = () => {
        const removeObjList = [
            "#masthead",
            ".entry-footer",
            "#nav-below",
            "#comments",
            "#secondary",
            "#colophon",
        ];
        removeObjList.forEach((item) => mikeLib.removeElement(document, item));

        // 主畫面拉寬
        const primary = document.getElementById("primary");
        primary.style.width = "100%";

        // 把圖都直接載入, 來方便正常跳轉
        const lazyHidden = document.querySelectorAll(".lazy-hidden");
        lazyHidden.forEach((item) =>
            item.setAttribute("src", item.getAttribute("data-lazy-src")),
        );
    };

    // 處理 遊民星空
    const process_gamersky = () => {
        const removeObjList = [
            ".QZnav",
            ".QZshade",
            ".QZlogin",
            "#tgs_back_down1000",
            ".bodybg",
            ".header",
            ".bgAdWrap",
            ".Mid_top",
            //
            ".gs_comm_content_bot_fun",
            ".Relevant",
            ".box",
            ".gs_nc_editor",
            ".gs_ccs_solve",
            ".Comment",
            //
            ".Mid2_R",
            ".Bot",
        ];
        removeObjList.forEach((item) => mikeLib.removeElement(document, item));

        const Mid2_L = document.querySelector(".Mid2_L");
        Mid2_L.style.width = "100%";

        const Mid2L_List = document.querySelectorAll('[class^="Mid2L_"]');
        Mid2L_List.forEach((item) => (item.style.width = "100%"));
    };

    // ⭐ 關鍵:對外輸出
    global.mikeLib = {
        waitElement,
        removeElement,
        waitAndKillElement,
        resetMarginPadding,
        getPlatform,
        getPlatformByHostname,
        initChapterNavigator,
        process_ali213,
        process_entertainment14,
        process_gamersky
    };

})(window);