ameboide / Embiggen Images

// ==UserScript==
// @name        Embiggen Images
// @namespace   ameboide
// @author      ameboide
// @description Shows CSS-resized images (and some thumbnails) in their original size by holding Shift while hovering over the image (or links to images)
// @include     *
// @version     1.10
// ==/UserScript==

var show = false;
var keep = false;
var testing = null;

var keyShow = 16; //shift
var keyKeep = 17; //ctrl

//match common thumbnail urls
var reThumb = [
	[/(-|_)\d+x\d+(?=\.\w+$)|:thumb$|(_mini|_reasonably_small|_normal|_bigger)(?=\.\w+$)|\?(w|h)=\d+&(w|h)=\d+$/, ''],
	[/(\.gravatar\.com\/avatar\/\w+)(\?.+)?$/, '$1?s=529'], //gravatar
	[/(\.gravatar\.com\/avatar)\.php\?.*gravatar_id=(\w+).*$/, '$1/$2?s=529'], //gravatar alt
	[/\._.+(\.\w+)$/, '$1'], //imdb, amazon
	[/\/mini\//, '/large/'], //twitpic
	[/_500(\.\w+)$/, '_1280$1'], //tumblr
	[/(fbcdn.+_)q(\.\w+)$/, '$1n$2'], //facebook avatars
	[/^.+(\?|&)url=([^&]+)(&.+)?/, '$2'], //proxy (g+)
	[/(\/photos\/images\/)list\//, '$1newsfeed/'] //knowyourmeme
];
//match links to images
var reImg = [
	[/\.(png|jpg|jpeg|gif|svg)(\?.+)?$/, '$&'],
	[/^.+&imgurl=([^&]+).*$/, function(x, url){ //google images
		return decodeURIComponent(decodeURI(url));
	}]
];
//match css urls
var reCssUrl = /^url\("(.+)"\)$/;

var lastTarget = null;

var testingClass = 'testing-embiggenable';
var div, bigImg, testImg;

function init(){
	div = document.createElement('div');
	div.style.position = 'fixed';
	div.style.top = 0;
	div.style.left = 0;
	div.style.maxWidth = '100%';
	div.style.maxHeight = '100%';
	div.style.overflow = 'auto';
	div.style.display = 'none';
	div.style.zIndex = (1<<30)*2-1; //max int32
	document.body.appendChild(div);

	bigImg = document.createElement('img');
	div.appendChild(bigImg);

	var css = document.createElement('style');
	css.innerHTML = '.'+testingClass+'{border:1px dotted red !important;}';
	div.appendChild(css);

	testImg = document.createElement('img');
	testImg.addEventListener('load', function(){
		if(show && testing){
			bigImg.src = testImg.src;
			bigImg.setAttribute('style', '');
			div.style.display = '';
		}
		endTesting();
	}, true);

	testImg.addEventListener('error', endTesting, true);
	testImg.addEventListener('abort', endTesting, true);
}

function testTarget(element, src){
	if(!div) init();
	endTesting();
	element.classList.add(testingClass);
	testing = element;
	testImg.src = src;
}

function endTesting(hide){
	if(hide){
		show = false;
		if(div) div.style.display = 'none';
	}
	if(testing){
		testing.classList.remove(testingClass);
		testing = null;
	}
}

function testReList(img, src, reList){
	for(var i=0; i<reList.length; i++){
		var re = reList[i];
		if (re[0].test(src)){
			testTarget(img, src.replace(re[0], re[1]));
			return true;
		}
	}
	return false;
}

function processTarget(img){
	var parent = img.parentNode;
	if(img.tagName == 'IMG'){
		if(img.width != img.naturalWidth || img.height != img.naturalHeight){
			testTarget(img, img.src);
		}

		if(parent.tagName == 'A' && testReList(img, parent.href, reImg)){
			return true;
		}

		return testReList(img, img.src, reThumb);
	}
	if(img.tagName == 'A' && testReList(img, img.href, reImg)){
		return true;
	}
	while(true){
		var style = window.getComputedStyle(img);
		if(reCssUrl.test(style.backgroundImage)){
			var src = style.backgroundImage.replace(reCssUrl, '$1');
			if(style.backgroundSize != 'auto auto'){
				testTarget(img, src);
			}
			return testReList(img, src, reThumb);
		}
		if(img.offsetWidth != parent.offsetWidth || img.offsetHeight != parent.offsetHeight){
			return false;
		}
		//fake target?
		img = parent;
		parent = img.parentNode;
	}
}

window.addEventListener('keydown', function(e){
	if(e.keyCode == keyShow && !show){
		show = true;
		if(lastTarget){
			processTarget(lastTarget);
		}
	}
	else if(e.keyCode == keyKeep){
		keep = true;
	}
}, true);
window.addEventListener('keyup', function(e){
	if(e.keyCode == keyKeep){
		keep = false;
	}
	else if(!keep && e.keyCode == keyShow){
		endTesting(true);
	}
}, true);

window.addEventListener('mouseover', function(e){
	if(e.target == bigImg) return;
	lastTarget = e.target;
	if(show){
		processTarget(lastTarget);
	}
}, true);

//left click + right click
var b1 = false, stopClick = 0;
window.addEventListener('mousedown', function(e){
	if(b1 && e.buttons == 3){
		if(show){
			endTesting(true);
		}
		else{
			show = true;
			lastTarget = e.target;
			processTarget(lastTarget);
		}
		stopClick = 3;
	}
	b1 = e.buttons == 1;
}, true);

window.addEventListener('click', function(e){
	var b = e.button || 1;
	if(b & stopClick){
		e.preventDefault();
		e.stopPropagation();
		stopClick ^= b;
	}
}, true);