// ==UserScript==
// @name Open links in current tab
// @author wOxxOm
// @description Open links in current tab regardless of _target or site's preferences. Ctrl-click: background tab, Ctrl-Shift-click: foreground tab, Shift-click: new window
// @namespace http://target._blank.is.retarded
// @version 2.3.0
// @include *
// @run-at document-start
// @grant GM_openInTab
// ==/UserScript==
if (window === top) {
window.addEventListener('message', function (e) {
if (!/^{/.test(e.data))
return;
var data = tryParse(e.data);
if (data.name === GM_info.script.name)
navigate(data.url);
});
}
var pageBase = location.href.split('#', 1)[0];
var suppressing, clickedElement;
window.addEventListener('click', prevent, true);
window.addEventListener('auxclick', prevent, true);
window.addEventListener('mousedown', remember, true);
window.addEventListener('mouseup', check, true);
function remember(e) {
clickedElement = e.composedPath ? e.composedPath()[0] : e.target;
}
function check(e) {
var el = e.composedPath ? e.composedPath()[0] : e.target;
if (e.button > 1 || el !== clickedElement)
return;
var a = el.closest('a');
if (!a)
return;
blockWindowOpenAndMutations(a);
var url = a.href;
if (url.lastIndexOf('javascript:', 0) === 0)
return;
var base = document.querySelector('base[target="_blank"]');
if (base)
base.target = '';
if (!url || url.split('#', 1)[0] === pageBase) {
clearLinkTarget(a);
return;
}
var b = e.button, c = e.ctrlKey, alt = e.altKey, s = e.shiftKey, m = e.metaKey;
if (b === 1 || c && !alt && !m)
GM_openInTab(url, !s || b === 1);
else if ((window.chrome || !CSS.supports('-moz-appearance', 'none')) && b === 0 && s && !c && !alt && !m)
a.cloneNode().dispatchEvent(new MouseEvent('click', {shiftKey: true}));
else if (!c && !s && !m && !alt) {
clearLinkTarget(a);
return;
} else
return;
suppressing = true;
prevent(e);
}
function clearLinkTarget(a) {
if (a.target === '_blank')
a.target = '';
}
function prevent(e) {
if (!suppressing)
return;
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
setTimeout(function () {
suppressing = false;
}, 50);
}
function blockWindowOpenAndMutations(a) {
var observer = new MutationObserver(function () {
if (a.target === '_blank') {
a.removeAttribute('target');
console.log('[Open links in current tab] prevented dynamic target=_blank for', a.href);
navigate(a.href);
}
});
observer.observe(a, {attributes: true, attributeFilter: ['target'], characterData: true});
var _open = unsafeWindow.open;
var timeout = setTimeout(function () {
unsafeWindow.open = _open;
observer.disconnect();
}, 50);
unsafeWindow.open = function (url, name, opts) {
let o0 = `${opts || ''}`, o1, o2, rel = [
(o1 = o0.replace(/(^|,)\s*noopener\s*($|,)/gi, '')) !== o0 && 'noopener',
(o2 = o1.replace(/(^|,)\s*noreferrer\s*($|,)/gi, '')) !== o1 && 'noreferrer',
];
if (!o2.trim()) {
console.log('[Open links in current tab] prevented window.open for', url);
if (rel.some(Boolean)) a.relList.add.apply(a.relList, rel.filter(Boolean));
navigate(a.href);
} else
_open(url, name, opts);
unsafeWindow.open = _open;
clearTimeout(timeout);
};
}
function navigate(url) {
if (window === top) {
var a = document.createElement('a');
a.href = url;
a.dispatchEvent(new MouseEvent('click'));
} else
top.postMessage(JSON.stringify({name: GM_info.script.name, url: url}), '*');
}
function tryParse(str) {
try {
return JSON.parse(str);
} catch (e) {}
}