Greasy Fork

Greasy Fork is available in English.

增強漫畫櫃

漫畫櫃自動隐藏頂部元素、中鍵捲動頁面、圖片高寬調整、自動切換上下一章、更改cookie、簡易觸控手勢、Backspace及觸控下滑在漫畫頁面時回目錄,在目錄時回進入目錄之前

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name 增強漫畫櫃
// @namespace http://tampermonkey.net/
// @version 1.4
// @description 漫畫櫃自動隐藏頂部元素、中鍵捲動頁面、圖片高寬調整、自動切換上下一章、更改cookie、簡易觸控手勢、Backspace及觸控下滑在漫畫頁面時回目錄,在目錄時回進入目錄之前
// @license MIT
// @match *://www.manhuagui.com/*
// @run-at document-end
// @grant none
// ==/UserScript==

(function($) {
    'use strict';

    // 禁用 tbBox.live
    function disableTbBoxLive() {
        $('#tbBox').off && $('#tbBox').off();
        $('#tbBox').die && $('#tbBox').die();
    }

    $(document).ready(disableTbBoxLive);

    new MutationObserver(() => {
        $('#tbBox').length && disableTbBoxLive();
    }).observe(document.body, { childList: true, subtree: true });
})(window.jQuery);

(function() {
    'use strict';

    // 滑鼠中鍵捲動頁面(優化版)
    let isMiddleButtonPressed = false;
    let [lastX, lastY] = [0, 0];

    document.addEventListener('mousedown', e => {
        if (e.button === 1) {
            isMiddleButtonPressed = true;
            document.body.style.cursor = 'grab';
            [lastX, lastY] = [e.clientX, e.clientY];
            e.preventDefault();
        }
    });

    document.addEventListener('mouseup', e => {
        if (e.button === 1) {
            isMiddleButtonPressed = false;
            document.body.style.cursor = 'default';
        }
    });

    document.addEventListener('mousemove', e => {
        if (isMiddleButtonPressed) {
            const deltaX = e.clientX - lastX;
            const deltaY = e.clientY - lastY;
            window.scrollBy(-deltaX * 1.5, -deltaY * 4); // 調整滑動速度
            [lastX, lastY] = [e.clientX, e.clientY];
        }
    });
const url = window.location.href;
if (url.includes('html')&&url.includes('/comic/')) {
    //改變css style
    const style = document.createElement('style');
    style.textContent = `
        html {
            overflow: overlay;
        }
        .notice-bar .notice{
            width:initial;
            float: initial;
        }
        .w998, .w728, .w980, .chapter, .chapter-list, .latest-list, .latest-list ul, .contList, .book-list ul, .cmt-cont, .cover-list, .tbCenter {
            width:100%;
        }
        .w860 {
            float:left;
        }
        .tbCenter {
            border:0px;
            background-color: transparent;
        }
        .footer-cont {
            width:100%;
            padding: 0;
        }
        .sub-btn {
            width:980px;
            margin:0px auto;
        }
    `;
    document.head.appendChild(style);
    // 隱藏頁面元素
    const elementsToHide = ['.header-inner', '.title', '.main-btn', '.w980.clearfix.sub-btn'];
    const header = document.querySelector('.header');
    const headerHeight = '50px';

    if (header) {
        Object.assign(header.style, {
            position: 'absolute', top: '0', left: '0', width: '100%', height: headerHeight,
            display: 'block', opacity: '0', zIndex: '1', marginBottom: '0'
        });

        [...elementsToHide, '.header'].forEach(selector => {
            const el = document.querySelector(selector);
            el && el.addEventListener('mouseover', () => toggleHeaderVisibility(true));
            el && el.addEventListener('mouseout', () => toggleHeaderVisibility(false));
        });

        // 頁面載入時先隱藏元素
        elementsToHide.forEach(selector => {
            const el = document.querySelector(selector);
            el && (el.style.display = 'none');
        });
    }

    function toggleHeaderVisibility(show) {
        header.style.opacity = show ? '1' : '0';
        elementsToHide.forEach(selector => {
            const el = document.querySelector(selector);
            el && (el.style.display = show ? 'block' : 'none');
        });
        header.style.height = show ? '34px' : headerHeight;
        header.style.position= show ? 'relative' : 'absolute';
    }

    // 動態改變圖片大小
    function resizeImage() {
        const img = document.getElementById('mangaFile');
        const images = document.querySelectorAll('#mangaMoreBox img');
        if (!img || !img.complete) return;

        const [windowHeight, windowWidth] = [window.innerHeight, window.innerWidth];
        const adjustedWidth = (windowHeight / img.naturalHeight) * img.naturalWidth;
        if (img.naturalHeight > img.naturalWidth && windowHeight > 1.5*windowWidth) {
            // 圖片高度大於圖片寬度且視窗寬度大於1.5倍視窗高度
            img.style.width = `${windowWidth}px`;
            img.style.height = 'auto';
/*          let style = document.getElementById('mangaStyle');

            if (!style) {
                style = document.createElement('style');
                style.id = 'mangaStyle';
            document.head.appendChild(style);
            }
            style.textContent = `
                #mangaMoreBox img {
                    width: ${windowWidth}px;
                    height: auto;
                }
            `;*/

            // 設定下拉模式的mangaMoreBox
            images.forEach(img => {
                img.style.width = `${windowWidth}px`;
                img.style.height = 'auto';
            });
            document.body.style.width = `${windowWidth}px`;
            header.style.width = '100%';
//        } else if (img.naturalHeight > windowHeight && adjustedWidth > windowWidth) {
            // 高度大於視窗高度且調整過圖片寬度大於視窗寬度,將圖片高度設為視窗高度且header, .main-nav .main-bar為調整過寬度
//            img.style.height = `${windowHeight}px`;
//            img.style.width = 'auto';
//            document.body.style.width = `${adjustedWidth}px`;
//            header.style.width = `${adjustedWidth}px`;
        } else if (pVars.curFunc==3) {
            // 下拉模式
            if (img.naturalWidth > windowWidth || windowHeight > 1.5*windowWidth) {
                img.style.width = `${windowWidth}px`;
            } else {
                img.style.width = 'auto';
            }
            img.style.height = 'auto';
            // 設定下拉模式的mangaMoreBox
            images.forEach(img => {
                if (img.naturalWidth > windowWidth || windowHeight > 1.5*windowWidth) {
                    img.style.width = `${windowWidth}px`;
                } else {
                    img.style.width = 'auto';
                }
                img.style.height = 'auto';
            });
        } else if (img.naturalHeight > 2.5*img.naturalWidth) {
            // 條漫為auto
            img.style.height = 'auto';
            img.style.width = 'auto';
            document.body.style.width = '100%';
            header.style.width = `100%`;
        } else if (img.naturalHeight > windowHeight || img.naturalHeight > img.naturalWidth || adjustedWidth < windowWidth) {
            // 圖片高度大於視窗高度和圖片寬度,將圖片高度設為視窗高度
            img.style.height = `${windowHeight}px`;
            img.style.width = 'auto';
            document.body.style.width = '100%';
            header.style.width = `100%`;
        } else if (img.naturalWidth > windowWidth) {
            // 圖片寬度度大於視窗寬度,將header, .main-nav .main-bar為圖片寬度
            img.style.height = 'auto';
            img.style.width = 'auto';
            document.body.style.width = `${img.naturalWidth}px`;
            header.style.width = `${img.naturalWidth}px`;
        } else {
            // 其他情況,auto
            img.style.height = 'auto';
            img.style.width = 'auto';
            document.body.style.width = '100%';
            header.style.width = `100%`;
        }
    }

    new MutationObserver(resizeImage).observe(document.body, { childList: true, subtree: true });
    window.addEventListener('load', resizeImage);

    // 自動捲動到右側大圖
    function scrollToRightIfNeeded() {
        const viewportWidth = window.innerWidth;
        document.querySelectorAll('img').forEach(img => {
            if (img.complete && img.offsetWidth > viewportWidth) {
                setTimeout(() => window.scrollTo({ left: document.documentElement.scrollWidth }), 50);
            }
        });
    }

    window.addEventListener('load', scrollToRightIfNeeded);
    new MutationObserver(scrollToRightIfNeeded).observe(document.body, { childList: true, subtree: true });

    // 自動上下一章
    new MutationObserver(() => {
        const okButton = document.querySelector('.pb-ok');
        okButton && okButton.click();
    }).observe(document.body, { childList: true, subtree: true });

    // 最後一頁自動回到目錄
    new MutationObserver(() => {
    const backLink = document.querySelector('.tip-alert a');
        if (backLink) backLink.click();
    }).observe(document.body, { childList: true, subtree: true });


} else {
        document.querySelectorAll('a[target]').forEach(link => {link.setAttribute('target', '_self');});
}
    //⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇記錄歷史頁面給Backspace回到漫畫的前一頁用⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
    // 初始化 sessionStorage 中的歷史記錄陣列
    if (!sessionStorage.getItem('urlHistory')) {
        sessionStorage.setItem('urlHistory', JSON.stringify([]));
    }
    // 更新歷史記錄
    function updateHistory() {
        const currentUrl = window.location.href;
        let history = JSON.parse(sessionStorage.getItem('urlHistory'));
        if (history[history.length - 1] !== currentUrl) { // 避免重複記錄相同 URL
            history.push(currentUrl);
            sessionStorage.setItem('urlHistory', JSON.stringify(history));
            console.log('Updated history:', history);
        }
    }
    // 查找上一個與當前 URL 相同的記錄的上一筆,並計算步數
    function findPreviousInstanceStep() {
        const currentUrl = window.location.href;
        let history = JSON.parse(sessionStorage.getItem('urlHistory'));
        console.log('Current history:', history);
        console.log('Current URL:', currentUrl);
    // 從倒數第二筆開始查找上一個與當前 URL 相同的記錄
        for (let i = history.length - 2; i >= 0; i--) {
            if (history[i] === currentUrl) {
                console.log('Found previous match at index:', i, 'URL:', history[i]);
                    if (i > 0) { // 確保有上一筆
                        const targetIndex = i - 1;
                        const currentIndex = history.length - 1;
                        const steps = targetIndex - currentIndex;
                        console.log('Target index:', targetIndex, 'Target URL:', history[targetIndex], 'Current index:', currentIndex, 'Steps:', steps);
                        return steps;
                    }
                console.log('No prior entry before match');
                break;
            }
        }
        console.log('No previous match found');
        return null;
    }

    // 在頁面加載時更新歷史記錄
    updateHistory();

    // 監聽 URL 變化
    window.addEventListener('popstate', updateHistory);
    window.addEventListener('hashchange', updateHistory);

    // 覆蓋 pushState
    (function(history) {
        const pushState = history.pushState;
        history.pushState = function(state) {
            pushState.apply(history, arguments);
            updateHistory();
        };
    })(window.history);
/*
    // 輪詢檢查 URL 變化(應對未觸發事件的情況)
    let lastUrl = window.location.href;
    setInterval(() => {
        const currentUrl = window.location.href;
        if (currentUrl !== lastUrl) {
            console.log('Detected URL change via polling:', currentUrl);
            updateHistory();
            lastUrl = currentUrl;
        }
    }, 500); // 每 500ms 檢查一次*/
    //⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆記錄歷史頁面給Backspace回到漫畫的前一頁用⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆

    // backspace回到上一層
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Backspace' && !e.target.isContentEditable && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
            const currentUrl = window.location.href;
            const matchHtml = currentUrl.match(/(https?:\/\/[^/]+\/comic\/\d+)\/.*html.*/);
            const matchNumber = currentUrl.match(/(https?:\/\/[^/]+\/comic\/\d+)\/?$/);

            if (matchHtml) {
                window.location.href = matchHtml[1] + '/';
            } else if (matchNumber) {
                //回到漫畫的前一頁
                const steps = findPreviousInstanceStep();
                if (steps !== null) {
                    console.log('Executing history.go(' + steps + ')');
                    history.go(steps);
                } else {
                    console.log('No valid step to go back');
                }

//                const rootUrl = matchNumber[1].replace(/\/comic\/\d+\/?$/, '/update/');
//                window.location.href = rootUrl;
            }
        }
    });
    //插入li
    const insertTip = (container) => {
        const ol = container.querySelector('ol');
        if (ol && !ol.querySelector('.backspace-tip')) { // 防止重複插入
            const newLi = document.createElement('li');
            newLi.className = 'backspace-tip';
            newLi.innerHTML = '<strong>回上层:</strong>Backspace键';
            ol.appendChild(newLi);
        }
    };

    const observeAndInsert = () => {
        const tipContainers = document.querySelectorAll('div.shadow.tip-cont');
        tipContainers.forEach(insertTip);
    };

    // 使用 setTimeout 確保 DOM 完全載入後執行
    setTimeout(observeAndInsert, 3000);

    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === 1 && node.classList.contains('shadow') && node.classList.contains('tip-cont')) {
                    insertTip(node);
                }
            });
        });
    });

    // 漫畫頁面時觸控手勢控制
    let startX = 0;
    let startY = 0;
    let dragLength = 150;
    let isSingleTouch = false;

    window.addEventListener('touchstart', function(e) {
        if (e.touches.length === 1) { // Only trigger for single touch
            isSingleTouch = true;
            startX = e.touches[0].clientX;
            startY = e.touches[0].clientY;
        } else {
            isSingleTouch = false;
        }
    }, false);

    window.addEventListener('touchend', function(e) {
        if (isSingleTouch && e.changedTouches.length === 1 && e.touches.length === 0) { // Ensure only single touch ends
            const endX = e.changedTouches[0].clientX;
            const endY = e.changedTouches[0].clientY;

            const deltaX = endX - startX;
            const deltaY = endY - startY;

            const currentUrl = window.location.href;
            const matchHtml = currentUrl.match(/(https?:\/\/[^/]+\/comic\/\d+)\/.*html.*/);
            const matchNumber = currentUrl.match(/(https?:\/\/[^/]+\/comic\/\d+)\/?$/);

            if (Math.abs(deltaY) > Math.abs(deltaX)) {
                if (window.scrollY === 0 && deltaY > dragLength) {
                    if (matchHtml) {
                        window.location.href = matchHtml[1] + '/';
                    } else if (matchNumber) {
                        //回到漫畫的前一頁
                        const steps = findPreviousInstanceStep();
                        if (steps !== null) {
                            console.log('Executing history.go(' + steps + ')');
                            history.go(steps);
                        } else {
                            console.log('No valid step to go back');
                        }
//                        const rootUrl = matchNumber[1].replace(/\/comic\/\d+\/?$/, '/update/');
//                        window.location.href = rootUrl;
                    }
                }
            } else {
                if (window.scrollX === 0 && deltaX > dragLength && matchHtml) {
                    const prevButton = Array.from(document.querySelectorAll('.btn-red.prev')).find(btn => btn.textContent.trim() === '上一页');
                    if (prevButton) {
                        prevButton.click();
                    }
                } else if ((window.innerWidth >= document.body.scrollWidth || (window.innerWidth + window.scrollX) >= document.body.scrollWidth) && deltaX < -dragLength && matchHtml) {
                    const nextButton = Array.from(document.querySelectorAll('.btn-red.next')).find(btn => btn.textContent.trim() === '下一页');
                    if (nextButton) {
                        nextButton.click();
                    }
                }
            }
        }
    }, false);

    observer.observe(document.body, { childList: true, subtree: true });
    // 修改 cookie
    const targetCookie = 'country=CN; path=/; domain=.manhuagui.com; expires=' + new Date(Date.now() + 7 * 864e5).toUTCString();
    document.cookie = targetCookie;
})();