您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Previews covers in novelupdates.com when hovering over hyperlinks that lead to novel pages.
当前为
// ==UserScript== // https://gf.qytechs.cn/scripts/26439-novelupdates-cover-preview/ // @name novelupdates Cover Preview // @namespace somethingthatshouldnotclashwithotherscripts // @include https://www.novelupdates.com/* // @include http://www.novelupdates.com/* // @version 0.5.8 // @description Previews covers in novelupdates.com when hovering over hyperlinks that lead to novel pages. // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @require http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js // @license http://creativecommons.org/licenses/by-nc-sa/4.0/ // ==/UserScript== var MaxCacheAge = 60* 60 * 1000; // Max Age for the Cached data is 1 hour in milliseconds //h * min * sec * ms //get value from key. Decide if timestamp is older than MaxCacheAge function GM_getCachedValue(key) { var currentTime = Date.now(); var keyCache = key+'cachedTime'; if(GM_getValue(keyCache)) //has previous timestamp for key { var measuredTimedifference = currentTime-parseInt(GM_getValue(keyCache)); if(measuredTimedifference < MaxCacheAge ) { if(GM_getValue(key)) { return GM_getValue(key); //when time difference smaller MaxCacheAge and value available return value } else GM_deleteValue(keyCache); //if no value available delete previous key with timestamp } else { //when time difference bigger than MaxCacheAge delete timestamp and value; GM_deleteValue(keyCache); GM_deleteValue(key); } } else //when no timestamp available return false return false; } //set value and currenttime for key function GM_setCachedValue(key, value) { var currentTime = Date.now(); // current datetime in milliseconds GM_setValue(key, value); GM_setValue(key+'cachedTime', currentTime); } var pathname = document.URL; var NovelPageTest = "novelupdates.com/series/"; var onHover = false; var currentTitelHover; // popupPositioning function jQuery.fn.popupPos = function (event, element, style) { var offsetY = 5; var offsetX = 5; var X,Y; var targetX,targetY; var tipToBottom, tipToRight; //Initialising variables (multiple usages) var scrollTop = $(window).scrollTop(); var scrollLeft = $(window).scrollLeft(); var elementParentOffset = element.parents().offset(); var elementOffset = element.offset(); var elementPopup = $(this); var elementParentOuterHeight = element.parents().outerHeight(); var elementParentOuterWidth = element.parents().outerWidth(); var elementOuterHeight = element.outerHeight(); var elementOuterWidth = element.outerWidth(); if(style==1){ offsetY = elementParentOuterHeight; targetX = elementParentOffset.left; targetY = elementParentOffset.top; X = targetX + elementParentOuterWidth; Y = targetY + elementParentOuterHeight + elementOuterHeight; } else if(style==2) { offsetY = elementOuterHeight; targetX = elementOffset.left + offsetX; targetY = elementOffset.top +offsetY; X = targetX + elementOuterWidth; Y = targetY + elementOuterHeight; } else { targetX = event.pageX;// + offsetX; targetY = event.pageY;// + offsetY; X = targetX; Y = targetY; } // Distance to the right tipToRight = $(window).width() - (X - scrollLeft + elementPopup.outerWidth() ); // Tooltip too close to the right? if(tipToRight < offsetX) { X += tipToRight; } if(X+offsetX < scrollLeft) X = scrollLeft + offsetX; // Distance to the bottom tipToBottom = $(window).height() - (Y - scrollTop + elementPopup.outerHeight() ); // Tooltip too close to the bottom? if(tipToBottom < offsetY) { Y += tipToBottom; } //Tooltip over top border? //if(Y+offsetY < scrollTop) Y = scrollTop + offsetY; this.css('top', Y + 'px'); this.css('left', X + 'px'); console.log("position "+X+' # '+Y); return this; }; $('body').append('<div ID="popover" class="breadcrumb_nu" style="display:flex !important;flex-direction: column; align-items:center;pointer-events:none;width:500px;height:auto;"></div>'); $('#popover').css('position', 'absolute'); $('#popover').css('z-index', '10'); $('#popover').css('box-shadow', '0px 0px 5px #7A7A7A'); var style=1; //.wpb_wrapper a = title links on individual seriepage $('.wpb_wrapper > a').mouseenter(function (e) { style=2; }); //td a = links in table cells (index and group page) $('td a').mouseenter(function (e) { style=1; }); //add additional stylesheet for "@keyframe spin" into head after document finishes loading $(window).on('load', function () { //@keyframes spin is used for die loading spinner var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = 'body {}'; document.getElementsByTagName('head')[0].appendChild(style); this.stylesheet = document.styleSheets[document.styleSheets.length-1]; try { this.stylesheet.insertRule(` @keyframes spin { 100% { transform: rotate(360deg); } }`, this.stylesheet.cssRules.length); } catch (e) {alert('error');} }); //when selected link is entered load imageurl and write popover content $('td a , .wpb_wrapper > a').mouseenter(function (e) { var Href = $(this).attr('href'); var element = $(this); if (Href.search(NovelPageTest) != - 1) //only trigger for links that point to serie pages { //define refreshPopover function function refreshPopover(title, link) { /* clear popup * append title and image into popup * when img loading is finished reposition (popupPos) to element/border */ if(currentTitelHover == suppressedNativTitle) //popup only gets refreshed when currentTitelHover == suppressedNativTitle { $('#popover').empty(); $('#popover').append('<div class="tbl_sort" style="width:100%;text-align:center !important">'+title+'</div><img src="' + link + '" style="width:500px;height:400px;align-items: stretch;align-self: stretch;object-fit: contain;"></img>'); $('#popover img').on('load', function () { console.log(Href + "onload is executed"); // for testing purposes if(onHover && (currentTitelHover == title)) //is mouse still hovering over same title after loading finishes? $('#popover').popupPos(e, element, style); //else // $('#popover').empty(); //clear popover }); } } onHover = true; $('#popover').show(); var shortSerieTitle = element.text(); //get linkname var suppressedNativTitle; //move native title to custom data attribute. Suppress nativ title if(!element.attr('datatitle')) { element.attr('datatitle', element.attr('title')); element.removeAttr('title'); } var serieTitle = element.attr('datatitle'); if(!serieTitle) //has no set nativ long title -> use (available shortend) linkname serieTitle = shortSerieTitle; suppressedNativTitle = GM_getCachedValue(shortSerieTitle); //was title cached? if(!suppressedNativTitle) //no cache -> use nativ title / shortend linkname and save them to cache { suppressedNativTitle = serieTitle; GM_setCachedValue(shortSerieTitle, serieTitle); } if(suppressedNativTitle.match("^Recommended by")) //catch individual serie page has Recommended by x people in nativ title -> use linkname suppressedNativTitle = shortSerieTitle; currentTitelHover = suppressedNativTitle; //mark which titel is currently hovered //$(this).css('font-weight', 'bold'); // Bolds previously hovered links. var retrievedImgLink = GM_getCachedValue(Href); //was imageurl cached? if (retrievedImgLink) { refreshPopover(suppressedNativTitle, retrievedImgLink); //popup only gets refreshed when currentTitelHover == suppressedNativTitle console.log(link +' on the page '+Href + " has been found and retrieved from the cache."); // for testing purposes } else { //vv popup loading spinner vv $('#popover').empty(); $('#popover').append('<div class="tbl_sort" style="width:100%;text-align:center !important">'+suppressedNativTitle+'</div><div style="position: relative;width:150px; height:150px;color:#fff;display: flex; justify-content: center; flex-direction: column; text-align: center;">Getting image url<div style="z-index: -100;position:absolute;top:0;left:0;background-color:#000; box-sizing: border-box; width: 150px; height: 150px; border-radius: 100%; border: 10px solid rgba(255, 255, 255, 0.2); border-top-color: #FFF; animation: spin 1s infinite linear;"></div></div>'); $('#popover').popupPos(e, element, style); //^^ popup loading spinner ^^ //get imgurl async $.ajax({ url: Href, type: "GET", dataType: 'text', success: function (data) { //vvv get imageurl link vvv var htmlData = $('<div>').html(data)[0]; var imagelinkLoggedIn = htmlData.getElementsByClassName('serieseditimg')[0]; var imagelink; if(imagelinkLoggedIn) //need to consider different img classes for logged in and anonymous users imagelink = imagelinkLoggedIn.getElementsByTagName('img')[0].src; else imagelink = htmlData.getElementsByClassName('seriesimg')[0].getElementsByTagName('img')[0].src; // ^^^ get imageurl link ^^^ refreshPopover(suppressedNativTitle, imagelink); //popup only gets refreshed when currentTitelHover == suppressedNativTitle console.log(Href + " has been found and retrieved from the page."); // for testing purposes // cache info GM_setCachedValue(Href, imagelink); //cache imageurl link console.log(imagelink + ') successfully cached.'); // for testing purposes } }); } } }); //hide and empty popup when mouse is not over title $('td a , .wpb_wrapper > a').mouseleave(function () { //close popup when mouse leaves titlelink //$('#popover').empty(); $('#popover').hide(); onHover = false; }); $(document).mouseleave(function () { //force close when mouse is outside window and previous mouseleave does not get called $('#popover').hide(); onHover = false; }); $(window).blur(function () { //chrome fix -> force close when mouse is outside window alt + tab $('#popover').hide(); onHover = false; });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址