Tutorials & Resources Novel Updates UserScript to preview cover images

Discussion in 'Novel Updates Site Discussion' started by sithkazar, Jan 9, 2017.

  1. sithkazar

    sithkazar Professional Screw Up

    Joined:
    Dec 14, 2015
    Messages:
    750
    Likes Received:
    944
    Reading List:
    Link
    @IIAtariaII created a thread earlier in general chat (here) talking about how it would be a nice feature on NU to be able to get a preview of the cover when your cursor hovers over the novels title.

    I have had a userscript for awhile (I did not make it) that I use on Baka/Manga Updates. I find it very useful for untranslated titles, as I get them mixed up easily. I posted the code for the userscript and @sz was kind and talented enough to adjust the code to work on NU (bottom of the first page).

    I'm not trying to take credit or anything, I just wanted to bring attention to it. All credit should go to the original creator of the code, Kuroonehalf, and @sz for their work.

    nu example.png

    For those that want to use the script, you need an add-on for you browser like "Grease Monkey" (firefox) or "Tampermonkey" (chrome). Copy the code from @sz onto your clipboard. On Grease Monkey you then select "New User Script.." from the drop-down menu and click "Copy Script from Clipboard" button on the bottom then "Save" and close the window. After refreshing Novel Updates it should work. I am not as familiar with chrome, but it should be a similar process. I am also sure that there are similar add-ons for other browsers.

    @sz's code:
    Code:
    // ==UserScript==
    // @name        novelupdates Cover Preview
    // @namespace   somethingthatshouldnotclashwithotherscripts
    // @include     https://www.novelupdates.com/*
    // @include     http://www.novelupdates.com/*
    // @version     0.1
    // @description Previews covers in novelupdates.com when hovering over hyperlinks that lead to manga pages.
    // @grant       GM_setValue
    // @grant       GM_getValue
    // @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
    // @license     http://creativecommons.org/licenses/by-nc-sa/4.0/
    // ==/UserScript==
    // Link title suppression
    $('[title]').each( function() {
       var $this = $(this);
       $this.data('title',$this.attr('title'));
       $this.removeAttr('title');
    });
    // Centering function
    var pathname = document.URL;
    var MangaPageTest = "novelupdates.com/series/";
    jQuery.fn.center = function () {
      this.css('top', Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) + $(window).scrollTop()) + 'px');
      if (pathname.search(MangaPageTest) != -1){
       this.css('left', Math.max(0, (($(window).width() - $(this).outerWidth()) * 0.64) + $(window).scrollLeft()) + 'px');
      }
      else {
       this.css('left', Math.max(0, (($(window).width() - $(this).outerWidth()) * 0.6) + $(window).scrollLeft()) + 'px');
      };
      return this;
    }
    
    $('body').append('<div ID="popover"></div>');
    $('#popover').css('position', 'absolute');
    $('#popover').css('z-index', '10');
    $('#popover').css('box-shadow', '0px 0px 5px #7A7A7A');
    
    $('td a, .wpb_wrapper a').mouseover(function () {
      var Href = $(this).attr('href');
      if (Href.search(MangaPageTest) != - 1) {
       //$(this).css('font-weight', 'bold'); // Bolds previously hovered links.
       if (GM_getValue(Href)) {
         var retrievedLink = GM_getValue(Href);
         $('#popover').empty();
         $('#popover').append('<img src="' + retrievedLink + '" style="height:400px"></img>');
         $('#popover img').load(function() {
           $('#popover').center();
         });
         console.log(Href + " has been found and retrieved from the cache."); // for testing purposes
       }
       else {
        $.ajax({
          url: Href,
          dataType: 'text',
          success: function (data) {
            var imagelink = $('<div>').html(data)[0].getElementsByClassName('serieseditimg')[0].getElementsByTagName('img') [0].src;
            // clear what's inside #popover and put the new image in there
            $('#popover').empty();
            $('#popover').append('<img src="' + imagelink + '" style="height:400px"></img>');
            $('#popover img').load(function () {
              $('#popover').center();
            });
            // cache info
            GM_setValue(Href, imagelink);
            console.log(imagelink + ') successfully cached.') // for testing purposes
          }
        });
       };
      };
    });
    $('td a, .wpb_wrapper a').mouseleave(function () {
      $('#popover').empty();
    });
    
    Edit: @sz has made some changes. Below is version 1.3 There may be some bugs as he alters it. It is a work in progress. He is pretty much done and its awesome!

    You can also view and install the script from here (It will be updated faster there).

    He also used it to make a manga updates version (Link).

    Code:
    // ==UserScript==
    // https://greasyfork.org/scripts/26439-novelupdates-cover-preview/
    // @name        novelupdates Cover Preview
    // @namespace   somethingthatshouldnotclashwithotherscripts
    // @include     https://www.novelupdates.com/*
    // @include     http://www.novelupdates.com/*
    // @version     1.3
    // @description Previews covers in novelupdates.com when hovering over hyperlinks that lead to novel pages.
    // @grant       GM_xmlhttpRequest
    // @grant       GM_setValue
    // @grant       GM_getValue
    // @grant       GM_deleteValue
    // @run-at       document-end
    // @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==
    const MAXCACHEAGE = 24 * 60 * 60 * 1000; // Max Age before Cached data gets overridden with current data. Max Age is 24 hour in milliseconds  //days * h * min  * sec * ms
    var STYLESHEETHIJACKFORBACKGROUND = "breadcrumb_nu"; //if unknown set empty ""; classname without leading dot
    var STYLESHEETHIJACKFORTITLE = "tbl_sort"; //if unknown set empty ""; classname without 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
    const SELECTOR2 = '.wpb_wrapper > 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 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 DEBUGLOG = false; //de-/activate console.log();
    const HASERROR = true;
    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;
    
    //http://stackoverflow.com/questions/1215392/how-to-quickly-and-conveniently-disable-all-console-log-statements-in-my-code
    var logger = function () {
       var oldConsoleLog = null;
       var pub = {};
    
       pub.enableLogger = function enableLogger() {
           if (oldConsoleLog === null)
               return;
    
           window.console.log = oldConsoleLog;
       };
    
       pub.disableLogger = function disableLogger() {
           oldConsoleLog = console.log;
           window.console.log = function () { };
       };
    
       return pub;
    } ();
    
    $(document).ready(
       function () {
           if (DEBUGLOG)
               logger.enableLogger();
           else
               logger.disableLogger();
       }
    );
    
    //get value from key. Decide if timestamp is older than MAXCACHEAGE than look for new image
    function GM_getCachedValue(key) {
       var currentTime = Date.now();
       var rawCover = GM_getValue(key, null);
       if (!rawCover) {
           return null;
       }
       var coverData;
       try { //is json parseable data? if not delete for refreshing
           coverData = JSON.parse(rawCover);
           if (!(coverData.url && coverData.cachedTime)) //has same variable definitions?
           {
               GM_deleteValue(key);
               return null;
           }
       } catch (e) {
           GM_deleteValue(key);
           return null;
       }
    
    
       var measuredTimedifference = currentTime - coverData.cachedTime;
       if (measuredTimedifference < MAXCACHEAGE)
           return coverData.url;
       else {
           GM_deleteValue(key);
           return null;
       }
       var imageUrl = coverData.url;
       return imageUrl;
    }
    
    //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;
    }
    
    // popupPositioning function
    jQuery.fn.popupPos = function (event, element, style) {
       var offsetToBottomBorderY = 5; //offset to bottom border
       var offsetToRightBorderX = 5; //offset to right border
       var X, Y;
       var hoveredSelectedPosX, hoveredSelectedPosY;
       var distanceToBottom, distanceToRight;
       let computedFontSize = parseInt(window.getComputedStyle(element.parents()[0]).fontSize);
    
       //console.log(computedFontSize);
    
       //Initialising variables (multiple usages)
       var scrollTop = windowCached.scrollTop();
       var scrollLeft = windowCached.scrollLeft();
       var elementPopup = $(this);
       var elementParentOffset = element.parents().offset();
       var elementParentOuterHeight = element.parents().outerHeight();
       var elementParentOuterWidth = element.parents().outerWidth();
       var elementOffset = element.offset();
       var elementOuterHeight = element.outerHeight();
       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 = elementParentOffset.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;
    
       // Distance to the right
       distanceToRight = windowCached.width() - (X - scrollLeft);
       // Tooltip too close to the right?
       if (distanceToRight < elementPopup.outerWidth())
           X += distanceToRight - elementPopup.outerWidth();
    
       // Distance to the bottom
       distanceToBottom = windowCached.height() - (Y - scrollTop);
       // Tooltip too close to the bottom?
       if (distanceToBottom < elementPopup.outerHeight()) //(offsetToBottomBorderY + elementPopup.outerHeight())
           Y += distanceToBottom - elementPopup.outerHeight() + computedFontSize;
       //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;
       this.css('top', Y + 'px');
       this.css('left', X + 'px');
       popover.show();
       //console.log("final popup position "+X+' # '+Y);
       return this;
    };
    
    //.wpb_wrapper a = title links on individual seriepage
    $(SELECTOR2).mouseenter(function (e) {
       style = 2;
    });
    //td a = links in table cells (index and group page)
    $(SELECTOR1).mouseenter(function (e) {
       style = 1;
    });
    
    function loadImgUrl(elementUrl) {
       // Create new promise with the Promise() constructor;
       // This has as its argument a function
       // with two parameters, resolve and reject
       return new Promise(function (resolve, reject) {
           let retrievedImgLink = GM_getCachedValue(elementUrl);
           if (retrievedImgLink !== null) {
               resolve(retrievedImgLink);
           } else {
               $.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
                   try {
                       var imagelinks = $(html).find(IMAGELINKCONTAINERS).find('img');
    
                       var imagelink = imagelinks[CONTAINERNUMBER].getAttribute("data-src");
                       console.log('init ' + imagelink);
                       GM_setCachedValue(elementUrl, imagelink); //cache imageurl link
                       resolve(imagelink);
                   } catch (error) {
                       showPopupLoadingSpinner(serieTitle, 1);
                       reject(elementUrl);
                   }
    
               })
                   .fail(function (xhr) {
                       console.log('error', xhr);
                   });
           }
       });
    }
    
    main();
    
    function main() {
       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);
           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;
                           console.log("onpageload cache init " + imgUrl);
                       }
                   }, function (Error) {
                       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');
       }
    }
    windowCached.on('load', function () {
       function styleSheetContainsClass(f) {
           var localDomainCheck = '^http://' + document.domain;
           //console.log("Domain check with: " + localDomainCheck);
           var hasStyle = false;
           var stylename = '.' + f;
           var fullStyleSheets = document.styleSheets;
           // console.log("start styleSheetContainsClass " + stylename);
           if (fullStyleSheets) {
               for (let i = 0; i < fullStyleSheets.length - 1; i++) {
                   //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)) {
                               if (styleSheet.cssRules) {
                                   for (let rulePos = 0; rulePos < styleSheet.cssRules.length - 1; rulePos++) {
    
                                       if (styleSheet.cssRules[rulePos] !== undefined) {
                                           // console.log("styleSheet.cssRules[rulePos] "+ stylename);
                                           if (styleSheet.cssRules[rulePos].selectorText) {
                                               if (styleSheet.cssRules[rulePos].selectorText == stylename) {
                                                   console.log('styleSheet class has been found - style: ' + stylename);
                                                   hasStyle = true; //break;
                                                   return hasStyle;
                                               }
                                           } // else console.log("undefined styleSheet.cssRules[rulePos] "+ stylename);
                                       }
                                       // else console.log("loop undefined styleSheet.cssRules[rulePos] "+ stylename);
                                   }
                               } //else console.log("undefined styleSheet.cssRules "+ stylename);
                           }
                       //console.log("stylesheet url " + styleSheet.href);
                   } //else console.log("undefined styleSheet "+ stylename);
                   if (hasStyle) break;
               }
           } //else console.log("undefined fullStyleSheets "+ stylename);
    
           console.log("styleSheet class has not been found - style: " + stylename);
           return hasStyle;
       }
       if (STYLESHEETHIJACKFORBACKGROUND !== "")
           if (!styleSheetContainsClass(STYLESHEETHIJACKFORBACKGROUND))
               STYLESHEETHIJACKFORBACKGROUND = "";
       if (STYLESHEETHIJACKFORTITLE !== "")
           if (!styleSheetContainsClass(STYLESHEETHIJACKFORTITLE))
               STYLESHEETHIJACKFORTITLE = "";
    
       $('body').append('<div ID="popover" ' + stylesheetForBackground() + '></div>');
       popover = $('#popover');
       popover.css('position', 'absolute');
       popover.css('z-index', '10');
       popover.css('box-shadow', '0px 0px 5px #7A7A7A');
    });
    
    
    function stylesheetForTitle() {
       if (STYLESHEETHIJACKFORTITLE !== "")
           return 'class="' + STYLESHEETHIJACKFORTITLE + '" style="display:inline-block;width:100%;text-align:center !important"';
       else
           return 'style="background-color:' + DEFAULTTITLEBACKGROUNDCOLOR + ';display:inline-block;width:100%;text-align:center !important"';
    }
    
    function stylesheetForBackground() {
       if (STYLESHEETHIJACKFORBACKGROUND !== "")
           return 'class="' + STYLESHEETHIJACKFORBACKGROUND + '" style="display:flex !important;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%;"';
    }
    
    //when selected link is entered load imageurl and write popover content
    concatenatedSelectors.mouseenter(function (e) {
       var element = $(this);
       var Href = element.attr('href');
    
       if (Href.search(INDIVIDUALPAGETEST) != -1) //only trigger for links that point to serie pages
       {
           let refreshPopover = function (title, link) {
               /*    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
               {
                   popover.empty();
                   if (inBlocklist(link)) {
                       popover.append('<div ' + stylesheetForTitle() + '>' + title + '</div>Blocked Image<br />No Cover Image<br />Unwanted Image');
                       popover.popupPos(e, element, style);
                   } else {
                       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>');
                       $('#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);
                       });
                   }
               }
           };
    
           //popup loading spinner
           var showPopupLoadingSpinner = function (title, error = false) {
               popover.empty();
               if (error)
                   popover.append('<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.append('<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>');
               popover.popupPos(e, element, style);
           };
    
    
           //async wait until image is loaded before refreshing popup
           var ajaxLoadImageUrlAndShowPopup = function (elementUrl, title) {
               loadImgUrl(elementUrl)
                   .then(function (imgUrl) {
                       let img = document.createElement("img"); //put img into dom. Let the image preload in background
                       img.src = imgUrl;
                       img.onload = () => {
                           console.log("imgurl " + imgUrl);
                           refreshPopover(title, imgUrl); //popup only gets refreshed when currentTitelHover == serieTitle     
                           // GM_setCachedValue(elementUrl, imgUrl); //cache imageurl link
                           console.log(elementUrl + " url has been found and is written to temporary cache.\n" + imgUrl + ' successfully cached.'); // for testing purposes                     
                       };
                   }, function (Error) {
                       console.log(Error + ' failed to fetch ' + elementUrl);
                   });
    
           };
    
    
           onHover = true;
    
           var shortSerieTitle = element.text(); //get linkname
    
           //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'); //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
    
           /* 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);
           }
       }
    });
    
    //hide and empty popup when mouse is not over title
    concatenatedSelectors.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;
    });
    
    windowCached.blur(function () { //chrome fix -> force close when mouse is outside window alt + tab
       popover.hide();
       onHover = false;
    });
    
    
     
    Last edited: Jan 20, 2017
    Ddraig, Dori, runsing and 11 others like this.
  2. Deleted member 41274

    Deleted member 41274 Guest

    Reading List:
    Link
    Give this man a medal.
     
    TheMrAzn and SenjiQ like this.
  3. TheMrAzn

    TheMrAzn [Blank]

    Joined:
    Jan 14, 2016
    Messages:
    730
    Likes Received:
    2,876
    Reading List:
    Link
    Hallelujah ~ If it gets implemented.
     
  4. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
    @Tony This man has done your work for you, give him a literal medal
     
  5. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
  6. sithkazar

    sithkazar Professional Screw Up

    Joined:
    Dec 14, 2015
    Messages:
    750
    Likes Received:
    944
    Reading List:
    Link
    What browser are you using? If it is firefox it should look like this when the menu drops down.

    [​IMG]
     
  7. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
    I'm using Firefox

    It should be working, I mean, the user script is there and all. It's there when I check the "Manage User Scripts", the name is
    novelupdates Cover Preview"
     
  8. sithkazar

    sithkazar Professional Screw Up

    Joined:
    Dec 14, 2015
    Messages:
    750
    Likes Received:
    944
    Reading List:
    Link
    Is the check mark there next to "enabled" and "novelupdates Cover Preview"? Have you refreshed the page? The page has to be reloaded the first time to start running the new script.
     
  9. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
    Yes, and yes.... still not working...
     
  10. sithkazar

    sithkazar Professional Screw Up

    Joined:
    Dec 14, 2015
    Messages:
    750
    Likes Received:
    944
    Reading List:
    Link
    huh.... I don't know... the only thing I can think is that maybe you have some security app that is interfering with it.

    Maybe double check that you copied the entire code... even missing a single bracket or comma would make it not work. Other then that, I am not sure what it could be. Sorry.



    Edit: Opps.. I listened to my own advise and double checked that I copied the code correctly and it isn't you, its me! I fixed it, should work now. My title is not just for show! I should have known I would screw it up!
     
    Last edited: Jan 9, 2017
    runsing, AliceShiki and Shio like this.
  11. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
    How do I say this.

    It's still not working :\
     
  12. sithkazar

    sithkazar Professional Screw Up

    Joined:
    Dec 14, 2015
    Messages:
    750
    Likes Received:
    944
    Reading List:
    Link
    I don't know then. I tried uninstalling and reinstalling from scratch to see if there was some step I was missing, but it works just fine for me... sorry. :(
     
  13. NZPIEFACE

    NZPIEFACE Leecher

    Joined:
    Mar 22, 2016
    Messages:
    6,216
    Likes Received:
    5,972
    Reading List:
    Link
    :|

    I feel like i misunderstood something but i wont dig too deep into it because it feels like its too much of a hassle
     
  14. noisypixy

    noisypixy Sacatunn que pen, que summum que tun.

    Joined:
    Jun 25, 2016
    Messages:
    716
    Likes Received:
    950
    Reading List:
    Link
    Installed it on Firefox 50.1.0 (Ubuntu 16.04).

    Works fine here.
     
  15. Nazgand

    Nazgand New Member

    Joined:
    Oct 1, 2016
    Messages:
    480
    Likes Received:
    407
    Reading List:
    Link
    It works for me, but is certainly not perfect.
    Google Chrome, Tamper Monkey, Windows 10.
     
  16. Nazgand

    Nazgand New Member

    Joined:
    Oct 1, 2016
    Messages:
    480
    Likes Received:
    407
    Reading List:
    Link
    I tried modifying the script to make it run on the forum too, and promptly ran into a Cross-Origin Resource Sharing nightmare.
     
    sithkazar likes this.
  17. sz

    sz Well-Known Member

    Joined:
    Mar 8, 2016
    Messages:
    48
    Likes Received:
    46
    Reading List:
    Link
    Seems interesting. I'll see if i can get it to work in the forum too, but maybe i'll also hit the crosssite scripting problem. Currently i am adding a little loading spinner to know that it is still working when it is a little slow in loading the serie page where it is getting the coverimage url from. Version with a loading spinner should be ready sometime during this day.
     
    runsing and sithkazar like this.
  18. noisypixy

    noisypixy Sacatunn que pen, que summum que tun.

    Joined:
    Jun 25, 2016
    Messages:
    716
    Likes Received:
    950
    Reading List:
    Link
    Are you uploading this script to any public repository, e.g. GitHub?
     
  19. sz

    sz Well-Known Member

    Joined:
    Mar 8, 2016
    Messages:
    48
    Likes Received:
    46
    Reading List:
    Link
    Just made a greasyfork account. From now on i'll upload my script there so that you can automatically pull updates on version change.

    https://greasyfork.org/de/scripts/26439-novelupdates-cover-preview

    Version 0.4
    • Added loading Spinner
    • Header Style hijacked class .tbl_sort
    [​IMG]
    [​IMG]
    I don't think i can get it to work on the forum. For that i'll need Cross site scripting access.
    Debug console is outputting "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin"
    If i am understanding it right a possible fix would need help of the novelupdate developer. The individual pages would need an additional response header. Something like
    Code:
    Access-Control-Allow-Origin: http://forum.novelupdates.com
    Alternativ could be to internally change whole domain to topdomain. Adding into some js of the series page
    Code:
    $(document).on('ready', function () {
       document.domain = 'novelupdates.com';
    });
    should then theoretically allow cross subdomain access.
     
    Last edited: Jan 11, 2017
    sithkazar likes this.
  20. sz

    sz Well-Known Member

    Joined:
    Mar 8, 2016
    Messages:
    48
    Likes Received:
    46
    Reading List:
    Link
    Actually it was Version 0.4. I'd say everything below V1.0 is a work in progress/beta since it is still not working how i intended it to.
    Next Version 0.5 should be available as auto update from https://greasyfork.org/scripts/26439-novelupdates-cover-preview. If i am not hearing about bugs and i can clear my one recognized bug i'll elevate the script to Version 1.0


    Version 0.5
    • updated with newer jquery (3.1.1)
    • Refactored code and added comments what each part should be doing
    • Known Bugs: When mouse hovers over next title and previous title finishes loading before next title, first cover gets still shown after current hovered title
     
    Last edited: Jan 11, 2017