您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Keyboard based navigation
当前为
// ==UserScript== // @name Keyboard navigation // @version 1.8.7 // @author Sly_North // @description Keyboard based navigation // @grant none // @run-at document-start // @namespace Sly_North // @include * // @license MIT // ==/UserScript== // Click first link (tag='a' or 'span') with text matching one of 'keywords' regex function ClickLink(tag, keywords) { var elts = document.getElementsByTagName(tag); for (var i = 0; i < elts.length; ++i) { var elt = elts[i]; for (k in keywords) { var regexp = keywords[k]; if (elt.textContent.match(keywords[k])) { console.log('Clicking ', elt.textContent); elt.click(); return true; } } } return false; } // Make 'link' visibly selected. var lastSel; // previous selected link function SelectLink(link, links) { if (lastSel) lastSel.style.backgroundColor = ""; lastSel = link; link.focus(); link.style.backgroundColor = "orange"; } // Select either link with preferred text or closer to the center. function SelectBestLink() { var links = document.getElementsByTagName('a'); var curr = document.activeElement; var viewport = window.visualViewport; var screenHeight = viewport.height; var midX = viewport.width/2; var midY = screenHeight/2; var minD = 1000000000; var best; var keywords = [/cliquez sur ce lien/i, /#unread/, /Discussions/]; for (var i = 0; i < links.length; ++i) { var link = links[i]; var br = link.getBoundingClientRect(); var d = Math.abs(br.left - midX) + Math.abs(br.top - midY); if ((link == curr)) continue; // Insert here other preferred link texts. for (var k in keywords) { if (link.text.match(keywords[k])) { // link.click(); SelectLink(link, links); return; } } // Select link to current page, if not already selected if (link.href == document.URL) { if ((br.top >= 0) && (br.top < screenHeight)) { // If on start, focus it, without highlighting it. SelectLink(link, links); return; } } // Select link closer to the center if (d < minD) { minD = d; best = link; } } if (best) { // If on start, focus it, without highlighting it. console.log("Select link", best.text); SelectLink(best, links); } } // Skip most simple cookie forms. function SkipCookieWall() { var elts = document.getElementsByTagName('span'); for (i in elts) { var t = elts[i].innerText; if (!t) continue; if (t.match(/Continuer sans accepter/) || t.match(/CONTINUER SANS ACCEPTER/) || t.match(/Continue without agree/) || t.match(/Only allow essential cookies/)) { console.log("Clic ", t); elts[i].click(); return; } } } // Unblock the page scrolling. function Unfreeze() { document.body.classList.remove('content-blurred'); document.body.classList.remove('noscroll'); document.documentElement.style.overflow = "scroll"; document.body.style.overflow = "scroll"; console.log('Unfreeze overflow'); } // Listen for a few control+alt + key document.addEventListener('keydown', function(e) { // console.log('ctrl=',e.ctrlKey,' alt=',e.altKey, ' meta=', e.metaKey, ' key=',e.keyCode); if (e.shiftKey || !e.ctrlKey || (!e.altKey && !e.metaKey)) return; var dx = 0, dy = 0, scaleX = 1; var maxDX = 10000000, maxDY = 10000000; var scaleWidth = 0; // Space=select best link, enter=click best link, #/del=GMail's delete old messages in trash, o/p=previous/next page if (e.keyCode == 32 || e.keyCode == 220) { SelectBestLink(); return; } else if (e.keyCode == 13 || e.keyCode == 90) { ClickLink('a', [/cliquez sur ce lien/, /click this link/, /unread#unread/]); return; } else if (e.keyCode == 46 || e.keyCode == 51) { ClickLink('span', [/^delete forever/]); return; } else if (e.keyCode == 79 || e.keyCode == 219) { if (!ClickLink('a', [/Précédent/i, /Prev/, /Previous page/, /Older/])) ClickLink('i', [/ chevron_left /]); return; } else if (e.keyCode == 80 || e.keyCode == 221) { if (!ClickLink('a', [/Suivant/i, /Next/, /Next page/, /Newer/])) { ClickLink('i', [/ chevron_right /]); } return; } else if (e.keyCode == 85) { Unfreeze(); return; } else if (e.keyCode == 67) { SkipCookieWall(); return; } // Select direction in which to look for 'best' link else if (e.keyCode == 37 || e.keyCode == 72) { dx = -1; scaleWidth = 1; maxDY = 50; } // left else if (e.keyCode == 39 || e.keyCode == 76) { dx = +1; scaleWidth = 1; maxDY = 50; } // right else if (e.keyCode == 38 || e.keyCode == 75) { dy = -1; scaleX = 0.5; } // up else if (e.keyCode == 40 || e.keyCode == 74) { dy = +1; scaleX = 0.5; } // down else { // console.log('Key ignored:', e.keyCode); return; } // Look for next link in a given direction var adx = Math.abs(dx), ady = Math.abs(dy); var curr = document.activeElement; var br = curr.getBoundingClientRect(); var sx = br.left + br.width*scaleWidth; // + br.width/2; var sy = br.top + br.height/2; var links = document.getElementsByTagName('a'); var best; var minD = 1500; // console.log('Arrow in dir x =',dx,' y =',dy); for (var i = 0; i < links.length; ++i) { var link = links[i]; if (link != curr) { var br2 = link.getBoundingClientRect(); var x = (br2.left + br2.width*scaleWidth /*+ br2.width/2*/ - sx) * scaleX; var y = br2.top + br2.height/2 - sy; var ax = Math.abs(x), ay = Math.abs(y); var distX = x*dx, distY = y*dy; if (ax <= maxDX && ay <= maxDY && distX >= adx && distY >= ady) { // console.log(Math.abs(x*dx + y*dy) , " vs ", Math.abs(x*dy + y*dx)); var d = ax + ay; if (Math.abs(x*dx + y*dy) < Math.abs(x*dy + y*dx)) d *= 2; // Penalize off-direction links if (d < minD) { if ((dx != 0 || ax/(1+ay) < 3) && (dy != 0 || ay < 100)) { // console.log(" new best link x = ",x," y = ", y, ' distX=',distX,' distY=', distY, " minD = ", minD, " ", link.text); minD = d; best = link; } } } } } if (best) SelectLink(best, links); }, false); setTimeout(() => {SkipCookieWall();}, 1000); // setTimeout(() => {SkipCookieWall();}, 1500); console.log('key navigation handler ready');