// ==UserScript== // @name Web Search Result Domain Filter // @namespace WebSearchResultDomainFilter // @description Filter search result based on domain names on web search of Bing, DuckDuckGo, Google, Yahoo. Some include search for news, books, etc. All exclude search for images and videos. // @author jcunews // @include *://www.bing.com/search* // @include *://www.bing.com/news/search* // @include *://duckduckgo.com/* // @include *://www.google.*/search* // @include *://www.google.*.*/search* // @include *://search.yahoo.com/yhs/search* // @include *://*.search.yahoo.com/search* // @version 1.0.0 // @grant none // @downloadURL none // ==/UserScript== (function() { var filter = JSON.parse(localStorage.WebSearchResultDomainFilter || "[]"); var rx = filter.join("|").replace(/\./g, "\\."); rx = rx ? (new RegExp(filter.join("|").replace(/\./g, "\\."))) : null; var getItems, getHostName, itemSelector, itemLinkSelector, setupEditFilterLink, cssPatch = ""; var items, ele, i, j, excLink = document.createElement("DIV"), link; var createFilterLink, filterEditor = document.createElement("DIV"); function trim(s) { return s.replace(/^(\s+|\r+|\n+)|(\s+|\r+|\n+)$/g, ""); } function updateFilter() { localStorage.WebSearchResultDomainFilter = JSON.stringify(filter); rx = filter.join("|").replace(/\./g, "\\."); rx = rx ? (new RegExp(filter.join("|").replace(/\./g, "\\."))) : null; } function abortEvent(ev) { ev.preventDefault(); if (ev.stopPropagation) ev.stopPropagation(); if (ev.stopImmediatePropagation) ev.stopImmediatePropagation(); } function processItems() { var items = document.querySelectorAll(itemSelector), i, link, lnk; if (getItems) { items = getItems(); } else items = document.querySelectorAll(itemSelector); for (i = items.length-1; i >= 0; i--) { link = items[i].querySelector(itemLinkSelector); if (!link) continue; if (!link.parentNode.querySelector(".domainFilterLink")) { lnk = excLink.cloneNode(true); lnk.addEventListener("click", function(ev) { var hn = getHostName(this.parentNode.querySelector("A")); if (!confirm('Do you want to hide all search result from below domain name?\n\n' + hn + '\n\nNote:\nSubdomain is not included.\ni.e. hiding "abc.com" will not hide "sub.abc.com" or vice versa.')) return filter.push(hn); updateFilter(); processItems(); abortEvent(ev); }, true); link.parentNode.appendChild(lnk); } if (rx) { items[i].style.display = rx.test(getHostName(link)) ? "none" : ""; } else items[i].style.display = ""; } } if ((/www\.bing\.com\/search/).test(location.href)) { itemSelector = "#b_results .b_algo"; itemLinkSelector = "h2 > a"; createFilterLink = function() { editFilterLink = document.createElement("A"); editFilterLink.style.marginLeft = "3ex"; return b_tween.appendChild(editFilterLink); }; cssPatch = '#b_results{width:580px}'; } else if ((/www\.bing\.com\/news\/search/).test(location.href)) { itemSelector = "#algocore .newsitem"; itemLinkSelector = ".title"; createFilterLink = function() { editFilterLink = document.createElement("A"); editFilterLink.style.cssText = 'float:left;margin:.85em 0 0 3ex'; var ele = document.querySelector(".nf .menu > ul"); return ele.appendChild(editFilterLink); }; cssPatch = '.search .newsitem .caption a.title{display:inline!important}'; } else if ((/duckduckgo\.com/).test(location.hostname)) { itemSelector = "#links .result"; itemLinkSelector = ".result__title > a"; createFilterLink = function() { var ele = document.querySelector(".organic-filters"); if (!ele || !ele.childElementCount) return; editFilterLink = document.createElement("A"); return ele.appendChild(editFilterLink); }; cssPatch = '#b_results{width:580px}'; if (window.nrn) { window._nrn = window.nrn; window.nrn = function() { var res = window._nrn.apply(this, arguments); processItems(); return res; }; } } else if ((/www\.google\./).test(location.hostname)) { itemSelector = "#rso .g"; itemLinkSelector = ".r a"; createFilterLink = function() { editFilterLink = document.createElement("A"); editFilterLink.style.marginLeft = "10ex"; return resultStats.appendChild(editFilterLink); }; } else if ((/search\.yahoo\.com/).test(location.hostname)) { itemLinkSelector = ".title > a, h4 > a"; getItems = function() { return Array.prototype.slice.call(document.querySelectorAll(".searchCenterMiddle > li, .compArticleList > li")).filter( function(v) { return !(/\bsys_/).test(v.firstElementChild.className); } ); }; createFilterLink = function() { editFilterLink = document.createElement("A"); if (window["refiner-time"]) { editFilterLink.style.cssText = 'margin-left:6ex'; return window["refiner-time"].appendChild(editFilterLink); } else { var ele = document.querySelector("#sidebar .bd"); return ele.appendChild(editFilterLink); } }; cssPatch = '.search .newsitem .caption a.title{display:inline!important}'; getHostName = function(link) { var a = unescape(link.href).match(/\/RU=(http.*?)\/R[A-Z]=/); if (a) { a = a[1].match(/\/\/(.*?)\//)[1]; } else a = link.hostname; return a; }; } if (!(getItems || itemSelector)) return; if (!getHostName) { getHostName = function(link) { return link.hostname; }; } filterEditor.id = "filterEditor"; filterEditor.innerHTML = '\ \
\ \
Edit Domain Filter
\ \ \ \ \
\
\ '; document.body.appendChild(filterEditor); domainFilterEditorOk.addEventListener("click", function(ev) { var txt = trim(domainFilterEditorEdit.value); filter = txt.split("\n").reduce(function(prev, cur) { cur = trim(cur); if (cur) prev.push(cur); return prev; }, []); updateFilter(); processItems(); domainFilterEditor.firstElementChild.innerHTML = ""; abortEvent(ev); }, true); domainFilterEditorCancel.addEventListener("click", function(ev) { domainFilterEditor.firstElementChild.innerHTML = ""; abortEvent(ev); }, true); excLink.textContent = "X"; excLink.title = "Exclude this domain name from search result"; excLink.className = "domainFilterLink"; (function addEditFilterLink() { if (editFilterLink = createFilterLink()) { editFilterLink.textContent = "Edit Domain Filter"; editFilterLink.title = "Edit search result domain filter"; editFilterLink.id = "domainFilterEditLink"; editFilterLink.addEventListener("click", function(ev) { var txt = filter.join("\n"); domainFilterEditorEdit.value = txt + (txt ? "\n" : ""); domainFilterEditor.firstElementChild.innerHTML = '\ body>*{display:none!important}\ #filterEditor{display:block!important}\ #domainFilterEditor{display:block}\ '; abortEvent(ev); }, true); processItems(); } else setTimeout(addEditFilterLink, 1000); })(); })();