// ==UserScript== // @name 强制页面在新标签页打开 // @namespace http://tampermonkey.net/ // @version 0.3 // @description 为了避免误触需要在油猴菜单里输入生效的dom元素的选择器,如果想要整个网页都生效,只需填入 body 即可 // @author meteora // @match http://*/* // @license MIT // @match https://*/* // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant unsafeWindow // @downloadURL none // ==/UserScript== ;(function () { "use strict" //排除iframe if (unsafeWindow.self !== unsafeWindow.top) { return } let domListText = localStorage.getItem("domListText") ? localStorage.getItem("domListText") : "" let domList = [] function hookATag() { // 获取页面上的所有链接元素 for (let domListElement of domList) { let links = domListElement.getElementsByTagName("a") for (let i = 0; i < links.length; i++) { // 遍历每个链接元素并添加目标属性 links[i].setAttribute("target", "_blank") //给标签添加点击事件,点击后标红 links[i].addEventListener("click", function () { this.style.color = "darkred" }) } } } function hookWindowOpen() { // 保存原始的 unsafeWindow.open 方法的引用 let originalOpen = unsafeWindow.open // 重写 unsafeWindow.open 方法 unsafeWindow.open = function (url, target, features) { // 在新标签页中打开链接 originalOpen.call(this, url, "_blank", features) } } //监听dom节点变化以应对异步刷新的场景,一旦dom节点发生变化则重新执行hookPage function hookPageWhenDomChange() { let MutationObserver = unsafeWindow.MutationObserver || unsafeWindow.WebKitMutationObserver let observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { hookATag() }) }) observer.observe(document.body, { childList: true, // 观察目标子节点的变化,是否有添加或者删除 subtree: true, // 观察后代节点,默认为 false attributes: false, // 观察属性变动 }) } //显示文本输入框浮窗,用于接收用户输入的需要生效的dom选择器 function showInputTextarea() { const dom = `
确定并刷新页面生效
取消
` document.body.insertAdjacentHTML("beforeend", dom) const inputTextarea = document.getElementById("inputTextarea-zuc08") inputTextarea.value = domListText //回显文本内容 inputTextarea.focus() //自动聚焦 //绑定事件 function close() { document.body.removeChild(document.getElementById("container-zuc08")) } //确定按钮 const confirmBtnDom = document.getElementById("confirm-btn-zuc08") confirmBtnDom.addEventListener("click", function () { domListText = inputTextarea.value localStorage.setItem("domListText", domListText) close() //刷新页面 location.reload() }) //取消按钮 const cancelBtnDom = document.getElementById("cancel-btn-zuc08") cancelBtnDom.addEventListener("click", function () { close() }) } //注册油猴菜单,呼出文本输入框 GM_registerMenuCommand("设置新标签页打开链接的dom选择器", showInputTextarea) function hookPage(domStringList) { //通过换行符切割 domListText 里的内容 for (let string of domStringList) { const innerDomList = document.querySelectorAll(string) for (let innerDomListElement of innerDomList) { domList.push(innerDomListElement) } } hookATag() } let timer = null let loop = 2 let isHooking = false function intervalHookPage() { return new Promise((resolve) => { if (domListText) { //防止多次触发 if (isHooking) { resolve() return } isHooking = true const temp = domListText.split("\n") //每隔一秒执行一次 if (timer) { clearInterval(timer) loop = 2 } timer = setInterval(() => { if (loop <= 0) { clearInterval(timer) loop = 2 isHooking = false resolve() return } hookPage(temp) loop-- }, 1500) hookPage(temp) } else { isHooking = false resolve() } }) } unsafeWindow.onload = function () { if (!domListText) return intervalHookPage() //监听页面地址变化 unsafeWindow.addEventListener("popstate", function () { intervalHookPage() }) unsafeWindow.addEventListener("hashchange", function () { intervalHookPage() }) //覆写 window.top.history.pushState 方法 let originalPushState = unsafeWindow.top.history.pushState unsafeWindow.top.history.pushState = function () { originalPushState.apply(this, arguments) intervalHookPage() } } })()