Bovverzoom

View linked images and animated GIFs on Reddit by hovering instead of having to click and navigate away.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        Bovverzoom
// @description View linked images and animated GIFs on Reddit by hovering instead of having to click and navigate away.
// @namespace   raina
// @include     /^https?:\/\/(\w+\.)?reddit\.com\//
// @version     1.9.6
// @done        They somehow broke it so I fixed it again, sorry for the wait.
// @done        Added support for Reddit hosted GIF animations.
// @done        Added respect for NSFW.
// @done        Rewrote Reddit hosted image support.
// @done        Added support for a newly spotted Giphy link pattern.
// @done        Added support for Imgur direct mp4 links.
// @done        Made Imgur page links with query parameters work.
// @done        Fixed v1.5 addition working only once per image per page load.
// @done        Changed Reddit hosted images' thumbnails link from comments to original image to activate them.
// @done        Support i.reddituploads.com.
// @done        Run on subdomains for languages, no participation mode etc...
// @done        Allow passive mixed content, so that images from hosts without HTTPS can load.
// @done        Avoid mixed content issues by stripping out explicit protocol. (E.g. GFYCat videos don't load over HTTP from an HTTPS Reddit session).
// @done        Handle Imgur ad hoc collection images.
// @done        Handle Imgur "gifv" clips.
// @todo        Handle DOM mutations.
// @todo        Handle Imgur albums and galleries somehow.
// @grant       none
// ==/UserScript==
(function() {
	"use strict";

	var i, j;
	var doc = document;
	var thumbs = [].slice.call(doc.getElementsByClassName("thumbnail"));
	var userText = doc.getElementsByClassName("usertext-body");
	var show = function() {
		this.style.display = "block";
	};
	var hide = function() {
		this.style.display = "none";
	};
	var img = doc.createElement("img");
		img.className = "bovverzoom";
		img.cache = "";
		img.show = show;
		img.hide = hide;

	var clip = doc.createElement("video");
		clip.className = "bovverzoom";
		clip.autoplay = "autoplay";
		clip.muted = "muted";
		clip.loop = "loop";
		clip.cache = "";
		clip.show = show;
		clip.hide = hide;

	var style = doc.createElement("style");
		style.type = "text/css";
		style.textContent = ".bovverzoom {" +
			"background-color: rgba(0,0,0,.01);" +
			"position: fixed;" +
			"right: 0;" +
			"top: 0;" +
			"z-index: 100;" +
			"max-width: 100%;" +
			"max-height: 100%;" +
			"pointer-events: none;" +
			"border-radius: 3px;" +
			"display: none;" +
			"}"+
 			".glow {" +
			"box-shadow: rgba(255, 255, 255, .5) 0 0 8px" +
 			"}";

	var fetchGFY = function(url, e) {
		img.hide();
		if (url != clip.cache) {
			var xhr = new XMLHttpRequest();
			xhr.addEventListener("load", showGFY, false);
			xhr.open("GET", url, true);
			xhr.send();
			clip.cache = url;
		} else {
			clip.show();
		}
	};

	var showGFY = function() {
		clip.show();
		var gfyItem = JSON.parse(this.responseText).gfyItem;
		var newClip = clip.cloneNode(false);

		var webmSrc = doc.createElement("source");
		webmSrc.src = gfyItem.webmUrl.replace(/^https?:/, "");
		webmSrc.type = "video/webm";
		newClip.appendChild(webmSrc);

		var mp4Src = doc.createElement("source");
		mp4Src.src = gfyItem.mp4Url.replace(/^https?:/, "");
		mp4Src.type = "video/mp4";
		newClip.appendChild(mp4Src);

		document.body.replaceChild(newClip, clip);
		newClip.hide = clip.hide;
		newClip.show = clip.show;
		clip = newClip;
		clip.show();
	};

	var showGIFV = function(url) {
		clip.show();
		var newClip = clip.cloneNode(false);

		var webmSrc = doc.createElement("source");
		webmSrc.src = url.replace(".gifv", ".webm").replace(/^https?:/, "");
		webmSrc.type = "video/webm";
		newClip.appendChild(webmSrc);

		var mp4Src = doc.createElement("source");
		mp4Src.src = url.replace(".gifv", ".mp4").replace(/^https?:/, "");
		mp4Src.type = "video/mp4";
		newClip.appendChild(mp4Src);

		document.body.replaceChild(newClip, clip);
		newClip.hide = clip.hide;
		newClip.show = clip.show;
		clip = newClip;
		clip.show();
	};

	var imgMe = function(src, e) {
		clip.hide();
		if (src != img.cache) {
			img.src = "";
			img.src = src;
			img.cache = src;
		}
		img.show();
	};

	var killMe = function(e) {
		clip.hide();
		img.hide();
	};

	var rigMe = function(src, el) {
		el.addEventListener("mouseover", swapper, false);
		el.addEventListener("mouseout", swapper, false);
		el.className = el.className + " glow";
	};

	var clipFunc = rigMe;
	var imgFunc = rigMe;
	var swapper = function(e) {
		var obj = e;
		if ("mouseover" === e.type) {
			if (e.target.matches('a')) {
				obj = e.target;
			} else {
				obj = e.target.parentElement;
			}
			clipFunc = obj.href.match(/gfycat/) ? fetchGFY : showGIFV;
			imgFunc = imgMe;
		}
		if ("mouseover" === e.type || "" === e.type) {
			if (obj.href.match(/^https?:\/\/(.*\.)?gfycat\.com\/.{1,}$/i)) { // gfycat.com, HTML5 video even for direct .gif links
				clipFunc("//gfycat.com/cajax/get/" + obj.href.replace(/^.*\.com\//, ""), e);
			} else if (obj.href.match(/^https?:\/\/((i|m|www)\.)?imgur\.com\/[^\/]{1,}\.(gifv|mp4)$/)) { // imgur.com HTML5 video
				clipFunc(obj.href, e);
			} else if (obj.href.match(/https?:\/\/g\.redditmedia\.com\/[\w]+\.gif/)) { // g.redditmedia.com
				clipFunc(obj.href, e);
			} else if (obj.href.match(/\.(bmp|gif|jpe?g|png|svg)(\?.*)?$/i)) { // images, any domain
				imgFunc(obj.href, e);
			} else if (obj.href.match(/^https?:\/\/i\.reddituploads\.com\/.+/)) { // i.reddituploads.com
				imgFunc(obj.href, e);
			} else if (obj.href.match(/^https?:\/\/giphy\.com\/gifs\//)) { // this one giphy.com url pattern
				imgFunc(obj.href.replace(/\/gifs\/([\w]+-)*/, "/media/") + "/giphy.gif", e);
			} else if (obj.href.match(/^https?:\/\/((www|m)\.)?imgur\.com(\/r\/[^\/]*)?\/[^\/]{1,}#[0-9]{1,}$/)) { // imgur.com ad hoc collections
				var imgList = obj.href.slice(obj.href.lastIndexOf("/") + 1, obj.href.lastIndexOf("#")).split(",");
				var index = obj.href.slice(obj.href.lastIndexOf("#") + 1);
				imgFunc("//i.imgur.com/" + imgList[index] + ".jpg", e);
			} else if (obj.href.match(/^https?:\/\/((www|m)\.)?imgur\.com(\/r\/[^\/]*)?\/[^\/]{1,}$/)) { // imgur.com, nonhotlinked single images
				imgFunc(obj.href.replace(/\/([^\/]*\.)?imgur\.com(\/r\/[^\/]*)?/, "/i.imgur.com").replace(/\?.*/, "") + ".jpg", e);
			} else { // not a recognized image/clip link
				killMe();
			}
		} else { // mouseout
			killMe();
		}
	};

	doc.head.appendChild(style);
	doc.body.appendChild(clip);
	doc.body.appendChild(img);

	thumbs.forEach(function(thumb) {
		if (thumb.classList.contains("nsfw")) {
			return false;
		} else if (thumb.href.match(/\/r\/\w+\/comments\//) && thumb.querySelector('img')) {
			var expandoButton = thumb.nextSibling.querySelector(".expando-button");
			var expando = thumb.nextSibling.querySelector(".expando");
			return setTimeout(function() {
				expandoButton.click();
				expando.style.display = "none";
				thumb.href = expando.querySelector('img, video source').src;
				thumb.setAttribute("data-href-url", thumb.href);
				expandoButton.click();
				return swapper(thumb);
			});
		}
		swapper(thumb);
	});

	for (i = 0; i < userText.length; i++) {
	var textLinks = userText[i].getElementsByClassName("md")[0].getElementsByTagName("a");
		if (textLinks.length) {
			for (j = 0; j < textLinks.length; j++) {
				swapper(textLinks[j]);
			}
		}
	}
}());