// ==UserScript==
// @name Prompt On New Tab
// @namespace https://gf.qytechs.cn/en/users/85671-jcunews
// @version 1.1.11
// @license GNU AGPLv3
// @description Display a confirmation dialog when the site wants to open a new tab. This won't work if the user opens a link in a new tab using web browser's "Open in a new tab", "Open in background tab", or similar which are web browser internal features or browser extension features.
// @author jcunews
// @match *://*/*
// @grant none
// @run-at document-start
// ==/UserScript==
/*
Information about rejectList and allowList can be found on below URL.
https://gf.qytechs.cn/en/scripts/38392-prompt-on-new-tab
*/
var rejectList = [
["*", "*://*.doubleclick.net/*"],
["*", /^https?:\/\/[^.]+\.adservices?\.com\//i],
["*://site.com/*", /^.*?:\/\/site\.com\/(offer|popup)/i]
];
var allowList = [
["*://www.bing.com/*", "*"],
["*://www.google.*/*", "*://*.google.*/*"]
];
[rejectList, allowList].forEach(function(list) {
list.forEach(function(pair) {
pair.forEach(function(str, i) {
if (("string" === typeof str) || (str instanceof String)) {
pair[i] = new RegExp("^" + str.replace(/([(){}\[\]\\^$.+?|])/g, "\\$1").replace(/([*])/g, ".*?") + "$", "i");
}
});
});
});
function checkUrl(target, curUrl) {
function checkUrlPair(pair) {
if (pair[0].test(curUrl) && pair[1].test(target)) return true;
}
curUrl = location.href;
if (rejectList.some(checkUrlPair)) {
return -1;
} else if (allowList.some(checkUrlPair)) {
return 1;
} else return 0;
}
function getFrameNames(fs, r) {
function doEle(ele, n, i, z) {
try {
n = ele.tagName;
} catch(z) {
n = "";
}
if (fs.indexOf(n) >= 0) {
try {
r.push(ele.name);
} catch(z) {}
} else if (n) {
for (i = ele.childElementCount-1; i >= 0; i--) {
try {
n = ele.children[i].tagName;
} catch(z) {
n = "";
}
if (fs.indexOf(n) >= 0) {
try {
r.push(ele.children[i].name);
} catch(z) {}
} else if (n) {
doEle(ele.children[i]);
}
}
}
}
fs = ["IFRAME", "FRAME"];
r = [];
doEle(document.body);
return r;
}
(function(open_, anchors, forms, ele) {
function dummy(){}
function isExistingFrameName(name) {
return (["_parent", "_self", "_top"].indexOf(name) >= 0) || (getFrameNames().indexOf(name) >= 0);
}
open_ = window.open;
window.open = function(url, name) {
var loc = {}, wnd = {
document: {
close: dummy,
location: loc,
open: dummy,
write: dummy
},
location: loc
};
if (isExistingFrameName(name)) {
return open_.apply(this, arguments);
} else switch (checkUrl(url)) {
case -1:
return wnd;
case 1:
return open_.apply(this, arguments);
default:
if (!confirm("This site wants to open a new tab.\nDo you want to allow it?\n\nURL:\n" + url)) {
return wnd;
} else return open_.apply(this, arguments);
}
};
function actionCheckUrl(url, msg, ev) {
switch (checkUrl(url)) {
case -1:
if (ev && ev.preventDefault) {
ev.preventDefault();
ev.stopPropagation();
ev.stopImmediatePropagation();
}
return false;
case 1:
return true;
default:
if (!confirm(msg + "\nDo you want to allow it?\n\nURL:\n" + url)) {
if (ev && ev.preventDefault) {
ev.preventDefault();
ev.stopPropagation();
ev.stopImmediatePropagation();
}
return false;
} else return true;
}
}
anchors = document.getElementsByTagName("A");
function onAnchorClick(ev) {
if (this.href && (/^https?:/).test(this.href) && this.target && !isExistingFrameName(this.target)) {
return actionCheckUrl(this.href, "This site wants to open a new tab.", ev);
} else return true;
}
forms = document.getElementsByTagName("FORM");
function onFormSubmit(ev) {
if (this.action && this.target && !isExistingFrameName(this.target)) {
if (actionCheckUrl(this.action, "This site wants to submit a form in a new tab.", ev)) {
return this.submit_pont.apply(this, arguments);
} else return false;
} else if (!ev || !ev.preventDefault) {
return this.submit_pont.apply(this, arguments);
}
}
setInterval(function(i) {
for (i = anchors.length-1; i >= 0; i--) {
if (!anchors[i].listended) {
anchors[i].listended = 1;
anchors[i].addEventListener("click", onAnchorClick, true);
} else break;
}
for (i = forms.length-1; i >= 0; i--) {
if (!forms[i].listended) {
forms[i].listended = 1;
forms[i].submit_pont = forms[i].submit;
forms[i].submit = onFormSubmit;
forms[i].addEventListener("submit", onFormSubmit, true);
} else break;
}
}, 500);
})();