Google & baidu Switcher (ALL in One)

最新版本的集合谷歌、百度、必应的搜索引擎跳转工具,必应跳转可在菜单进行自定义设置。此版本无外部脚本调用,更快速和准确的进行按钮定位,显示速度大大提升。如有异常请清空浏览器缓存,再次载入使用,感谢使用!

Od 21.11.2020.. Pogledajte najnovija verzija.

// ==UserScript==
// @name            Google & baidu Switcher (ALL in One)
// @name:en         Google & baidu & Bing Switcher (ALL in One)
// @name:zh         谷歌搜索、百度搜索、必应搜索的聚合跳转集合工具
// @name:zh-CN      谷歌搜索、百度搜索、必应搜索的聚合跳转集合工具
// @version         2.0.20201121.2
// @author          F9y4ng
// @description     最新版本的集合谷歌、百度、必应的搜索引擎跳转工具,必应跳转可在菜单进行自定义设置。此版本无外部脚本调用,更快速和准确的进行按钮定位,显示速度大大提升。如有异常请清空浏览器缓存,再次载入使用,感谢使用!
// @description:en  The latest version of Google, Baidu, Bing`s search engine, Bing option can be switched in the menu settings. If any exception or error, please clear the browser cache and reload it. again. Thank you!
// @namespace       https://openuserjs.org/scripts/t3xtf0rm4tgmail.com/Google_baidu_Switcher_(ALL_in_One)
// @feedback-url    https://greasyfork.org/zh-CN/scripts/12909-google-baidu-switcher-all-in-one/feedback
// @icon            https://www.google.com/favicon.ico
// @include         *://encrypted.google.*/search*
// @include         *://*.google*/search*
// @include         *://*.google*/webhp*
// @include         *://*.baidu.com/*
// @include         *://*.bing.com/*
// @compatible      Chrome
// @compatible      Firefox
// @compatible      Opera
// @compatible      Safari
// @grant           GM_info
// @grant           GM_registerMenuCommand
// @grant           GM_unregisterMenuCommand
// @grant           GM_openInTab
// @grant           GM_getValue
// @grant           GM_setValue
// @grant           GM_notification
// @license         GPL-3.0-only
// @create          2015-10-07
// @run-at          document-start
// ==/UserScript==

(! function() {

  'use strict';

  let isdebug = false;
  let debug = isdebug ? console.log.bind(console) : function() {};
  const defaultConfig = {
    Version: GM_info.script.version,
    lastRuntime: (new Date()).toLocaleString('chinese', {
      hour12: false
    }),
  };

  console.log("%c[GB-Init]%c\nVersion: " + defaultConfig.Version + "\nlastRuntime: " + defaultConfig.lastRuntime, "font-weight:bold;color:dodgerblue", "color:0");

  (! function() {

    let CONST = {
      isSecurityPolicy: false,
      isUseBing: (function() {
        let temp = GM_getValue('_if_Use_Bing_');
        if (temp === null || typeof(temp) === 'undefined') {
          GM_setValue('_if_Use_Bing_', false);
          console.log("%c[GB-Warning]%c\nThis Is Your First Visit, The Bing Search Button Will Not Be Inserted By Default.", "font-weight:bold;color:salmon", "color:1");
          return false;
        } else {
          return temp;
        }
      })(),
    };

    debug('//-> ' + CONST.isUseBing);

    let curretSite = {
      SiteTypeID: 1,
      SiteName: "",
      SplitName: "",
      MainType: "",
      HtmlCode: "",
      StyleType: "",
    };

    const listSite = {
      baidu: {
        SiteTypeID: 1,
        SiteName: "Baidu",
        SplitName: "tn",
        MainType: ".s_btn_wr",
        HtmlCode: CONST.isUseBing ?
          `<span id="ggyx">
          <input type="button" title="Google一下" value="Google"/>
          </span>
          <span id="bbyx">
            <input type="button" title="Bing一下" value="Bing®"/>
          </span>` : `<span id="ggyx">
            <input type="button" title="Google一下" value="Google一下"/>
          </span>`,
        StyleCode: CONST.isUseBing ?
          `#form {
            white-space: nowrap;
          }
          #u {
            z-index: 1!important;
          }
          #for_Baidu #ggyx, #for_Baidu #bbyx {
            margin-left: 2px;
          }
          #ggyx input, #bbyx input {
            background: #4e71f2;
            border-radius: 10px;
            cursor: pointer;
            height: 40px;
            color: #fff;
            width: 80px;
            border: 1px solid #2d78f4;
            font-size: 16px;
            font-weight:bold;
          }
          #ggyx input:hover, #bbyx input:hover {
            background: #4662D9;
            border: 1px solid #2d78f4;
          }` : `#for_Baidu {
            margin-left: 6px
          }
          #ggyx input {
            background: #4e71f2;
            border-radius: 10px;
            cursor: pointer;
            height: 40px;
            color: #fff;
            width: 112px;
            border: 1px solid #2d78f4;
            font-size: 16px
          }
          #ggyx input:hover {
            background: #4662D9;
            border: 1px solid #2d78f4;
          }`,
      },
      google: {
        SiteTypeID: 2,
        SiteName: "Google",
        SplitName: "tbm",
        MainType: "form button[type='submit']",
        HtmlCode: CONST.isUseBing ?
          `<span id="bdyx">
            <input type="button" title="百度一下" value="百度一下"/>
          </span>
          <span id="bbyx">
            <input type="button" title="Bing一下" value="Bing一下"/>
          </span>` : `<span id="bdyx">
            <input type="button" title="百度一下" value="百度一下"/>
          </span>`,
        StyleCode: CONST.isUseBing ?
          `#for_Google {
            margin: 3px 4px 0 -5px;
          }
          #for_Google #bbyx{
            margin-top:-1px;
          }
          #bdyx input, #bbyx input {
            cursor: pointer;
            border: 1px solid transparent;
            background: #1a73e8;
            box-shadow: none;
            border-radius: 24px;
            width: 90px;
            height: 38px;
            font-size: 15px;
            font-weight: bold;
            color: #fff
          }
          #bdyx input:hover, #bbyx input:hover {
            background: #2b7de9;
          }` : `#for_Google {
            margin: 3px 4px 0 -5px;
          }
          #bdyx input {
            cursor: pointer;
            border: 1px solid transparent;
            background: #1a73e8;
            box-shadow: none;
            border-radius: 24px;
            width: 90px;
            height: 38px;
            font-size: 14px;
            font-weight: bold;
            color: #ffffff;
          }
          #bdyx input:hover {
            background: #2b7de9;
          }`,
      },
      bing: {
        SiteTypeID: 3,
        SiteName: "Bing",
        SplitName: "/",
        MainType: "#sb_go_par",
        HtmlCode: `
          <span id="bdyx">
            <input type="button" title="百度一下" value="百度"/>
          </span>
          <span id="ggyx">
            <input type="button" title="Google一下" value="Google"/>
          </span>`,
        StyleCode: `
          #for_Bing {
            height: 44px;
            width: 120px;
            margin: 2px 10px 2px 0;
          }
          #bdyx input, #ggyx input {
            cursor: pointer;
            width: auto 60px;
            height: 36px;
            background-color: #f5f5f5;
            border: 1px solid #dddddd;
            color: #666666;
            margin-left:-2px;
          }
          #bdyx input:hover, #ggyx input:hover {
            transition:border linear .1s,box-shadow linear .3s;
            box-shadow:0 0 8px #4e4e4e;
          }`,
      },
      other: {
        SiteTypeID: 0,
      }
    };

    let newSiteType = {
      BAIDU: listSite.baidu.SiteTypeID,
      GOOGLE: listSite.google.SiteTypeID,
      BING: listSite.bing.SiteTypeID,
      OTHERS: 4
    };

    debug('//-> 程序开始进入执行阶段');

    if (location.host.includes(".baidu.com")) {
      curretSite = listSite.baidu;
    } else if (location.host.includes("google")) {
      curretSite = listSite.google;
    } else if (location.host.includes("bing")) {
      curretSite = listSite.bing;
    } else {
      curretSite = listSite.other;
    }

    if ((curretSite.SiteTypeID === newSiteType.GOOGLE && location.href.replace(/tbm=(isch|lcl|shop|flm|nws|vid|fin)/, "") !== location.href) ||
      (curretSite.SiteTypeID === newSiteType.BING && location.href.replace(/maps\?/, "") !== location.href) ||
      (curretSite.SiteTypeID === newSiteType.BAIDU && location.href.replace(/tn=(baiduimage|ikaslist|vsearch)/, "") !== location.href)) {
      console.log("%c[GB-Prohibit]%c\nCaused By: %c%s Security Policy%c.", "font-weight:bold;color:indigo", "color:0", "color:darkred", curretSite.SiteName, "color:0");
      CONST.isSecurityPolicy = true;
    }

    let menuManager = {

      menuDisplay: function() {

        let _Use_Bing_ = CONST.isUseBing;
        let _use_Bing_ID, in_Use_feedBack_ID;

        registerMenuCommand();
        debug('//-> ' + _Use_Bing_);

        function registerMenuCommand() {
          let _Use_Bing__;
          if (in_Use_feedBack_ID) {
            GM_unregisterMenuCommand(_use_Bing_ID);
            GM_unregisterMenuCommand(in_Use_feedBack_ID);
          }

          if (_Use_Bing_) {
            _Use_Bing__ = "√";
          } else {
            _Use_Bing__ = "×";
          }

          _use_Bing_ID = GM_registerMenuCommand(` [${_Use_Bing__}] \u6dfb\u52a0 Bing\u641c\u7d22\u8df3\u8f6c`,
            function() {
              inUse_switch(_Use_Bing_, '_if_Use_Bing_', 'Bing\u641c\u7d22\u8df3\u8f6c');
            });

          in_Use_feedBack_ID = GM_registerMenuCommand('\u4f7f\u7528\u53cd\u9988',
            function() {
              window.GM_openInTab('https://greasyfork.org/zh-CN/scripts/12909-google-baidu-switcher-all-in-one/feedback', {
                active: true,
                insert: true,
                setParent: true
              });
            });

          console.log("%c[GB-Status]%c\nLet The Bing Search Engine Insert: %c%s%c", "font-weight:bold;color:darkorange", "color:0", "font-weight:bold;color:red", (function() {
            return (_Use_Bing_).toString().toUpperCase();
          })(), "font-weight:normal;color:0");
        }

        function inUse_switch(_status, Name, Tips) {
          if (_status) {
            GM_setValue(`${Name}`, false);
            GM_notification(`\u60a8\u5df2\u5173\u95ed${Tips}\uff01\n\n\uff083\u79d2\u540e\u5c06\u81ea\u52a8\u5237\u65b0\u7f51\u9875\uff09`);
          } else {
            GM_setValue(`${Name}`, true);
            GM_notification(`\u60a8\u5df2\u5f00\u542f${Tips}\uff01\n\n\uff083\u79d2\u540e\u5c06\u81ea\u52a8\u5237\u65b0\u7f51\u9875\uff09`);
          }
          registerMenuCommand();
          window.setTimeout(function() {
              window.location.reload();
            },
            3000);
        }
      },
      init: function() {
        this.menuDisplay();
      }
    };

    let searchManager = {
      doSwitch: function() {

        try {
          let nodeName = '#for_' + curretSite.SiteName;
          if (curretSite.SiteTypeID !== newSiteType.OTHERS) {
            RAFInterval(function() {
              if (document.querySelector(nodeName) === null) {
                if (CONST.isSecurityPolicy) return;
                insertSearchButton();
                if (curretSite.SiteTypeID === newSiteType.GOOGLE) {
                  debug('//-> 开启Google滚动判断');
                  document.querySelector(nodeName).parentNode.style = 'width:700px!important';
                  scrollButton(nodeName + ' #bdyx input');
                  scrollButton(nodeName + ' #bbyx input');
                }
              }
            }, 500);
          }
        } catch (e) {
          debug('//-> ' + e.name);
        }

        function scrollButton(paraName) {
          let oDiv = document.querySelector(paraName),
            H = 0,
            Y = oDiv;
          while (Y) {
            H += Y.offsetTop;
            Y = Y.offsetParent;
          }
          document.addEventListener('scroll', function() {
            let s = document.body.scrollTop || document.documentElement.scrollTop;
            debug('//-> H-' + H);
            debug('//-> S-' + s);
            if (s > H + 35) {
              oDiv.style = "height:26px!important;font-size:13px;font-weight:normal";
            } else {
              oDiv.style = "";
            }
          });
        }

        function insertSearchButton() {
          const getTarget = curretSite.MainType;
          const doHtml = curretSite.HtmlCode;
          const doStyName = "InsertTo" + curretSite.SiteName;
          const doStyle = curretSite.StyleCode;
          let Target = document.querySelector(getTarget);
          let userSpan = document.createElement("span");
          userSpan.id = "for_" + curretSite.SiteName;
          userSpan.innerHTML = doHtml;

          if (document.querySelector('#' + userSpan.id) === null && getSearchValue().length > 0) {
            // const vim = GetUrlParam(curretSite.SplitName);
            // debug('//-> ' + vim);
            // if (vim.match(/(nws|vid|fin)/)) {
            //   Target = Target.lastChild;
            // }
            insterAfter(userSpan, Target);
            addStyle(doStyle, doStyName, "head", true);

            document.querySelectorAll('#ggyx, #bbyx, #bdyx').forEach(function(per) {
              per.addEventListener("click", function() {
                let gotoUrl = "about:blank";
                switch (per.id) {
                  case "ggyx":
                    gotoUrl = "https://www.google.com/search?newwindow=1&hl=zh-CN&source=hp&q=";
                    break;
                  case "bbyx":
                    gotoUrl = "https://cn.bing.com/search?q=";
                    break;
                  case "bdyx":
                    gotoUrl = "https://www.baidu.com/s?ie=utf-8&rqlang=cn&wd=";
                    break;
                  default:
                    break;
                }
                debug('//-> ' + per.id);
                window.GM_openInTab(gotoUrl + getSearchValue(), {
                  active: true,
                  insert: true,
                  setParent: true
                });
              });
            });
          }
        }

        function insterAfter(newElement, targetElement) {
          let parent = targetElement.parentNode;
          if (parent.lastChild === targetElement) {
            parent.appendChild(newElement);
          } else {
            parent.insertBefore(newElement, targetElement.nextSibling);
          }
        }

        function addStyle(css, className, addToTarget, isReload, initType) {
          RAFInterval(function() {
            let addTo = document.querySelector(addToTarget);
            if (typeof(addToTarget) === "undefined") {
              addTo = (document.head || document.body || document.documentElement || document);
            }
            isReload = isReload || false;
            initType = initType || "text/css";
            if (typeof(addToTarget) === "undefined" || (typeof(addToTarget) !== "undefined" && document.querySelector(addToTarget) !== null)) {
              if (isReload === true) {
                safeRemove("." + className);
              } else if (isReload === false && document.querySelector("." + className) !== null) {
                return true;
              }
              let cssNode = document.createElement("style");
              if (className !== null) {
                cssNode.className = className;
              }
              cssNode.setAttribute("type", initType);
              cssNode.innerHTML = css;
              try {
                addTo.appendChild(cssNode);
              } catch (e) {
                debug('//-> ' + e.name);
              }
              return true;
            }
          }, 20, true);
        }

        function safeRemove(Css) {
          safeFunction(() => {
            let removeNodes = document.querySelectorAll(Css);
            for (let i = 0; i < removeNodes.length; i++) {
              removeNodes[i].remove();
            }
          });
        }

        function safeFunction(func) {
          try {
            func();
          } catch (e) {
            debug('//-> ' + e.name);
          }
        }

        function GetUrlParam(paraName) {
          const url = document.location.toString();
          let arrObj = url.split("?");
          if (arrObj.length > 1) {
            let arrPara = arrObj[1].split("&");
            let arr;
            for (let i = 0; i < arrPara.length; i++) {
              arr = arrPara[i].split("=");
              if (arr !== null && arr[0] === paraName) {
                return arr[1];
              }
            }
            return "";
          } else {
            return "";
          }
        }

        function getSearchValue() {
          let kvl = location.search.substr(1).split("&");
          let searchV = "";
          for (let i = 0; i < kvl.length; i++) {
            let value = kvl[i].replace(/^(wd|query|q)=/, "");
            if (value !== kvl[i]) {
              searchV = value;
            }
          }
          searchV = searchV.replace("+", " ");
          return searchV;
        }

        function RAFInterval(callback, period, runNow) {
          const needCount = period / 1000 * 60;
          let times = 0;
          if (runNow === true) {
            const shouldFinish = callback();
            if (shouldFinish) {
              return;
            }
          }

          function step() {
            if (times < needCount) {
              times++;
              requestAnimationFrame(step);
            } else {
              const shouldFinish = callback() || false;
              if (!shouldFinish) {
                times = 0;
                requestAnimationFrame(step);
              } else {
                return;
              }
            }
          }
          requestAnimationFrame(step);
        }
      },

      init: function() {
        debug("//-> 执行跳转按钮");
        this.doSwitch();
        debug("//-> 调用加载菜单选项");
        menuManager.init();
      }
    };

    (function() {
      try {
        searchManager.init();
      } catch (e) {
        console.error("%c[GB-Error]%c\nConsole: %c%s%c.", "font-weight:bold;color:red", "color:0", "font-weight:bold;color:darkred", e, "color:0");
      } finally {
        console.log("%c[GB-Switch]%c\nNow Using The Search Engine: %c%s%c.", "font-weight:bold;color:Green", "color:0", "font-weight:bold;color:darkorange", (function() {
          return curretSite.SiteName.toString();
        })(), "font-weight:normal;color:0");
      }
    }());

  }());

}());