mike's lib

快速處理畫面操作

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/570074/1869594/mike%27s%20lib.js

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

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