Open links in current tab

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

  1. // ==UserScript==
  2. // @name Open links in current tab
  3. // @author wOxxOm
  4. // @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
  5. // @namespace http://target._blank.is.retarded
  6. // @version 2.3.0
  7. // @include *
  8. // @run-at document-start
  9. // @grant GM_openInTab
  10. // ==/UserScript==
  11.  
  12. if (window === top) {
  13. window.addEventListener('message', function (e) {
  14. if (!/^{/.test(e.data))
  15. return;
  16. var data = tryParse(e.data);
  17. if (data.name === GM_info.script.name)
  18. navigate(data.url);
  19. });
  20. }
  21.  
  22. var pageBase = location.href.split('#', 1)[0];
  23. var suppressing, clickedElement;
  24.  
  25. window.addEventListener('click', prevent, true);
  26. window.addEventListener('auxclick', prevent, true);
  27. window.addEventListener('mousedown', remember, true);
  28. window.addEventListener('mouseup', check, true);
  29.  
  30. function remember(e) {
  31. clickedElement = e.composedPath ? e.composedPath()[0] : e.target;
  32. }
  33.  
  34. function check(e) {
  35. var el = e.composedPath ? e.composedPath()[0] : e.target;
  36. if (e.button > 1 || el !== clickedElement)
  37. return;
  38. var a = el.closest('a');
  39. if (!a)
  40. return;
  41. blockWindowOpenAndMutations(a);
  42. var url = a.href;
  43. if (url.lastIndexOf('javascript:', 0) === 0)
  44. return;
  45. var base = document.querySelector('base[target="_blank"]');
  46. if (base)
  47. base.target = '';
  48. if (!url || url.split('#', 1)[0] === pageBase) {
  49. clearLinkTarget(a);
  50. return;
  51. }
  52. var b = e.button, c = e.ctrlKey, alt = e.altKey, s = e.shiftKey, m = e.metaKey;
  53. if (b === 1 || c && !alt && !m)
  54. GM_openInTab(url, !s || b === 1);
  55. else if ((window.chrome || !CSS.supports('-moz-appearance', 'none')) && b === 0 && s && !c && !alt && !m)
  56. a.cloneNode().dispatchEvent(new MouseEvent('click', {shiftKey: true}));
  57. else if (!c && !s && !m && !alt) {
  58. clearLinkTarget(a);
  59. return;
  60. } else
  61. return;
  62. suppressing = true;
  63. prevent(e);
  64. }
  65.  
  66. function clearLinkTarget(a) {
  67. if (a.target === '_blank')
  68. a.target = '';
  69. }
  70.  
  71. function prevent(e) {
  72. if (!suppressing)
  73. return;
  74. e.preventDefault();
  75. e.stopPropagation();
  76. e.stopImmediatePropagation();
  77. setTimeout(function () {
  78. suppressing = false;
  79. }, 50);
  80. }
  81.  
  82. function blockWindowOpenAndMutations(a) {
  83. var observer = new MutationObserver(function () {
  84. if (a.target === '_blank') {
  85. a.removeAttribute('target');
  86. console.log('[Open links in current tab] prevented dynamic target=_blank for', a.href);
  87. navigate(a.href);
  88. }
  89. });
  90. observer.observe(a, {attributes: true, attributeFilter: ['target'], characterData: true});
  91.  
  92. var _open = unsafeWindow.open;
  93. var timeout = setTimeout(function () {
  94. unsafeWindow.open = _open;
  95. observer.disconnect();
  96. }, 50);
  97.  
  98. unsafeWindow.open = function (url, name, opts) {
  99. let o0 = `${opts || ''}`, o1, o2, rel = [
  100. (o1 = o0.replace(/(^|,)\s*noopener\s*($|,)/gi, '')) !== o0 && 'noopener',
  101. (o2 = o1.replace(/(^|,)\s*noreferrer\s*($|,)/gi, '')) !== o1 && 'noreferrer',
  102. ];
  103. if (!o2.trim()) {
  104. console.log('[Open links in current tab] prevented window.open for', url);
  105. if (rel.some(Boolean)) a.relList.add.apply(a.relList, rel.filter(Boolean));
  106. navigate(a.href);
  107. } else
  108. _open(url, name, opts);
  109. unsafeWindow.open = _open;
  110. clearTimeout(timeout);
  111. };
  112. }
  113.  
  114. function navigate(url) {
  115. if (window === top) {
  116. var a = document.createElement('a');
  117. a.href = url;
  118. a.dispatchEvent(new MouseEvent('click'));
  119. } else
  120. top.postMessage(JSON.stringify({name: GM_info.script.name, url: url}), '*');
  121. }
  122.  
  123. function tryParse(str) {
  124. try {
  125. return JSON.parse(str);
  126. } catch (e) {}
  127. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址