UFIS!

By lschrff Last update Jun 13, 2006 — Installed 541 times.
// UFIS! Universal Flickr Image Search
// version 001 ALPHA
// no copyright
// done by lscherff
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Extras/Manage User Scripts,
// select "UFIS!", and click Uninstall.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          UFIS!
// @namespace     http://www.khm.de/~lscherff/ufis
// @description   Add a button to enable instant flickr CBIR and tag search for any JPG you come across.
// @include       *
// @exclude       http://www.khm.de/~lscherff/ufis/*
// ==/UserScript==
//
// --------------------------------------------------------------------
//
// To turn the script on/off click: Extras/User Script Commands/Toggle UFIS!
// 
// --------------------------------------------------------------------
//
// Version: 001 ALPHA
// Todo:
// - Use another CBIR system (one with more diverse image data and HTTP API)
// - Eliminate common words using some wordnet interface (http://wordnet.princeton.edu/links#web)
// - Button-images are not placed correctly over images that float right/center 

var flicks;
var retrs;
var flickrTags;
var currentURI;
var yOffset, xOffset;
var viewFIS;
var tmpView;

function done() {
	if (tmpView) document.body.removeChild(tmpView); tmpView = null;
	var srcImg = document.createElement('img'); srcImg.src = currentURI;
	var width = srcImg.width + 488; if (width==488) width = 500;	// middle image determines total width
	var x = xOffset-width/2; if (x<20) x = 20;
	var y = yOffset-100; if (y<0) y = 0;
	if (viewFIS) {
		x = parseInt(viewFIS.style.left);
		y = parseInt(viewFIS.style.top);
		document.body.removeChild(viewFIS);
	}
	viewFIS = document.createElement('div');
	viewFIS.style.position = 'absolute';
	viewFIS.style.zIndex = '1001';
	
	viewFIS.style.width = width+'px';
	viewFIS.style.top = y+'px';
	viewFIS.style.left = x+'px';
	viewFIS.style.backgroundColor = 'white';
	viewFIS.style.border = 'solid black 1px';
	viewFIS.style.color = '#505050';
	viewFIS.style.fontFamily = 'Helvetica,Arial,sans-serif !important';
	viewFIS.style.fontSize = '10pt !important';
	viewFIS.style.textAlign = 'left';
	document.body.appendChild(viewFIS);
	
	viewFIS.innerHTML = '<h1 style="font-family: Times New Roman; font-size: 14pt; padding: 4px; "><a href="http://www.khm.de/~lscherff/ufis" target="_blank" style="text-decoration: none; color: #c0c0c0; font-family: Times New Roman;">UFIS!</a> is giving you some <a href="http://www.khm.de/~lscherff/ufis" target="_blank" style="text-decoration: none; color: #c0c0c0; font-family: Times New Roman; ">similar</a> images.</h1>';
	var flickDiv = document.createElement('div');
	flickDiv.setAttribute('style','float: left; ');
	flickDiv.style.width = '240px';
	flickDiv.style.textAlign = 'right';
	flickDiv.style.verticalAlign = 'top';
	if (flicks.firstChild) {
		insertImages(flickDiv,0,flicks);
		var p = document.createElement('p');
		p.innerHTML = '...via <a href="http://flickr.com/search/" target="_blank" style="text-decoration: none; color: #c0c0c0; font-family: Helvetica,Arial,sans-serif; ">flickr tag search</a> (using tags '+flickrTags.replace(/,/g,', ')+')'
		flickDiv.appendChild(p);
	} else 	flickDiv.innerHTML += '<p style="margin: 2px;"><a href="http://www.flickr.com/photos/search/" target="_blank" style="text-decoration: none; color: #c0c0c0; font-family: Helvetica,Arial,sans-serif; font-size: 10pt; ">flickr tag search</a> did not find any images for tag(s) '+flickrTags.replace(/,/g,', ')+'</p>';
	viewFIS.appendChild(flickDiv);
	
	retrDiv = document.createElement('div');
	retrDiv.setAttribute('style','float: right; ');
	retrDiv.style.width = '240px';
	retrDiv.style.textAlign = 'left';
	retrDiv.style.verticalAlign = 'top';
	if (retrs.firstChild) {
		insertImages(retrDiv,0,retrs);
		var p = document.createElement('p');
		p.innerHTML = '...via <a href="http://labs.systemone.at/retrievr" style="text-decoration: none; color: #c0c0c0; font-family: Helvetica,Arial,sans-serif; ">retrievr</a>';
		retrDiv.appendChild(p);
	} else retrDiv.innerHTML += '<p style="margin: 2px;"><a href="http://labs.systemone.at/retrievr/" style="text-decoration: none; color: #c0c0c0; font-family: Helvetica,Arial,sans-serif; ">retrievr</a> did not find any images</p>';
	viewFIS.appendChild(retrDiv);
	
	var middleDiv = document.createElement('div');
	middleDiv.style.margin = '0 240px 0 240px';
	var css = 'float: none; ';
	srcImg.style.margin = '2px';
	middleDiv.appendChild(srcImg);
	viewFIS.appendChild(middleDiv);
	
	var closeFIS = document.createElement('img');
	closeFIS.style.position = 'absolute';
	closeFIS.style.top = '4px';
	closeFIS.style.right = '4px';
	closeFIS.style.border = 'solid black 1px';
	closeFIS.src = 'http://www.khm.de/~lscherff/ufis/close.gif';
	closeFIS.addEventListener('click', function(event) {
		document.body.removeChild(viewFIS);
		viewFIS = null;
		event.stopPropagation();
		event.preventDefault();
	}, true);
	viewFIS.appendChild(closeFIS);
}

function insertImages(targetDiv,from,sourceDiv) {
	var child = targetDiv.firstChild;
	if (child) while (child.nextSibling) { var next = child.nextSibling; targetDiv.removeChild(child); child = next; }
	if (from>0) {
		var lesser = document.createElement('p');
		var lessLnk = document.createElement('a');
		var lessFrom = from-6; if (lessFrom<0) lessfrom = 0;
		lessLnk.appendChild(document.createTextNode((lessFrom+1)+' - '+(lessFrom+6)));
		lessLnk.addEventListener('click', function(event) {
			insertImages(targetDiv,lessFrom,sourceDiv);
			event.stopPropagation();
			event.preventDefault();
		}, true);
		lesser.appendChild(lessLnk); 
		targetDiv.insertBefore(lesser,child);
	}
	var stop = from+6;
	for (var i=from; i<stop; i++) {
		var container = document.createElement('span');
		container.style.position = 'relative';
		var blaImage = document.createElement('img');
		blaImage.setAttribute('src', 'http://www.khm.de/~lscherff/ufis/ufis.gif');
		blaImage.setAttribute('width','10');
		blaImage.setAttribute('height','10');
		blaImage.setAttribute('data',sourceDiv.childNodes[i].firstChild.src);
		blaImage.setAttribute('alt',sourceDiv.childNodes[i].firstChild.getAttribute('alt'));
		blaImage.setAttribute('style','position: absolute; bottom: 5px; left: 2px; border: solid black 1px; padding: 0px; margin: 0px; ');
		blaImage.addEventListener('click', function(event) {
			var URI = event.target.getAttribute("data");
			currentURI = URI;
			retrieveImages(URI, event.target.getAttribute('alt'));
			event.stopPropagation();
			event.preventDefault();
		}, true);
		container.appendChild(sourceDiv.childNodes[i].cloneNode(true));
		container.appendChild(blaImage);
		targetDiv.insertBefore(container,child);
	}
	var moreFrom = from+6;
	if 	(moreFrom<sourceDiv.childNodes.length) {
		var morer = document.createElement('p');
		var moreLnk = document.createElement('a');
		var moreTo = moreFrom+7; if (moreTo>=sourceDiv.childNodes.length) moreTo = sourceDiv.childNodes.length;
		moreLnk.appendChild(document.createTextNode('next '+(moreFrom+1)+' - '+moreTo+' (of '+sourceDiv.childNodes.length+')'));
		moreLnk.addEventListener('click', function(event) {
			insertImages(targetDiv,moreFrom,sourceDiv);
			event.stopPropagation();
			event.preventDefault();
		}, true);
		morer.appendChild(moreLnk); 
		targetDiv.insertBefore(morer,child);
	}
}

function parseFlickrResponse(responseDetails) {
	GM_log('PFR');
	var text = responseDetails.responseText;
	var parser = new DOMParser();
	var responseDOM = parser.parseFromString(responseDetails.responseText, "application/xml");
	GM_log(responseDOM);
	var photos = responseDOM.getElementsByTagName('photo');
	GM_log('length: '+photos.length);
	var flickrDiv = document.createElement('div');
	if (photos.length==0) {
		flicks = flickrDiv;
	} else {
		for (var i=0; i<photos.length; i++) {
			var imgLink = document.createElement('a');
			imgLink.href = 'http://www.flickr.com/photos/'+photos[i].getAttribute('owner')+'/'+photos[i].getAttribute('id');
			imgLink.target = '_blank';
			var img = document.createElement('img');
			img.src = 'http://static.flickr.com/'+photos[i].getAttribute('server')+'/'+photos[i].getAttribute('id')+'_'+photos[i].getAttribute('secret')+'_t.jpg';
			img.setAttribute('style', 'margin: 2px; border: none; float: none; ');
			imgLink.appendChild(img);
			flickrDiv.appendChild(imgLink);
		}
		flicks = flickrDiv;
	}
	if (retrs!=null) done();
}

function parseRetrievrImages(responseDetails) {
	GM_log('PRI');
	GM_setValue('flickr',false);
	var html = responseDetails.responseText;
	var imgTags = html.match(/<a href[^<]*<img[^>]*><\/a>/g);
	var allImgs;
	if (!imgTags) allImgs = '';
	else {
		for (var i=0; i<imgTags.length; i++) {
			var pattern = /<a href=\\"([^\\]*)[^<]*<img src=\\"([^\\]*)\\".*/;
			pattern.exec(imgTags[i]);
			var aHref = RegExp.$1;
			var imgSrc = RegExp.$2;
			if (imgSrc.indexOf('http://')>-1 && aHref.indexOf('http://'>-1))
				allImgs += '<a href="'+aHref+'" target="_blank"><img src="'+imgSrc+'" style="border: none; margin: 2px; float: none; " /></a>';
		}
	}
	var retrievrDiv = document.createElement('div');
	retrievrDiv.innerHTML = allImgs;
	retrs = retrievrDiv;
	if (retrs.firstChild) retrs.removeChild(retrs.firstChild);	// don't ask me why
	if (flicks!=null) done();
}

function parseRetrievrResponse(responseDetails) {
	GM_log('PRR');
	GM_setValue('retrievr',false);
	var html = responseDetails.responseText;
	var iframeTag = html.match(/<iframe .*>/g);
	var pattern = /(src=")([^"]*)(".*)/;
	pattern.exec(iframeTag);
	var src = RegExp.$2;
	src = 'http://labs.systemone.at' + src;
	GM_xmlhttpRequest({
		method: 'GET',
		url: src,
		headers: {
			'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/0.3',
			'Accept': 'application/xhtml+xml',
		},
		onload: parseRetrievrImages
	});
}

function retrieveImages(URI,alt) {
    if (tmpView) document.body.removeChild(tmpView);
	tmpView = document.createElement('div');
	tmpView.style.padding = '2px';
	tmpView.style.position = 'absolute';
	tmpView.style.backgroundColor = 'white';
	tmpView.style.border = 'solid black 1px';
	tmpView.style.top = yOffset-10+'px';
	tmpView.style.left = xOffset-40+'px';
	var tp = document.createElement('span');
	tp.style.paddingRight = '30px';
	tp.appendChild(document.createTextNode("UFIS! is searching... "));
	tmpView.appendChild(tp);
	var abort = document.createElement('img');
	abort.style.position = 'absolute';
	abort.style.top = '2px';
	abort.style.right = '2px';
	abort.style.border = 'solid black 1px';
	abort.src = 'http://www.khm.de/~lscherff/ufis/close.gif';
	abort.addEventListener('click', function(event) {
		document.body.removeChild(tmpView);
		event.stopPropagation();
		event.preventDefault();
	}, true);
	tmpView.appendChild(abort);
	document.body.appendChild(tmpView);
	
	flicks = null; retrs = null;
	flickrTags = '';
	// get from retrievr
	var end = URI.indexOf('.jpg');
	if (end<URI.length-4) URI = URI.substring(0,end+4);
	GM_xmlhttpRequest({
		method: 'GET',
		url: 'http://labs.systemone.at/retrievr/?url=' + URI,
		headers: {
			'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/0.3',
			'Accept': 'application/xhtml+xml',
		},
		onload: parseRetrievrResponse
	});
	if (URI.indexOf('http://static.flickr.com')>-1) {
		var pattern = /(static.flickr.com\/[^\/]*\/)([^_]*)/;
		pattern.exec(URI);
		var flickrId = RegExp.$2;
		if (flickrId) {
			var flickrURI = 'http://www.flickr.com/services/rest/?method=flickr.tags.getListPhoto&api_key=86e1a4a541d4c0442c4a37592780d14f&photo_id='+flickrId;
			GM_xmlhttpRequest({
				method: 'GET',
				url: flickrURI,
				headers: {
					'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/0.3',
					'Accept': 'application/xhtml+xml',
				},
				onload: function(responseDetails) {
					var allTags = '';
					var parser = new DOMParser();
					var responseDOM = parser.parseFromString(responseDetails.responseText, "application/xml");
					var tags = responseDOM.getElementsByTagName('tag');
					for (var i=0; i<tags.length; i++) {
						allTags += tags[i].firstChild.nodeValue;
						if (i<tags.length-1) allTags+=',';
					}
					flickrTags = allTags;
					getFromFlickr();
				}
			});
		}
	} else {
		if (flickrTags=='') {
			URI = URI.replace(/ /g,'%2C');
			var pattern = /(find similar images for: )(.*)/;
			pattern.exec(alt);
			alt = RegExp.$2;
			if (alt == '' || alt == 'null') {
				// use page title
				var title = document.getElementsByTagName("title");
				if (title.length>0) {
					alt = title[0].text;
					alt = alt.replace(/ /g,',');
				} 
				if (alt == '' || alt == 'null') {
					// use filename
					alt = URI.match(/\/[^\/]*\.jpg/)[0];
					alt = alt.substring(1,alt.length-4);
				}
			} else alt = alt.replace(/ /g,',');
			flickrTags = alt;
			getFromFlickr();
		}
	}
}

function getFromFlickr() {
	var flickrURI = 'http://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=86e1a4a541d4c0442c4a37592780d14f&per_page=25&page=1&tags='+flickrTags;
	GM_xmlhttpRequest({
		method: 'GET',
		url: flickrURI,
		headers: {
			'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/0.3',
			'Accept': 'application/xhtml+xml',
		},
		onload: parseFlickrResponse
	});
}

function addFlink() {
	var imgs = document.getElementsByTagName('img');
	for (var i=0; i<imgs.length; ) {
		var image = imgs[i];
		if (image.getAttribute('src') && image.getAttribute('src').indexOf('.gif')<0 && image.getAttribute('src').indexOf('.jpg')>0) {
			var parent = image.parentNode;
			var URI;
			var src = image.getAttribute('src');
			if (src.indexOf('/') == 0) src = src.substring(1,src.length);
			if (image.getAttribute('src').search('http://')>-1) URI = src;
			else {
				URI = 'http://' + location.hostname + location.pathname;
				if (URI.lastIndexOf('/') < URI.length-1)	URI = URI.substring(0,URI.lastIndexOf('/')+1);
				URI = URI + src;
			}
			var container = document.createElement('div');
			container.style.position = 'relative';
			var blaImage = document.createElement('img');
			blaImage.setAttribute('src', 'http://www.khm.de/~lscherff/ufis/ufis.gif');
			blaImage.setAttribute('width','10');
			blaImage.setAttribute('height','10');
			blaImage.setAttribute('data',URI);
			blaImage.setAttribute('alt', 'find similar images for: '+image.getAttribute('alt'));
			blaImage.setAttribute('style', 'position: absolute; top: -2px; left: -2px; border: solid black 1px; float: left; ');
			blaImage.addEventListener('click', function(event) {
				var URI = event.target.getAttribute("data");
				yOffset = event.pageY;
				xOffset = event.pageX;
				currentURI = URI;
				if (viewFIS) document.body.removeChild(viewFIS); viewFIS = null;
				retrieveImages(URI, event.target.getAttribute('alt'));
				event.stopPropagation();
				event.preventDefault();
			}, true);
			container.appendChild(image.cloneNode(true));
			container.appendChild(blaImage);
			image.parentNode.replaceChild(container, image);
			i+=2;
		} else i++;
	}
}

GM_registerMenuCommand('Toggle UFIS!', function(event) {
	var on = GM_getValue('on', false);
	on = !on;
	GM_setValue('on',on);
	if (on) addFlink();
});

if (!GM_getValue('on', false)) return;
else window.addEventListener(
		'load', 
		addFlink(),
		true);