左右鍵翻頁 Navigate with Arrow Keys

使用左右鍵來翻上下頁

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         左右鍵翻頁 Navigate with Arrow Keys
// @namespace    https://github.com/Shen255313/tampermonkey-scripts
// @version      1.2.6
// @description  使用左右鍵來翻上下頁
// @author       ShenYJ
// @homepage     https://greasyfork.org/zh-TW/scripts/510257-左右鍵翻頁-navigate-with-arrow-keys
// @icon         https://img.ixintu.com/download/jpg/20201127/b2a55453b5000509eda6a939275250e6_512_512.jpg
// @match        *://*/*
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_unregisterMenuCommand
// ==/UserScript==


 (function() {
    'use strict'; // 使用嚴格模式

    // 記錄日誌函數
    function log(message) {
        console.log(`[翻頁腳本] ${message}`); // 在控制台輸出日誌信息
    }

    // 配置選項
    const config = {
        prevPageSelectors: ['a', 'button'], // 支援的元素選擇器
        nextPageSelectors: ['a', 'button'], // 支援的元素選擇器
        prevPageKeywords: ['上一頁', '前一頁', '上一節', '上一章', '上一頁', '前一頁', '前一章', '上一页', '前一页', '上一节', '上一页', '前一页', '前一章'], // 上一頁的同義詞
        nextPageKeywords: ['下一頁', '後一頁', '下一節', '下一章', '下一頁', '後一節', '後一章', '下一页', '后一页', '下一节', '下一页', '后一节', '后一章'], // 下一頁的同義詞
        prevKey: 'ArrowLeft', // 上一頁按鍵
        nextKey: 'ArrowRight', // 下一頁按鍵
        logLevel: 'info', // 日誌記錄級別
        spacekeymode: GM_getValue('spacekeymode', false) // 空白鍵雙擊翻頁模式,從存儲中讀取狀態
    };

    // 更新空白鍵模式菜單
    let menuCommandId = GM_registerMenuCommand(`空白鍵雙擊翻頁 ${config.spacekeymode ? '關閉' : '開啟'}`, toggleSpacekeyMode);

    // 切換空白鍵雙擊翻頁模式
    function toggleSpacekeyMode() {
        config.spacekeymode = !config.spacekeymode;
        GM_setValue('spacekeymode', config.spacekeymode); // 保存狀態到存儲中
        const status = config.spacekeymode ? '開啟' : '關閉';
        log(`空白鍵雙擊翻頁已${status}`);
        // 更新菜單命令文字
        GM_unregisterMenuCommand(menuCommandId);
        menuCommandId = GM_registerMenuCommand(`空白鍵雙擊翻頁 ${status}`, toggleSpacekeyMode);
    }

    // 查找符合條件的元素
    function findPageElement(keywords, selectors) {
        for (const selector of selectors) { // 遍歷所有選擇器
            const elements = document.querySelectorAll(selector); // 查找所有符合選擇器的元素
            for (const element of elements) { // 遍歷所有元素
                for (const keyword of keywords) { // 遍歷所有關鍵詞
                    if (element.textContent.includes(keyword)) { // 如果元素的文本內容包含關鍵詞
                        return element; // 返回該元素
                    }
                }
            }
        }
        return null; // 如果沒有找到符合條件的元素,返回 null
    }

    // 處理按鍵事件
    function handleKeydown(event) {
        if (event.key === config.prevKey) { // 如果按下的是上一頁按鍵
            const prevPageElement = findPageElement(config.prevPageKeywords, config.prevPageSelectors); // 查找上一頁的元素
            if (prevPageElement) { // 如果找到上一頁的元素
                prevPageElement.click(); // 點擊該元素
                log('翻到上一頁'); // 記錄日誌
                highlightElement(prevPageElement); // 高亮顯示該元素
            } else {
                log('未找到上一頁的元素'); // 如果沒有找到上一頁的元素,記錄日誌
            }
        } else if (event.key === config.nextKey) { // 如果按下的是下一頁按鍵
            const nextPageElement = findPageElement(config.nextPageKeywords, config.nextPageSelectors); // 查找下一頁的元素
            if (nextPageElement) { // 如果找到下一頁的元素
                nextPageElement.click(); // 點擊該元素
                log('翻到下一頁'); // 記錄日誌
                highlightElement(nextPageElement); // 高亮顯示該元素
            } else {
                log('未找到下一頁的元素'); // 如果沒有找到下一頁的元素,記錄日誌
            }
        }
    }

    // 高亮顯示被點擊的元素
    function highlightElement(element) {
        element.style.outline = '2px solid red'; // 設置元素的外框為紅色
        setTimeout(() => {
            element.style.outline = ''; // 500 毫秒後移除外框
        }, 500);
    }

    // 防重複點擊機制
    let lastRightClickTime = 0; // 上次點擊 ArrowRight 鍵的時間
    function preventRightDoubleClick() {
        const now = Date.now(); // 獲取當前時間
        if (now - lastRightClickTime < 1000) { // 如果距離上次點擊 ArrowRight 鍵的時間小於 1000 毫秒
            return true; // 返回 true,表示重複點擊
        }
        lastRightClickTime = now; // 更新上次點擊 ArrowRight 鍵的時間
        return false; // 返回 false,表示不是重複點擊
    }

    // 空白鍵雙擊翻頁
    let spacebarClickTime = 0; // 上次點擊的時間
    function spacebarDoubleClick() {
        const now = Date.now(); // 獲取當前時間
        if (now - spacebarClickTime < 600) { // 如果距離上次點擊的時間小於 500 毫秒
            const event = new KeyboardEvent('keydown', { key: 'ArrowRight', code: 'ArrowRight', keyCode: 39, which: 39 });
            document.dispatchEvent(event);
        }
        spacebarClickTime = now; // 更新上次點擊的時間
    }

    // 監聽按鍵事件
    document.addEventListener('keydown', event => {
        if (event.key === 'ArrowRight') {
            if (preventRightDoubleClick()) { // 如果是重複點擊
                log('重複點擊,忽略此次操作'); // 記錄日誌
                return; // 忽略此次操作
            }
            handleKeydown(event); // 處理按鍵事件
        } else if (event.key === ' ' && config.spacekeymode) {
            spacebarDoubleClick();
        } else {
            handleKeydown(event); // 處理其他按鍵事件
        }
    });

    // 初始掃描現有的 DOM
    function initialScan() {
        log('進行初始掃描'); // 記錄日誌
        const prevPageElement = findPageElement(config.prevPageKeywords, config.prevPageSelectors); // 查找上一頁的元素
        const nextPageElement = findPageElement(config.nextPageKeywords, config.nextPageSelectors); // 查找下一頁的元素
        log(`初始掃描結果: 上一頁元素${prevPageElement ? '已找到' : '未找到'}, 下一頁元素${nextPageElement ? '已找到' : '未找到'}`); // 記錄掃描結果
    }

    // 監聽動態加載內容
    const observer = new MutationObserver(() => {
        log('檢測到動態加載內容'); // 記錄日誌
        initialScan(); // 進行初始掃描
    });

    try {
        observer.observe(document.body, { childList: true, subtree: true }); // 監聽 DOM 變化
        log('MutationObserver 已啟動'); // 記錄日誌
    } catch (error) {
        log(`MutationObserver 啟動失敗: ${error.message}`); // 記錄錯誤信息
    }

    // 提供停止 MutationObserver 的機制
    function stopObserver() {
        observer.disconnect(); // 停止監聽 DOM 變化
        log('MutationObserver 已停止'); // 記錄日誌
    }
  
    // 初始掃描現有的 DOM
    initialScan(); // 進行初始掃描

    log('翻頁腳本已啟動'); // 記錄日誌
})();