HjklNavigation

Shortcuts for Google Search result. j/k to move focus, l/h to open in new/background tab.

目前为 2021-05-02 提交的版本。查看 最新版本

// ==UserScript==
// @name         HjklNavigation
// @namespace    com.gmail.fujifruity.greasemonkey
// @version      1.5.2
// @description  Shortcuts for Google Search result. j/k to move focus, l/h to open in new/background tab.
// @author       fujifruity
// @include      https://www.google.com/search*
// @grant        GM.openInTab
// @license      MIT
// ==/UserScript==

{
    const items = [...document.querySelectorAll('#rso .g')].filter(e => e.className == 'g')

    const open = isBackground => {
        const url = findCurrentItem().querySelector('a').href
        GM.openInTab(url, isBackground)
    }
    const tag = "hjklNavigationCurrentItem"
    const findCurrentItem = () => items.find(e => e.hasAttribute(tag))

    const moveCursor = step => {
        const currentItem = findCurrentItem()
        const r = currentItem.getBoundingClientRect();
        const isVisible = 0 < r.top && r.top < window.innerHeight || 0 < r.bottom && r.bottom < window.innerHeight
        if (!isVisible) {
            const dist = e => {
                const r = e.getBoundingClientRect()
                return Math.abs(window.innerHeight - (r.top + r.bottom))
            }
            const nearest = items.reduce((acc,e) => dist(acc) < dist(e) ? acc : e )
            select(nearest)
            return
        }
        const nextIdx = (items.indexOf(currentItem) + step + items.length) % items.length
        select(items[nextIdx])
    }
    const highlight = e => {
        e.style.backgroundColor = 'lightyellow'
        e.setAttribute(tag, '')
    }
    const select = item => {
        // deselect current item
        const currentItem = findCurrentItem()
        currentItem?.setAttribute('style', "background-color: null;")
        currentItem?.removeAttribute(tag)
        highlight(item)
        item.scrollIntoView({ behavior: "smooth", block: "center" })
    }
    highlight(items[0])

    window.addEventListener('keydown', event => {
        if (event.target.tagName == "INPUT" || event.ctrlKey || event.altKey) return
        switch (event.key) {
            case 'j': {
                moveCursor(+1)
                break
            }
            case 'k': {
                moveCursor(-1)
                break
            }
            case 'l': {
                open(false)
                break
            }
            case 'h': {
                open(true)
                break
            }
        }
    })

}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址