NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name FA Justified Gallery // @namespace Artex // @description sorts galleries into a justified grid // @include https://www.furaffinity.net/* // @include http://www.furaffinity.net/* // @exclude https://www.furaffinity.net/view/* // @exclude http://www.furaffinity.net/view/* // @version 1.0.2 // @grant none // ==/UserScript== //TODO: write cases for story, music, and flash thumbnails. // for stories always display title. // if feeling motivated provide description preview on thumb. var SIZE = 300; //thumbnail height - any number you please. If it's higher then RES thumbnails may be blurred. var RES = 400; //thumbnail resolution - I haven't done a thorough check, but I know 150, 200, 300, and 400 are valid resolutions var flexImages=function(){function e(e){function t(e,r,n,i){function o(e){n.maxRows&&g>n.maxRows||n.truncate&&e&&g>1?c[a][0].style.display="none":(c[a][4]&&(c[a][3].setAttribute("src",c[a][4]),c[a][4]=""),c[a][0].style.width=l+"px",c[a][0].style.height=h+"px",c[a][0].style.display="block")}for(var a,l,s,d,f=1,g=1,u=e.clientWidth-2,c=[],m=0,h=n.rowHeight,w=0;w<r.length;w++)if(c.push(r[w]),m+=r[w][2]+n.margin,m>=u){var p=c.length*n.margin;for(f=(u-p)/(m-p),h=Math.ceil(n.rowHeight*f),s=0,l,a=0;a<c.length;a++)l=Math.ceil(c[a][2]*f),s+=l+n.margin,s>u&&(l-=s-u),o();c=[],m=0,g++}for(a=0;a<c.length;a++)l=Math.floor(c[a][2]*f),d=Math.floor(n.rowHeight*f),o(!0);i||u==e.clientWidth||t(e,r,n,!0)}if(document.querySelector){var r={selector:0,container:".item",object:"img",rowHeight:180,maxRows:0,truncate:0};for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);for(var i="object"==typeof r.selector?[r.selector]:document.querySelectorAll(r.selector),o=0;o<i.length;o++){var a=i[o],l=a.querySelectorAll(r.container),s=[],d=(new Date).getTime();if(l.length){var f=window.getComputedStyle?getComputedStyle(l[0],null):l[0].currentStyle;r.margin=(parseInt(f.marginLeft)||0)+(parseInt(f.marginRight)||0)+(Math.round(parseFloat(f.borderLeftWidth))||0)+(Math.round(parseFloat(f.borderRightWidth))||0);for(var g=0;g<l.length;g++){var u=l[g],c=parseInt(u.getAttribute("data-w")),m=c*(r.rowHeight/parseInt(u.getAttribute("data-h"))),h=u.querySelector(r.object);s.push([u,c,m,h,h.getAttribute("data-src")])}t(a,s,r);var w=function(){t(a,s,r)};document.addEventListener?(window["flexImages_listener"+d]=w,window.removeEventListener("resize",window["flexImages_listener"+a.getAttribute("data-flex-t")]),delete window["flexImages_listener"+a.getAttribute("data-flex-t")],window.addEventListener("resize",window["flexImages_listener"+d])):a.onresize=w,a.setAttribute("data-flex-t",d)}}}}return e}();!function(){"function"==typeof define&&define.amd?define("flexImages",function(){return flexImages}):"undefined"!=typeof module&&module.exports?module.exports=flexImages:window.flexImages=flexImages}(); function injectCSS() { var style = [ "center.flow u { display: unset; }", ".frontpage { max-height: unset !important; }", ".item a { border: none !important;}", ".r-mature { outline: 1px solid #697cc1 !important;}", ".r-adult { outline: 1px solid #971c1c !important; }", ".checked { opacity: 0.6;}", ".checked:hover { opacity: 1 }", ".item span { background-color: rgba(0,0,0,0.5); position: absolute; bottom: 0; left: 0; width: 100%; height: 35px;}", "center.flow s { display: unset; }", "center.flow s > a { width: 100%; height: 100%;}", //FLEX-IMAGES CSS ".flex-images { overflow: hidden; }", ".flex-images .item { float: left; margin: 4px; box-sizing: content-box; overflow: hidden; position: relative; }", ".flex-images .item img { display: block; width: 100%; height: 100%; }", ]; var styleEl = document.createElement("style"); styleEl.innerHTML = style.join(""); document.head.appendChild(styleEl); } function moveTitle(thumb) { let title = thumb.getElementsByTagName("span")[0]; if (title) {//home page doesn't have titles let artist = thumb.getElementsByTagName("small"); artist = artist[artist.length - 1]; //quick work around to fix artists titles in notification center let a = thumb.getElementsByTagName("a")[0]; var i = thumb.getElementsByTagName("i")[0]; //description icon //these don't always exist if (i) { a.removeChild(i); } if (artist) { title.appendChild(artist); } title.style.display = "none"; a.appendChild(title); thumb.addEventListener("mouseenter", function() { title.style.display = "unset"; //switch to css classes for any further modifications }); thumb.addEventListener("mouseleave", function() { title.style.display = "none"; }); } } function upscaleThumbs(gallery) { let thumbs = gallery.querySelectorAll(".r-general, .r-mature, .r-adult"); for(var i = 0; i < thumbs.length; i++) { let img = thumbs[i].getElementsByTagName("img")[0]; img.src = img.src.replace(/@\d+/,"@" + RES); thumbs[i].style.maxWidth = "unset"; thumbs[i].style.maxHeight = "unset"; thumbs[i].style.width = "unset"; //flex-images thumbs[i].setAttribute("data-w", img.width == 0 ? SIZE : img.width * (SIZE/200)); thumbs[i].setAttribute("data-h", img.height == 0 ? SIZE : img.height * (SIZE/200)); img.style.maxWidth = "unset"; img.width = "100%"; img.height = "100%"; thumbs[i].classList.add("item"); //deal with titles moveTitle(thumbs[i]); } gallery.classList.add("flex-images"); new flexImages({ selector: gallery, rowHeight: SIZE}); } window.addEventListener("DOMContentLoaded", function() { var galleries = document.getElementsByClassName("flow"); if (galleries) { injectCSS(); for (var i = 0; i < galleries.length; i++) { upscaleThumbs(galleries[i]); } } });