Greasy Fork 还支持 简体中文。

Easy Keyboard Link Opener

Open links and click buttons easily using only the keyboard!

目前為 2021-03-22 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Easy Keyboard Link Opener
// @description  Open links and click buttons easily using only the keyboard!
// @version      0.2.8
// @namespace    https://greasyfork.org/en/users/55535-sllypper
// @author       sllypper
// @match        *://*/*
// @grant        none
// @todo         add TAB to cycle between links
// ==/UserScript==

(function() {
    'use strict';

    // on the American keyboard layout, switch it to "`" instead
    // or whatever other key you want
    const HOTKEY = "'"

    // Colors
    const textColor = "#fff"
    const backgroundColor = "#555"

    //

    let isSet = false;
    let visibleLinks = [];
    //let page;

    function setListeners() {
        document.addEventListener("keydown", event => {
            if (!isSet) {
                if (event.key === HOTKEY && event.ctrlKey) {
                    actionHot();
                }
            } else {
                if (event.key >= 0 && event.key < 10) {
                    let chosen
                    chosen = event.key === "0" ? visibleLinks[9] : visibleLinks[parseInt(event.key)-1]
                    chosen.click()
                }
                /*else if (event.key === "Tab") {

                }*/
                //console.log(event.key)
                clearAction()
            }
        })
    }

    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 actionHot() {
        let links = Array.from(document.querySelectorAll('a,button')).filter(
            (el) => isInViewport(el) && !(el.offsetWidth === 0 || el.offsetHeight === 0) && !(el.nodeName === "A" && el.getAttribute('href') == null)
        )

        let numlinks = 0

        for (const el of links) {
            // create 1-9 tooltips then create tooltip 0 and break
            visibleLinks.push(el)
            if (numlinks >= 9) {
                createTooltip(el, 0)
                break;
            }
            numlinks += 1
            createTooltip(el, numlinks)
        }
        isSet = true
    }

    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)
        );
    }

    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()

})();