您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show thumbgallery preview images when hovering on a NexusMods main mod link or mod thumbnail, works for any game. Preview popup is fixed near the anchor, mouse can interact with popup.
// ==UserScript== // @name Nexus Mods Gallery Preview Hover (Universal) // @namespace http://tampermonkey.net/ // @version 0.5 // @description Show thumbgallery preview images when hovering on a NexusMods main mod link or mod thumbnail, works for any game. Preview popup is fixed near the anchor, mouse can interact with popup. // @author GPT // @license MIT // @match *://*/* // @grant GM_xmlhttpRequest // @connect nexusmods.com // ==/UserScript== (function() { 'use strict'; let previewDiv = null; let previewTimer = null; let currentLink = null; let hoverOnPreview = false; let hoverOnLink = false; // Only match main mod links (mods/<number>), for any game on NexusMods function isModMainLink(href) { // e.g. https://www.nexusmods.com/skyrimspecialedition/mods/12345 // https://www.nexusmods.com/fallout4/mods/6789 return /^https?:\/\/(www\.)?nexusmods\.com\/[^\/]+\/mods\/\d+$/.test(href); } // Create the preview popup near the anchor (link or image) function createPreview(images, anchor) { removePreview(); previewDiv = document.createElement('div'); previewDiv.style.position = 'absolute'; previewDiv.style.zIndex = 99999; previewDiv.style.background = '#222'; previewDiv.style.padding = '8px'; previewDiv.style.borderRadius = '8px'; previewDiv.style.boxShadow = '0 2px 12px rgba(0,0,0,0.35)'; previewDiv.style.maxWidth = '560px'; previewDiv.style.maxHeight = '420px'; previewDiv.style.overflowY = 'auto'; previewDiv.style.overflowX = 'hidden'; previewDiv.style.display = 'grid'; previewDiv.style.gridTemplateColumns = '1fr 1fr'; previewDiv.style.gap = '8px'; // Add all images to the popup grid for (let img of images) { let i = document.createElement('img'); i.src = img; i.style.maxHeight = '180px'; i.style.maxWidth = '260px'; i.style.width = '100%'; i.style.objectFit = 'cover'; i.style.borderRadius = '4px'; previewDiv.appendChild(i); } document.body.appendChild(previewDiv); // Position the preview below and slightly to the right of the anchor let rect = anchor.getBoundingClientRect(); let scrollX = window.scrollX || document.documentElement.scrollLeft; let scrollY = window.scrollY || document.documentElement.scrollTop; let left = rect.left + scrollX + 8; let top = rect.bottom + scrollY + 6; previewDiv.style.left = left + 'px'; previewDiv.style.top = top + 'px'; // When mouse enters/leaves the popup previewDiv.addEventListener('mouseenter', function() { hoverOnPreview = true; clearTimeout(previewTimer); }); previewDiv.addEventListener('mouseleave', function() { hoverOnPreview = false; startPreviewTimeout(); }); } // Start delayed removal of preview function startPreviewTimeout() { previewTimer = setTimeout(() => { removePreview(); }, 200); } // Remove the preview popup function removePreview() { if (previewDiv && previewDiv.parentNode) { previewDiv.parentNode.removeChild(previewDiv); previewDiv = null; } currentLink = null; clearTimeout(previewTimer); hoverOnPreview = false; hoverOnLink = false; } // Fetch thumbgallery images from the mod page function fetchGallery(link, anchor) { if (currentLink === link) return; // Prevent duplicate requests currentLink = link; GM_xmlhttpRequest({ method: 'GET', url: link, onload: function(response) { let html = response.responseText; let match = html.match(/<ul class="thumbgallery gallery clearfix"[^>]*>([\s\S]*?)<\/ul>/); if (match) { let ul = match[1]; let imgRegex = /<img\s+[^>]*src="([^"]+)"[^>]*>/g; let images = []; let m; while ((m = imgRegex.exec(ul)) !== null) { images.push(m[1]); } if (images.length > 0) { createPreview(images, anchor); } } } }); } // Listen for mouseover on mod main links document.body.addEventListener('mouseover', function(e) { let target = e.target; if (target.tagName === 'A' && isModMainLink(target.href)) { hoverOnLink = true; fetchGallery(target.href, target); target.addEventListener('mouseleave', function handler() { hoverOnLink = false; startPreviewTimeout(); target.removeEventListener('mouseleave', handler); }); } }, true); // Listen for mouseover on mod thumbnails (img inside mod main link) document.body.addEventListener('mouseover', function(e) { let target = e.target; // Typical thumbnails are <img> inside <a> if ( target.tagName === 'IMG' && target.closest('a') && isModMainLink(target.closest('a').href) ) { let a = target.closest('a'); hoverOnLink = true; fetchGallery(a.href, target); a.addEventListener('mouseleave', function handler() { hoverOnLink = false; startPreviewTimeout(); a.removeEventListener('mouseleave', handler); }); } }, true); // Remove preview when clicking elsewhere on the page document.addEventListener('mousedown', function(e) { if (previewDiv && !previewDiv.contains(e.target)) { removePreview(); } }); })();