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