您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Open links and click buttons easily using only the keyboard!
// ==UserScript== // @name Mouseless Link Opener // @description Open links and click buttons easily using only the keyboard! // @version 0.4.0 // @author sllypper // @homepage https://gf.qytechs.cn/en/users/55535-sllypper // @namespace sllypper // @match *://*/* // @grant GM_openInTab // ==/UserScript== (function() { 'use strict'; // for American keyboard layout, switch it to "`" instead // so you can use it with one hand // or whatever other key you want const HOTKEY = "'" const also_other_elements = true // Label Colors const textColor = "#fff" const backgroundColor = "#555" // let elBag = []; let isSet = false; let visibleLinks = []; //let page; function setListeners() { document.addEventListener("keydown", event => { if (!isSet) { if (event.key === HOTKEY && event.ctrlKey) { event.preventDefault() getElements() filterElements() pickTooltips() placeTooltips() isSet = true } } else { if (event.key >= 0 && event.key < 10) { event.preventDefault() if (chooseTooltip(parseInt(event.key), event.ctrlKey)) { clearTooltips() isSet = false } } else if (event.key === "Tab") { event.preventDefault() shiftTooltips() } else if (event.ctrlKey) { event.preventDefault() } else { clearTooltips() isSet = false } } }) } function chooseTooltip(num, ctrl) { if (num > visibleLinks.length || (num === 0 && visibleLinks.length < 10)) return false if (num === 0) { if (!ctrl) visibleLinks[9].click() else clickNewTab(visibleLinks[9]) return true } // console.log(visibleLinks[num-1]) // console.log(ctrl) if (!ctrl) visibleLinks[num-1].click() else clickNewTab(visibleLinks[num-1]) return true } function clickNewTab(el) { GM_openInTab(el.href, {'insert': true, 'setParent': true}) // GM_openInTab(el.href, {'active': true, 'insert': true, 'setParent': true}) } function shiftTooltips() { visibleLinks = [] clearTooltips() if (elBag.length > 0) { pickTooltips() placeTooltips() } else { getElements() filterElements() pickTooltips() placeTooltips() } } function clearAction() { // let el for (let el of document.querySelectorAll('.displayText_container')) { el.remove() } for (let el of document.querySelectorAll('.displayText')) { el.remove() } visibleLinks = [] isSet = false } function clearTooltips() { for (let el of document.querySelectorAll('.displayText_container')) { el.remove() } for (let el of document.querySelectorAll('.displayText')) { el.remove() } visibleLinks = [] } function pickTooltips() { // gets up to 10 tooltips from elBag into visibleLink visibleLinks = [] let i, len = elBag.length for (i=0; i <= 9 && i < len; i++) { visibleLinks.push(elBag.shift()) } } function placeTooltips() { //console.log('placing '+visibleLinks.length+' tooltips', visibleLinks, elBag) for (let i = 0; i <= 8 && i < visibleLinks.length; i++) { createTooltip(visibleLinks[i], i+1) } if (visibleLinks.length === 10) { createTooltip(visibleLinks[9], 0) } } function getElements() { if (also_other_elements) { elBag = Array.from(document.querySelectorAll('div,a,button')) return } elBag = Array.from(document.querySelectorAll('a,button')) } function filterElements() { elBag = elBag.filter( (el) => isInViewport(el) && !(el.offsetWidth === 0 || el.offsetHeight === 0) && !(el.nodeName === "A" && el.getAttribute('href') == null) ) if (also_other_elements) elBag = elBag.filter((el) => el.tagName == "A" || el.tagName == "BUTTON" || window.getComputedStyle(el).cursor == "pointer" || el.type == "checkbox" || el.type == "radio") elBag = elBag.filter(isVisible) } function createTooltip(el, num) { let oldDisplay = el.style.display el.style.display = "inline-block" const rect = getCoords(el); el.style.display = oldDisplay const tooltip = document.createElement("div") tooltip.setAttribute("class", "displayText") tooltip.innerText = num tooltip.style.left = rect.right + 'px' tooltip.style.top = rect.top + 'px' document.body.appendChild(tooltip) return tooltip } function addCustomCSS() { let customStyles = document.createElement("style"); customStyles.setAttribute("type", "text/css"); let styles = ".displayText { position: absolute; top: 0; right: -16px; margin: 0; overflow: visible !important; width: min-content; background-color: " + backgroundColor + "; color: " + textColor + "; text-align: center; border-radius: 2px; padding: 0px 2px; line-height: 20px; font-size: 14px; z-index: 9999; }" customStyles.innerHTML = styles; document.getElementsByTagName("head")[0].appendChild(customStyles); } /*! * Determine if an element is in the viewport * (c) 2017 Chris Ferdinandi, MIT License, https://gomakethings.com * @param {Node} elem The element * @return {Boolean} Returns true if element is in the viewport */ var isInViewport = function (elem) { var distance = elem.getBoundingClientRect(); return ( distance.top >= 0 && distance.left >= 0 && distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) && distance.right <= (window.innerWidth || document.documentElement.clientWidth) ); } var isVisible = function (elem) { const elemCenter = { x: elem.getBoundingClientRect().left + elem.offsetWidth / 2, y: elem.getBoundingClientRect().top + elem.offsetHeight / 2 }; let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y); do { if (pointContainer === elem) return true; } while (pointContainer = pointContainer.parentNode); return false; } function getCoords(elem) { let box = elem.getBoundingClientRect(); return { top: box.top + window.pageYOffset, right: box.right + window.pageXOffset, bottom: box.bottom + window.pageYOffset, left: box.left + window.pageXOffset }; } addCustomCSS() setListeners() })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址