Baidu++

By blizzchris Last update Nov 15, 2009 — Installed 5,462 times. Daily Installs: 49, 64, 67, 51, 43, 41, 38, 39, 57, 45, 43, 23, 26, 35, 29, 15, 33, 27, 27, 25, 26, 16, 21, 50, 46, 45, 30, 24, 20, 17, 23, 22

There are 72 previous versions of this script.

Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)

var meta = <><![CDATA[
// ==UserScript==
// @name           baidu++
// @namespace      http://www.5isharing.com
// @version        1.5.0
// @include        http://www.baidu.com/s?* 
// @include        http://www.baidu.com/baidu?*
// @description    增强百度搜索结果页
// @copyright      2009+, chrisyue
// @license        GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==
]]></>.toString();

// ==Functions==
function $(id)
{
    return document.getElementById(id);
}

function c(cls, parent)
{
    return (parent || document).getElementsByClassName(cls);
}

function t(tag, parent)
{
    return (parent || document).getElementsByTagName(tag);
}

function n(name)
{
    return document.getElementsByName(name);
}

function x(xpath, element, type, result)
{
    return document.evaluate(xpath, element || document, 
                             null,  type || 7, result);
}

function create(type)
{
    return document.createElement(type);
}

function createText(text)
{
    return document.createTextNode(text);
}

function remove(elm)
{
    if (elm.snapshotItem) {
        for (var i = 0; i < elm.snapshotLength; i++) {
            remove(elm.snapshotItem(i));
        }
    } else if (elm[0]) {
        while (elm[0]) {
            remove(elm[0]);
        }
    } else {
        elm.parentNode.removeChild(elm);
    }
}

function append(elm, parent, first)
{
    if (elm.snapshotItem) {
        for (var i = 0; i < elm.snapshotLength; i++) {
            append(elm.snapshotItem(i), parent, first);
        }
    } else if (elm[0]) {
        for (var i = 0; i < elm.length; i++) {
            append(elm[i], parent, first);
        }
    } else {
        if (first && parent.firstChild) {
            parent.insertBefore(elm, parent.firstChild);
        } else {
            parent.appendChild(elm);
        }
    }
}

function clear(elm)
{
    while (elm.firstChild) remove(elm.firstChild);
}

function before(n, o)
{
    o.parentNode.insertBefore(n, o);
}

function after(n, o)
{
    o.nextSibling ? before(n, o.nextSibling) : append(n, o.parentNode);
}

function gm(name, value)
{
    var ret;
    if ((ret = GM_getValue(name)) || typeof ret == "boolean") {
        return ret;
    }
    return value;
}

function getTld(hostname)
{
    // a very easy way, not very accurate
    var hostParts = hostname.split(".");
    if (hostParts.length < 3) return hostname;
    // this info must be no mistake 'cause it is from wiki
    var gTLD = ["aero", "asia", "cat", "coop", "int", "com", "net", "org", "gov", "edu", 
                "biz", "info", "name", "jobs", "mil", "mobi", "museum", "pro", "tel", "travel"];
    var rootDomain = hostParts[hostParts.length - 2] + "."
                   + hostParts[hostParts.length - 1];
    if (gTLD.hasGot(hostParts[hostParts.length - 2])) {
        rootDomain = hostParts[hostParts.length - 3] + "." 
                   + rootDomain;
    }
    return rootDomain;
}

function generateImageFromUrl(image, url, data)
{
    // this is the most interesting part ... I'm so cool :)
    var request = {
        method: "GET",
        url: url,
        overrideMimeType: 'text/plain; charset=x-user-defined',
        onload: function(xhr) {
            var data = xhr.responseText.toBinary();
            var base64_data = btoa(data);
            var data_url = 'data:' + getMimeFromData(data)
                         + ';base64,' + base64_data;
            image.src = data_url;
        }
    }
    
    if (data) {
        request.method = "POST";
        request.headers = {'Content-type':'application/x-www-form-urlencoded'};
        request.data = data;
    }
    
    GM_xmlhttpRequest(request);
}

function getMimeFromData(data)
{
    if( 'GIF' == data.substr(0,3) ) return 'image/gif';
    else if( 'PNG' == data.substr(1,3) ) return 'image/png';
    else if( 'JFIF' == data.substr(6,4) ) return 'image/jpg';
    return false;
}

function parseHeaders(metadataBlock)
{
    var headers = {};
    var line, name, prefix, header, key, value;

    var lines = metadataBlock.split(/\n/).filter(/\/\/ @/);
    for (var i = 0; i < lines.length; i++) {
        line = lines[i];
        [, name, value] = line.match(/\/\/ @(\S+)\s*(.*)/);

        switch (name) {
            case "licence":
                name = "license";
                break;
        }

        [key, prefix] = name.split(/:/).reverse();

        if (prefix) {
            if (!headers[prefix]) 
                headers[prefix] = new Object;
            header = headers[prefix];
        } else
            header = headers;

        if (header[key] && !(header[key] instanceof Array))
            header[key] = new Array(header[key]);

        if (header[key] instanceof Array)
            header[key].push(value);
        else
            header[key] = value;
    }

    headers["licence"] = headers["license"];

    return headers;
}

Array.prototype.hasGot = function(value) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == value) return true;
    }
    return false;
}

String.prototype.toBinary = function() {
    var data_string = '';
    var il = this.length
    for (var i = 0; i < il; i++) {
        data_string += String.fromCharCode(this[i].charCodeAt(0) & 0xff);
    }
    return data_string;
}
// ==/Functions==

var baidu = {

    results: function() {
        return x("//td[@class='f']/parent::tr/parent::tbody/parent::table");
    },
    
    related: function() {
        return x("//td[text()='相关搜索']/ancestor::div[1]").snapshotItem(0);
    },
    
    info: function() {
        return c("bi")[0];
    },

    ads: function() {
        return x("//div[starts-with(@style, 'border-left')][1]").snapshotItem(0);
    },
    
    promotions: function() {
        return x("//a[text()='推广']/ancestor::table");
    },
    
    sponsors: function() {
        return x("//td[@class='f16']/ancestor::table");
    },
    
    brands: function() {
        return x("//a[text()='品牌推广']/ancestor::table");
    },
    
    keyword: function() {
        return n("wd")[0].value;
    },
    
    stock: function() {
        return x("//a[starts-with(@href, 'http://baidu.hexun.com/stock/q.php?code=')]/ancestor::table[not(@style)]");
    },
    
    tip: function() { // 您要找的是不是
        return x("//strong[@class='f14'][1]/parent::p[1]").snapshotItem(0);
    },
    
    tool: function() {
        return x("//p/parent::ol[1]").snapshotItem(0);
    },
    
    body: function() {
        return document.body;
    },
    
    sideBar: function() {
        return x("//table[@align='right'][1]").snapshotItem(0);
    },
    
    mobile: function() {
        return x("//div[@style='margin: 0pt 0pt 0pt 15px; font-size: 14px; line-height: 20px;'][1]")
                .snapshotItem(0);
    },
    
    ip: function() {
        return x("//p[@style='margin: 0px; padding: 0pt 0pt 0pt 15px; line-height: 120%; font-size: 14px;'][1]")
                .snapshotItem(0);
    },
    
    zhidao: function() {
        return x("//p[@style='margin: 24px 0pt 5px 15px; line-height: 25px;'][1]").snapshotItem(0);
    },
    
    exchange: function() {
        return x("//div[@style='margin: 0pt 0pt 0pt 15px; line-height: 150%;'][1]").snapshotItem(0);
    },
    
    get: function(name, refresh) {
        var ret;
        var code = <><![CDATA[
        if (this._name == null || refresh) {
            this._name = this.name();
        }
        ret = this._name;
]]></>.toString();
        eval(code.replace(/name/g, name));
        return ret;
    }
};

var image = {
    loading: "data:image/gif;base64,R0lGODlhIgAiAPQAADk5OVJSUlpaWmtra3t7e4SEhIyMjJSUlJycnKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAgFAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAIgAiAAAFhiAljmRJLYmprqx4AG1cBgb5yjjVCDacxxKBYnT7lQoI0mBA9BlHEOToIYC4nE9RNCUa1CjFLLTAdQQmYKyYshUJkodAVhFBQwkpB2OtSygYEVMFVnwjDSh0hSwSDX6EiioOj5CUJRIPEJiamJATERESn6CflaWmp6ipqqusra6vsLGys6ohACH5BAgFAAAALAAAAAAiACIAhCEhISkpKVpaWmNjY2tra3Nzc4SEhIyMjJSUlKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWTICWOZElJiqmuZkMqAiurUPHG4wNEM2ukIsWAJAj0SBPSwzASjiQA15HyUCRFEoPUKSIApqNF4kpBALkUwAIctoqWSW4BQGYv3BTDmhs4sEsKQAx%2BCjYJABBTDg91EwprKCQJBGwQixIjjg5%2FLBAPDhF1nCwRDw%2BJoz0SmKmtrq%2BwsbKztLW2t7i5uru8vb6%2FwL4hACH5BAgFAAAALAAAAAAiACIAhCEhISkpKTk5OUJCQkpKSlJSUlpaWmNjY3Nzc4SEhIyMjJSUlJycnK2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWT4CWOZCk6ZqqaFAkha5xSjJuQiiHHTTRCt1FBsltNGj%2BYaKEriiQTUoXRugBHB%2BSoEpBFoiMHRPQSPQqVEQUg2H3VNWswobxMAIOiBTrqXR43FQU%2BdnhOFxZvFxFIEAsXDE0SAASHIntRFYRmPpMFliOJVSkAn6BOQaeqq6ytrq%2BwsbKztLW2t7i5uru8vb6%2FwIchACH5BAgFAAAALAAAAAAiACIAhCEhIUJCQlJSUlpaWnNzc4SEhIyMjJSUlJycnKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWVICWOZCk2Zqqu4qOwcDk55JOQShGvTzS6JMNrl3o8frdWwUc0TR6T1pCCMJAag2YL0kpKCtyTYEqUHClASm6kGBy0I4fPJiqcGQOyFnKEvBYFUW0IcCQTTCIONHiEJBIMhSUSAo0iDAEAABKRJEwSCpkBBJwmDgKZBIikJAUBOquwsbKztLW2t7i5uru8vb6%2FwMHCsCEAIfkECAUAAAAsAAAAACIAIgCEISEhKSkpQkJCWlpaY2Nja2tre3t7hISEjIyMlJSUnJycra2ttbW1vb29xsbGzs7O1tbW3t7e5%2Bfn7%2B%2Fv9%2Ff3%2F%2F%2F%2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYlgJY5kKU5mqq7nw76vBJGRAt%2FV5I4Ng8OyEWUh%2Bb0mM5FjQaIcjKWgSFE8GRJQkk70YJ4O2OxISrXaxKNJpNKlVCSHM7oUcbzjpQdhPsKfHAMDT3wVDVwGgQluhCIQBAMFcowiDAlrk5g4CZucnIt8AgEAogClAAiZqaqrrK2ur7CxsrO0tbavIQAh%2BQQIBQAAACwAAAAAIgAiAIQhISEpKSlKSkpra2t7e3uEhISMjIyUlJScnJylpaWtra21tbW9vb3GxsbOzs7W1tbe3t7n5%2Bfv7%2B%2F39%2Ff%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFjCAljmRpnmiqriwbPW1cOpJsS7AtQxA5KbqUYzL6LYInSI4iURyRpkeN6YSaIg6RJMGwmiTEZte3tHJJkAOh4BVlmY8CIVH2QhCFArBdYiQafIE6BwaFBgSIBGNehAYIj48Lb4KUIgkElSQKAAADPZkUCgEAAgagFAwCnAOnEQsARKeys7S1tre4uYEhACH5BAgFAAAALAAAAAAiACIAhCEhIUJCQkpKSlJSUlpaWmNjY2tra4yMjJSUlJycnK2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWEICWOZGmeaKqubOu%2BcCzP6EOvk2Pf6PRAvN4vePIBiSVjMkIcjiILRYIoEU0gUsaRGGEkFI4JcvRg7MboVYOxbrjd1WDiQK%2FTGen8ArFNPwoDBVNoYhQPCQQDCExBCgANIzmJBkQEAA4lEINBlph5IgMAZ3mhfWkCAKZoAQCfrq%2BwsS8hACH5BAgFAAAALAAAAAAiACIAhCEhIUJCQkpKSlJSUlpaWnNzc4SEhIyMjJSUlJycnKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWCYCWOZGmeaKqubOu%2BcCzPdG3feK7T1D5SkcfDN4E8IhId0Jj0SZC%2BaCoCqVqrucVCse0qHNLdgxGuPAwFxoQoghgMCUhOMmiMIgjDYVEzgBMDfCMTDQY1AQMiCQR2OggAaxWLgjkAlAuBOgUAJIAIcwCNIgsEOgIBZZuRUqFlPWUsIQAh%2BQQIBQAAACwAAAAAIgAiAIQxMTFSUlJaWlpjY2Nzc3OEhISMjIyUlJScnJylpaWtra21tbW9vb3GxsbOzs7W1tbe3t7n5%2Bfv7%2B%2F39%2Ff%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgSAljmRpnmiqrmzrvnAsz3Rt33iu73zv%2F8DgSRIhGosTHOTBbDIjwhvEAYQkFI2kD6JIMCA5BwEqiiwU2BqDmiiARxKrLHCgHAQiRIFsA9QlAVQUenw0fiIFBCN6En11FA4BfAgEWjOHIgMIJHo1mHYCljefFIE6pAZ4OaQ8B28uIQAh%2BQQIBQAAACwAAAAAIgAiAIQhISEpKSlCQkJSUlJaWlpjY2Nra2tzc3N7e3uEhISMjIyUlJScnJylpaWtra21tbW9vb3GxsbW1tbe3t7n5%2Bfv7%2B%2F39%2Ff%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFkOAljmRpnmiqrmzrvnAsz3Rt33iu73zv%2F8CgcEgcVShAS0QyqfwskigSR2k4RRaKJDJtRRqkyOQCcXSxkhfgcHEg2gpR%2BSqDAJAOw2WSmEKsMwIDInkiCg4jfxYxEwAPhAUiDwmLkg6VLgwBIw6RIglpIw9gamyQnAk1diSdIxYJYzMBnoQEJAsLOg62T4gvIQAh%2BQQIBQAAACwAAAAAIgAiAIQhISFaWlpjY2Nzc3N7e3uEhISMjIycnJylpaWtra21tbW9vb3GxsbOzs7W1tbe3t7n5%2Bfv7%2B%2F39%2Ff%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFkeAkjmRpnmiqrmzrvnAsz3Rt33iu73zv%2F8CgcEgs2hpAAiCCkjQkM6Vi4kiQHJDJw8GEDQDWycAwSSwmjKm20W19DyJIAHmYPhLdbVv1Hi0CIgdnZQ4jD2wrXwgkAXATCGoNYSJ6KgCOIg0BUBOCIwhZhkgvAgWfkwyTMhEBg2WuEqA0miQIqgqjOAquPQy5LSEAIfkECAUAAAAsAAAAACIAIgCEISEhMTExOTk5SkpKWlpaY2Nja2trc3Nze3t7hISEjIyMnJycra2ttbW1vb29xsbGzs7O1tbW3t7e5%2Bfn7%2B%2Fv9%2Ff3%2F%2F%2F%2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABY%2BgJY5kaZ5oqq5s675wLM90bd94ru987%2F%2FAoHCIexgWPUQAIHjoJgYAoAARVXADaeMqigwit2ZJQkhYJNURhTuTDMyWRMPiAEvAs0m5m7gywBURbC8TAwgjC0gWDXgREzEUBAdqCXh%2FIhNpL5IkEHCLeBYRFDYJDCOXInc1EocjjJ2DMAqnqKFntzapPoIwIQAh%2BQQIBQAAACwAAAAAIgAiAIQ5OTlSUlJaWlpra2t7e3uEhISMjIyUlJScnJylpaWtra29vb3GxsbOzs7W1tbe3t7n5%2Bfv7%2B%2F39%2Ff%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFguAkjmRpnmiqrmzrvnAsz3Rt33iu73zv%2F0DYAUAsEgO4xWHJZAaDEsSi9zAEBI7dYRAYNEQPnEEgIGRFiYLkJmhESOnsI6xLEOiK7%2BNtQxToDwkiDhB9fyMKDGCFNH50ExAKfA58M4cjCwojlDoSeZuMOBCCIw%2BhN4kknD%2BrPhGVLSEAIfkECAUAAAAsAAAAACIAIgCEISEhKSkpQkJCWlpaY2Nja2trc3Nze3t7hISEjIyMlJSUpaWlra2ttbW1vb29xsbG1tbW3t7e5%2Bfn7%2B%2Fv9%2Ff3%2F%2F%2F%2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYRgJY5kaZ5oqq5s675wLM90bd94HgMOpZcEAAAB%2BZEMAYDAYRw9BkJmszI5LKY%2FCmPL5eIYA4K4QC4ksOhRhCH9NRIIRUQ3YSAQDIloflPciyMODDhyJYJ6FBM%2FDguKFRB6OQ0MjhMPOow%2Be3w3k5oVFBCONwyfFRKAUw%2BRTaFoq2mxNyEAIfkECAUAAAAsAAAAACIAIgCEISEhWlpaY2Njc3Nze3t7hISEjIyMnJycpaWlra2ttbW1vb29xsbGzs7O1tbW3t7e5%2Bfn7%2B%2Fv9%2Ff3%2F%2F%2F%2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYLgJI5kaZ5oqq5s675wLJPAMLdIfbOHvqsK3w%2B1ABCGokakFBQgAwFBgxRkIBcF6AIiWiJFEoMgMHB8TQ1D4swmOQ4IBFyOWA8bi8RCwc8v2oApDwxmbQ0JCQpcXxIMdQ5eEkiICYsiD4U%2FSiWYXm2dgaCAmJKjkIETDpaorK2ur4AhACH5BAgFAAAALAAAAAAiACIAhCEhITExMTk5OVJSUlpaWmNjY2tra3Nzc3t7e4SEhIyMjJycnKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5%2B%2Fv7%2Ff39%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWM4CWOZGmeaKqurDCw8PkAVWyPgHGrRD06gF3qMKCMKgCEEHUgGEWFwBKFKIoggMj0VJ2IArqpwktKDCQXiGLLSCQivkuCYNmSGu4FOm03QdoJZH0mFQ5ag4gnEg4ODYyODQ%2BDFhKVlpaJmTAWFHGJFJaefRMSEROidqQRdZoXEqytsbKztLW2t7i5tCEAOw%3D%3D"
};

var modules = {

    config: {
        name: function() {
            return "设置面板";
        },
        
        groups: [
            { title: "广告", color: "#fdd" },
            { title: "外观", color: "#ffd" },
            { title: "增强", color: "#dfd" },
            { title: "样式", color: "#fdf" },
            { title: "其他", color: "#ddf" },
            { title: "关于", color: "#dff" }
        ],
        
        btn: function() {
            if (!this._btn) {
                this._btn = create("a");
                with (this._btn) {
                    innerHTML = "设置<span style='color:#f99'>b</span><span style='color:#9f9'>a</span>i<span style='color:#99f'>d</span>u++";
                    href = "javascript:void(0)";
                    addEventListener("click", function() {
                        with (modules.config) {
                            shadow().show();
                            panel().show();
                            about();
                        }
                    }, false);
                    with (style) {
                        background = "#000";
                        color = "white";
                        textDecoration = "none";
                        padding = "0 3px";
                    }
                }
            }
            return this._btn;
        },
        
        about: function() {
            if (!this._about) {
                var helpBody = x(".//table[last()]/tbody[1]", this.options()).snapshotItem(0);
                var p = create("p"); this._about = p;
                with (p) {
                    innerHTML = <><![CDATA[
baidu++ v##VERSION##
<br /><a target="_blank" href="http://hi.baidu.com/chrisyue/blog/item/0e6655df55ff401b48540341.html">脚本发布页</a>
<br /><a target="_blank" href="http://userscripts.org/scripts/show/47560">脚本发布页(userscripts.org)</a>
<br /><a target="_blank" href="http://www.firefox.net.cn/forum/viewtopic.php?t=26711">脚本讨论页(www.firefox.net.cn)</a>
<br /><a href="mailto:blizzchris@gmail.com">联系作者</a>
<br />技术宅改变世界
]]></>.toString().replace(/##VERSION##/, modules.version.local());
                    addEventListener("dblclick", function() { // in loving memory of Michael Jackson the King of Pop ...
                        alert("19588292009625"); 
                    }, false);
                }
                var tr = create("tr"); append(tr, helpBody, true);
                var td = create("td"); append(td, tr);
                var td = create("td"); append(td, tr);
                append(p, td);
            }
        },
        
        panel: function() {
            if (!this._panel) {
                this._panel = create("div");

                this._panel.show = function() {
                    if (this.style.display == "none") {
                        this.style.display = "";
                    } else {
                        this.init();
                    }
                    this.adjustPos();
                }
                
                this._panel.hide = function() {
                    this.style.display = "none";
                }
                
                this._panel.init = function() {
                    with (this.style) {
                        width = height = "420px";
                        padding = "20px"; border = "1px solid #ccf"; background = "#fff";
                        position = "fixed"; zIndex = 2000; MozBorderRadius = "10px";
                    }
                    append(this, baidu.get("body"));
                    var form = create("form"); form.id = "bpp-config-form"; append(form, this);
                    var css = <><![CDATA[
#bpp-config-form > div {
    height: 350px; clear: both; padding: 10px;
}
#bpp-config-form ul {
    list-style: none; font-size: 9pt; margin: 0; padding: 0;
}
#bpp-config-form li {
    float: left;
}
#bpp-config-form li a { 
    text-decoration: none; color: #666; text-align: center; width: 50px; 
    display: block; padding:4px; -moz-border-radius: 4px 4px 0 0;
}

.bpp-config-tab-focus {
    color: #000 !important;
    text-shadow: 1px 1px 1px;
}

#bpp-config-form li a:hover,
#bpp-config-form li a:focus,
.bpp-config-tab-focus {
    font-weight: bold;
}

#bpp-config-form table {
    display: none;
}
.bpp-config-table-selected {
    display: table !important;
}
#bpp-config-form td {
    padding: 3px 0;
}
#bpp-config-form td > a {
    color: #0a0; margin: 0 3px;
}
#bpp-config-form td > a:hover {
    color: #0e0; cursor: help;
}
#bpp-config-form td textarea {
    display: block; font-size: 9pt; width:300px; height: 80px;
}
#bpp-config-form fieldset {
    margin: 5px;
}
#bpp-config-form legend {
    font-size: 9pt; color: #666;
}
#bpp-config-form fieldset p {
    margin: 0; font-size: 9pt; color: #333;
}
#bpp-config-form > button {
    float: right; margin: 10px;
}
#bpp-config-form > p {
    font-size:8pt; color: #666;
}
#bpp-config-form > div > table > tbody > tr > td > p {
    font-size:9pt; line-height: 200%;
}
#bpp-config-form > div > table > tbody > tr > td > p > a {
    margin: 0; c
}
]]></>.toString();
                    GM_addStyle(css);
                    with (modules.config) {
                        append(tabs(), form);
                        append(options(), form);
                        append(closeBtn(), form);
                        append(tip(), form);
                        closeBtn().focus();
                    }
                }
                
                this._panel.adjustPos = function() {
                    with (this.style) {
                        top  = baidu.get("body").clientHeight / 2 
                             - modules.config.panel().clientHeight / 2 
                             + "px";
                        left = baidu.get("body").clientWidth  / 2 
                             - modules.config.panel().clientWidth  / 2 
                             + "px";
                    }
                }
            }
            return this._panel;
        },
        
        shadow: function() {
            if (!this._shadow) {
                this._shadow = create('div');
                this._shadow.addEventListener("click", function() {
                    with (modules.config) {
                        panel().hide();
                        shadow().hide();
                    }
                }, false);
                
                this._shadow.show = function() {
                    with (this.style) {
                        if (display == "none") {
                            display = "";
                        } else {
                            this.init();
                        }
                    }
                }
                
                this._shadow.hide = function() {
                    this.style.display = "none";
                }
                
                this._shadow.init = function() {
                    append(this, baidu.get("body"));
                    with (this.style) {
                        width = screen.availWidth + "px"; height = screen.availHeight + "px";
                        background = "#000"; opacity = 0.5;
                        position = "fixed"; zIndex = 1000; top = 0;
                    }
                }
            }
            return this._shadow;
        },
        
        fieldset: function() {
            if (!this._fieldset) {
                this._fieldset = create("fieldset");
                var legend = create("legend");
                with (legend) {
                    innerHTML = "帮助";
                }
                append(legend, this._fieldset)
                var para = create("p");
                append(para, this._fieldset);
            }
            return this._fieldset;
        },
        
        tip: function() {
            if (!this._tip) {
                this._tip = create("p");
                this._tip.innerHTML = "如果您不想立刻刷新页面,请点击灰色阴影部分";
            }
            return this._tip
        },
        
        tabs: function() {
            if (!this._tabs) {
                this._tabs = create("ul");
                var config = modules.config;
                var groups = config.groups;
                
                this._tabs.select = function(tab) {
                    if (this._selected) {
                        this._selected.className = null;
                    }
                    tab.className = "bpp-config-tab-focus";
                    this._selected = tab;
                }
                
                for (var i = 0; i < groups.length; i++) {
                    var group = groups[i];
                    var li = create("li"); append(li, this._tabs);
                    var a  = create("a"); append(a, li);
                    with (a) {
                        href = "javascript:void(0)";
                        innerHTML = group.title;
                        className = "bpp-config-tab";
                        setAttribute("order", i);
                        with (style) {
                            backgroundColor = group.color;
                        }
                        // events
                        addEventListener("click", function() {
                            config.tabs().select(this);
                            t("p", config.fieldset())[0].innerHTML = "";
                            var options = config.options();
                            var order = this.getAttribute("order");
                            options.select(options.tables[order]);
                            options.style.background = groups[order].color;
                            config.closeBtn().focus();
                        }, false);
                    }
                    if (i == 0) {
                        config.tabs().select(a);
                    }
                }
            }
            return this._tabs;
        },
        
        options: function() {
            if (!this._options) {
                this._options = create("div");
                var config = modules.config; var groups = config.groups;
                with (this._options.style) {
                    background = groups[0].color;
                }
                for (var i = 0; i < groups.length; i++) {
                    var table = create("table"); append(table, this._options);
                    var tbody = create("tbody"); append(tbody, table);
                }
                for each(mod in modules) {
                    var hasConfig = mod.enable || mod.value || mod.content;
                    if (mod.config && hasConfig) {
                        var tr = create("tr"); append(tr, t("tbody", this._options)[mod.cid]);
                        if (mod.enable) {
                            var td = create("td"); append(td, tr);
                            append(config.createCheckbox(mod), td);
                        }
                        if (mod.name) {
                            var td = create("td"); append(td, tr);
                            append(config.createLabel(mod), td);
                        }
                        if (mod.value) {
                            append(config.createTextbox(mod), tr.lastChild);
                        }
                        if (mod.help) {
                            after(config.createHelpIcon(mod), mod.label);
                        }
                        if (mod.content) {
                            var tr2 = create("tr"); 
                            append(create("td"), tr2); append(create("td"), tr2);
                            append(config.createTextarea(mod), tr2.lastChild);
                            after(tr2, tr);
                            tr2.lastChild.style.padding = 0;
                        }
                    }
                }
                append(config.fieldset(), this._options);
                
                this._options.select = function(table) {
                    if (this._selected) {
                        this._selected.className = null;
                    }
                    table.className = "bpp-config-table-selected";
                    this._selected = table;
                }
                
                this._options.tables = t("table", this._options);
                
                this._options.select(this._options.tables[0]);
            }
            return this._options;
        },
        
        closeBtn: function() {
            if (!this._closeBtn) {
                var config = modules.config;
                this._closeBtn = create("button");
                with (this._closeBtn) {
                    innerHTML = "确认&重新载入页面";
                    type = "button";
                    addEventListener("click", function() {
                        location.reload();
                    }, false);
                }
            }
            return this._closeBtn;
        },
        
        createCheckbox: function(mod) {
            mod.checkbox = create("input");
            with (mod.checkbox) {
                type = "checkbox";
                id = mod.config;
                checked = mod.enable();
                addEventListener("change", function() {
                    GM_setValue(mod.config, this.checked);
                }, false);
            }
            if (mod.dependsOn) {
                mod.checkbox.disabled = !mod.dependsOn().checkbox.checked;
                mod.dependsOn().checkbox.addEventListener("change", function() {
                    mod.checkbox.checked = mod.enable();
                    mod.label.style.color = this.checked ? "#000" : "#999";
                    mod.checkbox.disabled = !this.checked;
                }, false);
            }
            return mod.checkbox;
        },
        
        createLabel: function(mod) {
            mod.label = create("label");
            with (mod.label) {
                htmlFor = mod.config;
                innerHTML = mod.name;
            }
            if (mod.dependsOn) {
                mod.label.style.color = mod.dependsOn().checkbox.checked ? "#000" : "#999";
            }
            return mod.label;
        },
        
        createTextbox: function(mod) {
            mod.textbox = create("input");
            with (mod.textbox) {
                type = "text";
                value = mod.value();
                disabled = !mod.enable();
                addEventListener("blur", function() {
                    GM_setValue(mod.config2, this.value);
                }, false);
                switch (mod.valueType) {
                    case "string":
                        style.width = "250px";
                        break;
                    case "number":
                        style.width = "40px";
                        break;
                    default:
                }
            }            
            mod.checkbox.addEventListener("change", function() {
                mod.textbox.disabled = !this.checked;
            }, false);
            if (mod.dependsOn) mod.dependsOn().checkbox.addEventListener("change", function() {
                mod.textbox.disabled = !mod.enable() || mod.checkbox.disabled;
            }, false);
            return mod.textbox;
        },
        
        createTextarea: function(mod) {
            mod.textarea = create("textarea");
            with (mod.textarea) {
                innerHTML = mod.content();
                disabled = !mod.enable();
                mod.checkbox.addEventListener("change", function() {
                    mod.textarea.disabled = !this.checked;
                }, false);
                addEventListener("blur", function() {
                    GM_setValue(mod.config2, this.value);
                }, false);
            }
            return mod.textarea;
        },
        
        createHelpIcon: function(mod) {
            mod.helpIcon = create("a");
            with (mod.helpIcon) {
                href = "javascript:void(0)";
                innerHTML = "[?]"; title = "点击显示帮助"
                addEventListener("click", function() {
                    var content = mod.help;
                    if (mod.dependsOn) {
                        content += "<br />依赖于【" + mod.dependsOn().name + "】模块";
                    }
                    t("p", modules.config.fieldset())[0].innerHTML = content;
                }, false);
            }
            return mod.helpIcon;
        },

        enable: function() { return true; },
        
        run: function() {
            var elm = x("//a[text()='把百度设为主页'][1]").snapshotItem(0);
            append(this.btn(), elm.parentNode);
            remove(elm);
        }
    },
    
    sideBar: {
        
        name: "显示侧边栏",
        
        config: "bpp-sidebar",
        
        cid: 1,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        init: function() {
            !this.enable() 
            && baidu.get("sideBar")
            && remove(baidu.get("sideBar"));
        },
        
        run: function() {}
    },
    
    adCleaner: {
    
        name: "广告移除", 
        
        cid: 0,
        
        config: "bpp-removeAds",
        
        help: "如果侧边栏不开启,侧边栏里的广告必须被移除",
        
        enable: function() {
            return !modules.sideBar.enable() || gm(this.config, true);
        },
        
        dependsOn: function() {
            return modules.sideBar;
        },
        
        run: function() {
            if (baidu.get("ads")) {
                remove(baidu.get("ads"));
            }
        }
    },
    
    prmtCleaner: {
    
        name: "推广移除",
        
        config: "bpp-removePromotions",
        
        cid: 0,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if ((cnt = baidu.get("promotions").snapshotLength) > 0) {
                remove(baidu.get("promotions"));
                util.notice("**** baidu++:" + cnt + "个推广被屏蔽 ****");
            }
        }
    },
    
    spnsrCleaner: {
    
        name: "推广链接(原赞助商连接)移除",
        
        config: "bpp-removeSponsors",
        
        cid: 0,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if ((cnt = baidu.get("sponsors").snapshotLength) > 0) {
                remove(baidu.get("sponsors"));
                util.notice("**** baidu++:" + cnt + "个推广链接被屏蔽 ****");
            }
        }
    },
    
    brandsCleaner: {
    
        name: "品牌推广移除",
        
        config: "bpp-removeBrands",
        
        cid: 0,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if ((cnt = baidu.get("brands").snapshotLength) > 0) {
                remove(baidu.get("brands"));
                util.notice("**** baidu++:" + cnt + "个品牌推广被屏蔽 ****");
            }
        }
    },
    
    enhanceLayout: {
    
        name: "布局改善",
        
        config: "bpp-layoutEnhance",
        
        config2: "bpp-columnCnt",
        
        valueType: "number",
        
        cid: 1,

        autopagerize: true,
        
        help: <><![CDATA[可大大改善百度和Autopagerize的布局,强烈建议开启。<br />
输入框为列数,如果您有一个较宽的显示器,建议设为两列以上。]]></>.toString(),
        
        enable: function() {
            return gm(this.config, true);
        },
        
        value: function() {
            return Math.max(parseInt(gm(this.config2)), 1) || 1;
        },
        
        enhanceInfo: function() {
            baidu.get("info").style.marginBottom = 0;
        },
        
        enhanceSideBar: function() {
            if (baidu.get("sideBar") && !baidu.get("sideBar").getAttribute("enhanced")) {
                with (baidu.get("sideBar")) {
                    with (style) {
                        width = "302px"; marginRight = "10px"; MozBorderRadius = "10px";
                        background = "rgb(239, 242, 250)"; border = "1px solid rgb(223, 226, 234)";
                        marginTop = "10px";
                    }
                    setAttribute("enhanced", "enhanced");
                }
                var td = t("td", baidu.get("sideBar"))[0];
                with (td) {
                    with (style) {
                        padding = "10px";
                    }
                }
            }
        },
        
        hideBr: function() {
            if (!this.hideBrCss) {
                this.hideBrCss = <><![CDATA[
body > br + br { display: none }
]]></>.toString();
                GM_addStyle(this.hideBrCss);
            }
        },
        
        enhanceResults: function() {
            var res = x("//table[@id][not(@id='st')][not(@enhanced)]"), cnt;
            if ((cnt = res.snapshotLength) > 0) {
                var frame = util.frame();
                var table = create("table"); append(table, frame); table.cellSpacing = 10;
                var tbody = create("tbody"); append(tbody, table);
                var cols  = this.value(); var trCnt = Math.ceil(cnt / cols);
                for (var i = 0; i < trCnt; i++) {
                    var tr = create("tr"); append(tr, tbody);
                    for (var j = 0; j < cols; j++) {
                        var r;
                        if (r = res.snapshotItem(i * cols + j)) {
                            var td = create("td"); append(td, tr); append(r, td);
                            r.setAttribute("enhanced", "enhanced");
                            r.style.width = '100%';
                        } else {
                            break;
                        }
                    }
                }
            }
            if (!this.resultCss) {
                this.resultCss = <><![CDATA[
.bpp-frame > table {
    width: 100%; table-layout: fixed;
}
.bpp-frame > table td {
    padding: 0 !important; height: 100%; vertical-align: top;
}
.bpp-frame > table > tbody > tr > td > table {
    padding: 10px; border: 1px solid #dde; background: #eef; 
    -moz-border-radius: 10px; width: 100%; height: 100%; table-layout: fixed;
}
.bpp-frame > table > tbody > tr > td > table > tbody > tr > td {
    width: auto !important;
}
]]></>.toString();
                GM_addStyle(this.resultCss);
            }
        },
        
        enhanceOthers: function() {
            this.enhanceTip();
            this.enhanceTool();
            this.enhanceStock();
            this.enhancePromotions();
            this.enhanceSponsors();
            this.enhanceBrands();
            this.enhanceMobile();
            this.enhanceIp();
            this.enhanceZhidao();
            this.enhanceExchange();
        },
        
        enhancePromotions: function() {
            var p = baidu.get('promotions', true);
            for (var i = 0; i < p.snapshotLength; i++) {
                this.enhance2(p.snapshotItem(i));
            }
        },
        
        enhanceTip: function() {
            this.enhance(baidu.get("tip"));
        },
        
        enhanceTool: function() {
            this.enhance(baidu.get("tool"));
            if (baidu.get("tool")) with (t("p", baidu.get("tool"))[0].style) {
                margin = 0; padding = 0;
            }
        },
        
        enhanceStock: function() {
            var stock = baidu.get("stock");
            if (stock.snapshotLength) {
                this.enhance2(stock);
                for (var i = 0; i < stock.snapshotLength; i++) {
                    stock.snapshotItem(i).setAttribute("enhanced", "enhanced");
                    stock.snapshotItem(i).setAttribute("colorized", "colorized");
                }
            }
        },
        
        enhanceSponsors: function() {
            var s = baidu.get("sponsors", true), cnt;
            if (cnt = s.snapshotLength) {
                this.enhance2(s);
                for (var i = 0; i < cnt; i++) {
                    s.snapshotItem(i).style.margin = 0;
                }
                s.snapshotItem(0).parentNode.style.background = "#f5f5f5";
                var tds = t("td", s.snapshotItem(0));
                tds[0].width = tds[1].width = "auto";
            }
        },
        
        enhanceBrands: function() {
            var s = baidu.get("brands", true), cnt;
            if (cnt = s.snapshotLength) {
                this.enhance2(s);
                for (var i = 0; i < cnt; i++) {
                    s.snapshotItem(i).style.margin = 0;
                }
                s.snapshotItem(0).parentNode.style.background = "#f5f5f5";
                var tds = t("td", s.snapshotItem(0));
                tds[0].width = tds[1].width = "auto";
            }
        },
        
        enhanceMobile: function() {
            this.enhance(baidu.get("mobile"));
            if (baidu.get("mobile")) {
                remove(t("br", baidu.get("mobile")));
            }
        },
        
        enhanceIp: function() {
            this.enhance(baidu.get("ip"));
        },
        
        enhanceZhidao: function() {
            this.enhance(baidu.get("zhidao"));
        },
        
        enhanceExchange: function() {
            this.enhance(baidu.get("exchange"))
        },
        
        enhance: function(elm) {
            if (elm) {
                append(elm, util.frame());
                with (elm.style) {
                    background = "#eef";
                    border = "1px solid #dde";
                    padding = "10px"; margin = "10px 10px 0";
                    MozBorderRadius = "10px";
                }
            }
        },
        
        enhance2: function(elm) {
            var div = create("div");
            with (div.style) {
                margin = "10px 10px 0"; padding = "10px"; border = "1px solid #eee";
                MozBorderRadius = "10px";
            }
            append(elm, div);
            append(div, util.frame());
        },
        
        firstRun: true,
        
        run: function() {
            if (baidu.get("results").snapshotLength > 0) {
                modules.autopagerize.improveUi();
                if (this.firstRun) {
                    this.hideBr();
                    this.enhanceInfo();
                    this.enhanceSideBar();
                    this.enhanceOthers();
                    this.firstRun = false;
                }
                this.enhanceResults();
            }
        }
    },
    
    colorful: {
        
        name: "随机背景",
        
        config: "bpp-colorfulBg",
        
        cid: 1,
        
        help: <><![CDATA[按根域名分组,类似ie8标签的效果。<br />
此模块已经独立出来为一个脚本,可用于google, yahoo, bing,
点击<a href="http://userscripts.org/scripts/show/52119">这里</a>下载使用
]]></>.toString(),

        colors: [],

        autopagerize: true,

        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if (baidu.get("results").snapshotLength > 0) {
                var tables = x("//td[@class='f']/../../..[not(@colorized)]");
                for (var i = 0; i < tables.snapshotLength; i++) {
                    var table = tables.snapshotItem(i); 
                    table.setAttribute("colorized", "colorized");
                    var hostname = t("a", table)[0].hostname;
                    var tld = getTld(hostname);
                    
                    if (!this.colors[tld]) {
                        this.colors[tld] = [];
                        var r = parseInt(Math.random() * 48) + 220;
                        var g = parseInt(Math.random() * 48) + 220;
                        var b = parseInt(Math.random() * 48) + 220;
                        this.colors[tld]['bg'] = 'rgb(' + r + ',' + g + ',' + b + ')';
                        this.colors[tld]['bd'] = 'rgb(' + (r - 16) + ',' + (g - 16) 
                                               + ',' + (b - 16) + ')';
                    }
                    with (table.style) {
                        background = this.colors[tld]['bg'];
                        borderColor = this.colors[tld]['bd'];
                    }
                }
            }
        }
    },
    
    highlight: {

        name: "关键词高亮",

        config: "bpp-hl",

        cid: 1,

        autopagerize: true,

        colors: [],

        enable: function() {
            return gm(this.config, false);
        },

        run: function() {
            var colors = ['0ff', 'af2', '0f0', '7f0', '4ed', '0ff', 'dad', 'ff0', 'fb1', 'dbd'];
            var bcolors= ['0cc', '7c0', '0c0', '4c0', '1ba', '0cc', 'a7a', 'cc0', 'c80', 'a8a'];
            var kws = x("//table[@id]/descendant::font[@color='#c60a00'][not(@highlight)]");
            for (var i = 0; i < kws.snapshotLength; i++) {
                var elm = kws.snapshotItem(i);
                var html = elm.innerHTML.replace(/(^\s+)|(\s+$)/, '')
                              .toLowerCase();
                if (!this.colors[html]) {
                    this.colors[html] = [];
                    var index = parseInt(Math.random() * colors.length);
                    this.colors[html]['bg'] = '#' + colors[index];
                    this.colors[html]['bd'] = '#' + bcolors[index];
                }

                with (elm.style) {
                    background = this.colors[html]['bg'];
                    border = "1px inset " + this.colors[html]['bd'];
                }

                elm.setAttribute("highlight", "highlight");
            }
        }
    },

    fixedSearch: {
        
        name: "固定搜索栏",

        cid: 3,

        config: "bpp-fixedSearch",

        help: "固定搜索框在顶部。可能会导致页面滚动变得有点卡",

        enable: function() {
            return gm(this.config, false);
        },

        run: function() {
            GM_addStyle(<><![CDATA[
table[width='100%'][height='54'] {
    position: fixed;
    z-index: 100; 
    background: #fff; 
    top: 0;
    padding-top: 5px;
    padding-bottom: 5px;
    border-bottom: 2px solid #aaa
}

body { margin-top: 60px; }
]]></>.toString());
        }
    },

    limitResultWidth: {

        name: "限制内容显示宽度",

        cid: 3,

        config: "bpp-limitResultWidth",

        help: "如果您使用的是较宽的屏幕却不想使用多列显示,每条结果的内容会被拉得很长而不宜阅读。开启此选项可以将结果的内容限制在一个舒适的宽度内",

        enable: function() { return gm(this.config, true); },

        run: function() {
            GM_addStyle(<><![CDATA[
.f > a + br + font,
.f > p {
    display: block !important; max-width: 42em; 
}
.f > a + br + font + br {
    display: none;
}
]]></>.toString());
        }
    },

    customCss: {
    
        name: "自定义css",
        
        cid: 3,
        
        config: "bpp-customCss",
        
        config2: "bpp-css",
        
        help: "如果您会css,可以在这里添加自己的css样式。在<a href='http://userscripts.org/topics/38054'>这里</a>你能获得更多的样式。",
        
        enable: function() {
            return gm(this.config, false);
        },
        
        content: function() {
            var def = "/*在此添加您自己的css*/";
            return gm(this.config2, def);
        },
        
        run: function() {
            GM_addStyle(this.content());
        },
    },
    
    openSearch: {
    
        name: "Open Search",

        enable: function() { return true; },
        
        run: function() {
            var search = create("link");
            with (search) {
                rel = "search"; title = "Baidu";
                type = "application/opensearchdescription+xml";
                href = "http://baiduplusplus.googlecode.com/files/baidu.xml";
            }
            append(search, t("head")[0]);
        }
    },
    
    /*fanfou: {
        
        name: "饭否相关讨论",
        
        config: "bpp-fanfou",
        
        config2: "bpp-fanfouMax",
        
        cid: 2,
        
        title: "相关讨论 - 饭否",
        
        valueType: "number",
        
        help: "输入框内为饭否显示条目数",
        
        enable: function() {
            return modules.sideBar.enable() && gm(this.config, false);
        },
        
        value: function() {
            return gm(this.config2, 6);
        },
        
        dependsOn: function() {
            return modules.sideBar;
        },
        
        run: function() {
            if (this.enable() && baidu.get("sideBar", true)) {
                var fanfou = util.createSidePanel(this); fanfou.className += " bpp-fanfou";
                var loadingImage = util.createLoadingImage();
                append(loadingImage, fanfou);
                
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: "http://api.fanfou.com/search/public_timeline.json?q=" 
                       + encodeURIComponent(baidu.get("keyword")),
                    headers: {
                        'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
                        'Accept': 'text/html',
                    },
                    onload: function(response) {
                        remove(loadingImage);
                        
                        var data = eval("(" + response.responseText + ")");
                        if ( data.length == 0 ) {
                            fanfou.innerHTML = "无相关讨论";
                            return 0;
                        }
                        
                        var colors = ['eff', 'fef', 'ffe'];
                        var max = modules.fanfou.value();
                        var css = <><![CDATA[
.bpp-fanfou p {
    margin: 0; padding: 10px; clear: both; min-height: 48px;
}
.bpp-fanfou img {
    float: left; margin-right: 10px; border-color: #fff;
}
]]></>.toString();
                        GM_addStyle(css);
                        for (var i = 0; i < data.length && i < max; i++) {
                            var p = create('p');
                            with (p.style) {
                                background = "#" + colors[i % 3];
                            }
                            append(p, fanfou);
                            p.innerHTML = data[i].text;
                            
                            var img = create("img");
                            img.alt = 'avatar';
                            img.src = data[i].user.profile_image_url;
                            
                            var a = create("a");
                            a.href = "http://fanfou.com/" + data[i].user.id;
                            append(img, a);
                            
                            before(a, p.firstChild);
                        }
                    }
                });
            }
        }
    },
    */
    wiki: {
        
        name: "Wiki模块",
        
        config: "bpp-wiki",
        
        cid: 2,
        
        title: "Wiki",
        
        help: "返回wiki可能有的定义",
        
        enable: function() {
            return modules.sideBar.enable() && gm(this.config, true);
        },
        
        dependsOn: function() {
            return modules.sideBar;
        },
        
        run: function() {
            if (baidu.get('sideBar', true)) {
                var wiki = util.createSidePanel(this); wiki.className += " bpp-wiki";
                var loadingImage = util.createLoadingImage();
                append(loadingImage, wiki);
                
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: "http://zh.wikipedia.org/w/api.php?action=opensearch&search=" 
                       + encodeURIComponent(baidu.get("keyword")),
                    headers: {
                        'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
                        'Accept': 'text/html',
                    },
                    onload: function(response) {
                        var r = eval("(" + response.responseText + ")")[1];
                        var l;
                        remove(loadingImage);
                        if ((l = r.length) > 0) {
                            var css = <><![CDATA[
.bpp-wiki {
    background: #fff url(http://upload.wikimedia.org/wikipedia/zh/6/62/Wiki_zh-hans.png) right bottom no-repeat;
}
.bpp-wiki ul {
    list-style-image: url(http://zh.wikipedia.org/favicon.ico);
    margin: 10px 10px 40px 35px;
    padding: 0;
}
.bpp-wiki a {
    position: relative;
    top: -3px;
}
]]></>.toString();
                            GM_addStyle(css);
                            var ul = create("ul");
                            append(ul, wiki);
                            for (var i = 0; i < l; i++) {
                                var li = create("li");
                                append(li, ul);
                                var link = create("a");
                                link.href = "http://zh.wikipedia.org/wiki/" + r[i];
                                link.innerHTML = r[i];
                                append(link, li);
                            }
                        } else {
                            wiki.innerHTML += "无相关定义";
                        }
                    }
                });
            }
        }
    },
    
    flickr: {
    
        name: "Flickr相册搜索",
        
        config: "bpp-flickr",
        
        title: "Flickr",
        
        cid: 2,
        
        help: "在侧边栏开启flickr的图片相关结果",
        
        enable: function() {
            return modules.sideBar.enable() && gm(this.config, true);
        },
        
        run: function() {
            if (baidu.get("sideBar", true)) {
                var flickr = util.createSidePanel(this);
                this.showData(1);  // First run
            }
        },
        
        dependsOn: function() {
            return modules.sideBar;
        },
        
        showData: function(page) {
            var title = this.header;
            var flickr = this.body;
            var keyword = baidu.get("keyword");
            // clear paging container, 'cos i will recreate it later..
            if (title.firstChild.tagName == 'DIV') {
                remove(title.firstChild);
            }
            while (title.nextSibling) { // clear the result ..
                remove(title.nextSibling);
            }
            var loadingImage = util.createLoadingImage();
            append(loadingImage, flickr);
            
            // flickr api params
            // @link http://www.flickr.com/services/api/flickr.photos.search.html
            var param = [];
            param.push("method=flickr.photos.search");
            param.push("api_key=2d828cb62dd8467013a32cd0efed6ab1");
            param.push("text=" + encodeURIComponent(keyword));
            param.push("sort=relevance");
            param.push("per_page=16");
            param.push("page=" + page);
            param.push("format=json");
            param.push("nojsoncallback=1");
            
            var api_url = "http://api.flickr.com/services/rest?" + param.join("&");

            var request = {
                method: 'GET',
                url: api_url,
                headers: {
                    'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
                    'Accept': 'text/html',
                },
                onload: function(response) {
                    remove(loadingImage);
                    var data = eval("(" + response.responseText + ")");
                    if ( data.photos.total == 0 ) { // No any photo ...
                        append(createText("无相关图片"), flickr);
                        return;
                    }
                    
                    if ( data.photos.pages > 1 ) { // If there are more than 1 pages ..
                        var divPage = create("div");
                        divPage.style.cssFloat = "right";
                        before(divPage, title.firstChild);
                        
                        if ( 1 < page ) { // If current page is not first
                            var prev = create("a");
                            with (prev) {
                                href = "javascript:void(0)"; title = "上一页"; innerHTML = "<";
                                style.fontSize = "9pt";
                                style.margin = "4px";
                                addEventListener("click", function() {
                                    modules.flickr.showData(page - 1);
                                }, false);
                            }
                            append(prev, divPage);
                        }
                        var current = create("span");
                        with (current) {
                            innerHTML = page;
                            style.fontSize = "9pt";
                        }
                        append(current, divPage);
                        if ( data.photos.pages > page ) { // If current page is not last
                            var next = create("a");
                            with (next) {
                                href = "javascript:void(0)"; title = "下一页"; innerHTML = ">";
                                style.fontSize = "9pt"; style.margin = "4px";
                                addEventListener("click", function() {
                                    modules.flickr.showData(page + 1);
                                }, false);
                            }
                            append(next, divPage);
                        }
                    }
                    
                    var images = data.photos.photo;
                    for (var i = 0; i < images.length; i++) {
                        src = "http://farm" + images[i].farm
                            + ".static.flickr.com/" + images[i].server
                            + "/" + images[i].id + "_" + images[i].secret
                            + "_s.jpg";
                        url = "http://www.flickr.com/photos/" + images[i].owner
                            + "/" + images[i].id;
                        img = create("img");
                        img.alt = "载入中...";
                        img.src = src;
                        with (img.style) {
                            width = height = "75px"; borderWidth = 0; verticalAlign = "middle";
                        }
                        link = create("a");
                        with (link) {
                            href = url; target = "_blank";
                        }
                        append(img, link);
                        append(link, flickr);
                    }
                }
            };
            
            GM_xmlhttpRequest(request);
        }
    },
    
    altSearch: {
        
        name: "其他引擎搜索",
        
        config: "bpp-altSearch", 
        
        cid: 2,

        config2: "bpp-searchesJson",

        help: '显示其他搜索引擎的连接<br />如果您需要更多的搜索选择,请看<a href="http://userscripts.org/topics/38564">这里</a>',

        content: function() {
            return gm(this.config2) || <><![CDATA[
{ name: "谷歌", query: "http://www.google.cn/search?q=" },
{ name: "必应", query: "http://cn.bing.com/search?q=" }
]]></>.toString(); 
        },
        
        engines: function() {
            return eval("[" + this.content() + "]");
        },
        
        enable: function() {
            return modules.sideBar.enable() && gm(this.config, true);
        },
        
        dependsOn: function() {
            return modules.sideBar;
        },
        
        run: function() {
            if (baidu.get("sideBar", true)) {
                var sideBar = baidu.get("sideBar");
                var ul = create("ul"); append(ul, t("td", sideBar)[0], true);
                with (ul.style) {
                    padding = 0; margin = "0 0 10px"; listStyle = "none";
                }
                var keyword = baidu.get("keyword");
                
                var engines = this.engines();
                for (var i = 0; i < engines.length; i++) {
                    var link = create("a");
                    var ico  = create("img");
                    var span = create("span");
                    with (ico) {
                        ico.alt = "fav";
                        ico.src = "http://" + engines[i].query.split('/')[2] + "/favicon.ico";
                        with (style) {
                            marginRight = "8px"; position = "relative"; top = "4px";
                        }
                    }
                    with (span) {
                        style.color = "red"; innerHTML = keyword;
                    }
                    append(createText("使用【" + engines[i].name + "】搜索"), link);
                    append(span, link);
                    with (link) {
                        link.href   = engines[i].query + encodeURIComponent(keyword);
                        link.target = "_blank";
                    }
                    var li = create("li"); append(ico, li); append(link, li);
                    append(li, ul);
                }
            }
        }
    },
    
    keywordOnTop: {
        
        name: "顶部相关搜索",
        
        config: "bpp-relatedKeywordCopy",
        
        cid: 2,
        
        help: "复制相关搜索到顶部,很适合使用autopagerize的同学",
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if (baidu.get("related")) {
                var clone = baidu.get("related").cloneNode(true);
                before(clone, baidu.get("info"));
            }
        }
    },
    
    favicon: {
    
        name: "网站图标",
        
        config: "bpp-favicon",
        
        cid: 2,

        autopagerize: true,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            var titles = x("//td[@class='f'][not(@icon)]/a[1]");
            if (titles.snapshotLength > 0) {
                if (!this.icoCss) {
                    this.icoCss = <><![CDATA[
.bpp-favicon {
    width: 16px; height: 16px; background: url(chrome://global/skin/icons/folder-item.png);
    float: left; margin: 0 5px 0 0 !important; position: relative; top: 1px;
}
]]></>.toString();
                    GM_addStyle(this.icoCss);
                }
                for (var i = 0; i < titles.snapshotLength; i++) {
                    var a = titles.snapshotItem(i); a.parentNode.setAttribute("icon", "icon");
                    var div = create("div"); div.className = "bpp-favicon";
                    
                    var ico = create("img");
                    with (ico) {
                        alt = ""; width = 16;
                        src = "http://" + a.hostname + "/favicon.ico"; 
                        style.background = a.parentNode.parentNode
                                            .parentNode.parentNode.style.backgroundColor;
                    }
                    append(ico, div);
                    before(div, a);
                }
            }
        }
    },
    
    preview: {
    
        name: "网站缩略图",
        
        config: "bpp-preview",
        
        cid: 2,
        
        help: "搜索结果旁显示网站缩略图",

        autopagerize: true,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            if (baidu.get("results", true).snapshotLength) {
                var titles = x("//table[@id]/tbody/tr/td/a/font/parent::a[not(@preview)]");
                if (!this.previewCss) {
                    this.previewCss = <><![CDATA[
.bpp-preview {
    display: block; float: left; margin: 0 8px 8px 0;
}
]]></>.toString();
                    GM_addStyle(this.previewCss);
                }
                for (var i = 0; i < titles.snapshotLength; i++) {
                    this.addPreview(titles.snapshotItem(i)); // run it
                    titles.snapshotItem(i).setAttribute("preview", "preview");
                }
            }
        },
        
        addPreview: function(title) {
            var a = title; var link = create("a");
            with (link) {
                href = a.href; target = "_blank"; className = "bpp-preview";
            }
            // create a empty <img />
            var image = util.createLoadingImage(); append(image, link);
            image.style.borderColor = "#ddd";
            // these 2 lines are from GoogleMonkeyR, it seems images are stored in different servers by name
            var sl = a.href.match(/:\/\/www.(\w)|:\/\/(\w)/);
            sl = sl[1] || sl[2];
            // append it to td
            before(link, a.parentNode.firstChild);
            var url = "http://" + sl + ".googlepreview.com/preview?s=" 
                    + a.protocol + "//" + a.hostname;
            generateImageFromUrl(image, url);
        }
    },
    
    shortcut: {
    
        name: "快捷键",
        
        config: "bpp-shortcut",
        
        cid: 2,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        help: '同vim风格:J上一条,K下一条,回车打开连接,?(shift-/)跳到搜索栏(如果只是/键与firefox默认快捷键有冲突),Esc离开搜索栏',
        
        run: function() {
            var id = 0;
            var s = this;
            var box = n("wd")[0];
            
            GM_addStyle(<><![CDATA[
.bpp-hl { font-weight: bold; text-shadow: 0 0 5px; color: red; }
.bpp-hl:before { content: "»"; }
.bpp-hl:after { content: "«"; }
]]></>.toString());

            var f = false;
            box.addEventListener('focus', function() {
                f = true;
            }, false);
            
            box.addEventListener('blur', function() {
                f = false;
            }, false);

            document.addEventListener('keypress', function(e) {
                var kc = e.keyCode || e.which;
                switch (true) {
                    case kc == 63:
                        box.focus(); break;
                    case f && kc == 27:
                        if (id > 0) {
                            s._a(id).focus();
                            setTimeout(
                              function() {
                                window.scrollTo(0, s._getTop(s._a(id)) - document.body.clientHeight / 2);
                              }, 1
                            );
                        } else {
                            s._hl(id = 1);
                        }
                        break;
                    case !f && (kc == 74 || kc == 106):
                        if ($(id + 1)) {
                            if ($(id)) s._nohl(id);
                            s._hl(++id);
                        }
                        break;
                    case !f && (kc == 75 || kc == 107):
                        if ($(id - 1)) {
                            if ($(id)) s._nohl(id);
                            s._hl(--id);
                        } else if (id < 1) {
                            s._hl(id = 1);
                        }
                        break;
                    default:
                }
            }, false);
        },
        
        _hl: function(id) {
            var a = this._a(id);
            a.className += ' bpp-hl';
            a.focus();
            window.scrollTo(0, this._getTop(a) - document.body.clientHeight / 2);
        },
        
        _nohl: function(id) {
            this._a(id).className = this._a(id).className.replace('bpp-hl', '');
        },
        
        _a: function(id) {
            return x('.//a[count(img)=0][1]', $(id)).snapshotItem(0);
        },
        
        _getTop: function(obj) {
            if (obj.offsetParent) {
                return obj.offsetTop + this._getTop(obj.offsetParent);
            } else {
                return 0;
            }
        }
    },
    
    autopagerize: {
    
        name: "Autopagerize兼容",
        
        config: "bpp-autopagerize",
        
        help: "把Autopagerize脚本放在Baidu++之前才能生效",
        
        cid: 4,
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            this.improveUi();
            // copy from favicon with google3, nice job
            var scrollHeight = document.documentElement.scrollHeight;
            document.addEventListener("scroll", function() {
                if( scrollHeight != document.documentElement.scrollHeight ) {
                    scrollHeight = document.documentElement.scrollHeight;
                    for each(mod in modules) {
                        mod.autopagerize 
                        && mod.enable()
                        && mod.run();
                    }
                }
            }, false);
        },
        
        improveUi: function() {
            var hr = c('autopagerize_page_separator')[0];
            if (hr) {
                var p = hr.nextSibling;
                if (!this.autopagerizeCss) {
                    this.autopagerizeCss = <><![CDATA[
.autopagerize_page_info {
    margin: 0 10px; padding: 10px; border: 1px solid #bcd; text-align: center;
    background: #cde; -moz-border-radius: 10px;
}

hr { display: none }
]]></>.toString();
                    GM_addStyle(this.autopagerizeCss);
                }
                append(p, util.frame());
                remove(hr);
            }
        }
    },
    
    version: {
    
        name: "版本更新检测",
        
        cid: 5,
        
        config: "bpp-version",
        
        config2: "bpp-checkInterval",
        
        valueType: "number",
        
        help: "输入框内容为版本检测周期,单位为天",
        
        value: function() {
            return gm(this.config2, 2);
        },
        
        enable: function() {
            return gm(this.config, true);
        },
        
        run: function() {
            var now = Math.ceil(Date.now() / 1000);
            if (now - gm("bpp-verCheckAt", 0) > this.value() * 86400) {
                GM_xmlhttpRequest({
                    method:"GET",
                    url:"https://userscripts.org/scripts/source/47560.meta.js",
                    headers:{
                        "Accept":"text/javascript; charset=UTF-8"
                    },
                    overrideMimeType:"application/javascript; charset=UTF-8",
                    onload:function(response) {
                        var httpsMETA = parseHeaders(response.responseText);
                        var remoteVersion = httpsMETA["version"] ? httpsMETA["version"] : "0.0.0";
                        GM_setValue("bpp-remoteVersion", remoteVersion);
                        GM_setValue("bpp-verCheckAt", now);
                    }
                });
            }
            if (this.compare(this.local(), this.remote())) {
                this.showNotice(this.remote());
            }
        },
        
        local: function() {
            if (!this._local) {
                this._local = parseHeaders(meta)["version"];
            }
            return this._local;
        },
        
        remote: function() {
            if (!this._remote) {
                this._remote = gm("bpp-remoteVersion", "0.0.0");
            }
            return this._remote;
        },
        
        compare: function(o, n) {
            var o = o.split(/\./); var n = n.split(/\./);
            for (var i = 0; i < 3; i++) {
                if (n > o) return true;
            }
            return false;
        },
        
        showNotice: function(version) {
            var a = create("a");
            with (a) {
                with (style) {
                    color = "green"; background = "#000";
                }
                innerHTML = "baidu++检测到新版本[" + version + "]";
                href = "http://userscripts.org/scripts/show/47560";
                target = "_blank";
            }
            append(createText(" | "), t("td", baidu.get("info"))[0])
            append(a, t("td", baidu.get("info"))[0]);
        }
    }
};

var util = {
    frame: function() {
        if (!this._frame) {
            this._frame = create("div");
            with (this._frame) {
                className = "bpp-frame";
                if (baidu.get("sideBar", true) && !this.frameCss) {
                    this.frameCss = ".bpp-frame { margin-right: 334px }";
                    GM_addStyle(this.frameCss);
                }
            }
            before(this._frame, x("//body/br[1]").snapshotItem(0));
        }
        return this._frame;
    },
    
    notice: function(content) {
        var notice = create("p");
        with (notice) {
            className = "bpp-notice";
            innerHTML = content; 
        }
        if (!this.noticeCss) {
            this.noticeCss = <><![CDATA[
.bpp-notice {
    text-align: center; background: #ddd;
    border: 1px solid #ccc; -moz-border-radius: 10px;
    padding: 10px; margin: 10px 10px 0; color: #999;
}
]]></>.toString();
            GM_addStyle(this.noticeCss);
        }
        append(notice, this.frame(), true);
    },
    
    createSidePanel: function(module) {
        var titleText = module.title;
        var sideBar = t("td", baidu.get("sideBar"))[0];
        var div = create("div"); div.className = "bpp-sidePanel";
        module.body = div;
        var title = create("h3");
        module.header = title;
        append(createText(titleText), title);
        append(title, div);
        append(div, sideBar, true);
        if (!this.sidePanelCss) {
            this.sidePanelCss = <><![CDATA[
.bpp-sidePanel {
    width: 300px; background: #fff; margin-bottom: 10px; border: 1px solid #bbf;
}
.bpp-sidePanel > h3 {
    background: #ccf; margin: 0; padding: 5px; text-shadow: 1px 1px 1px
}
]]></>.toString();
            GM_addStyle(this.sidePanelCss);
        }
        return div;
    },
    
    createLoadingImage: function() {
        var img = create("img");
        with (img) {
            alt = "loading"; src = image.loading;
        }
        return img;
    }
}

var app = {
    run: function() {
        for each(mod in modules) {
            mod.init && mod.init();
            mod.enable() && mod.run();
        }
    }
};

app.run();