您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
PagePilot allows custom keybindings and CSS selectors for page-turning buttons to be uniquely configured per URL. Automatically detects webpage addresses and applies your preset rules, enabling precise one-click navigation across all sites.
当前为
// ==UserScript== // @name PagePilot // @name:zh-CN 键页通 // @namespace https://gf.qytechs.cn/scripts/541642 // @version 0.1.3 // @author oajsdfk // @description PagePilot allows custom keybindings and CSS selectors for page-turning buttons to be uniquely configured per URL. Automatically detects webpage addresses and applies your preset rules, enabling precise one-click navigation across all sites. // @description:zh-CN 键页通支持为不同网页(URL)独立配置按键策略与翻页按钮定位规则。自动识别当前访问网址,精准匹配预设的自定义按键及翻页按钮CSS选择器,实现一键翻页的个性化操控体验。 // @license MIT // @match *://*/* // @grant GM_getValue // @grant GM_setValue // ==/UserScript== (function () { 'use strict'; function pilot(url, event, options2) { const find = (keys) => { if (!keys) return false; if (keys.key?.find((i) => i === event.key)) return true; if (keys.code?.find((i) => i === event.code)) return true; return false; }; const g = []; for (const [k, v] of Object.entries(options2.globalKeys)) { if (find(v)) g.push(k); } function matchGlobal(k, p) { if (find(p.keys)) return true; if (typeof p.globalKeys === "boolean") { if (!p.globalKeys) return false; return g.indexOf(k) != -1; } else if (typeof p.globalKeys === "string") { return g.indexOf(p.globalKeys) != -1; } return g.indexOf(k) != -1; } function matchKey(p) { if (p.cur) { if (!p.next && !p.prev && !p.other) { for (const i of g) { if (i === "next") return { child: p.cur, sibling: 1 }; if (i === "prev") return { child: p.cur, sibling: -1 }; } return; } for (const k of ["prev", "next"]) { if (!p[k]) continue; let r = typeof p[k] === "string" ? { child: p.cur, sibling: k === "next" ? 1 : -1, deep: { child: p[k] } } : p[k]; if (matchGlobal(k, r)) return r; } for (const [k, v] of Object.entries(p.other ?? [])) { let r = typeof v === "string" ? { child: p.cur, sibling: k === "next" ? 1 : -1, deep: { child: v } } : v; if (matchGlobal(k, r)) return r; } } else { for (const k of ["prev", "next"]) { if (!p[k]) continue; let r = typeof p[k] === "string" ? { child: p[k] } : p[k]; if (matchGlobal(k, r)) return r; } for (const [k, v] of Object.entries(p.other ?? [])) { let r = typeof v === "string" ? { child: v } : v; if (matchGlobal(k, r)) return r; } } return; } for (const [r, p] of Object.entries(options2.pilots)) { if (!url.match(new RegExp(r))) continue; const q = matchKey(p); if (!q) continue; const { child, sibling, deep } = q; if (!child) continue; const cur = document.querySelector(child); const ele = queryDeep({ sibling, deep }, cur); if (!ele) continue; ele.click(); return ele; } return null; } function queryDeep({ sibling, child, deep }, e) { if (child) e = e?.querySelector(child); if (sibling) { let c = Math.abs(sibling); while (c > 0 && e) { c--; e = sibling > 0 ? e.nextElementSibling : e.previousElementSibling; } if (c !== 0) return null; } return deep ? queryDeep(deep, e) : e; } const lastOptionsVer = GM_getValue("pagepilot_options_ver"); let options = GM_getValue("pagepilot_options"); const optionsVer = 1; if (!options || lastOptionsVer !== optionsVer) { options = { globalKeys: { // 绑定名称的通用按键,所有网站的元素根据名称自动绑定到这些按键上 // Common keys bound by name, elements on all sites will be automatically bound to these keys prev: { code: ["ArrowUp", "PageUp", "KeyP", "KeyD"] }, next: { code: ["ArrowDown", "PageDown", "KeyN", "KeyF"] }, top: { code: ["Home", "KeyT"] }, bottom: { code: ["End", "KeyB"] } }, pilots: { // 站点正则 => 元素选择器或按键 // site regex => element selector or key "http://example1.com(/.*)?": { // 当点击元素对应的按键时候,触发元素的点击事件: PageUp => querySelector('.pg .prev_btn').click() // When the corresponding key is pressed, trigger the element's click event: PageUp => querySelector('.pg .prev_btn').click() prev: ".pg .prev_btn", next: ".pg .next_btn" }, // 通过当前页元素的兄弟来定位翻页按钮 // locate the page-turning buttons by the siblings of the current page element "https://(.*.)?example2.org(/.*)?": { cur: "#cur_page" }, // 通过当前页元素的兄弟的子孙来定位翻页按钮 // locate the page-turning buttons by the descendants of the siblings of the current page element "https?://(.*.)?example3.org(/.*)?": { cur: "#cur_page", prev: "a", // querySelector('#cur_page').prevElment.querySelector(a).click() next: "a" // querySelector('#cur_page').nextElment.querySelector(a).click() }, "https?://(.*.)?example4.org(/.*)?": { // 多层级子孙、兄弟的翻页按钮的定位规则: querySelector('.nav .pg').prevE.prevE.prevE.querySelector(a).click() // multi-level descendants and siblings page button location rules (): querySelector('.nav .pg').prevE.prevE.prevE.querySelector(a).click() prev: { child: ".nav", deep: { child: ".pg", sibling: -3, deep: { child: "a" } } }, next: { child: ".nav", deep: { child: ".pg", sibling: 5, // querySelector('.nav .pg') .nextE x5 .querySelector(a).click() deep: { child: "a" } } }, // 定义翻页以外的任意按钮 // define any buttons other than page turning other: { // 显示指定绑定或者禁用全局按键 // Explicitly bind or disable global keys top: "#top", bottom: { // 显示指定绑定或者禁用全局按键 // Explicitly bind or disable global keys globalKeys: false, // disable child: "#bottomBtn", // 指定只对该网站生效的按键 // Specify keys that only take effect on this site keys: { code: ["KeyN"] } }, close: { child: "#closeBtn", keys: { code: ["KeyC"] } } } } } }; GM_setValue("pagepilot_options", options); GM_setValue("pagepilot_options_ver", optionsVer); } console.log({ pilot_options: options }); window.addEventListener("keyup", function(e) { const ae = document.activeElement; if (ae && ["input", "select", "button", "textarea"].indexOf( ae.tagName.toLowerCase() ) !== -1) return; console.log({ key: e.key, code: e.code, options }); pilot(window.location.href, e, options); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址