您需要先安装一个扩展,例如 篡改猴、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();
- }
- });
- })();