Advanced Search Assistant for Google

Add an advanced search form to the top of the page

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name                    Advanced Search Assistant for Google
// @name:zh-CN              Google 高级搜索助手
// @namespace               http://tampermonkey.net/
// @version                 0.1.8
// @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 {
    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);
  }

  // Use the parent element of the search bar
  const searchContainer = document.querySelector(".RNNXgb"); // Replace with actual selector

  // Assuming `toggleButton` is your "Advanced Search" button already created
  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;
  });
})();