Search code examples
javascriptfiltergreasemonkeyadblock

How to conveniently hide elements selected using an adblocker via a userscript?


To block an element, one can use:

var adSidebar = document.getElementById('ads');
if (adSidebar) {
    adSidebar.parentNode.removeChild(adSidebar);
}

But that's for one specific element, for one specific site. To do block multiple elements in multiple sites, the userscript must @include many times, and in each site it should list the elements many times. Say I have a list of adblocker filters, how to covert it into a single userscript conveniently?

www.youtube.com###watch7-sidebar-contents
www.youtube.com##.yt-masthead-logo-container
www.facebook.com##._1uh-:nth-of-type(2)
www.facebook.com##._2t-e > ._4kny:nth-of-type(1)
www.facebook.com##._1uh-:nth-of-type(1)
www.facebook.com##._50tj._2t-a
www.facebook.com##._50ti._2s1y._5rmj._26aw._2t-a
www.facebook.com###u_0_0
www.facebook.com###fbDockChatBuddylistNub > .fbNubButton

I would like to keep that list in one place, so that if a new element in a new website needs to be blocked, I just simply add the line from uBlock into the list.


Solution

  • You can do this by creating a userscript that runs on all domains, parses a list of strings obtained from an ad blocker for the domain and query selector, see if it matches the window's domain and if the element(s) exist, then remove them if so. I've provided one way of doing so below:

    // ==UserScript==
    // @name         Custom element hider
    // @namespace    https://zachsaucier.com/
    // @version      0.1
    // @description  To show how one can hide elements like an ad blocker using userscripts
    // @author       Zach Saucier
    // @match        *://*/*
    // @grant        none
    // ==/UserScript==
    
    (function() {
        'use strict';
    
        // Set our list of sites and elements to block
        var blockList = [
            "www.youtube.com###watch7-sidebar-contents",
            "www.youtube.com##.yt-masthead-logo-container",
            "www.facebook.com##._1uh-:nth-of-type(2)",
            "www.facebook.com##._2t-e > ._4kny:nth-of-type(1)",
            "www.facebook.com##._1uh-:nth-of-type(1)",
            "www.facebook.com##._50tj._2t-a",
            "www.facebook.com##._50ti._2s1y._5rmj._26aw._2t-a",
            "www.facebook.com###u_0_0",
            "www.facebook.com###fbDockChatBuddylistNub > .fbNubButton"
        ];
    
        // Get the window's hostname
        var windowHostname = window.location.hostname;
    
        // Iterate through the blocklist, hiding elements as needed
        for(var i = 0; i < blockList.length; i++) {
            var entryParts = blockList[i].split('##');
    
            // Compare the hostnames; Only remove elements if they match
            if(windowHostname === entryParts[0]) {
                // Find the elements if they exists
                var matchedElements = document.querySelectorAll(entryParts[1]);
    
                // Actually remove the element(s) that match
                for(var j = 0; j < matchedElements.length; j++) {
                    var matchedElem = matchedElements[j];
    
                    matchedElem.parentNode.removeChild(matchedElem);
                }
            }
        }
    })();
    

    Though I'm not sure why you would want to write a userscript to do this when the ad blocker itself can do this...