Google 高级搜索助手

在谷歌搜索页面顶部添加一个高级搜索表单

当前为 2024-09-01 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                    Advanced Search Assistant for Google
// @name:zh-CN              Google 高级搜索助手
// @namespace               https://github.com/ChinaGodMan/UserScripts
// @version 0.1.9.31
// @description             Add an advanced search form to the top of the page
// @description:zh-CN       在谷歌搜索页面顶部添加一个高级搜索表单
// @author                         shiquda  &人民的勤务员 <[email protected]>
// @match                   *://www.google.com/search*
// @include                 *://*google*/search*
// @grant                   GM_addStyle
// @grant                   GM_setValue
// @grant                   GM_getValue
// @license                 MIT
// @icon                      https://github.com/ChinaGodMan/UserScripts/raw/main/docs/icon/Scripts%20Icons/Google-advance-search.png
// @supportURL              https://github.com/ChinaGodMan/UserScripts/issues
// @homepageURL   https://github.com/ChinaGodMan/UserScripts
// ==/UserScript==

(function () {
    "use strict"
    let isMobile = false
    if (
        navigator.userAgent.match(/Android/i) ||
        navigator.userAgent.match(/webOS/i) ||
        navigator.userAgent.match(/iPhone/i) ||
        navigator.userAgent.match(/iPad/i) ||
        navigator.userAgent.match(/iPod/i) ||
        navigator.userAgent.match(/BlackBerry/i) ||
        navigator.userAgent.match(/Windows Phone/i)
    ) {
        // On mobile device
        isMobile = true
    }

    let isDarkMode = false

    try {
        if (
            window.matchMedia &&
            window.matchMedia("(prefers-color-scheme: dark)").matches
        ) {
            // Dark mode is enabled
            isDarkMode = true
            console.log("Dark mode is enabled.")
        }
    } catch (error) {
        console.log("Failed to determine the color mode.", error)
    }

    const userLanguage = "" // You can set your language config here manually. 'zh-CN' & 'en' are supported now.

    const supportedLanguages = ["zh-CN", "en"]

    const translation = {
        as_q: {
            "zh-CN": "搜索字词:",
            en: "Search word:",
        },
        as_epq: {
            "zh-CN": "与以下字词完全匹配:",
            en: "Match the following words exactly:",
        },
        as_oq: {
            "zh-CN": "包含以下任意字词:",
            en: "Contains any of the following words:",
        },
        as_eq: {
            "zh-CN": "排除以下字词:",
            en: "Exclude the following words:",
        },
        as_nlo: {
            "zh-CN": "包含的数字范围:从",
            en: "Number range: from",
        },
        as_nhi: {
            "zh-CN": "到:",
            en: "to:",
        },
        lr: {
            "zh-CN": "语言:",
            en: "Language:",
        },
        cr: {
            "zh-CN": "地区:",
            en: "Region:",
        },
        as_qdr: {
            "zh-CN": "最后更新时间:",
            en: "Last update time:",
        },
        as_sitesearch: {
            "zh-CN": "网站或域名:",
            en: "Website or domain:",
        },
        as_occt: {
            "zh-CN": "字词出现位置:",
            en: "Word position:",
        },
        as_filetype: {
            "zh-CN": "文件类型:",
            en: "File type:",
        },
        tbs: {
            "zh-CN": "使用权限:",
            en: "Usage rights:",
        },
        advancedSearch: {
            "zh-CN": "高级搜索",
            en: "Advanced Search",
        },
        search: {
            "zh-CN": "搜索",
            en: "Search",
        },
        clear: {
            "zh-CN": "清空",
            en: "Clear",
        },
        as_qdr_select: {
            "": {
                "zh-CN": "请选择",
                en: "Please select",
            },
            d: {
                "zh-CN": "一天内",
                en: "Past 24 hours",
            },
            w: {
                "zh-CN": "一周内",
                en: "Past week",
            },
            m: {
                "zh-CN": "一月内",
                en: "Past month",
            },
            y: {
                "zh-CN": "一年内",
                en: "Past year",
            },
        },
        as_occt_select: {
            "": {
                "zh-CN": "请选择",
                en: "Please select",
            },
            title: {
                "zh-CN": "网页标题中",
                en: "In the title of the web page",
            },
            body: {
                "zh-CN": "网页正文中",
                en: "In the body of the web page",
            },
            url: {
                "zh-CN": "网页网址中",
                en: "In the URL of the web page",
            },
            links: {
                "zh-CN": "指向网页的链接中",
                en: "In the links to the web page",
            },
        },
    }
    const style = `
    #advancedSearchToggleButton {
        margin-right: 10px;
        border: none;
        border-radius: 5px;
        background-color: #007bff;
        color: #fff;
        font-size: 14px;
        font-weight: bold;
        margin: 10px;
    }


    #advancedSearchFormContainer {
        position: fixed;
        ${isMobile ? "top: 150px;" : "top: 130px;"}
        ${isMobile ? "left: 15px;" : "left: 30px;"}
        display: none;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 5px;
        font-size: 14px;
        font-weight: bold;
        ${isDarkMode
            ? "background-color: rgba(0, 0, 0, 1);"
            : "background-color: rgba(255, 255, 255, 1);"
        }
        ${isMobile ? "column-count: 2;" : ""} /* 在移动设备上分为两列 */
        z-index: 1000; // Make sure the button is on top of the search bar
    }


    #advancedSearchFormContainer label {
        display: block;
        margin-top: 5px;
    }


    #advancedSearchFormContainer input[type="text"] {
        margin-top: 5px;
        padding: 5px;
        border: 1px solid #ccc;
        border-radius: 5px;
    }

    #advancedSearchFormContainer select {
        margin-top: 5px;
        padding: 5px;
        border-radius: 5px;
    }

    #advancedSearchFormContainer button {
        border: none;
        border-radius: 5px;
        background-color: #007bff;
        color: #fff;
        font-size: 14px;
        font-weight: bold;
        margin: 20px;
    }
    `
    GM_addStyle(style)

    let language = "en"
    if (userLanguage.length > 0) { // userLanguage is set manually
        if (supportedLanguages.includes(userLanguage)) {
            language = userLanguage
        } else {
            console.log(`Unsupported language: ${userLanguage}`)
        }
    } else {
        // Check if any of the user's preferred languages are supported
        language =
            navigator.languages
                .map((lang) => lang.split("-")[0]) // Consider only the language part, not the region
                .map((lang) => supportedLanguages.find((supportedLang) => supportedLang.split("-")[0] === lang)) // Match with the supported languages
                .filter(Boolean) // Remove undefined values
                .shift() // Take the first matched language
            || "en" // Default to 'en' if no match found
        console.log(`Here is the language: ${language}`)
    }

    // Create user interface
    const toggleButton = document.createElement("button")
    toggleButton.className = "nfSF8e"
    toggleButton.textContent = translation["advancedSearch"][language]
    toggleButton.id = "advancedSearchToggleButton"
    if (isMobile) {
        document.querySelector(".Fh5muf").appendChild(toggleButton)
    } else {
        document.querySelector(".logo").appendChild(toggleButton)
        const searchContainer = document.querySelector(".RNNXgb")
        searchContainer.appendChild(toggleButton)
    }



    // Add minimal style for positioning
    toggleButton.style.marginTop = "5px" // Add some space above the button
    toggleButton.style.marginLeft = "5px" // Add some space to the left of the button
    // Add any additional styles to match the search bar's height or other styling

    const formContainer = document.createElement("div")
    formContainer.id = "advancedSearchFormContainer"
    document.body.appendChild(formContainer)

    //
    const form = document.createElement("form")
    formContainer.appendChild(form)

    const params = {
        as_q: translation["as_q"][language],
        as_epq: translation["as_epq"][language],
        as_oq: translation["as_oq"][language],
        as_eq: translation["as_eq"][language],
        as_nlo: translation["as_nlo"][language],
        as_nhi: translation["as_nhi"][language],
        // 'lr': translation['lr'][language],
        // 'cr': translation['cr'][language],
        as_qdr: {
            name: translation["as_qdr"][language],
            options: {
                "": translation["as_qdr_select"][""][language],
                d: translation["as_qdr_select"]["d"][language],
                w: translation["as_qdr_select"]["w"][language],
                m: translation["as_qdr_select"]["m"][language],
                y: translation["as_qdr_select"]["y"][language],
            },
        },
        as_sitesearch: translation["as_sitesearch"][language],
        as_occt: {
            name: translation["as_occt"][language],
            options: {
                "": translation["as_occt_select"][""][language],
                title: translation["as_occt_select"]["title"][language],
                body: translation["as_occt_select"]["body"][language],
                url: translation["as_occt_select"]["url"][language],
                links: translation["as_occt_select"]["links"][language],
            },
        },
        as_filetype: translation["as_filetype"][language],
        // 'tbs': translation['tbs'][language],
    }

    for (const param in params) {
        if (typeof params[param] === "object") {
            const label = document.createElement("label")
            label.textContent = params[param].name
            const select = document.createElement("select")
            select.name = param

            Object.keys(params[param]["options"]).forEach((option) => {
                const optionElement = document.createElement("option")
                optionElement.value = option
                optionElement.textContent = params[param]["options"][option]
                select.appendChild(optionElement)
            })

            form.appendChild(label)
            form.appendChild(select)
            form.appendChild(document.createElement("br"))
            continue
        }
        const label = document.createElement("label")
        label.textContent = params[param]
        const input = document.createElement("input")
        input.name = param
        input.type = "text"
        form.appendChild(label)
        form.appendChild(input)
        form.appendChild(document.createElement("br"))
    }

    const searchButton = document.createElement("button")
    searchButton.textContent = translation["search"][language]
    form.appendChild(searchButton)

    // Add a clear button to reset the form
    const clearButton = document.createElement("button")
    clearButton.textContent = translation["clear"][language]
    clearButton.addEventListener("click", function (event) {
        event.preventDefault()
        form.reset()
    })
    form.appendChild(clearButton)

    // Load saved data and fill the form when opening a new page
    window.addEventListener("load", function () {
        for (const param in params) {
            const savedValue = GM_getValue(param)
            if (savedValue) {
                form[param].value = savedValue
            }
        }
    })

    // Save form data to Greasemonkey storage
    form.addEventListener("input", function () {
        for (const param in params) {
            GM_setValue(param, form[param].value)
        }
    })

    // Toggle the form display
    toggleButton.addEventListener("click", function (event) {
        event.preventDefault()
        let status = formContainer.style.display
        status = status === "none" || status === "" ? "block" : "none"
        formContainer.style.display = status
    })

    // Submit the form
    form.addEventListener("submit", function (event) {
        event.preventDefault()
        const searchParams = new URLSearchParams()
        for (const param in params) {
            const value = form[param].value
            if (value) {
                searchParams.set(param, value)
            }
        }
        const searchUrl =
            "https://www.google.com/search?" + searchParams.toString()
        window.location.href = searchUrl
    })
})()