您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Keyboard navigation for LetsRun.com
// ==UserScript== // @name LRC Keyboard Nav // @namespace https://habs.sdf.org // @description Keyboard navigation for LetsRun.com // @match https://www.letsrun.com/forum* // @version 1.1 // @grant none // @license AGPLv3 // ==/UserScript== (() => { const keys = { UP: 'k', DOWN: 'j', LEFT: 'h', RIGHT: 'l', NEXT: 'p', BACK: 'y', } const VERT = [keys.UP, keys.DOWN]; const HORZ = [keys.LEFT, keys.RIGHT]; const DIRS = [...VERT, ...HORZ]; const BORDER = '3px solid red'; const mode = { '/forum': 'thread', '/forum/flat_read.php': 'post', }[window.location.pathname]; const selector = { 'thread': '.thread', 'post': '.forum-post-container', }; if (!mode) return; let headerHeight; const items = document.querySelectorAll(selector[mode]); let selIdx = 0; items[selIdx].style.border = BORDER; document.addEventListener('keypress', e => { if (!headerHeight) headerHeight = document.querySelector('.page-container').getBoundingClientRect().height; if (document.activeElement.tagName === 'INPUT' || document.activeElement.classList.contains('rx-editor')) return; const [ voteUp, voteDown ] = items[selIdx].querySelectorAll('.forum-post-vote-button'); if (VERT.includes(e.key)) items[selIdx].style.border = ''; switch (e.key) { case keys.UP: selIdx--; break; case keys.DOWN: selIdx++; break; case keys.RIGHT: if (mode === 'thread') window.location.href = items[selIdx].querySelector('.subject > a').href; else voteDown.click(); break; case keys.LEFT: if (mode === 'post') voteUp.click(); break; case keys.NEXT: [...document.querySelectorAll('.dbr-paginated-thread')].at(-1).click(); break; case keys.BACK: window.location.href = 'https://www.letsrun.com/forum'; break; } if (VERT.includes(e.key)) { if (selIdx < 0) selIdx = 0; if (selIdx >= items.length) selIdx = items.length - 1; items[selIdx].style.border = BORDER; const rect = items[selIdx].getBoundingClientRect(); if (rect.top < headerHeight) { items[selIdx].scrollIntoView(true); window.scrollBy(0, -headerHeight); } if (rect.bottom > window.innerHeight) items[selIdx].scrollIntoView(false); } }); })();