Behind The Overlay

One click to close any overlay on any website

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);