百度搜索 - 优化

1、屏蔽百度推广 2、关闭百度广告联盟信息收集 3、绑定快捷键 4、布局调整 5、居中单列(可选) 6、居中双列(可选)

目前为 2019-02-04 提交的版本。查看 最新版本

// ==UserScript==
// @name         百度搜索 - 优化
// @namespace    http://tampermonkey.net/
// @home-url     https://greasyfork.org/zh-CN/scripts/31642
// @description  1、屏蔽百度推广 2、关闭百度广告联盟信息收集 3、绑定快捷键 4、布局调整 5、居中单列(可选) 6、居中双列(可选)
// @version      4.1.7
// @author       浮生未歇
// @run-at       document-start
// @include      https://www.baidu.com/
// @include      https://www.baidu.com/s?*
// @incluce      https://www.baidu.com/#*
// @include      https://www.baidu.com/baidu?*
// @exclude      https://www.baidu.com/home*
// @exclude      https://www.baidu.com/sf*
// @exclude      https://www.baidu.com/search*
// @exclude      https://www.baidu.com/link*
// @exclude      https://www.baidu.com/s*tn=news*
// @resource     baiduIndexStyle   https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/indexStyle.css
// @resource     baiduCommonStyle  https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/commonStyle.css
// @resource     baiduMenu         https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/menu.css
// @resource     baiduOne          https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/one.css
// @resource     baiduTwo          https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/two.css
// @resource     baiduThree        https://cdn.jsdelivr.net/gh/sinlin/[email protected]/2018-10-30/three.css
// @connect      *
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_getResourceURL
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_xmlhttpRequest
// ==/UserScript==


(() => {
    //初始化配置
    const Config = {
        //是否调试
        IS_DEBUG: false,
        //壁纸地址
        BACKGROUND_URL: "https://ss2.bdstatic.com/lfoZeXSm1A5BphGlnYG/skin/37.jpg",
        //菜单按钮 ID
        MENU_BUTTON_ID: "CustomMenu",
        //菜单功能页 ID
        MENU_PAGE_ID: "menulist",
        //菜单保存按钮 ID
        MENU_SAVA_ID: "menusava",
        //功能配置
        OPTIONS: [
            //页面布局:1:普通页面,2:单列居中,3:双列居中,4:三列居中
            { name: "SELECT_PAGE", value: 1 },
            //重定向
            { name: "SWITCH_IS_REDIRECT", value: false },
            //加载下一页
            { name: "SWITCH_IS_LOADPAGE", value: false },
            //固定侧边栏
            { name: "SWITCH_IS_FIXEDSILDER", value: false },
            //加载背景
            { name: "SWITCH_IS_BACKGOUND", value: false }
        ],
        //百度样式
        BAIDU_STYLES: [
            {
                //百度首页
                INDEX: GM_getResourceText("baiduIndexStyle"),
                //普通页
                COMMON: GM_getResourceText("baiduCommonStyle"),
                //菜单
                MENU: GM_getResourceText("baiduMenu"),
                //单页
                ONE: GM_getResourceText("baiduOne"),
                //双页
                TWO: GM_getResourceText("baiduTwo"),
                //三页
                THREE: GM_getResourceText("baiduThree")
            }
        ],
        //过滤功能 ,不能设置 G(已被 Google搜索 占用)
        FILTERS: [
            {
                name: "B",
                value: "-baijiahao"
            },
            {
                name: "C",
                value: "site:bbs.csdn.net"
            },
            {
                name: "T",
                value: "site:tieba.baidu.com"
            },
            {
                name: "J",
                value: "site:juejin.im"
            },
            {
                name: "S",
                value: "site:segmentfault.com"
            },
            {
                name: "V",
                value: "site:v2ex.com"
            },
            {
                name: "Z",
                value: "site:zhihu.com"
            }
        ]
    };
    //打包
    const BaiduConfig = { window, document, location, Config };
    //Baidu
    const Baidu = (({ window, document, location, Config }) => {
        //创建空对象
        const Baidu = Object.create(null);
        const Options = Object.create(null);
        //引用
        const BAIDU_STYLES = Config.BAIDU_STYLES[0];
        const BAIDU_OPTIONS = Config.OPTIONS;
        //菜单功能页选项
        Options.SELECT_PAGE = BAIDU_OPTIONS[0];
        Options.SWITCH_IS_REDIRECT = BAIDU_OPTIONS[1];
        Options.SWITCH_IS_LOADPAGE = BAIDU_OPTIONS[2];
        Options.SWITCH_IS_FIXEDSILDER = BAIDU_OPTIONS[3];
        Options.SWITCH_IS_BACKGOUND = BAIDU_OPTIONS[4];
        /**
         * 实现 ready 功能, 文档完成后即执行
         * 举例 : Baidu.ready = function(){}
         */
        Reflect.defineProperty(Baidu, "ready", {
            set: fn => {
                if (document.readyState === "complete") {
                    fn();
                }
                else if (!!document.addEventListener) {
                    document.addEventListener("DOMContentLoaded", () => {
                        fn();
                    }, true);
                }
                else {
                    throw new Error("Baidu.ready can't use");
                }
            }
        });
        /**
         * 延时执行
         */
        Baidu.delayRun = (callback, count = 0) => {
            if (count === 0) {
                window.requestAnimationFrame(() => {
                    callback();
                });
            }
            else {
                window.requestAnimationFrame(() => {
                    Baidu.delayRun(callback, --count);
                });
            }
        };
        /**
         * DOM缓存
         */
        class DomCache {
            constructor() {
                this.cache = {};
            }
            hasDomCache(name) {
                return this.cache.hasOwnProperty(name) && !!this.cache[name]
                    ? true
                    : false;
            }
            deleteCache() {
                this.cache = {};
            }
            getElementById(name) {
                if (!this.hasDomCache(name)) {
                    this.cache[name] = document.getElementById(name);
                }
                return this.cache[name];
            }
        }
        Baidu.DOM = new DomCache();
        /**
         * GM数据类
         * @class GM
         */
        let GM = class {
            static getValue(selection) {
                try {
                    return GM_getValue(selection.name, selection.value);
                }
                catch (error) {
                    throw new Error(error);
                }
            }
            static setValue(name, value) {
                try {
                    GM_setValue(name, value);
                }
                catch (error) {
                    throw new Error(error);
                }
            }
            static addStyle(style) {
                try {
                    GM_addStyle(style);
                }
                catch (error) {
                    throw new Error(error);
                }
            }
            static xmlhttpRequest(object) {
                try {
                    GM_xmlhttpRequest(object);
                }
                catch (error) {
                    throw new Error(error);
                }
            }
        };
        /**
         * 减少执行
         */
        class ReduceExecute {
            constructor() {
                this.isNormalExecuteState = true;
            }
            /**
             * 是否正常执行
             */
            isNormalExecute() {
                return this.isNormalExecuteState;
            }
            /**
             * 停止正常执行
             */
            stopNormalExecute() {
                this.isNormalExecuteState = false;
                return this;
            }
            /**
             * 恢复正常执行
             * @param time 时间片 1 = 16.7ms
             */
            regainNormalExecute(time) {
                Baidu.delayRun(() => {
                    this.isNormalExecuteState = true;
                }, time);
            }
        }
        /**
         * 缓存类
         * 用于对数据的缓存
         * @class Cache
         *
         */
        class Cache {
            constructor() {
                this.cache = "";
            }
            /**
             * 删除缓存
             */
            delCache() {
                this.cache = "";
            }
            /**
             * 添加缓存
             * @param Content {string} 缓存内容
             */
            addCache(Content) {
                this.cache += Content;
            }
            /**
             * 获取缓存内容
             */
            getCache() {
                return this.cache;
            }
        }
        /**
         * 样式
         * @class Style
         * @extends Cache
         *
         */
        class Style {
            constructor() {
                this.Cache = new Cache();
                this.GM = GM;
            }
            /**
             * 导入样式
             * @method importStyle
             *
             */
            importStyle() {
                let styles = this.Cache.getCache();
                try {
                    this.GM.addStyle(styles);
                }
                catch (error) {
                    throw new Error("can't import styles:" + error);
                }
            }
            /**
             * 将样式加入缓存
             * @param {stirng} style 样式
             * @return {Style} this 该实例
             */
            add(style) {
                this.Cache.addCache(style);
                return this;
            }
            /**
             * 结束
             * 开始将缓存样式导入,并清空缓存
             */
            end() {
                this.importStyle();
                this.Cache.delCache();
            }
        }
        /**
         * 函数执行器 - 组合执行
         */
        class Commond {
            constructor() {
                this.commondList = [];
            }
            /**
             * 添加数组缓存中
             * @param {object} command 对象实例
             */
            add(command) {
                this.commondList.push(command);
            }
            /**
             * 执行数值缓存中的实例
             * 如果执行实例返回 true 停止执行。
             */
            execute(isSplitExecute = false) {
                for (let i = 0, command; (command = this.commondList[i++]);) {
                    command.execute();
                }
            }
        }
        /**
         * 检测功能 - 避免代码多次执行
         * @class AvoidMulExecute
         */
        class AvoidMulExecute {
            constructor() {
                //标志名称
                this.signName = "isRun";
            }
            /**
             * 增加标志位
             */
            setSign() {
                let signName = this.signName;
                let container = document.getElementById("content_left");
                container.setAttribute(signName, true);
            }
            /**
             * 判断是否存在标志位
             */
            hasSign() {
                let signName = this.signName;
                let container = document.getElementById("content_left");
                return !!container.hasAttribute(signName);
            }
        }
        /**
         * 重定向搜索地址
         * @class RedirectURL
         */
        class RedirectURL {
            constructor() {
                this.end = "&baidu";
            }
            /**
             * 重定向地址
             * @method redirectURL
             */
            redirectURL() {
                let end = this.end;
                let URL = location.href;
                if (!URL.endsWith(end)) {
                    //判断是否存在步进值,没有使用默认值 20
                    if (!URL.includes("&rn=")) {
                        URL += "&rn=20";
                    }
                    //拼接地址
                    URL += end;
                    //去除推广链接
                    URL = URL.replace(/\&tn=\S+\&/, "&");
                    //跳转
                    location.href = URL;
                }
            }
            /**
             * 初始化
             * @method init
             */
            init() {
                this.redirectURL();
            }
            /**
             * 启动
             * @method execute
             */
            execute() {
                this.init();
            }
        }
        /**
         * 首页样式
         * @class IMportIndexStyle
         */
        class ImportIndexStyle {
            constructor() {
                //实例化
                this.Style = new Style();
            }
            /**
             * 导入样式
             * @method import
             */
            import() {
                let style = this.Style;
                style.add(BAIDU_STYLES.INDEX);
                style.end();
            }
            /**
             * 初始化
             * @method init
             */
            init() {
                this.import();
            }
            /**
             * 执行
             * @method execute
             */
            execute() {
                this.init();
            }
        }
        /**
         * 导入普通结果页样式
         * @class ImportCommonStyle
         */
        class ImportCommonStyle {
            constructor() {
                //实例化
                this.Style = new Style();
                this.GM = GM;
                //功能选项
                this.Options = Options;
                //背景地址
                this.backgoundURL = Config.BACKGROUND_URL;
                //布局类型
                this.layoutType = Number(this.GM.getValue(this.Options.SELECT_PAGE));
                //是否导入背景
                this.isImportBackground = Boolean(this.GM.getValue(this.Options.SWITCH_IS_BACKGOUND));
                //是否导入样式
                this.isImportFixedSlider = Boolean(this.GM.getValue(this.Options.SWITCH_IS_FIXEDSILDER));
            }
            /**
             * 样式 - 背景
             * @method styleForBackground
             * @returns {string} 样式
             */
            styleForBackground() {
                let defaultURL = this.backgoundURL;
                if (this.isImportBackground) {
                    return `body{background-color:transparent!important}body:after{content:"";position:fixed;top:0;bottom:0;left:0;right:0;background-image:url(${defaultURL})!important;background-size:cover!important;z-index:-1}#head{background-color:hsla(0, 0%, 100%, 0.65)!important;border-bottom-color:hsla(0, 0%, 52%, 0.3)!important}#content_left .c-container,#rs{border:none!important;background: hsla(0, 0%, 100%, 0.85)!important}#form>.s_ipt_wr.bg{background:#fff!important}#u>a{color: hsl(216, 80%, 63%)!important}#u>a:after{background:transparent!important;border:1px solid!important;}`;
                }
                else {
                    return "";
                }
            }
            /**
             * 样式 - 固定侧边栏
             * @method styleForFixedSilder
             * @returns {string} 样式
             */
            styleForFixedSilder() {
                if (this.isImportFixedSlider) {
                    return "#s_tab{left:0!important;opacity:1!important;}";
                }
                else {
                    return "";
                }
            }
            /**
             * 样式  - 页面布局
             * @method styleForPageLayout
             * @returns {string} 样式
             */
            styleForPageLayout() {
                let layoutType = this.layoutType;
                switch (layoutType) {
                    case 1:
                        return "";
                    case 2:
                        return BAIDU_STYLES.ONE;
                    case 3:
                        return BAIDU_STYLES.TWO;
                    case 4:
                        return BAIDU_STYLES.THREE;
                }
            }
            /**
             * 样式 - 菜单
             * @method styleForMenu
             * @returns {string} 样式
             */
            styleForMenu() {
                return BAIDU_STYLES.MENU;
            }
            /**
             * 样式 - 结果页
             * @method styleForCommand
             * @returns {string} 样式
             */
            styleForCommand() {
                return BAIDU_STYLES.COMMON;
            }
            /**
             * 导入样式
             * @method import
             */
            import() {
                let style = this.Style;
                style.add(this.styleForCommand());
                style.add(this.styleForMenu());
                style.add(this.styleForPageLayout());
                style.add(this.styleForFixedSilder());
                style.add(this.styleForBackground());
                style.end();
            }
            /**
             * 初始化
             * @method init
             */
            init() {
                this.import();
            }
            /**
             * 执行
             * @method execute
             */
            execute() {
                this.init();
            }
        }
        /**
         * 菜单功能页
         * @class MenuItemsOptions
         * @extends MenuCommand
         */
        class MenuItemsOptions {
            constructor() {
                this.GM = GM;
                this.Options = Options;
                this.layoutTagName = "baidupage";
                this.switchTagName = "baiduswitch";
                //页面布局类型
                this.layoutType = Number(this.GM.getValue(this.Options.SELECT_PAGE));
            }
            /**
             * 获得 HTML - 页面布局选项
             * @param content 显示的内容
             * @param layoutType 页面布局类型
             */
            getContentPageSelect(content, layoutType) {
                let checked = this.layoutType === layoutType ? "checked" : "";
                return `<li><input type="radio" name="${this.layoutTagName}" value="${layoutType}" ${checked}>${content}</li>`;
            }
            /**
             * 获得 HTML - 功能选项选项
             * @param content 显示的内容
             * @param selection 功能配置
             */
            getContentFunSelect(content, selection) {
                let switchName = selection.name;
                let checked = Boolean(this.GM.getValue(selection))
                    ? "checked"
                    : "";
                return `<li><input type="checkbox" name="${this.switchTagName}" value="${switchName}" ${checked}>${content}</li>`;
            }
            /**
             * 获得 HTML - 保存
             * @param content 显示的内容
             */
            getContentSava(content) {
                let idName = Config.MENU_SAVA_ID;
                return `<input id='${idName}' type='button' style='display:block;width:100%' value='${content}'>`;
            }
            //获取整体 HTML
            getContent() {
                let content = "";
                content += "<ol>页面选择";
                content += this.getContentPageSelect("普通页面", 1);
                content += this.getContentPageSelect("单页居中", 2);
                content += this.getContentPageSelect("双页居中", 3);
                content += this.getContentPageSelect("三页居中", 4);
                content += "</ol>";
                content += "<ol>功能选择";
                content += this.getContentFunSelect("使用重定向", this.Options.SWITCH_IS_REDIRECT);
                content += this.getContentFunSelect("自动下一页", this.Options.SWITCH_IS_LOADPAGE);
                content += this.getContentFunSelect("固定侧边栏", this.Options.SWITCH_IS_FIXEDSILDER);
                content += this.getContentFunSelect("加载背景", this.Options.SWITCH_IS_BACKGOUND);
                content += "</ol>";
                content += this.getContentSava("保存");
                return content;
            }
            /**
             * 绑定保存事件
             */
            bindSavaClick() {
                let sava = document.getElementById(Config.MENU_SAVA_ID);
                sava.onclick = event => {
                    let e = event || window.event;
                    //页面布局选项
                    let radios = document.getElementsByName(this.layoutTagName);
                    for (let i = 0, radio; (radio = radios[i++]);) {
                        if (radio.checked) {
                            let name = Options.SELECT_PAGE.name;
                            let value = radio.value;
                            this.GM.setValue(name, value);
                            break;
                        }
                    }
                    //功能选项
                    let checkboxs = document.getElementsByName(this.switchTagName);
                    for (let i = 0, checkbox; (checkbox = checkboxs[i++]);) {
                        let name = checkbox.value;
                        if (checkbox.checked) {
                            this.GM.setValue(name, true);
                        }
                        else {
                            this.GM.setValue(name, false);
                        }
                    }
                    e.stopPropagation();
                    location.href = location.href;
                };
            }
            /**
             * 插入节点
             */
            insertNode() {
                let container = document.getElementById("u"), content = this.getContent(), div = document.createElement("div");
                div.id = Config.MENU_PAGE_ID;
                div.style.display = "none";
                div.innerHTML = `<div>${content}</div>`;
                container.insertBefore(div, container.firstChild);
            }
            /**
             * 初始化
             */
            init() {
                let isExecute = document.getElementById(Config.MENU_PAGE_ID);
                if (!isExecute) {
                    this.insertNode();
                    //异步执行绑定事件
                    Baidu.delayRun(() => {
                        this.bindSavaClick();
                    }, 10);
                }
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    try {
                        this.init();
                    }
                    catch (e) {
                        throw new Error(e);
                    }
                };
            }
        }
        /**
         * 菜单按钮
         * @class MenuButton
         * @extends MenuCommand
         */
        class MenuButton {
            constructor() {
                this.MenuItemsOptions = new MenuItemsOptions();
            }
            /**
             * 修复未登录按钮错位问题
             */
            fixedNoLoginButtonPosition() {
                let container = document.getElementById("u");
                let isExecute = container.querySelector("#u>a[name='tj_login']");
                if (isExecute) {
                    let selector = document.getElementById(Config.MENU_BUTTON_ID);
                    selector.setAttribute("style", "top:-4px!important");
                }
            }
            /**
             * 第二次单击隐藏
             */
            bindClickHide() {
                document.onclick = event => {
                    let e = event || window.event;
                    let container = document.getElementById("container");
                    let items = document.getElementById(Config.MENU_PAGE_ID);
                    let isScreenClick = e.target
                        ? e.target == container
                        : e.srcElement == container;
                    if (isScreenClick) {
                        items.style.display = "none";
                    }
                };
            }
            /**
             * 单击打开功能选项页
             */
            bindClick() {
                let container = document.getElementById(Config.MENU_BUTTON_ID);
                container.onclick = event => {
                    let e = event || window.event;
                    let items = document.getElementById(Config.MENU_PAGE_ID);
                    let style = items.style;
                    let isShow = style.display === "block";
                    if (isShow) {
                        style.display = "none";
                    }
                    else {
                        style.display = "block";
                    }
                    //阻止冒泡
                    e.stopPropagation();
                };
            }
            /**
             * 插入节点
             */
            insertNode() {
                let container = document.getElementById("u");
                let div = document.createElement("a");
                div.id = Config.MENU_BUTTON_ID;
                div.innerHTML = "自定义";
                container.insertBefore(div, container.firstChild);
            }
            /**
             * 初始化
             */
            init() {
                let isExecute = document.getElementById(Config.MENU_BUTTON_ID);
                if (!isExecute) {
                    this.insertNode();
                    //异步绑定事件
                    Baidu.delayRun(() => {
                        this.bindClick();
                        this.bindClickHide();
                    }, 10);
                }
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    Promise.resolve().then(() => {
                        this.init();
                    });
                };
                //执行菜单功能面板
                Promise.resolve().then(() => {
                    this.MenuItemsOptions.execute();
                });
            }
        }
        /**
         * 多页布局
         * @class MUlPageLayout
         */
        class MulPageLayout {
            constructor() {
                this.GM = GM;
                this.DOM = Baidu.DOM;
                this.container = null;
                this.lists = null;
                //多列布局值集合
                this.layoutTypes = [3, 4];
                //当前布局类型
                this.layoutType = Number(this.GM.getValue(Options.SELECT_PAGE));
                //根据 类名 模拟高度
                this.VIRTUAL_HEIGHTS_BY_CLASSNAE = [
                    { name: ".c-container>.op-b2b-straight", value: 420 },
                    { name: ".c-container>.c-offset", value: 320 },
                    { name: ".c-container>.c-border", value: 270 },
                    {
                        name: ".c-container>.op-tieba-general-lookmore",
                        value: 260
                    },
                    {
                        name: ".c-container>.op-img-address-desktop-cont",
                        value: 210
                    },
                    { name: ".c-container>.c-gap-top-small", value: 130 }
                ];
                //根据 srcid 属性值 模拟高度
                this.VIRTUAL_HEIGHTS_BY_SRCID = [
                    { name: 1599, value: 128 },
                    { name: 1508, value: 170 },
                    { name: 1527, value: 170 },
                    { name: 1528, value: 220 },
                    { name: 1529, value: 220 },
                    { name: 1537, value: 510 },
                    { name: 1539, value: 280 },
                    { name: 1545, value: 230 },
                    { name: 1547, value: 230 },
                    { name: 4515, value: 540 },
                    { name: 5103, value: 400 },
                    { name: 8041, value: 260 },
                    { name: 8191, value: 200 },
                    { name: 10, value: 260 },
                    { name: 13, value: 220 },
                    { name: 19, value: 200 }
                ];
            }
            /**
             * 是否为多列布局
             * @return {boolean}
             */
            isMulLayout() {
                let layoutType = this.layoutType;
                let layoutTypes = this.layoutTypes;
                return layoutTypes.includes(layoutType);
            }
            /**
             * 初始化
             */
            resetDOM() {
                this.container = null;
                this.lists = null;
            }
            /**
             * 获取 #content_left 节点
             */
            getDomForContainer() {
                if (!this.container) {
                    this.container = this.DOM.getElementById("content_left");
                }
                return this.container;
            }
            /**
             * 获取 list 节点
             */
            getDomForLists() {
                if (!this.lists) {
                    let container = this.getDomForContainer();
                    this.lists = container.getElementsByClassName("list");
                }
                return this.lists;
            }
            //获取list高度合集
            getListsHeight() {
                let lists = this.getDomForLists();
                let heights = [];
                for (let i = 0, list; (list = lists[i++]);) {
                    heights.push(list.clientHeight);
                }
                return heights;
            }
            /**
             * 模拟高度
             * 防止获取真实高度导致性能问题
             * @param item
             */
            getItemVirtualHeight(item) {
                // 获取虚拟高度合集
                let VIRTUAL_DATAS = this.VIRTUAL_HEIGHTS_BY_SRCID;
                //默认高度
                let height = 122;
                //匹配 srcid 正则
                let reg = /srcid="\d+"/;
                //获取srcid
                let srcid = Number(/\d+/.exec(reg.exec(item.outerHTML)));
                //根据srcid值获取虚拟高度
                for (let i = 0, data; (data = VIRTUAL_DATAS[i++]);) {
                    //大于 10000 直接赋予新高度
                    if (srcid > 10000) {
                        height = 310;
                        break;
                    }
                    else if (srcid === data["name"]) {
                        height = data["value"];
                        break;
                    }
                }
                return height;
            }
            /**
             * 01 - 添加内容到lists
             * 使用 DOM 到 DOM, 即将 #content_left 下的子元素移动到 lists
             * 注意:需要提前将 DOM片段 添加到 #content_left下
             */
            addWebUseDomToDom() {
                let container = this.getDomForContainer();
                let lists = this.getDomForLists();
                let items = container.querySelectorAll("#content_left>.c-container");
                let heights = this.getListsHeight();
                let frames = [];
                //初始化
                for (let i = 0, length = lists.length; i < length; i++) {
                    //缓存
                    frames.push(document.createDocumentFragment());
                }
                //将 item 添加到虚拟DOM中
                for (let i = 0, item; (item = items[i++]);) {
                    //获取最小的高度值
                    let minHeight = Reflect.apply(Math.min, null, heights);
                    //获取最小的高度的索引值
                    let index = heights.indexOf(minHeight);
                    //添加到高度
                    heights[index] += item.clientHeight;
                    //缓存
                    frames[index].appendChild(item);
                }
                //添加到真实DOM
                for (let i = 0, length = lists.length; i < length; i++) {
                    Baidu.delayRun(() => {
                        lists[i].appendChild(frames[i]);
                    }, i);
                }
            }
            /**
             * 02 - 添加内容到lists
             *
             *
             * @param frame DOM片段
             */
            addWebUseFrameToDom(frame) {
                //获取lists
                let lists = this.getDomForLists();
                //获取列表合集
                let items = frame.getElementsByClassName("c-container");
                //获取初始化高度集合
                let heights = this.getListsHeight();
                //将 item 添加到list中
                for (let i = 0, item; (item = items[i]);) {
                    //获取高度合集
                    //获取最小的高度值
                    let minHeight = Reflect.apply(Math.min, null, heights);
                    //获取最小的高度的索引值
                    let index = heights.indexOf(minHeight);
                    //添加到list中
                    lists[index].appendChild(item);
                    //更新高度
                    heights = this.getListsHeight();
                }
            }
            /**
             * 03 - 添加内容到 lists
             * 使用"模拟高度"进行添加
             *
             * @param frame DOM片段
             */
            addWebUseVirtualToDom(frame) {
                let lists = this.getDomForLists();
                let frames = [];
                //获取列表合集
                let items = frame.getElementsByClassName("c-container");
                if (items.length <= 0) {
                    return;
                }
                //获取初始化高度集合
                let heights = this.getListsHeight();
                //初始化
                for (let i = 0, length = lists.length; i < length; i++) {
                    frames[i] = document.createDocumentFragment();
                }
                //将 item 添加到list中
                for (let i = 0, item; (item = items[i]);) {
                    //获取最小的高度值
                    let minHeight = Reflect.apply(Math.min, null, heights);
                    //获取最小的高度的索引值
                    let index = heights.indexOf(minHeight);
                    //获取模拟高度
                    heights[index] += this.getItemVirtualHeight(item);
                    //添加到list中
                    frames[index].appendChild(item);
                }
                Baidu.delayRun(() => {
                    //插入内容到list
                    for (let i = 0, length = lists.length; i < length; i++) {
                        lists[i].appendChild(frames[i]);
                    }
                }, 1);
            }
            /**
             * 是否存在list节点
             */
            hasListNode() {
                let lists = this.getDomForLists();
                return lists.length > 0;
            }
            /**
             * 向网页添加列表
             */
            insertListNode() {
                let layoutType = this.layoutType;
                let container = this.getDomForContainer();
                let frame = document.createDocumentFragment();
                //创建list节点
                for (let i = 1, div, length = layoutType; i < length; i++) {
                    div = document.createElement("div");
                    div.id = "list" + i;
                    div.className = "list";
                    frame.appendChild(div);
                }
                //将节点插入到文档中
                container.insertBefore(frame, container.firstChild);
                return this;
            }
            /**
             * 添加内容到 lists
             */
            addListContent(frame) {
                this.resetDOM();
                Baidu.delayRun(() => {
                    this.addWebUseVirtualToDom(frame);
                }, 0);
            }
            /**
             * 初始化
             */
            init() {
                try {
                    this.resetDOM();
                    if (!this.hasListNode()) {
                        //插入list节点并刷新节点
                        this.insertListNode();
                    }
                    this.addWebUseDomToDom();
                }
                catch (error) {
                    console.error(error);
                }
            }
            /**
             * 执行
             */
            execute() {
                if (this.isMulLayout()) {
                    Baidu.ready = () => {
                        this.init();
                    };
                }
            }
        }
        /**
         * 自动加载下一页
         * @class AutoLoadNextPage
         */
        class AutoLoadNextPage {
            /**
             * 构造函数
             */
            constructor() {
                //赋值
                this.GM = GM;
                //DOM
                this.DOM = Baidu.DOM;
                //实例化 - 多页布局
                this.MulpageLayout = new MulPageLayout();
                //实例化 - 重定向
                this.Redirect = new Redirect();
                //实例化 -
                this.Parser = new DOMParser();
                //减少频率
                this.Reduce = new ReduceExecute();
                this.isExecute = Boolean(this.GM.getValue(Options.SWITCH_IS_LOADPAGE));
            }
            /**
             * 重置
             */
            reset() {
                //是否第一次执行
                this.isFirstRun = true;
                //是否导入过
                (this.isImport = false),
                    //下一页真实地址
                    (this.realNextURL = null);
                //模板地址
                this.templateURL = null;
                //步进值(默认值)
                this.step = 0;
                //每页起始值
                this.count = 0;
                //偏移高度
                this.offsetHight = 1000;
                //缓存
                this.cache = [];
                //缓存量
                this.cacheSize = 1;
                //节点缓存
                this.container = this.DOM.getElementById("content_left");
            }
            /**
             * 获取真实下一个的地址
             * @returns {string} 下一页地址
             */
            getNextPageRealURL() {
                if (!this.realNextURL) {
                    let page = document.getElementById("page");
                    this.realNextURL = page
                        .getElementsByClassName("n")[0]
                        .getAttribute("href");
                }
                return this.realNextURL;
            }
            /**
             * 获取步进值
             * @returns {number} 步进值
             */
            getNextPageStepValue() {
                if (!this.step) {
                    //提取 &pn=20 中的20
                    let regParam = /(&pn=\d+)/;
                    let regValue = /\d+/;
                    let result = regParam.exec(this.getNextPageRealURL());
                    this.step = Number(regValue.exec(result));
                }
                return this.step;
            }
            /**
             * 获取模板地址
             * @returns {string} this.templateURL: 模板地址
             */
            getTempletURL() {
                this.templateURL =
                    this.templateURL ||
                        this.getNextPageRealURL().replace(/&pn=\d+/, "");
                return this.templateURL;
            }
            /**
             * 获取下一页合成地址
             * @returns {sting} 下一页的地址
             */
            getNextPageComposeURL() {
                this.count += this.getNextPageStepValue();
                return this.getTempletURL() + `&pn=${this.count}`;
            }
            /**
             * 判断是否存在缓存
             * @returns {boolean} 存在: true
             * @returns {boolean} 不存在:false
             */
            hasCache() {
                return this.cache.length >= this.cacheSize;
            }
            /**
             * 将响应文本添加到缓存中
             * @param responseText 响应文本
             */
            addCache(responseText) {
                //转化为DOM对象
                let reg = /<body[\s\S.]+<\/body>/;
                let parser = this.Parser;
                let htmlDoc = parser.parseFromString(reg.exec(responseText)[0], "text/html");
                //获取Items
                let items = htmlDoc
                    .getElementById("content_left")
                    .getElementsByClassName("c-container");
                //添加到缓存
                let frame = document.createElement("div");
                //appendchild 自动执行迭代器 导致 i++ (小心);
                for (let i = 0, item; (item = items[i]);) {
                    frame.appendChild(item);
                }
                //加入缓存
                this.cache.push(frame);
            }
            /**
             * 监测滚动位置
             */
            checkScrollPosition() {
                if (this.Reduce.isNormalExecute()) {
                    this.Reduce.stopNormalExecute().regainNormalExecute(5);
                    let element = document.documentElement, clientHeight = element.clientHeight, scrollTop = element.scrollTop ||
                        window.pageYOffset ||
                        document.body.scrollTop ||
                        0, scrollHeight = Number(element.scrollHeight);
                    //判断
                    if (clientHeight + scrollTop + this.offsetHight >
                        scrollHeight) {
                        this.removeScrollEvent();
                        this.task();
                    }
                }
            }
            /**
             * 移除滚动事件
             */
            removeScrollEvent() {
                document.onscroll = event => {
                    let e = event || window.event;
                    e.preventDefault();
                };
                return this;
            }
            /**
             * 绑定滚动触发事件
             */
            bindScrollEvent() {
                document.onscroll = () => {
                    this.checkScrollPosition();
                };
            }
            /**
             * 将 DOM 插入到相应的位置
             */
            addItemsToWeb() {
                //插入内容到DOM节点
                if (this.MulpageLayout.isMulLayout()) {
                    this.MulpageLayout.addListContent(this.cache.shift());
                }
                else {
                    this.container.innerHTML += this.cache.shift().innerHTML;
                }
            }
            /**
             * 发送请求
             */
            requireNextPageContent() {
                this.GM.xmlhttpRequest({
                    method: "GET",
                    url: this.getNextPageComposeURL(),
                    timeout: 3000,
                    responseType: "text",
                    onload: response => {
                        if (response.status === 200 ||
                            response.status === 304) {
                            //如果不存在缓存,再发一次
                            if (!this.hasCache()) {
                                this.requireNextPageContent();
                            }
                            //添加响应文本到缓存
                            this.addCache(response.responseText);
                            //开始导入数据到网页
                            if (!this.isImport) {
                                this.import();
                            }
                        }
                    },
                    onerror: response => {
                        console.error(response);
                    }
                });
            }
            /**
             * 导入数据到网页
             */
            import() {
                this.isImport = true;
                //添加内容到网页
                this.addItemsToWeb();
                //重定向
                this.Redirect.execute();
                //绑定滚动事件
                Baidu.delayRun(() => {
                    this.removeScrollEvent().bindScrollEvent();
                }, 3);
            }
            /**
             * 任务调度
             * @param URL
             */
            task() {
                //设置有导入过
                this.isImport = false;
                //发送请求
                this.requireNextPageContent(); //如果有缓存
                //如果存在缓存
                if (this.hasCache()) {
                    this.import();
                }
            }
            /**
             * 隐藏元素
             */
            hideElement() {
                let page = document.getElementById("page");
                page.style.visibility = "hidden";
            }
            /**
             * 初始化
             */
            init() {
                //重置配置
                this.reset();
                //开始加载
                this.task();
                //隐藏元素
                Baidu.delayRun(() => {
                    this.hideElement();
                }, 3);
            }
            /**
             * 入口
             * @returns {void}
             */
            execute() {
                if (this.isExecute) {
                    Baidu.ready = () => {
                        this.init();
                    };
                }
            }
        }
        /**
         * 重定向
         * @class Redirect
         */
        class Redirect {
            constructor() {
                this.GM = GM;
                this.DOM = Baidu.DOM;
                //重定向后需添加类名(防止重复重定向)
                this.redirectClassName = "isredirect";
                //是否执行
                this.isExecute = Boolean(this.GM.getValue(Options.SWITCH_IS_REDIRECT));
            }
            /**
             * 重定向
             * @param item a节点
             */
            redirect(item) {
                this.GM.xmlhttpRequest({
                    method: "HEAD",
                    url: item.href,
                    onload: response => {
                        let realURL = response.finalUrl;
                        item.href = realURL;
                        //加入重定向标志
                        item.className = this.redirectClassName;
                        //移除不必要的属性
                        item.removeAttribute("data-click");
                    }
                });
            }
            /**
             * 开始
             */
            start() {
                let container = this.DOM.getElementById("content_left");
                let items = container.querySelectorAll("h3>a:not([class])");
                for (let i = 0, item; (item = items[i++]);) {
                    //延时执行
                    Baidu.delayRun(() => {
                        this.redirect(item);
                    }, i);
                }
            }
            /**
             * 初始化
             */
            init() {
                this.start();
            }
            /**
             * 执行
             */
            execute() {
                if (this.isExecute) {
                    Baidu.ready = () => {
                        Baidu.delayRun(() => {
                            this.init();
                        }, 5);
                    };
                }
            }
        }
        /**
         * 回到顶部
         * @class BackToTop
         */
        class BackToTop {
            /**
             * 单击回到顶部
             */
            bindClick() {
                let container = document.getElementsByClassName("s_form")[0];
                container.onclick = event => {
                    let e = event || window.event;
                    let isContainer = e.target
                        ? e.target === container
                        : e.srcElement === container;
                    if (isContainer) {
                        //setInterval方案
                        let element = document.documentElement;
                        let body = document.body;
                        let node = element.scrollTop ? element : body;
                        let top = node.scrollTop;
                        let step = top / 20;
                        let timer = setInterval(() => {
                            if (node.scrollTop <= 0) {
                                node.scrollTop = 0;
                                clearInterval(timer);
                            }
                            node.scrollTop -= step;
                        }, 10);
                        e.stopPropagation();
                    }
                };
            }
            /**
             * 初始化
             */
            init() {
                this.bindClick();
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    Promise.resolve().then(() => {
                        Baidu.delayRun(() => {
                            this.init();
                        }, 10);
                    });
                };
            }
        }
        /**
         * 谷歌
         * 双击使用 google 搜索
         * @class Google
         */
        class Google {
            googleSearch() {
                let googlePath = "https://www.google.com/search?q=";
                let searchContent = document.getElementById("kw").value.trim();
                let url = googlePath + encodeURIComponent(searchContent);
                window.open(url);
            }
            /**
             * 绑定双击打开Google搜索
             */
            bindDoubleClick() {
                let button = document.getElementById("su");
                button.ondblclick = () => {
                    this.googleSearch();
                };
            }
            /**
             * 初始化
             */
            init() {
                this.bindDoubleClick();
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    Promise.resolve().then(() => {
                        this.init();
                    });
                };
            }
        }
        /**
         * 替换首页搜索栏
         * @class ReplaceSearch
         */
        class ReplaceSearch {
            constructor() {
                this.inputId = "baiduinput";
                this.searchPath = "https://www.baidu.com/s?ie=UTF-8&wd=";
            }
            /**
             * 搜索
             */
            search() {
                let value = document.getElementById(this.inputId).value.trim();
                if (value !== "") {
                    location.href = this.searchPath + encodeURIComponent(value);
                }
            }
            /**
             * 绑定提交事件
             */
            bindSubmit() {
                let button = document.getElementById("su");
                button.setAttribute("type", "button");
                button.onclick = event => {
                    let e = event || window.event;
                    this.search();
                    e.stopPropagation();
                };
            }
            /**
             * 检测输入
             */
            bindKeydown() {
                let input = document.getElementById(this.inputId);
                input = document.getElementById("form");
                input.onkeydown = event => {
                    let e = event || window.event;
                    let keyCode = e.keyCode || e.which || e.charCode;
                    if (keyCode === 13) {
                        this.search();
                    }
                    e.stopPropagation();
                };
            }
            /**
             * 插入节点
             * 覆盖原来的搜索框
             */
            insertNode() {
                //屏蔽原来文本输入
                document
                    .getElementById("kw")
                    .setAttribute("disabled", "disabled");
                let container = document.getElementById("s_kw_wrap") ||
                    document.getElementsByClassName("s_ipt_wr")[0];
                let div = document.createElement("input");
                div.id = this.inputId;
                div.type = "text";
                div.autofocus = true;
                div.autocomplete = "off";
                container.appendChild(div);
                //延时聚焦
                Promise.resolve().then(() => {
                    document.getElementById(this.inputId).focus();
                });
            }
            /**
             * 初始化
             */
            init() {
                try {
                    this.insertNode();
                    Promise.resolve().then(() => {
                        this.bindSubmit();
                        this.bindKeydown();
                    });
                }
                catch (e) {
                    throw new Error(e);
                }
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    this.init();
                };
            }
        }
        /**
         * 执行广告和无用的节点
         * @class RemoveNode
         */
        class RemoveNode {
            constructor() {
                this.nodes = ["content_right", "content_bottom", "foot"];
                this.style = "display:block !important";
            }
            /**
             * 根据 ID 移除
             */
            removeNodeForID() {
                let items = this.nodes;
                for (let i = 0, item; (item = items[i++]);) {
                    let node = document.getElementById(item);
                    node.parentNode.removeChild(node);
                }
            }
            removeNodeForStyle() {
                let container = document.getElementById("content_left");
                let items = container.querySelectorAll(`#content_left>div[style*="${this.style}"]`);
                for (let i = 0, item; (item = items[i++]);) {
                    item.parentNode.removeChild(item);
                }
            }
            /**
             */
            init() {
                try {
                    this.removeNodeForID();
                }
                catch (error) { }
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    this.init();
                };
            }
        }
        /**
         * 快捷键
         * @class ShortcutKeys
         */
        class ShortcutKeys {
            constructor() {
                this.Google = new Google();
                this.filters = Config.FILTERS;
                this.target = null;
                this.KEY_ENTER = 13;
                this.KEY_ALT = 18;
                this.KEY_SHIFT = 16;
                this.KEY_CTRL = 17;
                this.KEY_GOOGLE = "G";
            }
            /**
             * 过滤搜索
             */
            filterSearch(filterName) {
                //移除如 "-baijiahao" 正则
                let reg1 = /\s\-\S+/;
                //移除如 "site:baidu" 正则
                let reg2 = /\ssite\:\S+/;
                let URL = "https://www.baidu.com/s?ie=utf-8&wd=";
                let content = document.getElementById("kw").value.trim();
                content = content.replace(reg1, "").trim();
                content = content.replace(reg2, "").trim();
                location.href =
                    URL + encodeURIComponent(content) + " " + filterName;
            }
            /**
             * 选择全部
             */
            selectAllContent() {
                let input = document.getElementById("kw");
                input.focus();
                input.selectionStart = 0;
                input.selectionEnd = input.value.length;
            }
            /**
             * 绑定快捷键
             */
            bindKeys() {
                let defaultTarget = this.target;
                document.onkeyup = event => {
                    let e = event || window.event;
                    if (e.target === defaultTarget || e.target === document) {
                        let keyCode = e.keyCode || e.which || e.charCode;
                        //Ctrl + Enter 全选中
                        if (keyCode == this.KEY_ENTER && e.ctrlKey) {
                            this.selectAllContent();
                            return;
                        }
                        //谷歌搜索
                        if (keyCode ===
                            this.KEY_GOOGLE.toUpperCase().charCodeAt() && !e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
                            this.Google.googleSearch();
                            return;
                        }
                        //过滤搜索
                        for (let { name, value } of this.filters) {
                            if (keyCode === name.toUpperCase().charCodeAt() && !e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
                                this.filterSearch(value);
                                return;
                            }
                        }
                    }
                    e.stopPropagation();
                };
            }
            /**
             * 重置
             */
            reset() {
                this.target = document.getElementsByTagName("body")[0] || null;
            }
            /**
             * 初始化
             */
            init() {
                try {
                    this.reset();
                    this.bindKeys();
                }
                catch (error) { }
            }
            /**
             * 执行
             */
            execute() {
                Baidu.ready = () => {
                    this.init();
                };
            }
        }
        /**
         * Base地址重置
         */
        class BaseURL {
            run() {
                location.href = location.href.replace("https://www.baidu.com/#", "https://www.baidu.com/s?");
            }
        }
        /**
         *  首页
         */
        class PageIndex {
            run() {
                //组合模式
                let command = new Commond();
                command.add(new ImportIndexStyle());
                command.add(new ReplaceSearch());
                command.execute();
            }
        }
        /**
         *  搜索结果页
         */
        class PageCommon {
            run() {
                /**
                 * 01 - 初始化执行
                 */
                let command = new Commond();
                command.add(new ImportCommonStyle());
                command.add(new MenuButton());
                command.add(new MulPageLayout());
                command.add(new AutoLoadNextPage());
                command.add(new Redirect());
                command.add(new BackToTop());
                command.add(new Google());
                command.add(new ShortcutKeys());
                command.execute();
                /**
                 * 02 - 设置标志位
                 * 防止后期多次无用执行
                 */
                let avoidMulExecute = new AvoidMulExecute();
                //设置标志位
                Baidu.ready = () => {
                    avoidMulExecute.setSign();
                };
                /**
                 * 03 - 监测 DOM
                 */
                //调用函数
                let mutationfunc = () => {
                    //只执行一次
                    if (!avoidMulExecute.hasSign()) {
                        //设置标志位
                        avoidMulExecute.setSign();
                        //清除缓存
                        Baidu.DOM.deleteCache();
                        //执行
                        command.execute();
                    }
                };
                //加载完成后 - 根据 DOM 变化重新执行函数( 防止Bash值改变时不触发脚本)
                window.onload = () => {
                    let MutationObserver = window.MutationObserver ||
                        window.WebKitMutationObserver ||
                        window.MozMutationObserver;
                    if (!!MutationObserver) {
                        let observer = new MutationObserver(mutationfunc);
                        let wrapper = document.querySelector("#wrapper");
                        let observerConfig = {
                            childList: true,
                            subtree: true
                            //"attributes": true,
                            //"characterData":true,
                            //"attributesFilter": ["class"],
                        };
                        //开始观察
                        observer.observe(wrapper, observerConfig);
                    }
                    else {
                        console.error("百度搜索-优化: 浏览器不兼容 MutationObserver 接口, 请升级浏览器版本");
                    }
                };
            }
        }
        /**
         * 简单工厂
         */
        class Factory {
            /**
             *
             * @param url
             */
            static create(url) {
                //BASE地址(BASE地址会导致样式跳转,需要重定向)
                const URL_BASE = "https://www.baidu.com/#";
                //普通页 01
                const URL_COMMON_01 = "https://www.baidu.com/s";
                //普通页 02
                const URL_COMMON_02 = "https://www.baidu.com/baidu";
                //首页
                const URL_INDEX = "https://www.baidu.com";
                //返回BASE
                if (url.startsWith(URL_BASE)) {
                    return new BaseURL();
                }
                //返回结果页
                if (url.startsWith(URL_COMMON_01)) {
                    return new PageCommon();
                }
                //返回结果页
                if (url.startsWith(URL_COMMON_02)) {
                    return new PageCommon();
                }
                //返回首页
                if (url.startsWith(URL_INDEX)) {
                    return new PageIndex();
                }
            }
        }
        /**
         * 启动函数
         */
        Baidu.start = () => {
            Factory.create(location.href).run();
        };
        //返回对象
        return Baidu;
    })(BaiduConfig);
    //启动
    try {
        Baidu.start();
    }
    catch (msg) {
        if (Config.IS_DEBUG) {
            console.error(msg);
        }
    }
})();