Greasy Fork 还支持 简体中文。

搜索引擎壹鍵切換 soTab

在常用的搜索引擎頁面中添加互相切換的按鈕,包括圖片、視頻、知道、學術搜索。

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name                soTab - Search Engine Switcher
// @name:zh-CN          搜索引擎一键切换 soTab
// @name:zh-TW          搜索引擎壹鍵切換 soTab
// @description         Add links to each other in search engines. Including multiple search modes.
// @description:zh-CN   在常用的搜索引擎页面中添加互相切换的按钮,包括图片、视频、知道、学术搜索。
// @description:zh-TW   在常用的搜索引擎頁面中添加互相切換的按鈕,包括圖片、視頻、知道、學術搜索。

// @author              Moshel
// @namespace           http://hzy.pw
// @homepageURL         http://hzy.pw/p/1849
// @supportURL          https://github.com/h2y/link-fix
// @icon                http://q.qlogo.cn/qqapp/100229475/F1260A6CECA521F6BE517A08C4294D8A/100
// @license             GPL-3.0

// @match               *.baidu.com/*
// @exclude             *.baidu.com/link?*
// @match               *.so.com/*
// @match               *.bing.com/*
// @match               *.zhihu.com/search?*
// @match               *.soku.com/*
// @match               *.sogou.com/*
// @match               https://*.google.com/*
// @match               https://*.google.com.hk/*
// @grant               GM_addStyle
// @grant               window.onurlchange
// @run-at              document_end


// @date                11/25/2022
// @modified            12/18/2022
// @version             1.5.2.00
// ==/UserScript==
(function () {
  function soTabInit() {
    if (top !== window) {
      console.log('soTab! not top window');
      return;
    }

    // 判断搜索引擎,将仅使用hostname适配
    const sites = [
      'baidu',
      'bing',
      'so.com',
      '',
      'zhihu',
      'google',
      'soku',
      'sogou',
    ];
    const sitesName = [
      '百度',
      '必应',
      '好搜',
      'ALLSO',
      '知乎',
      '谷歌',
      '搜库',
      '搜狗',
    ];
    let siteID = -1;

    for (const site of sites) {
      if (site && location.hostname.includes(site)) {
        siteID = sites.indexOf(site);
        break;
      }
    }

    if (siteID === -1) {
      console.log("soTab can't match site.");
      return;
    }

    // 判断搜索类型,使用href适配
    let kind = [];
    // eslint-disable-next-line default-case
    switch (siteID) {
      case 0:
        kind = [
          'www.baidu',
          'image.baidu',
          'zhidao.baidu.com/search',
          'v.baidu',
          'xueshu.baidu.com/s',
        ];
        break;
      case 1: // bing
        kind = [
          '.com/search',
          '.com/images',
          '.com/knows/search',
          '.com/videos',
          '/academic/search',
        ];
        break;
      case 2:
        kind = [
          'www.so',
          'image.so',
          'wenda.so.com/search',
          'video.so',
        ];
        break;
      case 4: // zhihu
        kind = ['', '', '.com/search'];
        break;
      case 5: // google
        kind = ['', 'tbm=isch', '', 'tbm=vid', 'scholar.google'];
        break;
      case 6:
        // kind[3] = "soku";
        break;
      case 7: // sogou
        kind = [
          ['/web?', '/sogou?', 'weixin.sogou', 'english.sogou'],
          'pic.sogou',
          [
            'interation=196636',
            'mingyi.sogou',
            'wenwen.sogou',
            '.com/zhihu',
          ],
          'v.sogou',
          '.com/xueshu',
        ];
        break;
    }
    // 0:normal  1:pic  2:zhidao  3:video  4:xueshu
    let kindID = -1;
    for (let i = 0; i < kind.length; i++) {
      if (Array.isArray(kind[i])) {
        // 数组形式
        for (let j = 0; j < kind[i].length; j++) {
          if (location.href.includes(kind[i][j])) {
            kindID = i;
            break;
          }
        }
        if (kindID !== -1) break;
      } else if (location.href.indexOf(kind[i]) >= 0) {
        kindID = i;
        break;
      }
    }
    // 谷歌特殊处理
    if (siteID === 5 && kindID === -1) {
      if (location.href.indexOf('q=') >= 0) kindID = 0;
    }
    if (kindID === -1) {
      console.log('soTab! no kind found');
      return;
    }

    // 初始化搜索路径
    // "百度", "必应", "好搜", "ALLSO", "知乎", "谷歌", "搜库", "搜狗"
    let links = []; // link[siteID]
    if (kindID === 0) {
      // normal
      links = [
        'https://www.baidu.com/s?wd=',
        'https://cn.bing.com/search?q=',
        'https://www.so.com/s?q=',
        'http://h2y.github.io/allso/#',
        '',
        'https://www.google.com/search?q=',
        '',
        'https://www.sogou.com/web?query=',
      ];
    } else if (kindID === 1) {
      // pic
      links = [
        'https://image.baidu.com/search/index?tn=baiduimage&word=',
        'https://cn.bing.com/images/search?q=',
        'https://image.so.com/i?q=',
        '',
        '',
        'https://www.google.com/search?tbm=isch&q=',
      ];
    } else if (kindID === 2) {
      // zhidao
      links = [
        'https://zhidao.baidu.com/search?word=',
        'https://cn.bing.com/knows/search?q=',
        '',
        '',
        'https://www.zhihu.com/search?q=',
        '',
        '',
        'http://www.sogou.com/sogou?interation=196636&query=',
      ];
    } else if (kindID === 3) {
      // video
      links = [
        'https://v.baidu.com/v?ie=utf-8&word=',
        '',
        'https://video.so.com/v?q=',
        '',
        '',
        'https://www.google.com/search?tbm=vid&q=',
        'https://www.soku.com/v?keyword=',
      ];
    } else if (kindID === 4) {
      // xueshu
      links = [
        'https://xueshu.baidu.com/s?wd=',
        'https://cn.bing.com/academic/search?q=',
        '',
        '',
        '',
        'https://scholar.google.com/scholar?q=',
      ];
    }

    // 从url的searchParams中获取搜索关键词
    const searchParams = new URLSearchParams(location.search);
    const searchKeyWords = ['wd', 'word', 'w', 'q', 'query', 'search'];
    let searchWords = '';
    searchKeyWords.forEach((keyWord) => {
      if (searchParams.has(keyWord)) {
        let initialWords = searchParams.get(keyWord);
        searchWords = encodeURIComponent(initialWords);
      }
    });

    // 加载css

    const styleText = `
              .soTab {
                  position: fixed;
                  background-color: #000;
                  opacity: 0.3;
                  border-radius: 40px;
                  color: #fff;
                  padding: 15px 20px;
                  bottom: 100px;
                  height: 40px;
                  left: -320px;
                  width: 300px;
                  z-index: 9999999;
                  transition: all 400ms;
                  font-size: 14px;
              }
              .soTab:hover {
                  left: 0px;
                  opacity: 1;
                  border-radius: 10px;
                  box-shadow: 5px -5px 10px #777;
              }
              .soTab p {
                  margin: 0;
              }
              p.soTab_title {
                  font-weight: bold;
                  margin-bottom: 3px;
              }
              .soTab a {
                  color: #0cf;
                  margin-right: 25px;
              }

              `;
    // 生成切换框
    const bodyDOM = document.getElementsByTagName('body')[0];
    const soTabPanelDOM = document.createElement('div');
    soTabPanelDOM.id = 'soTab';
    let str = "<p class='soTab_title'>soTab 一键切换引擎:</p><p>";
    for (const link of links) {
      if (link && links.indexOf(link) !== siteID) {
        str += `<a href='${link}${searchWords}' target='_blank'>${sitesName[links.indexOf(link)]}</a>`;
      }
    }

    soTabPanelDOM.innerHTML = `${str}</p>`;
    soTabPanelDOM.className = `b_soTab soTab soTab_site${siteID} soTab_kind${kindID}`;// b_必须放在className首位,否则bing会监听增加的DOM并删除增加的元素
    const oldSoTabDOM = document.getElementById('soTab');
    if (oldSoTabDOM) {
      oldSoTabDOM.remove();
    }
    const style = GM_addStyle(styleText);
    style.dataset.for = "result"; // 给style标签加上data-for= "result"属性,防止被百度删除
    bodyDOM.prepend(soTabPanelDOM);// 将dom添加到body前面,防止被百度和BING删除
  }
  if (window.onurlchange === null) {
    // feature is supported
    window.addEventListener('urlchange', () => {
      console.log('url has changed');
      soTabInit();
    });
  }
  if (top === window) {
    console.log('init sotab here');
    soTabInit();
  }
}()); // end userScript