Behind The Overlay

One click to close any overlay on any website

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name          Behind The Overlay
// @namespace     Behind The Overlay
// @description   One click to close any overlay on any website
// @author        NicolaeNMV + daijro
// @version       2.0
// @include       *://*
// @icon          https://addons.cdn.mozilla.net/user-media/addon_icons/521/521928-32.png
// @grant         GM_registerMenuCommand
// ==/UserScript==

/**
 * This is a script that will remove overlay popups in the 99% of the cases.
 * It's doing that by detecting DOM elements.
 *
 * Originally from here: https://github.com/NicolaeNMV/BehindTheOverlay
 * Modified by daijro to work as a userscript
 **/

var debug = false;

var utils = (function () {
    function hideElement(element) {
        styleImportant(element, 'display', 'none');
    }

    function styleImportant(element, cssProperty, cssValue) {
        element.style[cssProperty] = '';
        var cssText = element.style.cssText || '';
        if (cssText.length > 0 && cssText.slice(-1) != ';')
            cssText += ';';
        // Some pages are using !important on elements, so we must use it too
        element.style.cssText = cssText + cssProperty + ': ' + cssValue + ' !important;';
    }

    function isVisible(element) {
        return element.offsetWidth > 0 && element.offsetHeight > 0;
    }

    function getZIndex(element) {
        return parseInt(window.getComputedStyle(element).zIndex);
    }

    function isAnElement(node) {
        return node.nodeType == 1; // nodeType 1 mean element
    }

    function nodeListToArray(nodeList) {
        return Array.prototype.slice.call(nodeList);
    }

    function forEachElement(nodeList, functionToApply) {
        nodeListToArray(nodeList).filter(isAnElement).forEach(function (element) {
            functionToApply.call(this, element);
        });
    }

    function collectParrents(element, predicate) {
        var matchedElement = element && predicate(element) ? [element] : [];
        var parent = element.parentNode;

        if (parent && parent != document && parent != document.body) {
            return matchedElement.concat(collectParrents(parent, predicate));
        } else {
            return matchedElement;
        }
    }

    // Calculate the number of DOM elements inside an element
    function elementWeight(element, maxThreshold) {
        var grandTotal = 0;
        var nextElement = element;
        var nextGrandChildNodes = [];

        function calculateBreathFirst(element) {
            var total = 0;
            var nextChildElements = [];

            var childNodes = element.childNodes;
            total = childNodes.length;

            forEachElement(childNodes, function (childNode) {
                var grandChildNodes = nodeListToArray(childNode.childNodes);
                total += grandChildNodes.length;
                nextChildElements = nextChildElements.concat(grandChildNodes.filter(isAnElement));
            });
            return [total, nextChildElements];
        }

        while (nextElement) {
            var tuple_total_nextChildElements = calculateBreathFirst(nextElement);
            var total = tuple_total_nextChildElements[0];

            grandTotal += total;
            nextGrandChildNodes = nextGrandChildNodes.concat(tuple_total_nextChildElements[1]);

            if (grandTotal >= maxThreshold) {
                break;
            } else {
                nextElement = nextGrandChildNodes.pop();
            }
        }

        return grandTotal;
    }

    return {
        hideElement: hideElement,
        isVisible: isVisible,
        getZIndex: getZIndex,
        forEachElement: forEachElement,
        collectParrents: collectParrents,
        elementWeight: elementWeight,
        styleImportant: styleImportant
    }
})();

var overlayRemover = function (debug, utils) {
    function hideElementsAtZIndexNear(nearElement, thresholdZIndex) {
        var parent = nearElement.parentNode;
        // The case when nearElement is a document
        if (parent === null) {
            return;
        }
        var children = parent.childNodes;

        utils.forEachElement(children, function (child) {
            if (utils.getZIndex(child) >= thresholdZIndex) {
                utils.hideElement(child);
            }
        })
    }

    // Check the element in the middle of the screen
    // Search fo elements that have zIndex attribute
    function methodTwoHideElementMiddle() {
        var overlayPopup = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);

        var overlayFound = utils.collectParrents(overlayPopup, function (el) {
            return utils.getZIndex(el) > 0;
        });

        if (debug)
            console.debug('Overlay found: ', overlayFound);

        if (overlayFound.length == 0)
            return false;

        var olderParent = overlayFound.pop();

        if (debug)
            console.debug('Hide parrent: ', olderParent);

        return olderParent;
    }

    function disableBlur() {
        var someContainerMaybe = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);

        var bluredParentsFound = utils.collectParrents(someContainerMaybe, function (el) {
            return window.getComputedStyle(el).filter.includes('blur');
        });

        if (bluredParentsFound.length == 0)
            return false;

        var topParent = bluredParentsFound.pop();

        // Some element can act as a container, that can be blured or masking the whole content
        var isContainerOccupyingAboutSpaceAsBody = topParent.offsetWidth >= (document.body.offsetWidth - 100);

        if (isContainerOccupyingAboutSpaceAsBody) {
            utils.styleImportant(topParent, 'filter', 'blur(0)');

            if (debug) console.log('Blur removed!', topParent);

            return true;
        }

        return false;
    }

    function containersOverflowAuto() {
        var containers = [document.documentElement, document.body];

        containers.forEach(function (element) {
            if (window.getComputedStyle(element).overflowY == 'hidden') {
                utils.styleImportant(element, 'overflow', 'auto');
            }
            if (window.getComputedStyle(element).position == 'fixed') {
                utils.styleImportant(element, 'position', 'static');
            }
        })
    }

    function run() {
        for (var i = 0; i < 10; i++) {
            var candidate = methodTwoHideElementMiddle();
            var first = i == 0;
            if (candidate === false) {
                if (first)
                    alert('No overlay has been found on this website.');
                break;
            } else {
                if (!first) {
                    // Prevent to hide the actual content
                    var weightThreshold = 100;
                    var candidateWeight = utils.elementWeight(candidate, weightThreshold)
                    if (candidateWeight < weightThreshold) {
                        if (debug)
                            console.log('Element is too lightweight, hide it', candidate);
                        utils.hideElement(candidate);
                    } else {
                        if (debug)
                            console.log("Element is too heavy, don't hide it", candidate);
                    }
                } else {
                    utils.hideElement(candidate);
                    containersOverflowAuto();
                    disableBlur();
                }
            }
        }
    }

    return {
        run: run
    };

};

function enableCommandMenu() {
    var commandMenu = true;
    try {
        if (typeof(GM_registerMenuCommand) == undefined) {
            return;
        } else {
            if (commandMenu == true ) {
                GM_registerMenuCommand('Remove overlay', function() {
                    overlayRemoverRun();
                });
            }
        }
    }
    catch(err) {
        console.log(err);
    }
}

overlayRemoverInstance = overlayRemover(debug, utils);

function overlayRemoverRun() {
    overlayRemoverInstance.run();
}

function keyPress(event) {
    if (event.ctrlKey && event.shiftKey && event.keyCode == 88) {
        overlayRemoverRun();
    }
}

enableCommandMenu();
document.addEventListener('keydown', keyPress);