您需要先安装一个扩展,例如 篡改猴、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/* // @include https://forum.novelupdates.com/* // @include http://forum.novelupdates.com/* // @version 1.3.5 // @description Previews covers in novelupdates.com when hovering over hyperlinks that lead to novel pages. // @inject-into content // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @run-at document-end // @license http://creativecommons.org/licenses/by-nc-sa/4.0/ // ==/UserScript== const MAXCACHEAGE = 7 * 24 * 60 * 60 * 1000; // Max Age before Cached data gets overridden with current data. Max Age is 7 days in milliseconds //days * h * min * sec * ms var STYLESHEETHIJACKFORBACKGROUND = ".l-canvas"; //if unknown set empty ""; classname with leading dot var STYLESHEETHIJACKFORTITLE = '.widgettitle_nuf'; //if unknown set empty ""; classname with leading dot const DEFAULTTITLEBACKGROUNDCOLOR = '#aac'; //if no hijack class style available use plain color const DEFAULTBACKGROUNDCOLOR = '#ccc'; //if no hijack class style available use plain color const SELECTOR1 = 'td a'; //index/group/readinglist pages , forum const SELECTOR2 = '.wpb_wrapper > a, .messageContent a'; //individual serie pages recommendation titles const PREDIFINEDNATIVTITLE = "^Recommended by"; //in case native title is used to display something different const INDIVIDUALPAGETEST = "novelupdates.com/series/"; const IMAGELINKCONTAINERS = '.serieseditimg, .seriesimg'; //instead of single element class name with dot const IMAGELINKCONTAINERSnonJquery = 'serieseditimg seriesimg'; //instead of single element class name with dot const IMAGEBLOCKER = "www.novelupdates.com/img/noimagefound.jpg"; //tested with string.match(). no need for prefixed http https in url. Can even be just the file name const CONTAINERNUMBER = 0; const preloadUrlRequests = true; const preloadImages = false; //^^^^ frontend settings over this line ^^^^ const RE = /\s*,\s*/; //Regex for split and remove empty spaces var defaultHeight = "400px"; var IMAGEBLOCKERARRAY = IMAGEBLOCKER.split(RE); var onHover = false; var currentTitelHover; //var windowCached = $(window); //var concatenatedSelectors = $(concatSelector()); var style = 1; var popover; var concatenatedSelectorAll = document.querySelectorAll(concatSelector()); //get value from key. Decide if timestamp is older than MAXCACHEAGE than look for new image function GM_getCachedValue(key) { const DEBUG = false; var currentTime = Date.now(); var rawCover = GM_getValue(key, null); DEBUG && console.group("GM_getCachedValue") DEBUG && console.log("rawCover: " + rawCover) let result = null; if (!rawCover) { result = null; } else { var coverData; try { //is json parseable data? if not delete for refreshing coverData = JSON.parse(rawCover); DEBUG && console.log("coverData: " + coverData) if (!(coverData.url && coverData.cachedTime)) //has same variable definitions? { GM_deleteValue(key); result = null; } } catch (e) { GM_deleteValue(key); result = null; } var measuredTimedifference = currentTime - coverData.cachedTime; if (measuredTimedifference < MAXCACHEAGE) result = coverData.url; else { GM_deleteValue(key); result = null; } } DEBUG && console.groupEnd("GM_getCachedValue") return result; } //set value and currenttime for key function GM_setCachedValue(key, value) { var coverData = { url: value, cachedTime: Date.now() }; GM_setValue(key, JSON.stringify(coverData)); } function inBlocklist(link) { if (IMAGEBLOCKERARRAY) if (IMAGEBLOCKERARRAY.length > 0) for (let i = 0; i < IMAGEBLOCKERARRAY.length; i++) if (IMAGEBLOCKERARRAY[i] !== "") if (link.match(IMAGEBLOCKERARRAY[i])) return true; return false; } function concatSelector() { var result; if (SELECTOR1) result = SELECTOR1; if (SELECTOR2) { if (SELECTOR1) //in case selector1 is missing result += ', '; result += SELECTOR2; } return result; } //https://medium.com/@alexcambose/js-offsettop-property-is-not-great-and-here-is-why-b79842ef7582 const getOffset = (element, horizontal = false) => { if (!element) return 0; return getOffset(element.offsetParent, horizontal) + (horizontal ? element.offsetLeft : element.offsetTop); } // popupPositioning function popupPos = function (event, element, style, nativElement) { const DEBUG = false; DEBUG && console.group("popupPos style:" + style) var offsetToBottomBorderY = 5; //offset to bottom border var offsetToRightBorderX = 5; //offset to right border var X, Y; var hoveredSelectedPosX, hoveredSelectedPosY; var distanceToBottom, distanceToRight; //console.log(element.parents()[0]) DEBUG && console.log(nativElement) //console.log(nativElement.parentElement) let parentElement = nativElement.parentElement; //let computedFontSizeJquery = parseInt(window.getComputedStyle(element.parents()[0]).fontSize); let computedFontSize = parseInt(window.getComputedStyle(parentElement).fontSize); //console.log(computedFontSize); //Initialising variables (multiple usages) let scrollPosY = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop; let scrollPosX = window.scrollX || window.scrollLeft || document.getElementsByTagName("html")[0].scrollLeft; // console.log(scrollPosX) var scrollTop = scrollPosY; // windowCached.scrollTop(); var scrollLeft = scrollPosX; //windowCached.scrollLeft(); //var elementPopup = this[0]; //this = ontop of jquery object let elementPopup = popover; let elementImg = elementPopup.getElementsByTagName("img"); DEBUG && console.log(popover) DEBUG && console.log(elementPopup) DEBUG && console.log("elementPopup.offsetHeight: " + elementPopup.offsetHeight) DEBUG && console.log("popover[0].offsetHeight: " + popover.offsetHeight) DEBUG && console.log(elementImg) if (elementImg) { DEBUG && console.log(elementImg) } //var elementParentOffset = element.parents().offset(); let elementParentOffset = { top: getOffset(parentElement), left: getOffset(parentElement, true) } DEBUG && console.log(elementParentOffset) //var elementParentOuterHeight = element.parents().outerHeight(); //var elementParentOuterWidth = element.parents().outerWidth(); let elementParentOuterHeight = parentElement.offsetHeight; let elementParentOuterWidth = parentElement.offsetWidth; //var elementOffset = element.offset(); let elementOffset = { top: getOffset(nativElement), left: getOffset(nativElement, true) } DEBUG && console.log(elementOffset) //var elementOuterHeight = element.outerHeight(); let elementOuterHeight = nativElement.offsetHeight; //var elementOuterWidth = element.outerWidth(); //var elementRect = element[0].getBoundingClientRect(); //var elementParentRect = element.parents()[0].getBoundingClientRect(); if (style == 1) //index: position next to parent table cell (SELECTOR1) { hoveredSelectedPosX = elementParentOffset.left + elementParentOuterWidth; //link position + tablecell width; + elementOuterWidth; hoveredSelectedPosY = elementParentOffset.top + computedFontSize; //link position + tablecell height; + elementOuterHeight; //console.log("height " + elementParentOuterHeight + ' - ' + elementOuterHeight); } else if (style == 2) //recommendations: position next to link height and parent (SELECTOR2) width { hoveredSelectedPosX = elementOffset.left + elementParentOuterWidth; //elementOffset.left + elementOuterWidth; hoveredSelectedPosY = elementOffset.top + elementOuterHeight; } else { //position to mouse hover position hoveredSelectedPosX = event.pageX; // + offsetToRightBorderX; hoveredSelectedPosY = event.pageY; // + offsetToBottomBorderY; } X = hoveredSelectedPosX; Y = hoveredSelectedPosY; DEBUG && console.log("hoveredSelectedPos x: " + X + ", y: " + Y) //windowCached.height() = window.innerHeight //document.body.clientWidth //window.innerWidth == document.body.clientWidth + scrollbarWidth // Distance to the right distanceToRight = window.innerWidth - (X - scrollLeft); DEBUG && console.log("distanceToRight: " + distanceToRight + ", elementPopup.outerWidth: " + elementPopup.offsetWidth) // Tooltip too close to the right? if (distanceToRight < elementPopup.offsetWidth - offsetToRightBorderX) X += distanceToRight - elementPopup.offsetWidth - offsetToRightBorderX; //elementPopup //console.log(document.body.clientHeight) //console.log("windowCached.height(): " + windowCached.height()) DEBUG && console.log("window.innerHeight: " + window.innerHeight) // Distance to the bottom distanceToBottom = window.innerHeight - (Y - scrollTop); DEBUG && console.log("distanceToBottom: " + distanceToBottom) DEBUG && console.log("elementPopup.offsetHeight: " + elementPopup.offsetHeight) DEBUG && console.log("popover[0].offsetHeight: " + popover.offsetHeight) DEBUG && console.log("parentElement.offsetHeight: " + parentElement.offsetHeight) let imgElement = elementPopup.getElementsByTagName("img")[0] DEBUG && console.log(imgElement) //console.log(elementPopup) // Tooltip too close to the bottom? if (distanceToBottom < elementPopup.offsetHeight - offsetToBottomBorderY) //(offsetToBottomBorderY + elementPopup.outerHeight()) Y += distanceToBottom - elementPopup.offsetHeight - offsetToBottomBorderY; //offsetToRightBorderX //offsetToBottomBorderY //console.log("Distance to the bottom " + distanceToBottom+" elementPopupHeight " +elementPopup.outerHeight()+ "\nDistance to the right " + distanceToRight+ " elementPopupouterWidth " +elementPopup.outerWidth()); //Tooltip over top border? //if(Y + offsetToBottomBorderY < scrollTop) Y = scrollTop + offsetToBottomBorderY; //if(X + offsetToRightBorderX < scrollLeft) X = scrollLeft + offsetToRightBorderX; /* console.log(elementPopup.style) this.css('top', Y + 'px'); this.css('left', X + 'px'); console.log(elementPopup.style) */ elementPopup.style.top = Y + 'px'; elementPopup.style.left = X + 'px'; //popover.show(); showPopOver(); DEBUG && console.groupEnd("popupPos") //console.log("final popup position "+X+' # '+Y); return this; }; //.wpb_wrapper a = title links on individual seriepage //http://youmightnotneedjquery.com/ //https://latteandcode.medium.com/vanilla-js-addeventlistener-queryselector-and-closest-e7e5503b6418 function changeStyleType(styleType) { //if (!e.target.matches(selectorType)) return; style = styleType; } function mouseenterAll(selectorType, styleType = 1) { let selectorAll = document.querySelectorAll(selectorType); //console.log("mouseenterAll for selectors: " + selectorType) selectorAll.forEach(function (selector) { selector.addEventListener("mouseenter", changeStyleType(styleType)) }) } mouseenterAll(SELECTOR1, 1); mouseenterAll(SELECTOR2, 2); function loadImgUrl(elementUrl) { const DEBUG = false; DEBUG && console.group("loadImgUrl: " + elementUrl) let PromiseResult = new Promise(async function (resolve, reject) { let retrievedImgLink = GM_getCachedValue(elementUrl); DEBUG && console.log("elementUrl: " + elementUrl); DEBUG && console.log("retrievedImgLink: " + retrievedImgLink) if (retrievedImgLink !== null) { DEBUG && console.log("loadImgUrl has retrievedImgLink: " + retrievedImgLink) resolve(retrievedImgLink); } else { DEBUG && console.log("make ajax request try to save image of page into cache: " + elementUrl); /* $.ajax({ url: elementUrl, type: "GET", dataType: 'text' }).done(function (data) { let html = data.replace(/src=/g, 'data-src='); //block resources loading when DOM gets opened DEBUG && console.log("html: " + html); try { var imagelinks = $(html).find(IMAGELINKCONTAINERS).find('img'); var imagelink = imagelinks[CONTAINERNUMBER].getAttribute("data-src"); DEBUG && console.log('init ' + imagelink); GM_setCachedValue(elementUrl, imagelink); //cache imageurl link resolve(imagelink); } catch (error) { DEBUG && console.log(error); showPopupLoadingSpinner(serieTitle, 1); reject(elementUrl); } }) .fail(function (xhr) { DEBUG && console.log('error', xhr); });*/ GM_xmlhttpRequest({ method: "GET", responseType: 'document', url: elementUrl, onload: function (xhr) { DEBUG && console.log(response.responseText); try { let temp = xhr.response.querySelectorAll(IMAGELINKCONTAINERS); let imageLinkByTag = temp[0].getElementsByTagName("img"); var imagelink = imageLinkByTag[CONTAINERNUMBER].getAttribute("src"); DEBUG && console.log('init ' + imagelink); GM_setCachedValue(elementUrl, imagelink); //cache imageurl link resolve(imagelink); } catch (error) { DEBUG && console.log(error); showPopupLoadingSpinner(serieTitle, 1); reject(elementUrl); } } }); } }); DEBUG && console.groupEnd("loadImgUrl: " + elementUrl) return PromiseResult; } main(); function main() { const DEBUG = false; function uniq(a) { return Array.from(new Set(a)); } if (preloadUrlRequests) { var getNovelLinks = function () { const links = Array.from( document.querySelectorAll('a[href*="' + INDIVIDUALPAGETEST + '"]') ); return links; }; const links = getNovelLinks(); const novelUrlList = links.map(function (el) { // console.log('novelUrlList ' + el.href); return el.href; }); const uniqueNovelUrlList = uniq(novelUrlList); /* console.group("uniqueNovelUrlList") console.log(uniqueNovelUrlList); console.groupEnd() */ const imageUrlList = uniqueNovelUrlList.map(function (elementUrl) { loadImgUrl(elementUrl) .then(function (imgUrl) { if (preloadImages) { let img = document.createElement("img"); //put img into dom. Let the image preload in background img.src = imgUrl; DEBUG && console.log("onpageload cache init " + imgUrl); } }, function (Error) { DEBUG && console.log(Error + ' failed to fetch ' + elementUrl); }); // console.log("imageUrlList " + elementUrl); }); } //circle spinner from http://codepen.io/Beaugust/pen/DByiE //add additional stylesheet for "@keyframe spin" into head after document finishes loading //@keyframes spin is used for the 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'); } } function loadStyleSheets() { //windowCached.on('load', function () { function styleSheetContainsClass(f) { // const DEBUG = true; var localDomainCheck = '^http://' + document.domain; var localDomainCheckHttps = '^https://' + document.domain; // DEBUG && console.log("Domain check with: " + localDomainCheck); var hasStyle = false; var stylename = f; var fullStyleSheets = document.styleSheets; // DEBUG && console.log("start styleSheetContainsClass " + stylename); if (fullStyleSheets) { for (let i = 0; i < fullStyleSheets.length - 1; i++) { //DEBUG && console.log("loop fullStyleSheets " + stylename); let styleSheet = fullStyleSheets[i]; if (styleSheet != null) { if (styleSheet.href !== null) //https://gold.xitu.io/entry/586c67c4ac502e12d631836b "However since FF 3.5 (or thereabouts) you don't have access to cssRules collection when the file is hosted on a different domain" -> Access error for Firefox based browser. script error not continuing if (styleSheet.href.match(localDomainCheck) || styleSheet.href.match(localDomainCheckHttps)) { if (styleSheet.cssRules) { //DEBUG && console.log("styleSheet.cssRules.length: " + styleSheet.cssRules.length) for (let rulePos = 0; rulePos < styleSheet.cssRules.length - 1; rulePos++) { if (styleSheet.cssRules[rulePos] !== undefined) { // DEBUG && console.log("styleSheet.cssRules[rulePos] "+ stylename); if (styleSheet.cssRules[rulePos].selectorText) { // console.log(styleSheet.cssRules[rulePos].selectorText) if (styleSheet.cssRules[rulePos].selectorText == stylename) { console.log('styleSheet class has been found - class: ' + stylename); hasStyle = true; //break; break; //return hasStyle; } } //else DEBUG && console.log("undefined styleSheet.cssRules[rulePos] "+rulePos +" - "+ stylename); } //else DEBUG && console.log("loop undefined styleSheet.cssRules[rulePos] "+ stylename); } } //else DEBUG && console.log("undefined styleSheet.cssRules "+ stylename); } // DEBUG && console.log("stylesheet url " + styleSheet.href); } //else DEBUG && console.log("undefined styleSheet "+ stylename); if (hasStyle) break; } } //else console.log("undefined fullStyleSheets=document.styleSheets "+ stylename); if (!hasStyle) console.log("styleSheet class has not been found - style: " + stylename); return hasStyle; } if (STYLESHEETHIJACKFORBACKGROUND !== "") if (!styleSheetContainsClass(STYLESHEETHIJACKFORBACKGROUND)) STYLESHEETHIJACKFORBACKGROUND = ""; else { STYLESHEETHIJACKFORBACKGROUND = STYLESHEETHIJACKFORBACKGROUND.replaceAll(".", " ").trim() } if (STYLESHEETHIJACKFORTITLE !== "") if (!styleSheetContainsClass(STYLESHEETHIJACKFORTITLE)) STYLESHEETHIJACKFORTITLE = ""; else { STYLESHEETHIJACKFORTITLE = STYLESHEETHIJACKFORTITLE.replaceAll(".", " ").trim() } // $('body').append('<div ID="popover" ' + stylesheetForBackground() + '></div>'); let bodyElement = document.getElementsByTagName("BODY")[0]; bodyElement.insertAdjacentHTML("beforeend", '<div ID="popover" ' + stylesheetForBackground() + '></div>'); //console.log(bodyElement.lastChild) popover = document.getElementById('popover'); popover.style['position'] = "absolute"; popover.style['z-index'] = '10'; popover.style['box-shadow'] = '0px 0px 5px #7A7A7A'; //console.log(popover) } window.addEventListener("load", loadStyleSheets); function stylesheetForTitle() { if (STYLESHEETHIJACKFORTITLE !== "") return 'class="' + STYLESHEETHIJACKFORTITLE + '" style="display:inline-block;width:100%;max-width:auto;text-align:center !important"'; else return 'style="background-color:' + DEFAULTTITLEBACKGROUNDCOLOR + ';display:inline-block;width:100%;max-width:auto;text-align:center !important"'; } function stylesheetForBackground() { if (STYLESHEETHIJACKFORBACKGROUND !== "") return 'class="' + STYLESHEETHIJACKFORBACKGROUND + '" style="display:flex !important;flex:1;flex-direction: column; align-items:center;pointer-events:none; width:auto; height:auto; max-width:100%; max-height:100%;"'; else return 'style="background-color:' + DEFAULTBACKGROUNDCOLOR + ';display:flex !important;flex-direction: column; align-items:center;pointer-events:none; width:auto; height:auto; max-width:100%; max-height:100%;"'; } function mouseEnterPopup(e) { if (!e.target.matches(concatSelector())) return; let element = undefined;//$(this); let nativElement = this; let Href = this.href;// element.attr('href'); if (Href.search(INDIVIDUALPAGETEST) != -1) //only trigger for links that point to serie pages { let refreshPopover = function (title, link) { const DEBUG = false; /* clear popup * append title and image into popup * when img loading is finished reposition (popupPos) to element/border */ if (currentTitelHover == title) //popup only gets refreshed when currentTitelHover == title { DEBUG && console.group("refreshPopover"); //popover.empty(); popover.innerHTML = ""; if (inBlocklist(link)) { // popover.append('<div ' + stylesheetForTitle() + '>' + title + '</div>Blocked Image<br />No Cover Image<br />Unwanted Image'); popover.insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div>Blocked Image<br />No Cover Image<br />Unwanted Image'); // popupPos(e, element, style, nativElement); } else { let imgElement = new Image();//document.createElement("img"); imgElement.src = link; let aspectRatio = imgElement.naturalWidth / imgElement.naturalHeight; DEBUG && console.log("aspectRatio: " + aspectRatio) //popover.append('<div ' + stylesheetForTitle() + '>' + title + '</div><img src="' + link + '" style="margin:5px; width:auto; height:' + defaultHeight + ' !important; max-width:100%;min-height:0; max-height:100% !important; align-items: stretch;align-self: stretch;object-fit: contain;"></img>'); if (aspectRatio <= 1) popover.insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div><img src="' + link + '" style="margin:5px; width:auto; height:' + defaultHeight + ' !important; max-width:100%;min-height:0; max-height:100% !important; align-items: stretch;align-self: stretch;object-fit: contain;"></img>'); //popover.insertAdjacentHTML("beforeend", '<div style="display:flex;flex-direction:column"><div ' + stylesheetForTitle() + '>' + title + '</div><img src="' + link + '" style="margin:5px; width:auto; height:' + defaultHeight + ' !important; max-width:100%;min-height:0; max-height:100% !important; align-items: stretch;align-self: stretch;object-fit: contain;"></img></div>'); else popover.insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div><img src="' + link + '" style="margin:5px; height:auto; width:' + defaultHeight + ' !important; max-height:100%;min-width:0; max-width:100% !important; align-items: stretch;align-self: stretch;object-fit: contain;"></img>'); // popover[0].insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div>'); //<img src="" style="margin:5px; width:auto; height:' + defaultHeight + ' !important; max-width:100%;min-height:0; max-height:100% !important; align-items: stretch;align-self: stretch;object-fit: contain;"></img> // popover[0].insertAdjacentElement("beforeend",imgElement); // let popoverElement = popover; //document.getElementById("popover") //console.log($('#popover img')) //console.log(popoverElement) // let popOverImg = popoverElement.getElementsByTagName("img")[0]; //console.log("popoverElement.offsetHeight: " + popover[0].offsetHeight) //console.log(popOverImg) // if (popOverImg) { /* popoverImg.onload = function () { //console.log(Href + "onload is executed"); // for testing purposes if (onHover) //is mouse still hovering over same title after loading finishes? requestAnimationFrame(() => { console.log("popoverElement.offsetHeight: " + popoverElement.offsetHeight) popoverElement.popupPos(e, element, style, nativElement); }); }; */ // imgElement.onload = () => { // DEBUG && console.log("onload is executed"); // for testing purposes // console.log("imgElement.addEventListener load"); //DEBUG && console.log("popoverElement.offsetHeight: " + popoverElement.offsetHeight); // console.log("popoverImg: " + popoverImg); // if (onHover) //is mouse still hovering over same title after loading finishes? //popoverElement.popupPos(e, element, style, nativElement); // popupPos(e, element, style, nativElement); // } // } /* $('#popover img').on('load', function () { //console.log(Href + "onload is executed"); // for testing purposes if (onHover) //is mouse still hovering over same title after loading finishes? popover.popupPos(e, element, style, nativElement); }); */ } DEBUG && console.groupEnd("refreshPopover"); if (onHover) popupPos(e, element, style, nativElement); } }; //popup loading spinner var showPopupLoadingSpinner = function (title, error = false) { const DEBUG = false; // console.group("showPopupLoadingSpinner") //popover.empty(); popover.innerHTML = ""; DEBUG && console.log("popover.offsetHeight: " + popover.offsetHeight); if (error) popover.insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div><div style="position: relative;width:150px; height:150px;color:#000;display: flex; justify-content: center; flex-direction: column; text-align: center;">imagecontainer setting is invalid</div>'); else { popover.insertAdjacentHTML("beforeend", '<div ' + stylesheetForTitle() + '>' + title + '</div><div style="position: relative;width:150px; height:150px;color:#fff;display: flex; justify-content: center; flex-direction: column; text-align: center;">Loading image<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>'); } DEBUG && console.log(popover) DEBUG && console.log("popover.offsetHeight: " + popover.offsetHeight); popupPos(e, element, style, nativElement); // console.groupEnd("showPopupLoadingSpinner") } //async wait until image is loaded before refreshing popup var ajaxLoadImageUrlAndShowPopup = function (elementUrl, title) { const DEBUG = false; // console.group("ajaxLoadImageUrlAndShowPopup") loadImgUrl(elementUrl) .then(function (imgUrl) { let img = document.createElement("img"); //put img into dom. Let the image preload in background img.onload = () => { DEBUG && console.log("imgurl " + imgUrl); DEBUG && console.log("popover[0].offsetHeight: " + popover.offsetHeight); refreshPopover(title, imgUrl); //popup only gets refreshed when currentTitelHover == serieTitle DEBUG && console.log("popover[0].offsetHeight: " + popover.offsetHeight); // GM_setCachedValue(elementUrl, imgUrl); //cache imageurl link DEBUG && console.log(elementUrl + " url has been found and is written to temporary cache.\n" + imgUrl + ' successfully cached.'); // for testing purposes }; img.src = imgUrl; }, function (Error) { DEBUG && console.log(Error + ' failed to fetch ' + elementUrl); }); // console.groupEnd("ajaxLoadImageUrlAndShowPopup") }; onHover = true; //console.log(this) // console.log(this.text) //shortTitle // console.log(this.title) //LongTitle let shortSerieTitle = this.text; //element.text(); //get linkname var serieTitle = this.title;//element.attr('datatitle'); //try to get nativ title if available from datatitle if (!serieTitle) //has no set nativ long title -> use (available shortend) linkname serieTitle = shortSerieTitle; else //no need to run check if it is already shortSerieTitle if (serieTitle.match(PREDIFINEDNATIVTITLE)) //catch on individual serie page nativ title begins with "Recommended by" x people -> use linkname serieTitle = shortSerieTitle; currentTitelHover = serieTitle; //mark which titel is currently hovered //console.log("serieTitle: " + serieTitle) //console.log("Href: " + Href) /* var retrievedImgLink = GM_getCachedValue(Href); //was imageurl cached? if (retrievedImgLink) { refreshPopover(serieTitle, retrievedImgLink); //popup only gets refreshed when currentTitelHover == serieTitle console.log(retrievedImgLink + ' on the page ' + Href + " has been found and retrieved from the cache."); // for testing purposes } else*/ showPopupLoadingSpinner(serieTitle); ajaxLoadImageUrlAndShowPopup(Href, serieTitle); } } //when selected link is entered load imageurl and write popover content concatenatedSelectorAll.forEach(function (selector) { selector.addEventListener("mouseenter", mouseEnterPopup) }) function hidePopOver() { popover.style.visibility = "hidden"; onHover = false; } function showPopOver() { popover.style.display = "flex" popover.style.visibility = "visible"; } function hideOnMouseLeave(e) { if (!e.target.matches(concatSelector())) return; //popover.hide(); hidePopOver(); } //hide and empty popup when mouse is not over title concatenatedSelectorAll.forEach(function (selector) { selector.addEventListener("mouseleave", hideOnMouseLeave) }) /* $(document).mouseleave(function () { //force close when mouse is outside window and previous mouseleave does not get called popover.hide(); onHover = false; }); */ window.addEventListener("blur", hidePopOver); function mouseenterAllRemoveListener(selectorType, styleType = 1) { let selectorAll = document.querySelectorAll(selectorType); //console.log("mouseenterAll for selectors: " + selectorType) selectorAll.forEach(function (selector) { selector.removeEventListener("mouseenter", changeStyleType) }) } window.onunload = function () { window.removeEventListener("blur", hidePopOver); window.removeEventListener("load", loadStyleSheets); //possible memoryleaks? concatenatedSelectorAll.forEach(function (selector) { selector.removeEventListener("mouseleave", hideOnMouseLeave) }) concatenatedSelectorAll.forEach(function (selector) { selector.removeEventListener("mouseenter", mouseEnterPopup) }) mouseenterAllRemoveListener(SELECTOR1, 1); mouseenterAllRemoveListener(SELECTOR2, 2); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址