谷歌搜索 - 优化

1.屏蔽推广 2.普通样式 3.单列居中 4双列居中

  1. // ==UserScript==
  2. // @name 谷歌搜索 - 优化
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.8
  5. // @description 1.屏蔽推广 2.普通样式 3.单列居中 4双列居中
  6. // @author 浮生未歇
  7. // @run-at document-start
  8. // @include https://www.google.com*/search*
  9. // @exclude https://www.google.com*/search*&source=lnms*
  10. // @resource googleCommon https://cdn.jsdelivr.net/gh/sinlin/google@1.2.1/2019-03-16/google-common.css
  11. // @resource googleOne https://cdn.jsdelivr.net/gh/sinlin/google@1.2.1/2019-03-16/google-one.css
  12. // @resource googleTwo https://cdn.jsdelivr.net/gh/sinlin/google@1.2.1/2019-03-16/google-two.css
  13. // @grant GM_addStyle
  14. // @grant GM_getResourceText
  15. // @grant GM_getResourceURL
  16. // @grant GM_setValue
  17. // @grant GM_getValue
  18. // @grant GM_deleteValue
  19. // @grant GM_xmlhttpRequest
  20. // ==/UserScript==
  21. (() => {
  22. //初始化配置
  23. let Configs = {
  24. //是否调试
  25. IS_DEBUG: false,
  26. //功能配置
  27. OPTIONS: [
  28. //页面布局:1:普通页面,2:单列居中,3:双列居中,
  29. { name: "SELECT_PAGE", value: 1 }
  30. ],
  31. //谷歌样式
  32. GOOGLE_STYLES: {
  33. COMMON: GM_getResourceText("googleCommon"),
  34. ONE: GM_getResourceText("googleOne"),
  35. TWO: GM_getResourceText("googleTwo"),
  36. }
  37. };
  38.  
  39. //Google对象参数配置
  40. let googleParamConfig = { Configs, window, document, location };
  41.  
  42. //Google对象
  43. let Google = (({ Config, window, document, location }, undefined) => {
  44. //创建空对象
  45. let Google = Object.create(null);
  46.  
  47. //绑定 Google.ready = functon(){} 功能
  48. Reflect.defineProperty(Google, "ready", {
  49. set: fn => {
  50. if (document.readyState === "complete") {
  51. fn();
  52. } else if (!!document.addEventListener) {
  53. document.addEventListener(
  54. "DOMContentLoaded",
  55. () => {
  56. fn();
  57. },
  58. true
  59. );
  60. } else {
  61. throw new Error("Google.ready can't use");
  62. }
  63. }
  64. });
  65.  
  66. /**
  67. * 函数执行器 - 组合执行
  68. */
  69. class Command {
  70. constructor() {
  71. this.commondList = [];
  72. }
  73. /**
  74. * 添加数组缓存中
  75. * @param {object} command 对象实例
  76. */
  77. add(command) {
  78. this.commondList.push(command);
  79. }
  80.  
  81. /**
  82. * 执行数值缓存中的实例
  83. */
  84. execute() {
  85. for (let i = 0, command; (command = this.commondList[i++]); ) {
  86. command.execute();
  87. }
  88. }
  89. }
  90.  
  91. /**
  92. * GM
  93. * 用于调用 TamperMonkey 内置API
  94. */
  95. class GM {
  96. /**
  97. * 获取数据储存
  98. */
  99. getGmValue(selection) {
  100. return GM_getValue(selection.name, selection.value);
  101. }
  102.  
  103. /**
  104. * 设置数据储存
  105. */
  106. SetGmValue(name, value) {
  107. GM_setValue(name, value);
  108. }
  109.  
  110. /**
  111. * 使用GM导入样式
  112. * @param {string} styles 样式
  113. */
  114. importGmStyle(styles) {
  115. if (typeof styles === "string") {
  116. GM_addStyle(styles);
  117. }
  118. }
  119. }
  120.  
  121.  
  122.  
  123. /**
  124. * 数据类
  125. * 用于获取跟初始化配置相关的信息
  126. */
  127. class Data extends GM {
  128. constructor() {
  129. super();
  130. this.DEFAULT_PAGE_LAYOUT_TYPE = Configs.OPTIONS[0];
  131. this.STYLE_CONTENT_COMMON = Configs.GOOGLE_STYLES.COMMON;
  132. this.STYLE_CONTENT_ONE_CENTER = Configs.GOOGLE_STYLES.ONE;
  133. this.STYLE_CONTENT_TWO_CENTER = Configs.GOOGLE_STYLES.TWO;
  134. }
  135.  
  136. getPageLayoutName () {
  137. return this.DEFAULT_PAGE_LAYOUT_TYPE["name"];
  138. }
  139.  
  140. getCurrentPageLayoutType() {
  141. return Number(this.getGmValue(this.DEFAULT_PAGE_LAYOUT_TYPE)) || 1;
  142. }
  143.  
  144. getCommonPageStyleContent() {
  145. return this.STYLE_CONTENT_COMMON || "";
  146. }
  147.  
  148. getOneCenterStyleContent() {
  149. return this.STYLE_CONTENT_ONE_CENTER || "";
  150. }
  151.  
  152. getTwoCenterStyleContent() {
  153. return this.STYLE_CONTENT_TWO_CENTER || "";
  154. }
  155. }
  156.  
  157. /**
  158. * 基础类
  159. */
  160. class Base extends Data{
  161. isHideElement(element) {
  162. return element.style.display === "none";
  163. }
  164.  
  165. hideElement(element) {
  166. element.style.display = "none";
  167. }
  168.  
  169. showElement(element) {
  170. element.style.display = "block";
  171. }
  172. }
  173.  
  174.  
  175.  
  176. /**
  177. * 样式类
  178. * @class Style
  179. */
  180. class Style extends Base {
  181. constructor() {
  182. super();
  183. this.cache = "";
  184. }
  185. /**
  186. * 清除缓存
  187. */
  188. clearCache() {
  189. this.cache = "";
  190. }
  191.  
  192. /**
  193. * 导入样式
  194. */
  195. importStyle() {
  196. super.importGmStyle(this.cache);
  197. }
  198.  
  199. /**
  200. * 将样式内容添加到缓存
  201. * @param {string} styleContent
  202. */
  203. add(styleContent) {
  204. if (typeof styleContent === "string") {
  205. this.cache += styleContent;
  206. } else {
  207. this.cache += "";
  208. }
  209. return this;
  210. }
  211.  
  212. /**
  213. * 结束标识符
  214. * 开始调用导入功能
  215. * 清空缓存
  216. */
  217. end() {
  218.  
  219. this.importStyle();
  220. this.clearCache();
  221. }
  222. }
  223.  
  224. /**
  225. * 样式-普通页
  226. */
  227. class StyleByCommon extends Style {
  228. constructor() {
  229. super();
  230. }
  231. /**
  232. * 获取普通样式
  233. */
  234. getCommonPageStyleContent() {
  235. return super.getCommonPageStyleContent();
  236. }
  237.  
  238. getMulPageStyleContent(){
  239. let currentLayoutType = this.getCurrentPageLayoutType();
  240. let style = "";
  241. switch (currentLayoutType) {
  242. //普通样式
  243. case 1: style = ""; break;
  244. //单页居中
  245. case 2: style = this.getOneCenterStyleContent(); break;
  246. //双页居中
  247. case 3: style = this.getTwoCenterStyleContent(); break;
  248. }
  249. return style;
  250. }
  251.  
  252. init () {
  253. super.add(this.getCommonPageStyleContent())
  254. .add(this.getMulPageStyleContent())
  255. .end();
  256. }
  257.  
  258. execute () {
  259. this.init();
  260. }
  261. }
  262.  
  263. /**
  264. * 菜单
  265. */
  266.  
  267. class MenuNode extends Base {
  268. constructor() {
  269. super();
  270.  
  271. this.MENU_BTN_ID = "myGoogleMenuButton";
  272. this.MENU_LISTS_ID = "myGoogleLists";
  273. this.MENU_SAVE_NAME="myGooglesave";
  274. }
  275.  
  276. /**
  277. * 获取父节点
  278. */
  279. getContainerNode() {
  280. // return document
  281. // .getElementById("gb")
  282. // .querySelector(".gb_Jf");
  283. //return document.getElementById("ab_options");
  284. return document.getElementById("abar_button_opt");
  285. }
  286.  
  287. getMenuSaveIdName () {
  288. return this.MENU_SAVE_NAME;
  289. }
  290.  
  291. getPageLayoutName () {
  292. return super.getPageLayoutName();
  293. }
  294.  
  295. /**
  296. * 获得 HTML - 页面布局选项
  297. * @param content 显示的内容
  298. * @param layoutType 页面布局类型
  299. */
  300. getContentPageSelect(content, layoutType) {
  301. let checked = super.getCurrentPageLayoutType() === layoutType ? "checked" : "";
  302. return `<li><input type="radio" name="${ this.getPageLayoutName()
  303. }" value="${ layoutType }" ${ checked }>${ content }</li>`;
  304. }
  305.  
  306. /**
  307. * 获得 HTML - 保存
  308. * @param content 显示的内容
  309. */
  310. getContentSava(content) {
  311. let menuSaveIdName = this.getMenuSaveIdName();
  312. return `<input id='${menuSaveIdName}' type='button' style='margin-top:3px;display:block;width:100%' value='${content}'>`;
  313. }
  314.  
  315. //获取整体 HTML
  316. getContent() {
  317. let content = "";
  318. content += "<ol>页面选择";
  319. content += this.getContentPageSelect("普通页面", 1);
  320. content += this.getContentPageSelect("单页居中", 2);
  321. content += this.getContentPageSelect("双页居中", 3);
  322. content += "</ol>";
  323. content += this.getContentSava("保存");
  324. return content;
  325. }
  326.  
  327. /**
  328. * 插入按钮
  329. */
  330. insertMenuBtnNode() {
  331. let container = this.getContainerNode();
  332. let div = document.createElement("div");
  333. div.innerHTML = "自定义";
  334. div.id = this.MENU_BTN_ID;
  335. // container.insertBefore(div, container.parentNode.firstChild);
  336. // container.appendChild(div);
  337. container.before(div);
  338.  
  339. }
  340.  
  341. /**
  342. * 插入功能列表
  343. */
  344. insertMenuItemsNode() {
  345. let container = this.getContainerNode();
  346. let div = document.createElement("div");
  347. div.innerHTML = this.getContent();
  348. div.id = this.MENU_LISTS_ID;
  349. div.style.display = "none";
  350. // container.insertBefore(div, container.firstChild);
  351. container.before(div);
  352. }
  353.  
  354. bindMenuBtnEvent () {
  355. let btn = document.getElementById(this.MENU_BTN_ID);
  356. let lists = document.getElementById(this.MENU_LISTS_ID);
  357. btn.onclick = () => {
  358. if(this.isHideElement(lists)){
  359. this.showElement(lists);
  360. }else{
  361. this.hideElement(lists);
  362. }
  363. }
  364. }
  365.  
  366. bindMenuSaveEvent () {
  367. let save = document.getElementById(this.MENU_SAVE_NAME);
  368. save.onclick = (event) => {
  369. let e = event || window.event;
  370. let radios = document.getElementsByName(this.getPageLayoutName());
  371.  
  372. for(let i = 0, raido; (raido = radios[i++]);){
  373. if (!!raido.checked){
  374. super.SetGmValue(this.getPageLayoutName(), raido.value);
  375. break;
  376. }
  377. }
  378. e.stopPropagation();
  379. location.href = location.href;
  380. }
  381. }
  382.  
  383. init() {
  384. this.insertMenuBtnNode();
  385. this.insertMenuItemsNode();
  386.  
  387. Promise.resolve().then(() => {
  388. this.bindMenuBtnEvent();
  389. this.bindMenuSaveEvent();
  390. });
  391.  
  392. }
  393.  
  394.  
  395.  
  396. execute() {
  397. Google.ready = () => {
  398. this.init();
  399. };
  400. }
  401. }
  402. /**
  403. * 多页布局
  404. * @class MulPageLayout
  405. */
  406. class MulPageLayout extends Base {
  407. constructor () {
  408. super();
  409. this.PageLayouts = [3];
  410. this.LISTS_CLASS_NAME = "googlelists";
  411. }
  412.  
  413.  
  414. isMulPageLayout () {
  415. let currentLayoutType = super.getCurrentPageLayoutType();
  416. return this.PageLayouts.includes(currentLayoutType);
  417.  
  418. }
  419.  
  420. getContainer () {
  421. return document.getElementById("rso");
  422. }
  423.  
  424. getLists () {
  425. return document.getElementsByClassName(this.LISTS_CLASS_NAME);
  426. }
  427.  
  428. getSearchResults () {
  429. // return document.getElementById("rso").querySelectorAll(".bkWMgd>.g, .srg>.g #rso>.g");
  430. return document.querySelectorAll("#rso>.g");
  431. }
  432.  
  433. getListsHeight(){
  434. let heights = [];
  435. let lists = this.getLists();
  436. for(let i = 0, list; (list = lists[i++]);){
  437. heights.push(list.clientHeight || 0);
  438. }
  439. return heights;
  440. }
  441.  
  442. isExistListsElement () {
  443. return document.getElementsByName(this.LISTS_CLASS_NAME).length > 0;
  444. }
  445.  
  446. insertListsElement () {
  447. if(this.isExistListsElement()){
  448. return;
  449. }
  450. let className = this.LISTS_CLASS_NAME;
  451. let container = this.getContainer();
  452. let frame = document.createDocumentFragment();
  453. for(let i = 1; i <= 2; i++){
  454. let div = document.createElement("div");
  455. div.className = `${className} ${className}${i}`;
  456. frame.appendChild(div);
  457. }
  458. container.insertBefore(frame, container.firstChild);
  459. }
  460.  
  461. moveSearchResultElement () {
  462. let lists = this.getLists();
  463. let items = this.getSearchResults()
  464. let heights = this.getListsHeight();
  465.  
  466. let frames = [];
  467. //初始化
  468. for (let i = 0, length = lists.length; i < length; i++) {
  469. //缓存
  470. frames.push(document.createDocumentFragment());
  471. }
  472.  
  473. //将 item 添加到虚拟DOM中
  474. for (let i = 0, item; (item = items[i++]); ) {
  475. //获取最小的高度值
  476. let minHeight = Reflect.apply(Math.min, null, heights);
  477. //获取最小的高度的索引值
  478. let index = heights.indexOf(minHeight);
  479. //添加到高度
  480. heights[index] += item.clientHeight;
  481. //缓存
  482. frames[index].appendChild(item);
  483. }
  484.  
  485. //添加到真实DOM
  486. for (let i = 0, length = lists.length; i < length; i++) {
  487. lists[i].appendChild(frames[i]);
  488. }
  489.  
  490. }
  491.  
  492. init () {
  493. this.insertListsElement();
  494. this.moveSearchResultElement();
  495.  
  496. }
  497.  
  498. execute () {
  499. if(this.isMulPageLayout()){
  500. Google.ready = () => {
  501. this.init();
  502. }
  503. }
  504. }
  505. }
  506.  
  507. /**
  508. * 普通页控制
  509. */
  510. class CommonPageControl {
  511. run() {
  512. let command = new Command();
  513. command.add(new StyleByCommon());
  514. command.add(new MulPageLayout());
  515. command.add(new MenuNode());
  516. command.execute();
  517.  
  518.  
  519.  
  520. }
  521. }
  522.  
  523. /**
  524. * 简单工厂模式
  525. */
  526. class Factory {
  527. static getConfig() {
  528. return [{ reg: /https/, useObject: CommonPageControl }];
  529. }
  530.  
  531. static create(URL) {
  532. let configs = this.getConfig();
  533. for (let { reg, useObject } of configs) {
  534. if (reg.test(URL)) {
  535. return new useObject();
  536. }
  537. }
  538. }
  539. }
  540.  
  541. /**
  542. * 启动函数
  543. */
  544. Google.start = () => {
  545. Factory.create(location.href).run();
  546. };
  547.  
  548. return Google;
  549. })(googleParamConfig);
  550.  
  551. Google.start();
  552. })();