Noise Reduction for Google & Bing

By smogami Last update Nov 3, 2009 — Installed 1,343 times. Daily Installs: 14, 6, 4, 3, 8, 7, 7, 9, 6, 10, 15, 18, 20, 12, 8, 10, 12, 7, 3, 6, 8, 7, 5, 9, 10, 6, 8, 11, 6, 6, 9, 8

There are 16 previous versions of this script.

// ==UserScript==
// @name          Google Noise Reduction
// @namespace     http://exoego.net/
// @description   Domainname-based filtering for Google's search results.
// @include       http://www.google.com/search*
// @include       http://www.google.com/#hl*
// @include       http://www.google.com.*/search*
// @include       http://www.google.com.*/#hl*
// @include       http://www.google.co.*/search*
// @include       http://www.google.co.*/#hl*
// @include       http://www.bing.com/search*
// @require       http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.js
// @version       0.2.5
// ==/UserScript==

(function(w, $){ // window, jQuery

/*    Setting
=============================================================================*/
var FilterDefault = [
    // "swik.net",
    // "pastebin.ca",
    // "search.yahoo.com",
]//

var SITEINFO = [
	{
		url:         "http://www.google.com/(?:search|#hl)*",
		linkNode:    "#res li.g h3 a.l",
		depthOfLink: "2",
		toolbox:     "#sff td.xsm",
		apLinkNode:  "li.g h3 a.l",
		meta:        ".gl",
		depthOfMeta: "3"
	}
	,{
		url:         "http://www.google.com.*/(?:search|#hl)*",
		linkNode:    "#res li.g h3 a.l",
		depthOfLink: "2",
		toolbox:     "#sff td.xsm",
		apLinkNode:  "li.g h3 a.l",
		meta:        ".gl",
		depthOfMeta: "3"
	}
	,{
		url:         "http://www.google.com.*/(?:search|#hl)*",
		linkNode:    "#rso li.g h3 a.l",
		depthOfLink: "2",
		toolbox:     "#sff td.xsm",
		apLinkNode:  "li.g h3 a.l",
		meta:        ".gl",
		depthOfMeta: "3"
	}
	,{
		url:         "http://www.google.co.*/(?:search|#hl)*",
		linkNode:    "#res li.g h3 a.l",
		depthOfLink: "2",
		toolbox:     "#header td.xsm",
		apLinkNode:  "li.g h3 a.l",
		meta:        ".gl",
		depthOfMeta: "3"
	}
	,{
		url:         "http://www.google.co.jp/(?:search|#hl)*",
		linkNode:    "#res li.g h3 a.l",
		depthOfLink: "2",
		toolbox:     "#sff td.xsm",
		apLinkNode:  "li.g h3 a.l",
		meta:        ".gl",
		depthOfMeta: "3"
	}
	,{
		url:         "http://www.bing.com/search*",
		linkNode:    "#wg0 h3 a",
		depthOfLink: "3",
		toolbox:     "#sc_expPane",
		apLinkNode:  "h3 a",
		meta:        ".sb_meta",
		depthOfMeta: "2"
	}
]

/*===========================================================================*/

function launchGNR(list){//
	for (var i=0, len=list.length; i < len; ++i) {
		var reg = list[i].url.replace(".","\.").replace("*", "(?:.*)");
		if (!location.href.match(reg)) {
			log("no match:" + reg);
		}
		else if ($(list[i].linkNode).length === 0) {
			log("linknode not found:" + reg);
		}
		else if ($(list[i].toolbox).length === 0) {
			log("toolbox not found :" + reg);
		}
		else {
			log("filter found:" + reg);
			SITEINFO = list[i];
			break;
		}
	}
	if (SITEINFO instanceof Array){
		log("filter not found, and EXIT");
		return;
	}
	GM_addStyle(style);

	Filter.init();
	Dialog.init();

	$(SITEINFO.linkNode).each(function(index, node){
	    Filter.check(node); // google
	});

	if(window.AutoPagerize.addFilter)
	    window.AutoPagerize.addFilter(function(page) {
			$(SITEINFO.apLinkNode, page).each(function(index, node){
	               Filter.check(node);
	        });
	    });

}

/*===========================================================================*/

var Dialog = {
    init: function(){
        var self = this;
        this.header = $('<h1>' + Lexicon["Click to remove filter"] + '</h1>');
        this.list   = $('<ul/>');
        this.buttonCancel  = $('<input/>')
            .attr({ type:"button", id:"GNR_cancel", value:Lexicon.closeDialog })
            .click(function(){ self.close(); });
        this.buttonSave = $('<input/>')
            .attr({ type:"button", id:"GNR_save", value:Lexicon.saveEdit })
            .click(function(){ self.saveEdit(); })
        this.title   = $('<span>' + Lexicon["View All Filters"] + '</span>')
            .attr({id:"GNR_title"})
            .click(function(){ self.openInEditMode(); });
        this.footer  = $('<p/>')
            .append(this.title, this.buttonSave, this.buttonCancel);
        this.wrapper = $('<div/>').attr({id:'GNR_dialog'})
            .append(this.header, this.list, this.footer)
            .appendTo("body")
            .hover(function(){ // in
                w.clearTimeout(self.timer);
            },function(){ // out
                self.timer = w.setTimeout(function(){ self.close() },
                    /*self.isEditMode ? 5000 :*/ 5000)
            });
        $('<br /><a href="#">' + Lexicon["Filter Setting"] + '</a>')
            .appendTo(SITEINFO.toolbox).click(function(){ self.openInEditMode() });
        GM_registerMenuCommand(Lexicon.commandName, function(){
            Dialog.openInEditMode();
        });
    },
    timer: 0,
    isEditMode: false,
    open: function(buttonLink){
        if (this.isEditMode) this.quitEditMode();
        var pos = $(buttonLink).position();
        this.wrapper.css({
            left: pos.left  + "px",
            top:  pos.top  + "px"
        }).show();
    },
    close: function(){
        if (this.isEditMode) this.quitEditMode();
        w.clearTimeout(this.time);
        this.wrapper.fadeOut("fast");
    },
    update: function(elmAddButton, domains) {
        var keys = domains.map(function(key){
            var li = $("<li />")
                    .attr({data:key}).html(key)
                    .click(function(){
                        Filter.add( this.getAttribute("data") );
                        Filter.save();
                        $(getLinkBlock(elmAddButton,SITEINFO.depthOfMeta)).remove();
                    Dialog.close();
                })[0];
            return li;
        });
        this.list.empty().append(keys)
    },
    saveEdit: function(){
        this.list.find("li.remove").each(function(index, elm){
            Filter.remove(elm.innerHTML)
        })
        Filter.save();
        this.close();
    },
    quitEditMode: function(){
        this.isEditMode = false;
        this.list.unbind("click");
        this.wrapper.fadeOut(function(){ Dialog.wrapper.removeClass("editMode") });
    },
    openInEditMode: function(){
        this.wrapper.hide();
        this.isEditMode = true;
        var tmp = [];
        for(var key in Filter.data) if (Filter.data.hasOwnProperty(key)) {
            tmp.push(key)
        }
        tmp = tmp.sort().map(function(item){ return "<li>"+item+"</li>"; }).join("");
        this.list.html(tmp).click(function(e){
            var item = e.originalTarget || null;
            if (!item || item.nodeName !== "LI") return;
            $(item).toggleClass("remove");
        })
        this.wrapper.css({top:"24px"}).addClass("editMode").show();
    }
}

/*===========================================================================*/
var Filter = {
    data:{},
    add: function(item){
        this.data[item] = true;
        this.save();
    },
    remove: function(item){
        if (this.data[item]) delete this.data[item];
    },
    save: function(){
        GM_setValue("blackList", this.data.toSource());
    },
    init: function(){
        var self = this;
        this.data = eval(GM_getValue("blackList")) || {};
        if (FilterDefault instanceof Array)
            FilterDefault.forEach(function(item){
                if(typeof item === "string")
                    self.add(item)
            })
    },
    check: function(link){
        var domains   = listupDomain(link);
        var self = this;
		var linkBlock = getLinkBlock(link, SITEINFO.depthOfLink);
        if (domains.some(function(key){ return self.data[key]; })) {
            $(linkBlock).remove();
            return;
        }

        var addToGNR = $("<a />").attr({
            href:link.href
        }).append(Lexicon.addToGNR).click(function(){
            Dialog.update(this, domains);
            Dialog.open(this);
            return false;
        });
//		log(SITEINFO, linkBlock, addToGNR);
        $(SITEINFO.meta, linkBlock).append(" - ", addToGNR);
     }
}

function getLinkBlock(node, num){
	for (var i=0, num=+num; i<num; ++i) node = node.parentNode;
	return node;
}


/*===========================================================================*/
var ccSLD = /^(?:net?|com?|gov?|org?|ac|edu?|gr)$/;

function listupDomain(link) {
	try {
	    var host = link.hostname;
	    var path = link.pathname.split("/")[1];
	    var subs = host.split(".");
	    subs.pop(); // remove TLD (com, jp, net, ...)
	    if (ccSLD.test(subs[subs.length-1])) subs.pop(); // remove ccSLD( co, ne, ac, ...)

	    for (var i=0, urls=[host], limit=subs.length - 1; i<limit; ++i)
	        urls.push( urls[i].replace(subs[i]+".", "") );

	    if (path) urls.unshift(host+"/"+path);
	    return urls;
	} catch(e){ log("can't list up domains". link, e); }
}

var style = <><![CDATA[
    #GNR_dialog {
        color:#fff;
        background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA1BMVEUAAACnej3aAAAAAXRSTlPM0jRW/QAAAAxJREFUeJxjYBjcAAAAoAABsAZiGAAAAABJRU5ErkJggg==");
        position:absolute;
        top:50px;
        display:none;
        left:25%;
        -moz-border-radius:4px;
        z-index:99999995;
        padding:5px 10px 10px 10px;
    }
    #GNR_dialog.editMode{
        top:50px;
        left:10px !important;
        right:10px !important;
    }
    #GNR_dialog h1 {
        display:none;
        font-size:16px; 
        border-bottom:1px solid #666;
    }
    #GNR_dialog.editMode h1 {
        display:block;
    }
    #GNR_dialog ul {
        padding:0 10px 0 0;
		margin:0;
    }
    #GNR_dialog.editMode ul {
        -moz-column-gap:   10px;
        -moz-column-width: 14em;
    }
    #GNR_dialog li {
        font-size:16px;
        padding:0;
        margin:3px 0;
        cursor:pointer;
        list-style:none;
        overflow:hidden;
    }
    #GNR_dialog.editMode li {
        font-size:14px;
    }
    #GNR_dialog li.remove {
        color:#666;
    }
    #GNR_dialog li:hover {
        color:#ff0;
        text-decoration:underline;
        overflow:visible;
    }
    #GNR_dialog li.remove:hover {
        color:#aa0;
    }
    #GNR_dialog p {
        text-align:right;
        margin:5px 0 0;
    }
    #GNR_save,
    #GNR_cancel {
        background:transparent;
        font-size:15px;
        border:1px solid #ccc;
        color:#fff;
        padding:1px 10px;
        cursor:pointer;
        margin-left:10px;
    }
    #GNR_save:hover,
    #GNR_cancel:hover {
        background:#555;
        border:1px solid #fff;
    }
    #GNR_dialog.editMode #GNR_save {
        display:inline;
    }
    #GNR_save {
        display:none;
    }
]]></>;

var Lexicon = (function(locale){
    var lang = navigator.language.slice(0,2);
    return locale[lang] || locale["en"];
})({
    ja: {
        addToGNR:    "フィルタ",
        closeDialog: "閉じる",
        commandName: "フィルターを閲覧/編集",
        saveEdit:    "保存",
        "View All Filters": "フィルターを見る",
        "Filter Setting": "GNRフィルターの設定",
        "Click to remove filter": "削除したい項目をクリックしてください。"
    },
    en: {
        addToGNR:    "filter",
        closeDialog: "close",
        commandName: "View/Edit filters",
        saveEdit:    "save",
        "View All Filters": "View All Filter",
        "Filter Setting": "Filter Setting",
        "Click to remove filter": "Click an item to remove from filter.",
    }
});


/*    Utility
=============================================================================*/
function log(){ if (w.console) w.console.log.apply(null, arguments) }


/*    Main
=============================================================================*/
$(document).ready(function(){
	launchGNR(SITEINFO);
});
return;

})(this.unsafeWindow, this.jQuery)