Полезная информация

Хотите узнать больше о расширениях? Посмотрите ролики, рассказывающие о работе с расширениями Firefox.

№113-08-2008 21:42:25

demetsuri
Участник
 
Группа: Extensions
Откуда: Санкт-Петербург
Зарегистрирован: 27-09-2006
Сообщений: 98
UA: Firefox 2.0

[GM] Google - Block unwanted results

Google - Block unwanted results

Описание: Удаляет ненужные результаты поиска в Google, при помощи вашего собственного черного списка.
Чтобы блокировать определенный сайт в результатах поиска, просто добавьте его в Блок-лист, кликнув на "Block result".
preview1.jpg
Разблокировать сайт или настроить вид блокировки можно кликнув на "Blocking options" под строкой поиска Google.
preview2.jpg

Иллюстрация работы скрипта на примере поиска книги:

Сначала обычный поиск книги - в результате сверху магазины и рекламщики.
th_47983_before_122_1020lo.jpg

Блокируем их
th_48040_blocking_122_80lo.jpg

В результате при следующем поиске имеем более приемлемый результат
th_48064_after_122_789lo.jpg

В последующих поисках блокированные сайты больше не встретятся никогда.

Код оригинального скрипта:

Выделить код

Код:

// ==UserScript==
// @name           Google - Block unwanted results
// @namespace      grease1 DOT daniboy AT antichef DOT com
// @description    Remove unwanted results from google, filtered by your own customizable blacklist
// @include        http://www.google.tld/search?*
// @date           2007-05-16
// @version        0.1
// @GM_version     0.6.8
// ==/UserScript==

/* ----- Script boot ------------------------------------------------ */

window.addEventListener("load", bootScript, false);

// Start running
function bootScript() {
  
  addControlLink();
  filterResults();
  
}

/* ----- Constants -------------------------------------------------- */


// Blocking methods
const BLOCKING_METHOD_HIDE = 0x00;
const BLOCKING_METHOD_FADE = 0x01;





/* ----- Main functions --------------------------------------------- */

// Add a link to open this script's control panel
function addControlLink() {
  
  // XPath to get the <font> node that the link will be appended before
  var xpFont = "//table[@class='t bt']//td[last()]/font[@size='-1']";
  var nodeFont = $x(xpFont)[0];
  
  // Create the link and add a click event to it
  var nodeControl = document.createElement("span");
  nodeControl.setAttribute("id", "GBUR_controlPanelLink");
  nodeControl.textContent = "Blocking options";
  nodeControl.addEventListener("click", openControlPanel, false);
  
  // Create a hyphen space ;)
  var nodeHyphen = document.createElement("span");
  nodeHyphen.textContent = " - ";
  nodeHyphen.style.fontSize = "small";
  
  // Attach CP link and hyphen before said font node
  nodeFont.parentNode.insertBefore(nodeControl, nodeFont);
  nodeFont.parentNode.insertBefore(nodeHyphen, nodeControl.nextSibling);
  
}


// Filter the results, removing the unwanted and showing the wanted
function filterResults() {
  
  // Get the list of blocked domains as a RegExp object
  reBlocked = getBlacklistedAsRegexp();
  
  // XPath to get all the result's anchors
  var xpAnchor = "//div[@class='g']/h2[@class='r']/a";
  var nlAnchors = $x(xpAnchor);
  
  // Get the blocking method
  var nBlockingMethod = getBlockingMethod();
  
  // Iterate through the results, acting on blocked results, and adding
  // a link to block each result
  for (var i = 0; i < nlAnchors.length; i++) {
    
    // Find the main <div> that contains the result
    var nodeDiv = nlAnchors[i].parentNode.parentNode;
    var strHref = nlAnchors[i].toString();
    
    // This array will be null if domain should not be blocked, and will
    // contain the blocking-rule if a match is found
    var arrBlockedAs = (reBlocked) ? reBlocked.exec(strHref) : null;
    
    // If matched, add an unblocking link to the result that will cancel
    // the blocking rule; otherwise, add a blocking link to block that
    // domain
    if (arrBlockedAs && arrBlockedAs.length == 2) {
      
      addBlockLink(nodeDiv, arrBlockedAs[1], true);
      
      switch (nBlockingMethod) {
        case BLOCKING_METHOD_FADE :
          nodeDiv.style.display = "block";
          nodeDiv.style.opacity = 0.25;
          break;
        case BLOCKING_METHOD_HIDE :
        default :
          nodeDiv.style.opacity = 1;
          nodeDiv.style.display = "none";
          break;
      }
      
    } else {
      
      addBlockLink(nodeDiv, strHref, false);
      nodeDiv.style.opacity = 1;
      nodeDiv.style.display = "block";
      
    }
    
  }
  
}


// Add a link to activate the result filtering
function addBlockLink(node, href, blocked) {
  
  // Find the node to which we will append the control link
  var nodeCorrectPlace = node.getElementsByTagName("nobr")[0];
  
  // Check for existing control link, if exists, remove - otherwise, add
  // a text hyphen
  var nodeControl = nodeCorrectPlace.lastChild;
  if (nodeControl && nodeControl.nodeName == "SPAN" && nodeControl.hasAttribute("href")) {
    removeNode(nodeControl);
  } else {
    var nodeTextHyphen = document.createTextNode(" - ");
    nodeCorrectPlace.appendChild(nodeTextHyphen);
  }
  
  
  nodeControl = document.createElement("span");
  nodeControl.className = "fl";
  nodeControl.setAttribute("href", href);
  nodeControl.textContent = (blocked) ? "Stop blocking" : "Block result";
  nodeControl.addEventListener("click", (blocked) ? unblockResultHref : blockResultHref, false);
  
  nodeCorrectPlace.appendChild(nodeControl);
  
}





/* ----- Event-called function -------------------------------------- */


// Add a domain to the blacklist (called by link under a result)
function blockResultHref(e) {
  
  // Get the basic domain, removing "www." if exists
  var reDomain = /^https?:\/\/(?:www\d*\.)?((?:[\w-]+\.)*(?:\w+))\//
  var arrDomain = reDomain.exec(this.getAttribute("href"));
  
  // Sanity check
  if (arrDomain && arrDomain.length == 2) {
    
    // Split domain to parts, based on levels. for example:
    // "sub.example.com" --> ["sub", "example", "com"]
    var strDomain = arrDomain[1];
    var arrDomainParts = strDomain.split(/\./);
    
    // Sanity check
    if (arrDomainParts) {
      
      // If the domain has only two parts, we block it, otherwise, we open
      // a selection screen for the user to choose which tomain to block.
      // Examples:
      // 1) example.com will automatically become blocked
      // 2) deeper.sub.example.com will open a selection screen
      if (arrDomainParts.length == 2) {
        addToBlacklist(strDomain);
      } else {
        openSelectionScreen(arrDomainParts, e);
      }
      
    } else {
      GM_log("Error! Error in this script");
    }
  } else {
    GM_log("Error! Domain is malformed (or this script is broken)");
  }
  
}


// Remove a domain from the blacklist (called by link under a result)
function unblockResultHref(e) {
  
  removeFromBlacklist(this.getAttribute("href"));
  
}


// Add a domain to the blacklist (called by link in selection box)
function blockSelectedHref(e) {
  
  var strDomain = this.getAttribute("href");
  addToBlacklist(strDomain);
  closeModals(e);
  
}


// Add or remove a domain from the blacklist (called by checkboxes in
// control panel)
function actOnCheckbox(e) {
  
  if (this.checked) {
    addToBlacklist(this.value);
  } else {
    removeFromBlacklist(this.value);
  }
  
  filterResults();
  
}


// Change the blocking method (called by radio in control panel)
function actOnRadio(e) {
  
  if (this.checked) {
    setBlockingMethod(this.value);
    filterResults();
  } else {
    GM_log("Warning! Change blocking method was called on unselected radio");
  }
  
}


// Open the script's main control panel (called by CP link)
function openControlPanel(e) {
  
  // Darken everything to isolate the control panel
  darkenAll();
  
  displayControlPanel();
  
}


// Open a selection box to select a domain from various subdomains
// (called by another event, hence not really an event-called function)
function openSelectionScreen(arrDomainParts, e) {
  
  // Darken everything to isolate the control panel
  darkenAll();
  
  displaySelectionScreen(arrDomainParts, e.pageX, e.pageY);
  
}


// Close any "modals" (called by clicking on dark mask or a cancel or
// apply button)
function closeModals(e) {
  
  undarkenAll();
  closeOpenPanel();
  
}





/* ----- GUI functions ---------------------------------------------- */


// Display the main control panel
function displayControlPanel() {
  
  // Create the main node for the control panel
  var nodeControlPanel = document.createElement("div");
  nodeControlPanel.setAttribute("id", "GBUR_controlPanel");
  nodeControlPanel.className = "GBUR_controlPanelMain";
  
  // Create a node to be the title of the control panel
  var nodeTitle = document.createElement("div");
  nodeTitle.className = "GBUR_controlTitle";
  nodeTitle.textContent = "Blocking options";
  nodeControlPanel.appendChild(nodeTitle);
  
  // Create a form for the control panel
  var nodeForm = document.createElement("form");
  
  // Create the form's first fieldset
  var nodeFieldsetFirst = document.createElement("fieldset");
  
  // Create the first fieldset's legend
  var nodeLegendFirst = document.createElement("legend");
  nodeLegendFirst.textContent = "Uncheck box to unblock domain";
  nodeFieldsetFirst.appendChild(nodeLegendFirst);
  
  // Get the list of blocked domains as array
  var arrBlocked = getBlacklistedAsArray();
  if (arrBlocked.length != 0) {
    
    // Create a div, so we can style the fieldset better
    var nodeDivInFieldsetFirst = document.createElement("div");
    
    // Inner function for the next array.foreach action
    function insertInputNode(element, index, array) {
      
      var nodeInput = document.createElement("input");
      nodeInput.type = "checkbox";
      nodeInput.checked = true;
      nodeInput.value = element;
      nodeInput.addEventListener("click", actOnCheckbox, false);
      
      var nodeLabel = document.createElement("label");
      nodeLabel.appendChild(nodeInput);
      nodeLabel.appendChild(document.createTextNode(' ' + element));
      
      nodeDivInFieldsetFirst.appendChild(nodeLabel);
      
    }
    
    // Sort blacklist, and insert a checkbox for each domain
    arrBlocked.sort();
    arrBlocked.forEach(insertInputNode);
    
    // Append div to first fieldset
    nodeFieldsetFirst.appendChild(nodeDivInFieldsetFirst);
    
  } else {
    
    nodeFieldsetFirst.textContent = "There are currently no blocked domains";
    
  }
  
  
  // Append first fieldset to form
  nodeForm.appendChild(nodeFieldsetFirst);
  
  
  // Create the form's second fieldset
  var nodeFieldsetSecond = document.createElement("fieldset");
  
  // Create the second fieldset's legend
  var nodeLegendSecond = document.createElement("legend");
  nodeLegendSecond.textContent = "How would you like to handle blocked domains?";
  nodeFieldsetSecond.appendChild(nodeLegendSecond);
  
  // Create input radio for "hide" option
  var nodeInputRadioHide = document.createElement("input");
  nodeInputRadioHide.type = "radio";
  nodeInputRadioHide.name = "GBUR_blockingMethod";
  nodeInputRadioHide.checked = (getBlockingMethod() == BLOCKING_METHOD_HIDE);
  nodeInputRadioHide.value = BLOCKING_METHOD_HIDE;
  nodeInputRadioHide.addEventListener("click", actOnRadio, false);
  
  // Create label for "hide" option
  var nodeLabelHide = document.createElement("label");
  nodeLabelHide.appendChild(nodeInputRadioHide);
  nodeLabelHide.appendChild(document.createTextNode(" Completely hide blocked results"));
  
  // Create input radio for "fade" option
  var nodeInputRadioFade = document.createElement("input");
  nodeInputRadioFade.type = "radio";
  nodeInputRadioFade.name = "GBUR_blockingMethod";
  nodeInputRadioFade.checked = (getBlockingMethod() == BLOCKING_METHOD_FADE);
  nodeInputRadioFade.value = BLOCKING_METHOD_FADE;
  nodeInputRadioFade.addEventListener("click", actOnRadio, false);
  
  // Create label for "hide" option
  var nodeLabelFade = document.createElement("label");
  nodeLabelFade.appendChild(nodeInputRadioFade);
  nodeLabelFade.appendChild(document.createTextNode(" Fade out blocked results"));
  
  // Append labels to second fieldset to form
  nodeFieldsetSecond.appendChild(nodeLabelHide);
  nodeFieldsetSecond.appendChild(nodeLabelFade);
  nodeForm.appendChild(nodeFieldsetSecond);
  
  
  // Append form to CP
  nodeControlPanel.appendChild(nodeForm);
  
  // Create a "Close" button for the CP
  var nodeClose = document.createElement("div");
  nodeClose.className = "GBUR_controlCancel";
  nodeClose.textContent = "Close";
  nodeClose.addEventListener("click", closeModals, false);
  nodeControlPanel.appendChild(nodeClose);
  
  // Finally, append CP to body
  document.body.appendChild(nodeControlPanel);
  
}


// Display domain selection screen, when domain has multiple parts
function displaySelectionScreen(arrDomainParts, x, y) {
  
  // Create the main node for the selection screen
  var nodeSelectionScreen = document.createElement("div");
  nodeSelectionScreen.setAttribute("id", "GBUR_controlPanel");
  nodeSelectionScreen.className = "GBUR_controlPanelSelectionScreen";
  nodeSelectionScreen.style.left = x+"px";
  nodeSelectionScreen.style.top = y+"px";
  
  // Create a node to be the title of the selection screen
  var nodeTitle = document.createElement("div");
  nodeTitle.className = "GBUR_controlTitle";
  nodeTitle.textContent = "Select which domain to block:";
  nodeSelectionScreen.appendChild(nodeTitle);
  
  // Create an unordered list node, to which all optional domains will be attaches
  var nodeList = document.createElement("ul");
  nodeList.className = "GBUR_controlList";
  
  // Work for each level of the domain
  do {
    
    // Get the actual domain as a string
    var strDomainOption = arrDomainParts.join('.');
    
    // Create the list item node
    var nodeItem = document.createElement("li");
    
    // Create the clickable link that will add this domain to the blacklist
    var nodeDomainOption = document.createElement("span");
    nodeDomainOption.className = "GBUR_controlLink";
    nodeDomainOption.setAttribute("href", strDomainOption);
    nodeDomainOption.textContent = strDomainOption;
    nodeDomainOption.addEventListener("click", blockSelectedHref, false);
    
    // Append link to list item, and list item to list
    nodeItem.appendChild(nodeDomainOption);
    nodeList.appendChild(nodeItem);
    
    // Take out the first last of the domain, and try again for next level
    arrDomainParts.shift();
    
  } while (arrDomainParts.length > 1);
  
  // Append the list to the selection screen
  nodeSelectionScreen.appendChild(nodeList);
  
  // Create a "Cancel" button for the selection screen
  var nodeCancel = document.createElement("div");
  nodeCancel.className = "GBUR_controlCancel";
  nodeCancel.textContent = "Cancel";
  nodeCancel.addEventListener("click", closeModals, false);
  nodeSelectionScreen.appendChild(nodeCancel);
  
  // Finally, append selection screen to body
  document.body.appendChild(nodeSelectionScreen);
  
}


// Closes any open control panel
function closeOpenPanel() {
  
  var nodePanel = document.getElementById("GBUR_controlPanel");
  if (nodePanel) {
    removeNode(nodePanel);
  } else {
    GM_log("Warning! Requested to close a nonexistent panel");
  }
  
}


// Create a "dark mask" to cover everything
function darkenAll() {
  
  var nodeDarkness = document.getElementById("GBUR_nodeDarkness");
  if (!nodeDarkness) {
    
    var nodeBody = document.body;
    
    nodeDarkness = document.createElement("div");
    nodeDarkness.setAttribute("id", "GBUR_nodeDarkness");
    nodeDarkness.addEventListener("click", closeModals, false);;
    
    nodeBody.appendChild(nodeDarkness);
    
  } else {
    GM_log("Warning! Dark mask already exist");
  }
  
}


// Remove the "dark mask" created with darkenAll
function undarkenAll() {
  
  var nodeDarkness = document.getElementById("GBUR_nodeDarkness");
  if (nodeDarkness) {
    removeNode(nodeDarkness);
  } else {
    GM_log("Warning! Requested to remove a nonexistent mask");
  }
  
}


// Display a tiny message in the corner, and disappears it after a while
function displayMessage(str, type) {
  
  // Take existing message node, or create a new one if not exist
  var nodeMessage = document.getElementById("GBUR_nodeMessage");
  if (nodeMessage) {
    
    // Clear existing timeout if exist
    if (window.GBUR_toFade) {
      window.clearTimeout(window.GBUR_toFade);
    }
    
  } else {
    
    // Create the message node, set it's id
    nodeMessage = document.createElement("div");
    nodeMessage.setAttribute("id", "GBUR_nodeMessage");
    
    // Append message node to body
    document.body.appendChild(nodeMessage);
    
  }
  
  // Set the base opacity for the message node
  nodeMessage.style.opacity = 1;
  
  // Set the message class by type, and text by str
  nodeMessage.className = "GBUR_message" + type;
  nodeMessage.textContent = str;
  
  // Begin fadeout of message, save timeout ID to window
  var toFade = window.setTimeout(fadeMessage, 3500);
  window.GBUR_toFade = toFade;
  
}


// Fade out the message in the corner, destroying it when it reaches 0 opacity
function fadeMessage() {
  
  var nodeMessage = document.getElementById("GBUR_nodeMessage");
  
  // Only work if there is such a node
  if (nodeMessage) {
    
    // Calculate new opacity
    var nOpacity = nodeMessage.style.opacity - 0.05;
    
    if (nOpacity > 0) {
      
      // Set new opacity
      nodeMessage.style.opacity = nOpacity;
      
      // Set timeout to continue fading
      var toFade = window.setTimeout(fadeMessage, 60);
      window.GBUR_toFade = toFade;
      
    } else {
      
      // Remove message node
      removeNode(nodeMessage);
      
    }
    
  }
  
}





/* ----- Backend (GM_get/setValue) functions ------------------------ */


// Load the blacklisted domains into a regexp object
function getBlacklistedAsRegexp() {
  
  var strBlacklist = GM_getValue("GBUR_blacklist", undefined);
  if (strBlacklist) {
    return new RegExp("^https?://(?:[\\w-]+\\.)*(" + strBlacklist.replace(/\./g, "\.") + ")/");
  } else {
    return false;
  }
  
}


// Load the blacklisted domains into an array
function getBlacklistedAsArray() {
  
  var strBlacklist = GM_getValue("GBUR_blacklist", undefined);
  if (strBlacklist) {
    return strBlacklist.split(/\|/).sort();
  } else {
    return new Array();
  }
  
}


// Add a domain to the blacklist, while checking for redundancies
function addToBlacklist(str) {
  
  // Get a list of all blacklisted domains
  var arrBlacklistedDomains = getBlacklistedAsArray();
  
  // Iterate through the list of blacklisted domains, and check if the
  // domain we're trying to block is already (or if a upper-level domain
  // that already contains the domain we're trying to block).
  for (var i = 0; i < arrBlacklistedDomains.length; i++) {
    
    var strBlacklistedDomain = arrBlacklistedDomains[i];
    
    // Dynamic RegExp object, checking if the an existing item already
    // blocks the new domain we're trying to block. for example:
    // New domain to block is "sub.example.com" - If we're already
    // blocking "example.com", code will exit gracefully.
    var reIsAlreadyListed = new RegExp("(?:[\\w-]+\\.)*" + strBlacklistedDomain.replace(/\./g, "\\.") + "$");
    
    if (reIsAlreadyListed.test(str)) {
      displayMessage("Already blocked as " + strBlacklistedDomain + "!", "Error");
      filterResults();
      return false;
    }
    
  }
  
  // Dynamic RegExp object, checking if str blocks an item
  var reIsSubAlreadyListed = new RegExp("(?:[\\w-]+\\.)*" + str.replace(/\./g, "\\.") + "$");
  
  // Inner function for the next array.filter action
  function filterBlacklist(element, index, array) {
    return !reIsSubAlreadyListed.test(element);
  }
  
  // Filter blacklist array to take out all domains that will be blocked
  // by the new domain we're blocking. for example:
  // New domain to block is "example.com", this will remove instances of
  // "sub.example.com", "othersub.example.com", etc.
  var arrNewBlacklist = arrBlacklistedDomains.filter(filterBlacklist);
  arrNewBlacklist.push(str);
  
  // Finally, save blacklist
  GM_setValue("GBUR_blacklist", arrNewBlacklist.sort().join('|'));
  displayMessage("Blocking: " + str, "On");
  
  // Re-filter the results
  filterResults();
  
}


// Remove a domain from the blacklist
function removeFromBlacklist(str) {
  
  // Get a list of all blacklisted domains as an array
  var arrBlacklistedDomains = getBlacklistedAsArray();
  
  // Dynamic RegExp object, find the domain
  var reFindDomain = new RegExp(str.replace(/\./g, "\\."));
  
  // Inner function for the next array.filter action
  function filterBlacklist(element, index, array) {
    return !reFindDomain.test(element);
  }
  
  // Filter blacklist to take out the domain we no longer want to block
  var arrNewBlacklist = arrBlacklistedDomains.filter(filterBlacklist);
  GM_setValue("GBUR_blacklist", arrNewBlacklist.join('|'));
  displayMessage("Unblocking: " + str, "Off");
  
  // Re-filter the results
  filterResults();
  
}


// Return the method of blocking
function getBlockingMethod() {
  
  return parseInt(GM_getValue("GBUR_method", BLOCKING_METHOD_HIDE));
  
}


// Set the method of blocking
function setBlockingMethod(method) {
  
  GM_setValue("GBUR_method", method);
  
}





/* ----- Helper function -------------------------------------------- */


// XPath helper
function $x(p, context) {
  if (!context) context = document;
  var i, arr = [], xpr = document.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  for (i = 0; item = xpr.snapshotItem(i); i++) arr.push(item);
  return arr;
}


// Remove DOM node
function removeNode(element) {
  element.parentNode.removeChild(element);
}





/* ----- Stylish! --------------------------------------------------- */


// Main page
GM_addStyle("span#GBUR_controlPanelLink {color: #0000CC; cursor: pointer; font-size: small; text-decoration: underline;}");
GM_addStyle("span.fl {color: #77c; cursor: pointer; text-decoration: underline;}");


// Messages
GM_addStyle("div#GBUR_nodeMessage {border-width: 2px; border-style: solid; cursor: default; font-weight: bold; padding: 0.2em 2em; position: fixed; top: 0; right: 0;}");
GM_addStyle("div.GBUR_messageOn {background-color: #e5ecf9; border-color: #36c; color: black;}");
GM_addStyle("div.GBUR_messageOff {background-color: #74ad74; border-color: green; color: white;}");
GM_addStyle("div.GBUR_messageError {background-color: #ffabab; border-color: red; color: black;}");


// Control panels, generic
GM_addStyle("div#GBUR_nodeDarkness {background-color: white; height: 100%; width: 100%; opacity: .7; position: fixed; top: 0; left: 0;");
GM_addStyle("div#GBUR_controlPanel {border: 1px solid #36c; background-color: #e5ecf9; padding: 1em; -moz-border-radius: 12px 0 0 12px;");
GM_addStyle("div.GBUR_controlCancel {color: blue; cursor: pointer; text-align: right; text-decoration: underline;}");


// Control panels, main CP
GM_addStyle("div.GBUR_controlPanelMain {overflow: auto; position: fixed; top: 3em; left: 3em; bottom: 2em; right: 3em;");
GM_addStyle("div#GBUR_controlPanel label {display: block;}");
GM_addStyle("div#GBUR_controlPanel div > label {max-width: 14em; overflow: hidden; white-space: pre;}");
GM_addStyle("div#GBUR_controlPanel legend {color: #36c; font-size: 1.1em;}");
GM_addStyle("div#GBUR_controlPanel fieldset {border: 3px groove green; margin: 1.3em 0; -moz-border-radius: 8px;}");
GM_addStyle("div#GBUR_controlPanel fieldset div {-moz-column-width: 14em;}");


// Control panels, selection screen
GM_addStyle("div.GBUR_controlPanelSelectionScreen {position: absolute;");
GM_addStyle("div.GBUR_controlTitle {font-size: 1.1em; font-weight: bold; margin-bottom: 0.3em;}");
GM_addStyle(".GBUR_controlList {list-style: square outside; padding: 0 0 0 1em;}");
GM_addStyle(".GBUR_controlLink {color: blue; cursor: pointer; text-decoration: underline;}");


/* ----- So Say We All ---------------------------------------------- */

Автор: daniel Rozenberg (исправлено LuisNaver)
Домашняя страница: http://userscripts.org/scripts/show/9275
Дата добавления/последнего обновления: 16-05-2007 (Version: 0.1)
Установить:
Оригинальная версия 0.1 устарела и не работает должным образом т.к. поисковик недавно изменил код своего сайта.
Исправленный скрипт можно найти здесь:
Поисковик изменил код сайта и скрипт вновь не работает.

Для блокирования ненужных результатов поиска можно также применять расширение CustomizeGoogle

Отредактировано demetsuri (09-09-2008 19:30:43)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]