Open Links in NEW BACKGROUND Tab

Open links (esp. from different domains) in NEW BACKGROUND tab

当前为 2022-12-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Open Links in NEW BACKGROUND Tab
  3. // @author Jerry
  4. // @description Open links (esp. from different domains) in NEW BACKGROUND tab
  5. // @grant GM_openInTab
  6. // @include http*://*
  7. // @namespace https://greasyfork.org/users/28298
  8. // @run-at document-start
  9. // @version 0.1
  10. // @license GNU GPLv3
  11. // ==/UserScript==
  12.  
  13.  
  14. // source:
  15. // https://greasyfork.org/en/scripts/20694-all-links-open-all-in-new-background-tab/code
  16. // https://greasyfork.org/en/scripts/12367-open-links-in-new-tab/code
  17.  
  18. attachHandler([].slice.call(document.getElementsByTagName('a')));
  19.  
  20. setMutationHandler(document, 'a', function(nodes) {
  21. attachHandler(nodes);
  22. return true;
  23. });
  24.  
  25. function attachHandler(nodes) {
  26. nodes.forEach(function(node) {
  27. // href will be auto expanded with window.location.origin, such as href="#" --> "https://example.com/#"
  28. // search-engine-a: more compatible with Search Engine Switcher script
  29. if ( (node.target != '_blank') && (!node.href.includes("javascript:")) && (!node.href.startsWith(window.location.origin)) && (node.className!="search-engine-a") ) {
  30. node.onclick = clickHandler;
  31. node.addEventListener('click', clickHandler);
  32. }
  33. });
  34. }
  35.  
  36. function clickHandler(e) {
  37. if (e.button > 1)
  38. return;
  39. e.preventDefault();
  40. e.stopPropagation();
  41. e.stopImmediatePropagation();
  42. // GM_openInTab(this.href, e.button || e.ctrlKey);
  43. GM_openInTab(this.href, true); // open in background
  44. }
  45.  
  46.  
  47.  
  48.  
  49. // https://greasyfork.org/scripts/12228/code/setMutationHandler.js
  50. // ==UserScript==
  51. // @name setMutationHandler
  52. // @description MutationObserver wrapper to wait for the specified CSS selector
  53. // @namespace wOxxOm.scripts
  54. // @author wOxxOm
  55. // @grant none
  56. // @version 3.0.2
  57. // ==/UserScript==
  58.  
  59. function setMutationHandler(target, selector, handler, options) {
  60. // or setMutationHandler(selector, handler, options) {
  61. // or setMutationHandler(options) {
  62. if (typeof arguments[0] == 'string') {
  63. options = arguments[2] || {};
  64. handler = arguments[1];
  65. selector = arguments[0];
  66. target = document;
  67. } else if (arguments.length == 1 && target && typeof target.handler == 'function') {
  68. options = arguments[0];
  69. handler = options.handler;
  70. selector = options.selector;
  71. target = options.target || document;
  72. } else if (!(target instanceof Node)) {
  73. throw 'Bad params for setMutationHandler.\n' +
  74. 'A: [optional Node] target, [String] selector, [Function] handler, [optional Object] options\n' +
  75. 'B: [Object] options\n' +
  76. 'Options: target, selector, handler, processExisting, childList, attributes, characterData, subtree, attributeOldValue, characterDataOldValue, attributeFilter';
  77. } else
  78. options = options || {};
  79.  
  80. if (options.processExisting && target.querySelector(selector))
  81. handler.call(null, Array.prototype.slice.call(target.querySelectorAll(selector)));
  82. if (!options.attributes && !options.characterData && !options.childList && options.subtree === undefined)
  83. options.childList = options.subtree = true;
  84.  
  85. var cb;
  86. if (/^#[\w\d-]+$/.test(selector)) {
  87. selector = selector.substr(1);
  88. cb = MOhandlerForId;
  89. } else {
  90. cb = MOhandler;
  91. }
  92. var observer = new MutationObserver(cb);
  93. observer.observe(target, options || {subtree:true, childList:true});
  94. return observer;
  95.  
  96. function MOhandler(mutations) {
  97. if (mutations.length > 100 && !document.querySelector(selector))
  98. return;
  99. var found = [];
  100. for (var i=0, m; (m = mutations[i++]); ) {
  101. switch (m.type) {
  102. case 'childList':
  103. var nodes = m.addedNodes, nl = nodes.length;
  104. var textNodesOnly = true;
  105. for (var j=0; j < nl; j++) {
  106. var n = nodes[j];
  107. textNodesOnly &= n.nodeType == 3; // TEXT_NODE
  108. if (n.nodeType != 1) // ELEMENT_NODE
  109. continue;
  110. if (n.matches(selector))
  111. found.push(n);
  112. else if (n.querySelector(selector)) {
  113. n = n.querySelectorAll(selector);
  114. if (n.length < 1000)
  115. found.push.apply(found, n);
  116. else
  117. found = found.concat(found.slice.call(n));
  118. }
  119. }
  120. if (textNodesOnly && m.target.matches(selector))
  121. found.push(m.target);
  122. break;
  123. case 'attributes':
  124. if (m.target.matches(selector))
  125. found.push(m.target);
  126. break;
  127. case 'characterData':
  128. if (m.target.parentNode && m.target.parentNode.matches(selector))
  129. found.push(m.target.parentNode);
  130. break;
  131. }
  132. }
  133. if (!found.length)
  134. return;
  135. if (handler.call(observer, found) === false)
  136. observer.disconnect();
  137. }
  138.  
  139. function MOhandlerForId(mutations) {
  140. var el = document.getElementById(selector);
  141. if (el && target.contains(el))
  142. if (handler.call(observer, [el]) === false)
  143. observer.disconnect();
  144. }
  145. }
  146.