// ==UserScript==
// @name youtube新标签页打开🙌😁😁😁
// @namespace neo_world_js
// @version 1.1.3
// @description 支持首页,搜索,频道,个人主页等在新标签打开,你懂的
// @author neoWorld
// @match https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @grant none
// ==/UserScript==
(function () {
"use strict";
const updateAEle = function (selector) {
const aEle = [...document.querySelectorAll(selector)];
for (let i = 0; i < aEle.length; i++) {
const ele = aEle[i];
ele.setAttribute("target", "_blank");
const href = ele.getAttribute("href");
ele.addEventListener("click", (e) => {
e.stopPropagation();
window.open(href, "_blank");
return false;
});
//ele.setAttribute("href", "#");
};
};
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
const updateAEleBatch = debounce(function (aEleList) {
if (globalVars.intervalTimes !== globalVars.intervalDefaultTimes) return; // 避免重复更新
for (let i = 0; i < aEleList.length; i++) {
updateAEle(aEleList[i]);
}
}, 250); // 250ms debounce time
const getCurPath = () => {
const { pathname } = window.location;
const secondIndex = pathname.indexOf("/", 2);
const path =
secondIndex === -1 ? pathname : pathname.substr(0, secondIndex);
return path;
};
const getSelectorAtCurPath = function () {
const path = getCurPath();
return (
globalVars.selectorPathMap[path] || {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]'],
}
);
};
const initObserver = function (selector) {
const observeEle = document.querySelector(selector.observeEle);
if (!observeEle) return;
new MutationObserver(() => {
updateAEleBatch(selector.aEle);
}).observe(observeEle, {
childList: true,
subtree: true, // 监视子孙节点
});
};
const watchPathChange = function (cb = () => { }) {
window.addEventListener("popstate", cb);
};
// init
const globalVars = {
selectorPathMap: {
"/": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]'],
},
"/results": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]'],
},
"/channel": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]', 'ytd-grid-playlist-renderer a[href^="/"]', '#channel a[href^="/"]'],
},
"/watch": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]', 'ytd-video-owner-renderer a[href^="/"]'],
},
"/playlist": {
observeEle: "#page-manager",
aEle: ['#content a[href^="/"]'],
},
"/user": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]'],
},
"/c": {
observeEle: "#page-manager",
aEle: ['ytd-grid-playlist-renderer a[href^="/"]', '#dismissible a[href^="/"]'],
},
"/feed": {
observeEle: "#page-manager",
aEle: ['#dismissible a[href^="/"]'],
},
},
initPath: window.location.pathname,
intervalDefaultTimes: 10,
intervalTimes: 10,
};
const selector = getSelectorAtCurPath();
window.onload = () => {
initObserver(selector);
updateAEleBatch(selector.aEle);
};
watchPathChange(() => {
initObserver(selector);
updateAEleBatch(selector.aEle);
});
})();