// ==UserScript== // @name 强制后台新建标签页打开所有链接 // @namespace https://greasyfork.org/ // @version 1.3 // @license MIT // @author pugfly // @match *://*/* // @grant GM_openInTab // @grant unsafeWindow // @run-at document-start // @description 所有链接强制后台新建标签页打开,兼容Firefox和Chrome // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ========== 核心逻辑 ========== // 1. 拦截链接点击(左键、中键、右键) function interceptLinkClicks(event) { let target = event.target; while (target && target.tagName !== 'A') { target = target.parentElement; } if (target?.tagName === 'A' && target.href) { event.preventDefault(); event.stopImmediatePropagation(); GM_openInTab(target.href, { active: false }); return false; } } document.addEventListener('click', interceptLinkClicks, true); document.addEventListener('auxclick', interceptLinkClicks, true); // 2. 专用处理搜索框逻辑(支持Bing及其他网站) let isProcessing = false; // 防重复标记 function handleSearchAction(event) { if (isProcessing) return; isProcessing = true; // 2.1 处理表单提交事件 if (event.type === 'submit') { const form = event.target; if (form.tagName === 'FORM') { event.preventDefault(); event.stopImmediatePropagation(); const url = new URL(form.action || window.location.href); const validInputs = [...form.elements].filter(el => el.name && el.value); validInputs.forEach(input => url.searchParams.append(input.name, input.value)); GM_openInTab(url.href, { active: false }); } } // 2.2 处理独立输入框的回车事件(如Bing结果页) else if (event.type === 'keydown' && event.key === 'Enter') { const input = event.target; if (input.tagName === 'INPUT' && (input.type === 'text' || input.type === 'search')) { event.preventDefault(); event.stopImmediatePropagation(); // 智能构造搜索URL(兼容Bing) let searchUrl; if (window.location.hostname.includes('bing.com')) { searchUrl = new URL('https://www.bing.com/search'); searchUrl.searchParams.append('q', input.value); } else { searchUrl = new URL(window.location.href.split('?')[0]); searchUrl.searchParams.append(input.name || 'q', input.value); } GM_openInTab(searchUrl.href, { active: false }); } } setTimeout(() => isProcessing = false, 50); // 重置标记 } // 3. 事件监听配置 document.addEventListener('submit', handleSearchAction, true); document.addEventListener('keydown', handleSearchAction, true); // 4. 重写表单submit方法(防止JS直接调用) const nativeFormSubmit = HTMLFormElement.prototype.submit; HTMLFormElement.prototype.submit = function() { const form = this; const url = new URL(form.action || window.location.href); [...form.elements].forEach(el => { if (el.name && el.value) url.searchParams.append(el.name, el.value); }); GM_openInTab(url.href, { active: false }); return false; }; // 5. 动态内容监控(防止SPA修改DOM) const observer = new MutationObserver(mutations => { mutations.forEach(({ addedNodes }) => { addedNodes.forEach(node => { if (node.nodeType === 1) { // ELEMENT_NODE node.querySelectorAll('a[href]').forEach(link => { link.setAttribute('target', '_blank'); link.onclick = e => e.preventDefault(); }); node.querySelectorAll('form').forEach(form => { form.setAttribute('target', '_blank'); form.onsubmit = e => e.preventDefault(); }); } }); }); }); observer.observe(document, { subtree: true, childList: true }); })();