Greasy Fork is available in English.
在Bangumi游戏条目上添加实用的按钮
当前为
// ==UserScript==
// @name Bangumi jump to multiple sites
// @namespace http://tampermonkey.net/
// @version 0.9.4
// @description 在Bangumi游戏条目上添加实用的按钮
// @author Sedoruee
// @match https://bgm.tv/subject/*
// @grant GM_setClipboard
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 获取条目类型和标题
const subjectType = document.querySelector('.nameSingle > .grey')?.textContent;
const gameTitle = document.querySelector('.nameSingle > a')?.textContent;
if (subjectType === '游戏' && gameTitle) {
const nameSingle = document.querySelector('.nameSingle');
// 辅助函数:创建按钮
const createButton = (text, clickHandler) => {
const button = document.createElement('button');
button.textContent = text;
button.style.marginLeft = '5px';
if (clickHandler) {
button.addEventListener('click', clickHandler);
}
nameSingle.appendChild(button);
return button;
};
// 单独搜索按钮
createButton('VNDB', () => {
window.location.href = `https://vndb.org/v?q=${encodeURIComponent(gameTitle)}`;
});
createButton('Hitomi', () => {
window.location.href = `https://hitomi.la/search.html?type%3Agamecg%20${encodeURIComponent(gameTitle)}%20orderby%3Apopular%20orderbykey%3Ayear`;
});
createButton('魔皇地狱', () => {
GM_setClipboard(gameTitle);
window.open('https://pan1.mhdy.shop/');
});
// “多搜索”按钮 —— 悬停1秒后触发
const multiSearchButton = createButton('多搜索');
let multiSearchTimer = null;
let previewWindows = []; // 保存窗口对象的数组
let monitorInterval = null; // 用于定时监控焦点的定时器
let focusMonitorDelayTimer = null; // 用于延迟启动焦点监控
multiSearchButton.addEventListener('mouseenter', () => {
multiSearchTimer = setTimeout(() => {
openPreviewWindows();
}, 1000);
});
multiSearchButton.addEventListener('mouseleave', () => {
if (multiSearchTimer) {
clearTimeout(multiSearchTimer);
multiSearchTimer = null;
}
});
// 打开三个预览窗口,固定在屏幕正中并排显示
function openPreviewWindows() {
// 如果已有预览窗口,则先关闭它们
closePreviewWindows();
// 设置窗口尺寸和间隔
const winWidth = 640;
const winHeight = 1600
const gap = 10;
const totalWidth = winWidth * 3 + gap * 2;
// 屏幕正中位置
const leftStart = Math.floor((screen.width - totalWidth) / 2);
const topPos = Math.floor((screen.height - winHeight) / 2);
// 定义三个预览网址
const urls = [
`https://www.ai2.moe/search/?q=${encodeURIComponent(gameTitle)}&updated_after=any&sortby=relevancy&search_in=titles`,
`https://www.moyu.moe/search?q=${encodeURIComponent(gameTitle)}`,
`https://2dfan.com/subjects/search?keyword=${encodeURIComponent(gameTitle)}`
];
previewWindows = []; // Reset the array before opening new windows
urls.forEach((url, index) => {
const leftPos = leftStart + index * (winWidth + gap);
const features = `width=${winWidth},height=${winHeight},left=${leftPos},top=${topPos},resizable=yes,scrollbars=yes`;
const newWin = window.open(url, '_blank', features);
if (newWin) {
previewWindows.push(newWin);
newWin.onload = () => {
newWin.document.addEventListener('click', function(event) {
if (event.target.tagName === 'A') {
event.preventDefault(); // 阻止默认链接行为在弹窗中打开
const href = event.target.href;
closePreviewWindows(); // 关闭所有弹窗
window.open(href, '_blank'); // 在新标签页中打开链接
}
});
};
} else {
console.warn("弹窗被拦截,无法打开:", url);
}
});
// 延迟 2 秒启动定时器,监控焦点
focusMonitorDelayTimer = setTimeout(() => {
startFocusMonitor();
}, 2000);
}
// 关闭所有预览窗口
function closePreviewWindows() {
stopFocusMonitor(); // 停止焦点监控定时器
if (focusMonitorDelayTimer) { // 清除延迟启动定时器
clearTimeout(focusMonitorDelayTimer);
focusMonitorDelayTimer = null;
}
// 避免在beforeunload事件中重复关闭,使用forEach安全地关闭所有窗口
previewWindows.forEach(win => {
if (win && !win.closed) {
win.close();
}
});
previewWindows = []; // 清空数组
}
// --- 焦点监控逻辑 ---
function startFocusMonitor() {
if (!monitorInterval) {
monitorInterval = setInterval(monitorFocus, 300); // 每 300ms 检查一次焦点
}
}
function stopFocusMonitor() {
if (monitorInterval) {
clearInterval(monitorInterval);
monitorInterval = null;
}
}
function monitorFocus() {
// **窗口关闭状态轮询和同步关闭**
for (let i = 0; i < previewWindows.length; i++) {
if (previewWindows[i] && previewWindows[i].closed) {
closePreviewWindows(); // 检测到任何窗口关闭,立即关闭所有
return; // 立即返回,避免重复检查
}
}
// 检查主窗口是否失去焦点 (原有的焦点监控逻辑)
if (!document.hasFocus()) {
let previewWindowFocused = false;
// 检查是否有预览窗口获得焦点
for (let win of previewWindows) {
if (win && !win.closed && win.document.hasFocus()) {
previewWindowFocused = true;
break;
}
}
// 如果主窗口和所有预览窗口都失去焦点,则关闭预览窗口
if (!previewWindowFocused) {
closePreviewWindows();
}
}
}
}
})();