Google & baidu Switcher (ALL in One)

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

当前为 2021-05-29 提交的版本,查看 最新版本

  1. /* jshint esversion: 8 */
  2. // ==UserScript==
  3. // @name Google & baidu Switcher (ALL in One)
  4. // @name:en Google & baidu & Bing Switcher (ALL in One)
  5. // @name:zh-TW 谷歌搜索、百度搜索、必應搜索的聚合跳轉集合工具
  6. // @version 2.4.20210529.7
  7. // @author F9y4ng
  8. // @description 最新版本的集合谷歌、百度、必应的搜索引擎跳转工具,必应跳转可在菜单进行自定义设置。此版本无外部脚本调用,更快速和准确的进行按钮定位,显示速度大大提升。如有异常请清空浏览器缓存,再次载入使用,感谢使用!
  9. // @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!
  10. // @description:zh-TW 最新版本的集合谷歌、百度、必應的搜索引擎跳轉工具,必應跳轉可在菜單進行自定義設置。此版本無外部腳本調用,更快速和準確的進行按鈕定位,顯示速度大大提升。如有異常請清空瀏覽器緩存,再次載入使用,感謝使用!
  11. // @namespace https://openuserjs.org/scripts/t3xtf0rm4tgmail.com/Google_baidu_Switcher_(ALL_in_One)
  12. // @supportURL https://github.com/F9y4ng/GreasyFork-Scripts/issues
  13. // @icon https://www.google.com/favicon.ico
  14. // @include *://*.google.*/search*
  15. // @include *://*.google.*/webhp*
  16. // @include *://www.baidu.com/*
  17. // @include *://image.baidu.com/*
  18. // @include *://*.bing.com/*
  19. // @exclude *://*.google.*/sorry/*
  20. // @compatible Chrome 兼容TamperMonkey, ViolentMonkey
  21. // @compatible Firefox 兼容Greasemonkey4.0+, TamperMonkey, ViolentMonkey
  22. // @compatible Opera 兼容TamperMonkey, ViolentMonkey
  23. // @compatible Safari 兼容Tampermonkey • Safari
  24. // @grant GM_info
  25. // @grant GM_registerMenuCommand
  26. // @grant GM.registerMenuCommand
  27. // @grant GM_unregisterMenuCommand
  28. // @grant GM_openInTab
  29. // @grant GM_getValue
  30. // @grant GM.getValue
  31. // @grant GM_setValue
  32. // @grant GM.setValue
  33. // @grant GM_notification
  34. // @grant GM.notification
  35. // @license GPL-3.0-only
  36. // @create 2015-10-07
  37. // @copyright 2015-2021, F9y4ng
  38. // @run-at document-start
  39. // ==/UserScript==
  40.  
  41. !(function () {
  42. ('use strict');
  43. const isVersionDetection = true; // Set "false" to turn off the Version Detection.
  44. const isdebug = false;
  45. const debug = isdebug ? console.log.bind(console) : () => {};
  46.  
  47. function titleCase(str, bool) {
  48. const RegExp = bool ? /( |^)[a-z]/g : /(^)[a-z]/g;
  49. return str
  50. .toString()
  51. .toLowerCase()
  52. .replace(RegExp, L => {
  53. return L.toUpperCase();
  54. });
  55. }
  56.  
  57. /* Perfectly Compatible For Greasemonkey4.0+, TamperMonkey, ViolentMonkey * F9y4ng * 20210209 */
  58.  
  59. let GMsetValue, GMgetValue, GMregisterMenuCommand, GMunregisterMenuCommand, GMnotification, GMopenInTab;
  60. const GMinfo = GM_info;
  61. const handlerInfo = GMinfo.scriptHandler;
  62. const isGM = Boolean(handlerInfo.toLowerCase() === 'greasemonkey');
  63.  
  64. debug(`//-> CheckGM: ${titleCase(isGM)} >> ${handlerInfo}`);
  65.  
  66. if (isGM) {
  67. GMsetValue = GM.setValue;
  68. GMgetValue = GM.getValue;
  69. GMregisterMenuCommand = GM.registerMenuCommand;
  70. GMunregisterMenuCommand = () => {};
  71. GMnotification = GM.notification;
  72. GMopenInTab = (a, b) => {
  73. window.open(a, Math.random().toString(b.length).slice(-6), '');
  74. };
  75. } else {
  76. GMsetValue = GM_setValue;
  77. GMgetValue = GM_getValue;
  78. GMregisterMenuCommand = GM_registerMenuCommand;
  79. GMunregisterMenuCommand = GM_unregisterMenuCommand;
  80. GMnotification = GM_notification;
  81. GMopenInTab = GM_openInTab;
  82. }
  83.  
  84. const defCon = {
  85. scriptName: GMinfo.script.name,
  86. curVersion: GMinfo.script.version,
  87. isNoticed: sessionStorage.getItem('nkey') || 0,
  88. isNeedUpdate: 0,
  89. fetchResult: true,
  90. isAutoUpdate: GMinfo.scriptWillUpdate ? GMinfo.scriptWillUpdate : true, // TODO :-)
  91. lastRuntime: new Date().toLocaleString('en-US', {
  92. timeZoneName: 'short',
  93. hour12: false,
  94. }),
  95. };
  96.  
  97. console.info(
  98. `%c[GB-Init]%c\nVersion: ${defCon.curVersion} %c[%s]%c\nlastRuntime: ${defCon.lastRuntime}`,
  99. 'font-weight:bold;color:dodgerblue',
  100. 'color:0',
  101. 'color:snow',
  102. Update_checkVersion() instanceof Object,
  103. 'color:0'
  104. );
  105.  
  106. function fetchVersion(u) {
  107. return new Promise((e, t) => {
  108. fetch(u, {
  109. method: 'GET',
  110. mode: 'cors',
  111. cache: 'no-store',
  112. credentials: 'omit',
  113. })
  114. .then(e => {
  115. if (!e.ok) {
  116. throw Error(e.statusText);
  117. }
  118. return e.text();
  119. })
  120. .then(t => {
  121. let n = defCon.curVersion;
  122. t.split(/[\r\n]+/).forEach(function (item) {
  123. let key = item.match(/^(\/\/\s+@version\s+)(\S+)$/);
  124. if (key) {
  125. n = key[2];
  126. }
  127. });
  128. if (n !== undefined) {
  129. switch (isUpgrade(n, defCon.curVersion)) {
  130. case 2:
  131. e([2, n, u]);
  132. break;
  133. case 1:
  134. e([1, n, u]);
  135. break;
  136. default:
  137. e([0, n, u]);
  138. break;
  139. }
  140. }
  141. })
  142. .catch(e => {
  143. debug('%c[GB-Update]%c\nRequest Failure: %c(%s)', 'font-weight:bold;color:red', 'color:0', 'font-weight:bold;color:darkred', e);
  144. t();
  145. });
  146. });
  147. }
  148.  
  149. function isUpgrade(current_version, compare_version) {
  150. let compare_version_array = compare_version.split('.');
  151. let current_version_array = current_version.split('.');
  152. let is_upgrade = 0;
  153. if (compare_version_array.length === 4 && current_version_array.length === 4) {
  154. for (let i = 0; i < compare_version_array.length; i++) {
  155. if (parseInt(compare_version_array[i]) < parseInt(current_version_array[i])) {
  156. is_upgrade = 2;
  157. break;
  158. } else {
  159. if (parseInt(compare_version_array[i]) === parseInt(current_version_array[i])) {
  160. continue;
  161. } else {
  162. is_upgrade = 1;
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. return is_upgrade;
  169. }
  170.  
  171. async function Update_checkVersion(s = isVersionDetection) {
  172. let t = [];
  173. if (s && defCon.isAutoUpdate) {
  174. t = await fetchVersion(
  175. String(
  176. `https://greasyfork.org/scripts/12909-google-baidu-switcher-all-in-one/code/` +
  177. `Google%20%20baidu%20Switcher%20(ALL%20in%20One).meta.js?${new Date().getTime()}`
  178. )
  179. ).catch(async () => {
  180. defCon.fetchResult = false;
  181. });
  182. if (!defCon.fetchResult) {
  183. t = await fetchVersion(
  184. `https://raw.githubusercontent.com/F9y4ng/GreasyFork-Scripts/master/Google%20%26%20Baidu%20Switcher.meta.js?${new Date().getTime()}`
  185. ).catch(async () => {
  186. t = [0, defCon.curVersion, ''];
  187. });
  188. }
  189. if (typeof t !== 'undefined') {
  190. defCon.isNeedUpdate = t[0];
  191. const lastestVersion = t[1];
  192. const updateUrl = t[2].replace('meta', 'user');
  193. const recheckURLs = updateUrl
  194. .replace('raw.githubusercontent', 'github')
  195. .replace('master', 'blob/master')
  196. .replace(/code\/[^/]+\.js/, '');
  197. switch (defCon.isNeedUpdate) {
  198. case 2:
  199. console.info(
  200. String(
  201. `%c[GB-Update]%c\nWe found a new version: %c${lastestVersion}%c.\n` +
  202. `Please upgrade from your update source to the latest version.\n` +
  203. `[${recheckURLs.split('/')[2]}]`
  204. ),
  205. 'font-weight:bold;color:crimson',
  206. 'color:0',
  207. 'color:crimson',
  208. 'color:0'
  209. );
  210. if (!defCon.isNoticed) {
  211. GMnotification({
  212. title: `${defCon.scriptName}`,
  213. text: String(
  214. `\u53d1\u73b0\u6700\u65b0\u7248\u672c\uff1a${lastestVersion}` +
  215. `\uff0c\u70b9\u51fb\u8fd9\u91cc\u8fdb\u884c\u76f4\u94fe\u66f4\u65b0` +
  216. `\u3002\n\u005b${recheckURLs.split('/')[2]}\u6e90\u005d`
  217. ),
  218. timeout: 20e3,
  219. highlight: true,
  220. onclick: () => {
  221. let w;
  222. if (isGM) {
  223. window.open(`${recheckURLs}`, `Update.Manual`, '');
  224. } else {
  225. w = window.open(`${updateUrl}`, `Update.Auto`, '');
  226. }
  227. setTimeout(() => {
  228. w ? w.close() : () => {};
  229. sessionStorage.clear();
  230. }, 1000);
  231. },
  232. });
  233. sessionStorage.setItem('nkey', 2);
  234. }
  235. break;
  236. case 1:
  237. console.warn(
  238. String(
  239. `%c[GB-Update]%c\nWe found a new version, But %cthe latest version ` +
  240. `(%c${lastestVersion}%c) is lower than your local version (%c${defCon.curVersion}%c).\n\n` +
  241. `Please confirm whether you need to upgrade your local script, and then you need to update it manually.\n\n` +
  242. `If you no longer need the update prompt, please set "isVersionDetection" to "false" in your local code!\n\n` +
  243. `[${recheckURLs.split('/')[2]}]`
  244. ),
  245. 'font-weight:bold;color:crimson',
  246. 'font-weight:bold;color:0',
  247. 'color:0',
  248. 'font-weight:900;color:tomato',
  249. 'color:0',
  250. 'font-weight:900;color:darkred',
  251. 'color:0'
  252. );
  253. if (!defCon.isNoticed) {
  254. GMnotification({
  255. title: `${defCon.scriptName}`,
  256. text: String(
  257. `\u53d1\u73b0\u5f02\u5e38\u7248\u672c\uff1a${lastestVersion}` +
  258. `\uff0c\u56e0\u6700\u65b0\u7248\u672c\u4f4e\u4e8e\u60a8\u7684\u672c` +
  259. `\u5730\u7248\u672c(${defCon.curVersion})\uff0c\u8bf7\u70b9\u51fb\u8fd9` +
  260. `\u91cc\u786e\u8ba4\u662f\u5426\u9700\u8981\u5347\u7ea7\uff1f` +
  261. `\u005b${recheckURLs.split('/')[2]}\u6e90\u005d`
  262. ),
  263. timeout: 25e3,
  264. highlight: true,
  265. onclick: () => {
  266. window.open(`${recheckURLs}`, `Update.Manual`, '');
  267. sessionStorage.clear();
  268. },
  269. });
  270. sessionStorage.setItem('nkey', 1);
  271. }
  272. break;
  273. default:
  274. debug(
  275. `%c[GB-Update]%c\nCurretVersion: %cV${defCon.curVersion}%c is up to date!`,
  276. 'font-weight:bold;color:darkcyan',
  277. 'color:0',
  278. 'color:red',
  279. 'color:0'
  280. );
  281. break;
  282. }
  283. } else {
  284. console.error(
  285. '%c[GB-Update]\n%cSome Unexpected Errors Caused Version Detection Failure.\nProbably Caused By NetworkError.',
  286. 'font-weight:bold;color:red',
  287. 'font-weight:bold;color:darkred'
  288. );
  289. }
  290. }
  291. }
  292.  
  293. !(async function () {
  294. const temp = parseInt(await GMgetValue('_if_Use_Bing_'));
  295. const CONST = {
  296. isSecurityPolicy: false,
  297. isUseBing: (() => {
  298. if (isNaN(temp)) {
  299. GMsetValue('_if_Use_Bing_', 0);
  300. console.warn(
  301. '%c[GB-Warning]%c\nThis is your first visit, the Bing search button will not be inserted by default.',
  302. 'font-weight:bold;color:salmon',
  303. 'color:1'
  304. );
  305. return false;
  306. } else {
  307. return Boolean(temp);
  308. }
  309. })(),
  310. };
  311.  
  312. debug(`//-> ${CONST.isUseBing}`);
  313.  
  314. let curretSite = {
  315. SiteTypeID: 1,
  316. SiteName: '',
  317. SplitName: '',
  318. MainType: '',
  319. HtmlCode: '',
  320. StyleType: '',
  321. };
  322.  
  323. const listSite = {
  324. baidu: {
  325. SiteTypeID: 1,
  326. SiteName: 'Baidu',
  327. SplitName: 'tn',
  328. MainType: '.s_btn_wr',
  329. HtmlCode: CONST.isUseBing
  330. ? `
  331. <span id="ggyx">
  332. <input type="button" title="Google一下" value="Google"/>
  333. </span>
  334. <span id="bbyx">
  335. <input type="button" title="Bing一下" value="Bing ®"/>
  336. </span>`
  337. : `
  338. <span id="ggyx">
  339. <input type="button" title="Google一下" value="Google一下"/>
  340. </span>`,
  341. StyleCode: CONST.isUseBing
  342. ? `
  343. #form {
  344. white-space: nowrap;
  345. }
  346. #u {
  347. z-index: 1!important;
  348. }
  349. #for_Baidu #bbyx {
  350. margin-left: -1.5px;
  351. }
  352. #for_Baidu #ggyx {
  353. margin-left: 2px;
  354. }
  355. #bbyx input{
  356. background: #4e6ef2;
  357. border-top-right-radius: 10px;
  358. border-bottom-right-radius: 10px;
  359. cursor: pointer;
  360. height: 40px;
  361. color: #fff;
  362. width: 80px;
  363. border: 1px solid #3476d2;
  364. font-size: 16px;
  365. font-weight:bold;
  366. }
  367. #ggyx input {
  368. background: #4e6ef2;
  369. border-top-left-radius: 10px;
  370. border-bottom-left-radius: 10px;
  371. cursor: pointer;
  372. height: 40px;
  373. color: #fff;
  374. width: 80px;
  375. border: 1px solid #3476d2;
  376. font-size: 16px;
  377. font-weight:bold;
  378. }
  379. #ggyx input:hover, #bbyx input:hover {
  380. background: #4662D9;
  381. border: 1px solid #3476d2;
  382. }`
  383. : `
  384. #form {
  385. white-space: nowrap;
  386. }
  387. #u {
  388. z-index: 1!important;
  389. }
  390. #for_Baidu {
  391. margin-left: 6px
  392. }
  393. #ggyx input {
  394. background: #4e6ef2;
  395. border-radius: 10px;
  396. cursor: pointer;
  397. height: 40px;
  398. color: #fff;
  399. width: 112px;
  400. border: 1px solid #3476d2;
  401. text-shadow: 0 0 2px #ffffff !important;
  402. font-size: 16px
  403. }
  404. #ggyx input:hover {
  405. background: #4662D9;
  406. border: 1px solid #3476d2;
  407. }`,
  408. },
  409. google: {
  410. SiteTypeID: 2,
  411. SiteName: 'Google',
  412. SplitName: 'tbm',
  413. MainType: "form button[type='submit']",
  414. HtmlCode: CONST.isUseBing
  415. ? `
  416. <span id="bdyx">
  417. <input type="button" title="百度一下" value="百度一下"/>
  418. </span>
  419. <span id="bbyx">
  420. <input type="button" title="Bing一下" value="Bing一下"/>
  421. </span>`
  422. : `
  423. <span id="bdyx">
  424. <input type="button" title="百度一下" value="百度一下"/>
  425. </span>`,
  426. StyleCode: CONST.isUseBing
  427. ? `
  428. #for_Google {
  429. margin: 3px 4px 0 -5px;
  430. }
  431. #for_Google #bdyx {
  432. padding:5px 0 4px 18px;
  433. border-left:1px solid #ddd;
  434. }
  435. #for_Google #bbyx {
  436. margin-left:-2px
  437. }
  438. .scrollspan{
  439. padding:1px 0 0 18px!important
  440. }
  441. .scrollbars {
  442. height: 26px!important;
  443. font-size: 13px!important;
  444. font-weight: normal!important;
  445. text-shadow: 0 0 1px #ffffff !important;
  446. }
  447. #bdyx input {
  448. cursor: pointer;
  449. padding: 1px 1px 1px 6px!important;
  450. border: 1px solid transparent;
  451. background: #1a73e8;
  452. box-shadow: none;
  453. border-top-left-radius: 24px;
  454. border-bottom-left-radius: 24px;
  455. width: 90px;
  456. height: 38px;
  457. font-size: 15px;
  458. font-weight: 600;
  459. color: #fff
  460. }
  461. #bbyx input {
  462. cursor: pointer;
  463. padding: 1px 6px 1px 1px!important;
  464. border: 1px solid transparent;
  465. background: #1a73e8;
  466. box-shadow: none;
  467. border-top-right-radius: 24px;
  468. border-bottom-right-radius: 24px;
  469. width: 90px;
  470. height: 38px;
  471. font-size: 15px;
  472. font-weight: 600;
  473. color: #fff
  474. }
  475. #bdyx input:hover, #bbyx input:hover {
  476. background: #2b7de9;
  477. }`
  478. : `
  479. #for_Google {
  480. margin: 3px 4px 0 -5px;
  481. }
  482. #for_Google #bdyx {
  483. padding:5px 0 4px 18px;
  484. border-left:1px solid #ddd;
  485. }
  486. .scrollspan{
  487. padding:1px 0 0 18px!important
  488. }
  489. .scrollbars {
  490. height: 26px!important;
  491. font-size: 13px!important;
  492. font-weight: normal!important;
  493. text-shadow: 0 0 1px #ffffff !important;
  494. }
  495. #bdyx input {
  496. cursor: pointer;
  497. border: 1px solid transparent;
  498. background: #1a73e8;
  499. box-shadow: none;
  500. border-radius: 24px;
  501. width: 90px;
  502. height: 38px;
  503. font-size: 14px;
  504. font-weight: 600;
  505. color: #fff;
  506. }
  507. #bdyx input:hover {
  508. background: #2b7de9;
  509. }`,
  510. },
  511. bing: {
  512. SiteTypeID: 3,
  513. SiteName: 'Bing',
  514. SplitName: 'undefined',
  515. MainType: '#sb_go_par',
  516. HtmlCode: `
  517. <span id="bdyx">
  518. <input type="button" title="百度一下" value="百度"/>
  519. </span>
  520. <span id="ggyx">
  521. <input type="button" title="Google一下" value="Google"/>
  522. </span>`,
  523. StyleCode: `
  524. #for_Bing {
  525. height: 44px;
  526. width: 120px;
  527. margin: 2px 10px 2px 0;
  528. }
  529. #bdyx input, #ggyx input {
  530. cursor: pointer;
  531. width: auto 60px;
  532. height: 40px;
  533. background-color: #f7faff;
  534. border: 1px solid #0095B7;
  535. color: #0095B7;
  536. margin-left: -1px;
  537. font-family: 'Microsoft YaHei'!important;
  538. font-size: 16px;
  539. font-weight: 700;
  540. border-radius: 4px;
  541. }
  542. .scrollspan {
  543. height: 32px!important;
  544. }
  545. .scrollbars {
  546. height: 30px!important;
  547. }
  548. #bdyx input:hover, #ggyx input:hover {
  549. background-color: #fff;
  550. transition:border linear .1s,box-shadow linear .3s;
  551. box-shadow: 1px 1px 8px #08748D;
  552. border: 2px solid #0095B7;
  553. text-shadow: 0 0 1px #0095B7 !important;
  554. color:#0095B7;
  555. }`,
  556. },
  557. other: { SiteTypeID: 0 },
  558. };
  559.  
  560. const newSiteType = {
  561. BAIDU: listSite.baidu.SiteTypeID,
  562. GOOGLE: listSite.google.SiteTypeID,
  563. BING: listSite.bing.SiteTypeID,
  564. OTHERS: 0,
  565. };
  566.  
  567. debug('//-> Initialization complete, start running...');
  568.  
  569. if (location.host.includes('.baidu.com')) {
  570. curretSite = listSite.baidu;
  571. } else if (location.host.includes('.google.')) {
  572. curretSite = listSite.google;
  573. } else if (location.host.includes('.bing.com')) {
  574. curretSite = listSite.bing;
  575. } else {
  576. curretSite = listSite.other;
  577. }
  578. if (
  579. (curretSite.SiteTypeID === newSiteType.GOOGLE && location.href.replace(/tbm=(lcl|flm|fin)/, '') !== location.href) ||
  580. (curretSite.SiteTypeID === newSiteType.BING && location.href.replace(/maps\?/, '') !== location.href) ||
  581. (curretSite.SiteTypeID === newSiteType.BAIDU && location.href.replace(/tn=(news|ikaslist|vsearch)|detail\?/, '') !== location.href)
  582. ) {
  583. CONST.isSecurityPolicy = true;
  584. }
  585.  
  586. let menuManager = {
  587. menuDisplay: function () {
  588. const _Use_Bing_ = CONST.isUseBing;
  589. let _use_Bing_ID, in_Use_feedBack_ID;
  590.  
  591. registerMenuCommand();
  592. console.log(
  593. '%c[GB-Status]%c\nInsert the Bing Search Button: %c%s%c',
  594. 'font-weight:bold;color:darkorange',
  595. 'color:0',
  596. 'font-weight:bold;color:red',
  597. titleCase(_Use_Bing_),
  598. 'font-weight:normal;color:0'
  599. );
  600. debug(`//-> CONST.isUseBing: ${_Use_Bing_}`);
  601.  
  602. function registerMenuCommand() {
  603. let _Use_Bing__;
  604. if (in_Use_feedBack_ID && !isGM) {
  605. GMunregisterMenuCommand(_use_Bing_ID);
  606. GMunregisterMenuCommand(in_Use_feedBack_ID);
  607. }
  608. if (_Use_Bing_) {
  609. _Use_Bing__ = '√';
  610. } else {
  611. _Use_Bing__ = '×';
  612. }
  613. _use_Bing_ID = GMregisterMenuCommand(` [${_Use_Bing__}] \u6dfb\u52a0 Bing \u641c\u7d22\u8df3\u8f6c`, () => {
  614. inUse_switch(_Use_Bing_, '_if_Use_Bing_', 'Bing\u6309\u94ae');
  615. });
  616. in_Use_feedBack_ID = GMregisterMenuCommand('\u4f7f\u7528\u53cd\u9988', () => {
  617. GMopenInTab('https://greasyfork.org/zh-CN/scripts/12909/feedback', {
  618. active: true,
  619. insert: true,
  620. setParent: true,
  621. });
  622. });
  623. }
  624.  
  625. function inUse_switch(_status, Name, Tips) {
  626. const title = `\u6e29\u99a8\u63d0\u793a\uff1a`;
  627. if (_status) {
  628. GMsetValue(`${Name}`, 0);
  629. GMnotification(`${Tips}\u5df2\u5173\u95ed\uff0c\u4e09\u79d2\u540e\u5c06\u5237\u65b0\uff01`, title);
  630. } else {
  631. GMsetValue(`${Name}`, 1);
  632. GMnotification(`${Tips}\u5df2\u5f00\u542f\uff0c\u4e09\u79d2\u540e\u5c06\u5237\u65b0\uff01`, title);
  633. }
  634. setTimeout(() => {
  635. let loc = location.href.replace(/&timestamp=(\d+)/, '');
  636. location.replace(loc + `&timestamp=` + new Date().getTime());
  637. }, 3000);
  638. }
  639. },
  640. init: function () {
  641. this.menuDisplay();
  642. },
  643. };
  644.  
  645. let searchManager = {
  646. doSwitch: function () {
  647. try {
  648. const idName = `#for_${curretSite.SiteName}`;
  649. const className = `.InsertTo${curretSite.SiteName}`;
  650. if (curretSite.SiteTypeID !== newSiteType.OTHERS) {
  651. if (CONST.isSecurityPolicy) {
  652. console.log(
  653. '%c[GB-Prohibit]%c\nBlocked By: %c%s Security Policy%c.',
  654. 'font-weight:bold;color:indigo',
  655. 'color:0',
  656. 'color:darkred',
  657. curretSite.SiteName,
  658. 'color:0'
  659. );
  660. return;
  661. } else {
  662. const callback = mutations => {
  663. mutations.forEach(mutation => {
  664. if (document.querySelector(className) && document.querySelector(idName)) {
  665. debug(`//-> Already Insert Button & CSS.`);
  666. } else {
  667. debug(
  668. '%c[GB-MutationObserver]\n%c(%c%s%c has changed: %c%s%c).',
  669. 'font-weight:bold;color:olive',
  670. 'color:0',
  671. 'color:olive',
  672. mutation.type,
  673. 'color:0',
  674. 'font-weight:bold;color:red',
  675. titleCase(insertSearchButton() && scrollDetect()),
  676. 'color:0'
  677. );
  678. }
  679. });
  680. };
  681. const opts = { childList: true, subtree: true };
  682. new MutationObserver(callback).observe(document, opts);
  683. RAFInterval(
  684. () => {
  685. if (!document.querySelector(idName) || !document.querySelector(className)) {
  686. return insertSearchButton() && scrollDetect();
  687. }
  688. },
  689. 500,
  690. true
  691. );
  692. console.log(
  693. '%c[GB-Switch]%c\nWe are using The %c%s%c Search Engine.',
  694. 'font-weight:bold;color:Green',
  695. 'color:0',
  696. 'font-weight:bold;color:darkcyan',
  697. curretSite.SiteName,
  698. 'font-weight:normal;color:0'
  699. );
  700. }
  701. }
  702. } catch (e) {
  703. debug(`//-> %c${e.name}`, 'color:darkred');
  704. }
  705.  
  706. function insertSearchButton() {
  707. try {
  708. const getTarget = curretSite.MainType;
  709. const doHtml = curretSite.HtmlCode;
  710. const doStyName = `InsertTo${curretSite.SiteName}`;
  711. const doStyle = curretSite.StyleCode;
  712. const vim = GetUrlParam(curretSite.SplitName);
  713. const userSpan = document.createElement('span');
  714. let Target = document.querySelector(getTarget);
  715. userSpan.id = `for_${curretSite.SiteName}`;
  716. userSpan.innerHTML = doHtml;
  717. const SpanID = `#${userSpan.id}`;
  718.  
  719. addStyle(doStyle, doStyName, 'head');
  720.  
  721. if (!document.querySelector(SpanID) && getSearchValue().length > 0 && Target) {
  722. if (/^(nws|vid|bks)$/.test(vim.trim())) {
  723. Target = Target.parentNode.parentNode.firstChild;
  724. Target.insertBefore(userSpan, Target.firstChild);
  725. if (document.querySelector(SpanID)) {
  726. document.querySelector(SpanID).setAttribute('style', 'float:right');
  727. }
  728. } else {
  729. insterAfter(userSpan, Target);
  730. // Baidu图片特殊检查 F9y4ng 20210402
  731. if (document.querySelector(SpanID) && /^baiduimage$/.test(vim.trim())) {
  732. document.querySelector(SpanID).setAttribute('style', 'margin-left:12px');
  733. }
  734. // Bing图片特殊检查 F9y4ng 20210403
  735. if (
  736. document.querySelector('.b_searchboxForm') &&
  737. /^images$/.test(vim.trim()) &&
  738. location.href.replace(/view=detailV2/, '') !== location.href
  739. ) {
  740. document.querySelector('.b_searchboxForm').setAttribute('style', 'width:640px');
  741. }
  742. }
  743.  
  744. debug(`//-> Target: ${Target}`);
  745.  
  746. document.querySelectorAll('#ggyx, #bbyx, #bdyx').forEach(per => {
  747. per.addEventListener('click', () => {
  748. let gotoUrl = 'about:blank';
  749. switch (per.id) {
  750. case 'ggyx':
  751. if (/^(baiduimage|images)$/.test(vim.trim())) {
  752. gotoUrl = 'https://www.google.com/search?hl=zh-CN&source=lnms&tbm=isch&sa=X&q=';
  753. } else {
  754. gotoUrl = 'https://www.google.com/search?hl=zh-CN&source=hp&newwindow=1&q=';
  755. }
  756. break;
  757. case 'bbyx':
  758. if (/^(isch|baiduimage)$/.test(vim.trim())) {
  759. gotoUrl = 'https://cn.bing.com/images/search?first=1&tsc=ImageBasicHover&q=';
  760. } else {
  761. gotoUrl = 'https://cn.bing.com/search?q=';
  762. }
  763. break;
  764. case 'bdyx':
  765. if (/^(images|isch)$/.test(vim.trim())) {
  766. gotoUrl = 'https://image.baidu.com/search/index?tn=baiduimage&ps=1&ie=utf-8&word=';
  767. } else {
  768. gotoUrl = 'https://www.baidu.com/s?ie=utf-8&rqlang=cn&wd=';
  769. }
  770. break;
  771. default:
  772. break;
  773. }
  774. debug(`//-> ${per.id}`);
  775. GMopenInTab(decodeURI(gotoUrl + getSearchValue()), {
  776. active: true,
  777. insert: true,
  778. setParent: true,
  779. });
  780. });
  781. });
  782. }
  783. return true;
  784. } catch (e) {
  785. debug(`//-> %c${e}`, 'color:darkred');
  786. return false;
  787. }
  788. }
  789.  
  790. function scrollDetect() {
  791. try {
  792. const nodeName = `#for_${curretSite.SiteName}`;
  793. const vim = GetUrlParam(curretSite.SplitName);
  794. switch (curretSite.SiteTypeID) {
  795. case newSiteType.GOOGLE:
  796. scrollButton(`${nodeName} #bdyx`, 'scrollspan', 35);
  797. scrollButton(`${nodeName} #bdyx input`, 'scrollbars', 35);
  798. if (CONST.isUseBing) {
  799. scrollButton(`${nodeName} #bbyx input`, 'scrollbars', 35);
  800. }
  801. break;
  802. case newSiteType.BING:
  803. if (/^(images|videos)$/.test(vim.trim())) {
  804. scrollButton(`${nodeName}`, 'scrollspan', 50);
  805. scrollButton(`${nodeName} #bdyx input`, 'scrollbars', 50);
  806. scrollButton(`${nodeName} #ggyx input`, 'scrollbars', 50);
  807. }
  808. break;
  809. default:
  810. debug(`//-> No scrolling detecting.`);
  811. break;
  812. }
  813. return true;
  814. } catch (e) {
  815. debug(`//-> %c${e.name}`, 'color:darkred');
  816. return false;
  817. }
  818. }
  819.  
  820. function scrollButton(paraName, classNameIn, scrollSize) {
  821. debug(`//-> ${curretSite.SiteName} Scrolling Detecting: ${paraName}`);
  822. const oDiv = document.querySelector(paraName);
  823. let H = 0;
  824. let Y = oDiv;
  825. if (Y !== null) {
  826. while (Y) {
  827. H += Y.offsetTop;
  828. Y = Y.offsetParent;
  829. }
  830. document.addEventListener('scroll', () => {
  831. const s = document.body.scrollTop || document.documentElement.scrollTop;
  832. debug(`//-> H=${H} S=${s} H-S=(${H - s})`);
  833. if (s > H + scrollSize) {
  834. oDiv.setAttribute('class', classNameIn);
  835. } else {
  836. oDiv.removeAttribute('class');
  837. }
  838. });
  839. }
  840. }
  841.  
  842. function addStyle(css, className, addToTarget, isReload, initType) {
  843. RAFInterval(
  844. () => {
  845. let addTo = document.querySelector(addToTarget);
  846. if (typeof addToTarget === 'undefined') {
  847. addTo = document.head || document.body || document.documentElement || document;
  848. }
  849. isReload = isReload || false;
  850. initType = initType || 'text/css';
  851. if (typeof addToTarget === 'undefined' || (typeof addToTarget !== 'undefined' && document.querySelector(addToTarget))) {
  852. if (isReload === true) {
  853. safeRemove(`.${className}`);
  854. } else if (isReload === false && document.querySelector(`.${className}`)) {
  855. return true;
  856. }
  857. const cssNode = document.createElement('style');
  858. if (className !== null) {
  859. cssNode.className = className;
  860. }
  861. cssNode.setAttribute('type', initType);
  862. cssNode.innerHTML = css;
  863. try {
  864. addTo.appendChild(cssNode);
  865. } catch (e) {
  866. debug(`//-> %c${e.name}`, 'color:darkred');
  867. }
  868. return true;
  869. }
  870. },
  871. 20,
  872. true
  873. );
  874. }
  875.  
  876. function safeRemove(Css) {
  877. safeFunction(() => {
  878. const removeNodes = document.querySelectorAll(Css);
  879. for (let i = 0; i < removeNodes.length; i++) {
  880. removeNodes[i].remove();
  881. }
  882. });
  883. }
  884.  
  885. function safeFunction(func) {
  886. try {
  887. func();
  888. } catch (e) {
  889. debug(`//-> %c${e.name}`, 'color:darkred');
  890. }
  891. }
  892.  
  893. function getSearchValue() {
  894. let val = '';
  895. document.querySelectorAll('input[name="wd"], input[name="q"], input[name="word"]').forEach((item, index, arr) => {
  896. val = arr[0].value;
  897. if (val) {
  898. debug(`//-> INPUT: ${val} - INDEX: ${index} - OLD: ${item.value}`);
  899. }
  900. });
  901. if (val === null || val === '' || typeof val === 'undefined') {
  902. const kvl = location.search.substr(1).split('&');
  903. for (let i = 0; i < kvl.length; i++) {
  904. let value = kvl[i].replace(/^(wd|word|kw|query|q)=/, '');
  905. if (value !== kvl[i]) {
  906. val = value;
  907. }
  908. }
  909. val = val.replace(/\+/g, ' ');
  910. if (val) {
  911. debug(`//-> QUERY: ${val}`);
  912. }
  913. }
  914. return encodeURIComponent(val);
  915. }
  916.  
  917. function RAFInterval(callback, period, runNow) {
  918. const needCount = (period / 1000) * 60;
  919. let times = 0;
  920. if (runNow === true) {
  921. const shouldFinish = callback();
  922. if (shouldFinish) {
  923. return;
  924. }
  925. }
  926.  
  927. function step() {
  928. if (times < needCount) {
  929. times++;
  930. requestAnimationFrame(step);
  931. } else {
  932. const shouldFinish = callback() || false;
  933. if (!shouldFinish) {
  934. times = 0;
  935. requestAnimationFrame(step);
  936. } else {
  937. return;
  938. }
  939. }
  940. }
  941. requestAnimationFrame(step);
  942. }
  943.  
  944. function insterAfter(newElement, targetElement) {
  945. if (targetElement !== null) {
  946. const parent = targetElement.parentNode;
  947. if (parent.lastChild === targetElement) {
  948. parent.appendChild(newElement);
  949. } else {
  950. parent.insertBefore(newElement, targetElement.nextSibling);
  951. }
  952. }
  953. }
  954.  
  955. function GetUrlParam(paraName) {
  956. if (paraName === 'undefined') {
  957. const parameter = document.location.pathname.toString();
  958. const arr = parameter.split('/');
  959. return arr[1];
  960. } else {
  961. const url = document.location.toString();
  962. const arrObj = url.split('?');
  963. if (arrObj.length > 1) {
  964. const arrPara = arrObj[1].split('&');
  965. let arr;
  966. for (let i = 0; i < arrPara.length; i++) {
  967. arr = arrPara[i].split('=');
  968. if (arr !== null && arr[0] === paraName) {
  969. return arr[1];
  970. }
  971. }
  972. return '';
  973. } else {
  974. return '';
  975. }
  976. }
  977. }
  978. },
  979.  
  980. init: function () {
  981. debug('//-> Loading menu...');
  982. menuManager.init();
  983. debug('//-> Insert button...');
  984. this.doSwitch();
  985. },
  986. };
  987.  
  988. (function () {
  989. try {
  990. searchManager.init();
  991. } catch (e) {
  992. 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');
  993. }
  994. })();
  995. })();
  996. })();