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, Alt-click: force open in current tab

当前为 2016-10-22 提交的版本,查看 最新版本

  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, Alt-click: force open in current tab
  5. // @namespace http://target._blank.is.retarded
  6. // @version 2.2.0
  7. // @include *
  8. // @run-at document-start
  9. // @grant GM_openInTab
  10. // ==/UserScript==
  11.  
  12. var suppressing, clickedElement;
  13. window.addEventListener('mousedown', function(e) {
  14. clickedElement = e.target;
  15. }, true);
  16.  
  17. window.addEventListener('mouseup', function(e) {
  18. if (e.button > 1 || e.target != clickedElement)
  19. return;
  20. var link = pierceShadow(e);
  21. if (!link || (link.getAttribute('href') || '').match(/^(javascript|#|$)/))
  22. return;
  23. var b = e.button, c = e.ctrlKey, a = e.altKey, s = e.shiftKey, m = e.metaKey;
  24. if (!a && link.target != '_blank')
  25. return blockWindowOpen({observer: freezeTarget(link)});
  26. if (!b && !c && !s && !m && (link.href.replace(/#.*/, '') != location.href.replace(/#.*/, '') || a || link.target == '_blank'))
  27. location.href = link.href;
  28. else if (b == 1 || c && !a && !m)
  29. GM_openInTab(link.href, !s);
  30. else if (window.chrome && !b && s && !c && !a && !m)
  31. link.cloneNode().dispatchEvent(new MouseEvent('click', {shiftKey: true}));
  32. else
  33. return;
  34. suppressing = true;
  35. prevent(e);
  36. }, true);
  37.  
  38. window.addEventListener('click', prevent, true);
  39. window.addEventListener('auxclick', prevent, true);
  40.  
  41. function prevent(e) {
  42. if (!suppressing)
  43. return;
  44. e.preventDefault();
  45. e.stopPropagation();
  46. e.stopImmediatePropagation();
  47. setTimeout(function() {
  48. suppressing = false;
  49. }, 50);
  50. }
  51.  
  52. function freezeTarget(link) {
  53. var observer = new MutationObserver(function(mutations) {
  54. if (link.target == '_blank') {
  55. link.removeAttribute('target');
  56. console.log('[Open links in current tab] prevented dynamic target=_blank for', link.href);
  57. }
  58. });
  59. observer.observe(link, {attributes:true, attributeFilter:['target'], characterData:true});
  60. return observer;
  61. }
  62.  
  63. function blockWindowOpen(params) {
  64. var _open = unsafeWindow.open;
  65. var timeout = setTimeout(function() {
  66. unsafeWindow.open = _open;
  67. if (params && params.observer)
  68. params.observer.disconnect();
  69. }, 50);
  70. unsafeWindow.open = exportFunction(function(url, name, features) {
  71. if (!features) {
  72. console.log('[Open links in current tab] prevented window.open for', url);
  73. location.href = link.href;
  74. } else
  75. _open(url, name, features);
  76. unsafeWindow.open = _open;
  77. clearTimeout(timeout);
  78. }, unsafeWindow);
  79. }
  80.  
  81. function pierceShadow(e) {
  82. var el = e.target;
  83. while (el.shadowRoot)
  84. el = el.shadowRoot.elementFromPoint(e.clientX, e.clientY);
  85. return el.closest('a');
  86. }