您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
使用 斜杠 ('/') 聚焦输入框,仅针对部分网页定制。
- // ==UserScript==
- // @name Slash To Search
- // @name:zh-CN 斜杠搜索 - Slash To Search
- // @namespace http://zhangmaimai.com/
- // @version 0.2
- // @description Type Slash ('/') to focus on search input, customized for some websites only.
- // @description:zh-CN 使用 斜杠 ('/') 聚焦输入框,仅针对部分网页定制。
- // @author Max
- // @license MIT
- // @match https://www.v2ex.com/*
- // @match https://stackoverflow.com/*
- // @match https://*.bilibili.com/*
- // @exclude https://message.bilibili.com/pages/nav/header_sync
- // @match https://www.douban.com/*
- // @match https://book.douban.com/*
- // @match https://*.wikipedia.org/*
- // @match https://gf.qytechs.cn/*
- // @exclude https://gf.qytechs.cn/*/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=gf.qytechs.cn
- // @grant none
- // @run-at document-idle
- // ==/UserScript==
- // @ts-check
- const { hostname } = window.location
- const secondLevel = hostname.split('.').slice(1).join('.')
- /** @typedef {Record<string, string>} StringMap */
- /**
- * Map series of URLs with same selector
- * @param {string[]} urls
- * @param {string} selector
- */
- const urlToSameSelector = (urls, selector) => Object.fromEntries(urls.map(url => [url, selector]))
- /**
- * Second level domain to a function to get selector by hostname
- * @type {Record<string, ()=>StringMap>}
- * */
- const getSelectorMap = {
- "bilibili.com": () => Object.assign({ "manga.bilibili.com": ".search-input" },
- urlToSameSelector([
- 'bilibili.com',
- 'www.bilibili.com',
- 't.bilibili.com',
- 'space.bilibili.com',
- ], '.nav-search-input')
- ),
- "v2ex.com": () => ({ 'www.v2ex.com': '#search', }),
- "stackoverflow.com": () => ({ 'stackoverflow.com': '.s-input' }),
- "douban.com": () => ({
- 'book.douban.com': '#inp-query',
- 'www.douban.com': '.inp input'
- }),
- "wikipedia.org": () => (urlToSameSelector([
- 'zh.wikipedia.org',
- 'en.wikipedia.org'
- ], '.cdx-text-input__input',
- )),
- "gf.qytechs.cn": () => ({
- "gf.qytechs.cn": ".home-search input"
- })
- }
- /**
- * @param {string} selector
- * @param {HTMLElement | Document | Element} root
- * @param {number} timeout
- * @returns {Promise<Element>}
- */
- const isElementLoaded = async (selector, root = document, timeout = 1e4) => {
- const start = Date.now()
- while (root.querySelector(selector) === null) {
- if (Date.now() - start > timeout) throw new Error(`Timeout: ${timeout}ms exceeded`)
- await new Promise(resolve => requestAnimationFrame(resolve))
- }
- return /** @type {HTMLElement} */(root.querySelector(selector))
- }
- /** @param {HTMLInputElement} search */
- const addSlashEvent = (search) => {
- const exceptActiveElement = ['INPUT', 'TEXTAREA']
- /** @type {(event: KeyboardEvent) => void } */
- const listener = (e) => {
- if (e.key !== '/' || exceptActiveElement.includes(document?.activeElement?.tagName || "")) return
- e.preventDefault()
- search.focus()
- }
- document.addEventListener('keydown', listener)
- }
- const main = async () => {
- const getSelector = () => {
- if (hostname in getSelectorMap) return getSelectorMap[hostname]()[hostname]
- if (!(secondLevel in getSelectorMap)) return
- const selectorMap = getSelectorMap[secondLevel]()
- return hostname in selectorMap ? selectorMap[hostname] : selectorMap['*']
- }
- const selector = getSelector()
- if (!selector) console.error(`No selector was found for url origin, downgrading to match <input> element with class contains "search"`)
- const searchElement = /** @type {HTMLDivElement?} */ (selector
- ? await isElementLoaded(selector)
- : await isElementLoaded('input[class*="search"]')
- )
- if (!searchElement || !(searchElement instanceof HTMLInputElement)) {
- throw Error(`Cannot detect search input element with selector ${selector}`)
- }
- addSlashEvent(searchElement)
- }
- main()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址