Tumblr Always HQ Media

Always load highest resolution version of images on any Tumblr page, not just direct URL

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        Tumblr Always HQ Media
// @description Always load highest resolution version of images on any Tumblr page, not just direct URL
// @version     1.4.0
// @require     https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// @namespace   https://greasyfork.org/en/scripts/32294-tumblr-always-hq-media
// @supportURL http://invertex.xyz
// @match	*://*.tumblr.com/*
// @grant       none
// ==/UserScript==
//oldinclude     /^https?://\d+\.media\.tumblr\.com/(.+/)*tumblr_.+_\d+\.(jpe?g|gif|png|bmp)(\?.*)?$/

var sizes = ['_raw.', '_1280.', '_540.', '_500.', '_400.', '_250.', '_100.' ];
var postCount = 0;
var thisJQ = $;

function checkIfJustImgURL(index) {
    if (index >= sizes.length) return;
    var url = window.location.href;
    if(!url.includes("media.")) { return; }
   // url = url.replace(/(.*(?=_))(_\d*.)(.*)/, '$1' + sizes[index] + '$3');
     for (var s = 1; s < sizes.length; s++)
    {
        url = url.replace(sizes[s], sizes[index]); //Replace any size with the max size.
    }
    if(index === 0)
    {
        url = "http://" + url.substring(url.indexOf(".") + 1).replace("media.", "data."); //remove sub-domain number if trying to access RAW image
    }
    if (url == window.location.href) {return;}
    thisJQ.ajax({
        url: url,
        type: 'HEAD',
        complete: function(data, textStatus, jqXHR) {
            window.location.replace(url);
        },
        error: function(jqXHR, textStatus, errorThrown) {
           // console.log(url + " failed to laod");
            checkIfJustImgURL(index + 1);
        }
    });
}
checkIfJustImgURL(0);

function decreaseURL(imgURL)
{
    var newURL = imgURL;

    if(imgURL.includes(".gif"))
    {
         for (var s = 1; s < sizes.length; s++)
         {
             newURL = newURL.replace(sizes[s], "_500."); //Replace any size with the max size.
         }

    }
    else
    {
        for (var s = 1; s < sizes.length; s++)
         {
             newURL = newURL.replace(sizes[s], "_1280."); //Replace any size with the max size.
         }
    }
    return newURL;
}

function processImages(element)
{
    var imgs = element.getElementsByTagName("img");
    
    for (var i = 0; i < imgs.length; i++)
    {
        if(!imgs[i].src.includes("inline")/* && !imgs[i].src.includes(".gif")*/)
        {
            var preSrc = imgs[i].src;
            
            for (var s = 1; s < sizes.length; s++)
            {
                imgs[i].src = imgs[i].src.replace(sizes[s], "_raw."); //Replace any size with the max size.
            }
        
            if(preSrc != imgs[i].src && imgs[i].src.includes(".media."))
            {
                imgs[i].src = "http://" + imgs[i].src.substring(imgs[i].src.indexOf(".") + 1).replace("media.", "data.");

                //Set the link wrapped around our image to point to the same image so as to not confuse people when they hover over it. Or if they do a save link as.
                thisJQ(imgs[i]).attr('data-highres', imgs[i].src);
                var p1 =  thisJQ(imgs[i]).parent();
                var attr = thisJQ(p1).attr('href');

                if(attr == null)
                {
                    p1 = thisJQ(p1).parent();
                }
                p1.attr('href', imgs[i].src);
                imgs[i].setAttribute('oldURL', preSrc);
               /* if(!imgs[i].complete)
                {
                    console.log(imgs[i].src + " failed to load");
                    imgs[i].src = preSrc;
                    thisJQ(imgs[i]).attr('data-highres', preSrc);
                }*/
                imgs[i].onerror = function ()
                {
                    var lowerURL = decreaseURL(this.getAttribute('oldURL'));
                    this.src = lowerURL;
                    thisJQ(imgs[i]).attr('data-highres', lowerURL);
                    thisJQ(this).parent().attr('href', lowerURL);
                };

            }
        }
    }
}

function processVideos()
{
    setTimeout(function()
    {


    var playBars = document.getElementsByClassName("vjs-control-bar");
    var vids = document.getElementsByTagName("video");
    var playButtons = document.getElementsByClassName("vjs-big-play-button");
    var bg = document.getElementsByClassName("vjs-poster");
    
        for(var z = 0; z < playBars.length; z++)
        {
            playBars[z].innerHTML += "<a href='http://google.com' class='vjs-menu-button vjs-control'>©</a>";
        }
        
    for(var b = 0; b < bg.length; b++)
    {
        bg[b].outerHTML = "";
    }
        for(var c = 0; c < playButtons.length; c++)
    {
        playButtons[c].setAttribute("style", "margin-top: 200px;");
    }
    for (var i = 0; i < vids.length; i++)
    {
        var source = vids[i].getElementsByTagName("source")[0];
        if(source.src.slice(-4) === "/480")
        {
            source.src = source.src.slice(0, -4);
        }
        vids[i].load();
       // playButtons[i].setAttribute("style", "margin-top: 100px;");
        
        //thisJQ(bg[i]).wrap('<a href="http://google.ca"></a>');
        
       // processVideoUI(vids[i]);
    }
            }, 1000);
}

function processVideoUI(videoElem)
{
    var parent = videoElem.parentElement;
    
    parent.getElementsByClassName("vjs-big-play-button")[0].setAttribute("style", "margin-top: 100px;");
    var bg = parent.getElementsByClassName("vjs-poster")[0];
    var wrapper = document.createElement("a");
    parent.appendChild(wrapper);
    wrapper.appendChild(bg);
    
    
}

function updatePageLinks(waitTime)
{
    
    setTimeout(function()
    {
        var lightBox = document.getElementsByClassName("tmblr-lightbox");

        processVideos();

        if(lightBox.length > 0)
        {
            console.log("lightbox active");
            processImages(lightBox[0]);
            thisJQ(lightBox[0]).on('click', function(){processImages(lightBox[0]);}); //Watch for lightbox click to update URLs again since they will be refreshed by tumblr back to lower res
        }
            processImages(document.body);

            var photosets = document.body.getElementsByTagName("iframe");
            for(var i = 0; i < photosets.length; i++)
            {
                processImages(photosets[i].contentWindow.document);
            }

        console.log("end change");
    }, waitTime);
}

function doSetup(){
       updatePageLinks(0);

    setTimeout(function() //Experimenting with dashboard scroll updating, but ran into cross-domain issues. Don't really need to resize dashboard previews anyways, still resizes when you click on them to expand or new page.
    {
       // window.jQ = thisJQ;
        var newPosts = document.getElementsByClassName('posts');
        if(newPosts.length > 0)
        {
            newPosts = document.getElementsByClassName('grid');
        }


        if(newPosts.length > 0)
        {
            $(newPosts[0]).bind('DOMSubtreeModified', function()
            {
                var childCnt = 0;
                childCnt = newPosts[0].children.length;
               // if(childCnt > postCount)
               // {
                    postCount = childCnt;
                    //processVideos();
                   // processImages();
                console.log("children changed");
                   updatePageLinks(0);
              //  }

            });
        }
        var observer = new MutationObserver(function(mutations){
    mutations.forEach(function(mutation){
        console.log("start change");
        updatePageLinks(500);
    });
});
observer.observe(document.body, {attributes: true, attributeFilter: ['style', 'class']});
    var grid = document.getElementsByClassName('grid');
    if(grid != null && grid.length > 0){
        observer.observe(grid[0], {attributes: true, attributeFilter: ['style', 'class']});
         console.log("grid watch");
    }
    var posts = document.getElementsByClassName('posts');
    if(posts != null && posts.length > 0){
        observer.observe(posts[0], {attributes: true, childList: true});
         console.log("post watch");
    } 
   var posts2 = document.getElementById('posts');
        if(posts2 != null){
           observer.observe(posts2, {attributes: true, childList: true});
         console.log("post watch"); 
        }
        
        
    }, 2000);

     
}

thisJQ(document).ready(function(){
     doSetup();

});

function checkLightbox(){
    setTimeout(function(){
     var lightBox = document.getElementById("tumblr_lightbox");

console.log("lightbox check");
        if(lightBox != null)
        {
            console.log("lightbox active");
            processImages(lightBox);
            //lightBox.onclick = checkLightbox;
           thisJQ(lightBox).on('click', function(){processImages(lightBox);}); //Watch for lightbox click to update URLs again since they will be refreshed by tumblr back to lower res
        }
       //  updatePageLinks(0);
    }, 200);
}
document.onclick = checkLightbox;

$.noConflict();