Google 高级搜索助手

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

当前为 2023-11-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name                    Advanced Search Assistant for Google
// @name:zh-CN              Google 高级搜索助手
// @namespace               http://tampermonkey.net/
// @version                 0.1.7
// @description             Add an advanced search form to the top of the page
// @description:zh-CN       在谷歌搜索页面顶部添加一个高级搜索表单
// @author                  shiquda
// @namespace               https://github.com/shiquda/shiquda_UserScript
// @supportURL              https://github.com/shiquda/shiquda_UserScript/issues
// @match                   *://www.google.com/search*
// @include                 *://*google*/search*
// @grant                   GM_addStyle
// @grant                   GM_setValue
// @grant                   GM_getValue
// @license                 MIT
// ==/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 {
        let logoImg = document.querySelector('#logo')?.querySelector('img') ? document.querySelector('#logo')?.querySelector('img') : document.querySelector('#qslc')?.querySelector('img'); //
        if (logoImg.src.match(/light/)) {
            // Dark mode is enabled
            isDarkMode = true;
        }
    }
    catch {
        console.log("Failed to determine the color mode.")
    }


    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;' : ''} /* 在移动设备上分为两列 */
    }


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

    const language = supportedLanguages.includes(userLanguage) ? userLanguage : supportedLanguages.includes(navigator.language) ? navigator.language : 'en'
    // 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 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;
    });
}
)();