NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
/* jshint laxcomma: true */ // ==UserScript== // @name e621 Thumbnail Enhancer // @version 0.74 // @description Resizes thumbnails on e621.net, replacing them with higher resoltion images and adding support for video previews. // @author rooshoes // @homepageURL http://twitter.com/rooshoos // @include http://*e621.net/post* // @include https://*e621.net/post* // @include http://*e621.net/pool* // @include https://*e621.net/pool* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_log // ==/UserScript== GM_addStyle([ "span.thumb {" ," width: auto;" ," height: 250px;" ," margin: 0 10px 10px 0;" ,"}" ,"span.thumb .preview {" ," display: block;" ," height: 220px;" ," width: auto;" ,"}" ,"#child-posts-expanded-thumbs span.thumb," ,"#child-posts-expanded-thumbs span.thumb .preview {" ," width: 180px;" ," height: auto;" ,"}" ,"span.thumb .post-score {" ," width: auto !important;" ,"}" ,"span.thumb .tooltip-thumb {" ," display: block;" ," position: relative;" ,"}" ,"span.thumb .gif," ,"span.thumb .video {" ," position: relative;" ," display: block;" ,"}" ,"span.thumb .gif:not(:hover)::after," ,"span.thumb .video:not(:hover)::after {" ," content: '';" ," display: block;" ," position: absolute;" ," top: 0; bottom: 0; left: 0; right: 0;" ,"}" ,"span.thumb .video:not(:hover)::after {" ," background: transparent " ," url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjA2IiBoZWlnaHQ9IjIwNiIgdmlld0JveD0iMCAwIDIwNiAyMDYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSI5MCIgY3k9IjkwIiByPSI5MCIvPjxmaWx0ZXIgeD0iLTUwJSIgeT0iLTUwJSIgd2lkdGg9IjIwMCUiIGhlaWdodD0iMjAwJSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI2LjUiIGluPSJzaGFkb3dPZmZzZXRPdXRlcjEiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbXBvc2l0ZSBpbj0ic2hhZG93Qmx1ck91dGVyMSIgaW4yPSJTb3VyY2VBbHBoYSIgb3BlcmF0b3I9Im91dCIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjI5NDE1NzYwOSAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzIDEzKSI+PHVzZSBmaWxsPSIjMDAwIiBmaWx0ZXI9InVybCgjYSkiIHhsaW5rOmhyZWY9IiNiIi8+PHVzZSBmaWxsLW9wYWNpdHk9Ii44ODEiIGZpbGw9IiNGRkYiIHhsaW5rOmhyZWY9IiNiIi8+PC9nPjxwYXRoIGZpbGwtb3BhY2l0eT0iLjQiIGZpbGw9IiMwMDAiIGQ9Ik04MS41IDE0Ny42NThWNTkuMzQybDY1IDQ0LjE1OCIvPjwvZz48L3N2Zz4=)" ," no-repeat center/80px;" ,"}" ,"span.thumb .gif:not(:hover)::after {" ," content: 'GIF';" ," width: 60px;" ," height: 30px;" ," margin: auto;" ," font-size: 16px;" ," font-weight: bold;" ," line-height: 30px;" ," color: rgba(0,0,0,0.4);" ," background-color: rgba(255,255,255,0.8);" ," border-radius: 6px;" ," box-shadow: 0 0 13px rgba(0,0,0,0.29);" ,"}" ,"span.thumb .gif:hover .preview {" ," display: none !important;" ,"}" ,"span.thumb .gif:hover img.preview {" ," display: block !important;" ,"}" ].join("")); (function(){ function is_gif(i) { return /^(?!data:).*\.gif/i.test(i.src); } function freeze_gif(i) { var c = document.createElement('canvas'); var w = c.width = i.naturalWidth; var h = c.height = i.naturalHeight; var p = i.parentNode; c.getContext('2d').drawImage(i, 0, 0, w, h); p.className = ['gif', p.className].join(' '); try { i.src = c.toDataURL("image/gif"); // if possible, retain all css aspects } catch(e) { // cross-domain -- mimic original with all its tag attributes replaceImg(c, i); i.style.display = 'none'; p.insertBefore(i, p.firstChild); } } function replaceImg(e, i) { e.className = i.className; var s = window.getComputedStyle(i); e.style.border = s.getPropertyValue('border'); e.style.borderRadius = s.getPropertyValue('border-radius'); i.parentNode.replaceChild(e, i); } function setVideo(thumb, videoUrl) { var video = document.createElement('video'), parent = thumb.parentNode; video.controls = false; video.loop = true; video.muted = true; video.preload = 'metadata'; video.addEventListener('loadedmetadata', function(){ parent.className = ['video', parent.className].join(' '); parent.addEventListener('mouseenter', function(){ video.play(); }); parent.addEventListener('mouseleave', function(){ video.pause(); }); replaceImg(this, thumb); }, false); video.src = videoUrl; } /* Replace video thumbnails with actual playable video */ function videoThumb(thumb, parseHTML) { parseHTML = parseHTML || false; var parent = thumb.parentNode; GM_xmlhttpRequest({ method: "GET", url: parent.href, headers: { "Accept": "text/xml" }, onload: function(response) { var videoUrl = null; if (response.readyState !== response.DONE) return; if (!response.responseXML) return; var file_url = response.responseXML.getElementsByTagName('file_url')[0]; if (!file_url) return; videoUrl = file_url.childNodes[0].nodeValue; setVideo(thumb, videoUrl); } }); } /* Replace image thumbnails with higher resolution */ function imageThumb(thumb) { var newThumb = new Image(), replace = function(thumb) { thumb.src = this.src; if (is_gif(thumb)) { freeze_gif(thumb); } }, tryGif = function(thumb) { this.onerror = null; this.src = thumb.src.replace('/preview/', '/').replace('.jpg','.gif'); }; newThumb.onload = replace.bind(newThumb, thumb); newThumb.onerror = tryGif.bind(newThumb, thumb); newThumb.src = thumb.src.replace('/preview/', '/sample/'); } function imgError(image) { image.onerror = ""; image.src = "/images/noimage.gif"; return true; } /* Run above on all thumbnails */ var thumbs = document.querySelectorAll('span.thumb img'); for (i=0; i<thumbs.length; i++) { var thumb = thumbs[i]; switch(true) { case /webm-preview.png/.test(thumb.src): // Slight delay for rate-limiting (function(thumb, i){ setTimeout(function(){ videoThumb(thumb); }, 100*i); })(thumb, i); break; default: imageThumb(thumb); } } })();