Flickr GeoRadar

By CK Last update Aug 24, 2006 — Installed 1,444 times.
// ==UserScript==
// @name          Flickr GeoRadar
// @version       1.1
// @description	  This script displays nearby geotagged photos on a fancy radar screen
// @namespace     http://webdev.yuan.cc/
// @include       http://flickr.com/photos/*
// @include       http://www.flickr.com/photos/*

// v1.0	08/23/06	initial release
// v1.1 08/28/06	Add Exif support
//
// Author: .CK ( http://www.flickr.com/photos/ckyuan/ )
// Web site: http://webdev.yuan.cc/
//           http://flickr.tw/
//
// ==/UserScript==

(function() {

var re = /http:\/\/(www\.)?flickr\.com\/photos\/[^\/]+\/\d+/;
if( ! re.test(document.location) ) return;

if(unsafeWindow) w = unsafeWindow;
else w = window;
var global_photos = w.global_photos;

function _gt(e) { return document.getElementsByTagName(e); }
function _gi(e) { return document.getElementById(e); }
function _ce(e) { return document.createElement(e); }
function _ct(e) { return document.createTextNode(e); }

var photoid = w.page_photo_id;
/*
var lat=lon='';
var tmp = new Array();
var tags = tmp.concat(w.global_photos[photoid].tags_rawA);
while( tags && tags.length > 0 ) {
    tag = tags.pop();
    splits = tag.split('=');
    if( splits[0] == 'geo:lat' ) var lat = 1*splits[1];
    if( splits[0] == 'geo:lon' || splits[0] == 'geo:long' ) var lon = 1*splits[1];
}
if( lat=='' || lon=='' ) return;
*/

var container;
var coord = {lat: '', lon: ''};

var N = 'data:image/gif;base64,R0lGODlhEAAQAPMAALUJCcM/P////759fbceHrtZWcPIyLpNTb1ra8Cfn7+NjcTQ0LUEBAAfk8Xf3////yH5BAEAAA8ALAAAAAAQABAAAARM8MlJq5Uh3Jt3bQzTeE/THCFiXo2zACHhOOPnKGGY0LYT5IzDrCZpGWA5wII3aQ2AoQGz6CgwCAJBbEqdeYeW1tdLpJi+K48pTSJFAAA7';
var NE = 'data:image/gif;base64,R0lGODlhEAAQALMJAM9dXcBGRjoXZv77+7wuLrYLC7UEBAAfk8Xf3////wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAARFMMlJq70458OPHABQcUiJCEJhENRhEkYsj0igyrE4uXVxx6eWKTAY5BCenamkKpSSEt6wAHjSlgHrdakdSZHQSyeswUQAADs=';
var NW = 'data:image/gif;base64,R0lGODlhEAAQALMJAM9dXcBGRjoXZv77+7wuLrYLC7UEBAAfk8Xf3////wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAARFMMlJq704VwCGPOBxEUYhCEiKgJbhvoQqUsD7FsFaoXaBp7MPomYYDHJAyiFVKKmSk+Xw9wwKEUiZRfqEVkBV6zakKUcAADs=';
var E = 'data:image/gif;base64,R0lGODlhEAAQAPMAAAsdi7YLC7cZGcI/P76Cgv///7tSUsTLy7UHB8Cfn2wPPrgoKAAfk7UEBMXf3////yH5BAEAAA8ALAAAAAAQABAAAARD8MlJq704Z8aZ5k7ocBcjGsQRepUZNg0yEEArOgIMBwrlhgWdcCD5OYJCGPFhTAp6PhEMYUiwoqFFalUykjYdjfgRAQA7';
var W = 'data:image/gif;base64,R0lGODlhEAAQAPMAAAsdi7YLC7cZGcI/P76Cgv///7tSUsTLy7UHB8Cfn2wPPrgoKAAfk7UEBMXf3////yH5BAEAAA8ALAAAAAAQABAAAARD8MlJq704Z8aZ5k7ocBcTHoQhehVADEjTrJUSyLIgjtKA/4Udy/eTBWkThaAorDAShtgsxKKYHKgF0nmlVksdjfgRAQA7';
var SE = 'data:image/gif;base64,R0lGODlhEAAQALMJAM9dXcBGRjoXZv77+7wuLrYLC7UEBAAfk8Xf3////wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAARFMMlJq70458OP5kiIcNchnqNlnkHoUasYFIALo4VR2FMcDAODofaSrGY5oQEhqJhmSiXAKSJEhaoYU5AjlDqSAWCqsUQAADs=';
var SW = 'data:image/gif;base64,R0lGODlhEAAQALMJAM9dXcBGRjoXZv77+7wuLrYLC7UEBAAfk8Xf3////wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAARFMMlJq70468PPPkiIcBconl5lBueohkDBopRZGEWbSiBgGIPBzDURIH6/giy0S/iQSVYzAf0RRE0CTmDETgGAAa+jKUcAADs=';
var S = 'data:image/gif;base64,R0lGODlhEAAQAPMAALUJCf///7ceHr59fcY/P7tZWbk/P7pNTb1ra8Cfn7+NjcTNzbUEBAAfk8Xf3////yH5BAEAAA8ALAAAAAAQABAAAARG8MlJq70458ab5k7ocFcjnqNloqFHmQLDBEFcpJM5yDwz4BLTAtADLICP1aFnaFVMiZ4CGQzFGEZqsIGQHUgbmUvzIBAuEQA7';
var Red = 'data:image/gif;base64,R0lGODlhBAAEAJEAAAAAAP////8AAAAAACH5BAEAAAEALAAAAAAEAAQAAAIElI8pBQA7';
var Green = 'data:image/gif;base64,R0lGODlhBAAEAJEAAAAAAP///wD/AAAAACH5BAEAAAEALAAAAAAEAAQAAAIElI8pBQA7';
var small_radar = 'data:image/gif;base64,R0lGODlhFAAUANUCAAQcBAQeAv///w0LDQUkEgQ0BAQfBQQhCgQjEQAZAAAVAAcdBwROCwIdAkuGRzU2NRKwEj93WhF5HAM/BgSdAxUkFQl8CQK9AQQaBAKRAwcgCAWjBkqNTANZAkqUSwAdDQ4mD0qeSwAbBgIdBAVSDA8pDxkmGQR3AwRkExCJEAePCBReFCxALAUjEQaMBgufCwgGCBo1JggxGAkpHBIrEw8nEBDBEEdHRwN6AgkfCQQrAxkrGgBnDgQfBAEBAQQeBCH5BAEAAAIALAAAAAAUABQAAAb3QJ9QCBMYj0bYcClE6iaMzurIbApyikaBgcJlKBbBTTk0KhKA3xZ1cm0uL2NZoADYDWucamMLgeRFGmh2alxeECEmCgsCAw8CaCN2AAUkXS8eFXUJLEY0DZM/GDokPCkcO2g/DX8CAQ0NAbJ2ExIONAk9sgEJRh8ICC0tBMAyETEfBMrKH0YiB9DRBwQzBtLQIkawsQABAA0HCAE95Lu9Ap8jPT89AD3TPQbk7KxHqiM/adPu8z+9D4Ea5Bs4jZ28VQYa+TAzsFs4dhAVyLGShSCBAAYMBJAogIkRQRjAIYCV4EeSKkdqJEjwIUEJKlWEDECCZACTIAA7';

function sign(params) {

    params.api_key = w.global_magisterLudi;
    params.auth_hash = w.global_auth_hash;
    params.auth_token = w.global_auth_token;

    var _11=[], _12='';
    for(var p in params) {
        params[p]=params[p];
        _11.push(p);
        _12+="&"+p+"="+w.escape_utf8(params[p]);
    }
    _11.sort();
    var cal=w.global_flickr_secret;
    if(cal!="") {
        for(var i=0;i<_11.length;i++) cal+=_11[i]+params[_11[i]];
        cal=w.md5_calcMD5(cal);
        _12="api_sig="+cal+_12;
    }
    return _12;
}

function getCoord() {
    var tmp = new Array();
    var photoid = w.page_photo_id;
    var tags = tmp.concat(w.global_photos[photoid].tags_rawA);
    while( tags && tags.length > 0 ) {
	tag = tags.pop();
	splits = tag.split('=');
	if( splits[0] == 'geo:lat' ) coord.lat = 1*splits[1];
	if( splits[0] == 'geo:lon' || splits[0] == 'geo:long' ) coord.lon = 1*splits[1];
    }
    if(coord.lat=='' || coord.lon=='' ) {
	var listener = function(result) {
	    var responseText = result.responseText;
	    var rExp = /[]/gi;
	    var text = '' + responseText;
	    text = text.replace(rExp, '');

	    var rsp = text.replace(/<\?xml.*\?>/,'');
	    rsp = new XML(rsp);
	    lat_dir = (rsp..exif.(@label == 'North or South Latitude').raw == 'S')?-1:1
	    lat = new String(rsp..exif.(@label == 'Latitude').raw);
	    lon_dir = (rsp..exif.(@label == 'East or West Longitude').raw == 'W')?-1:1
	    lon = new String(rsp..exif.(@label == 'Longitude').raw);
	    if((lat.length > 0) && (lon.length > 0)) {
		lat = lat.split(/[,\/]/);
		lat_deg = parseInt(lat[0])/parseInt(lat[1]);
		lat_min = parseInt(lat[2])/parseInt(lat[3]);
		lat_sec = parseInt(lat[4])/parseInt(lat[5]);
		coord.lat = lat_dir * (lat_deg + (lat_min+lat_sec/60)/60);
								
		lon = lon.split(/[,\/]/);
		lon_deg = parseInt(lon[0])/parseInt(lon[1]);
		lon_min = parseInt(lon[2])/parseInt(lon[3]);
		lon_sec = parseInt(lon[4])/parseInt(lon[5]);
		coord.lon = lon_dir * (lon_deg + (lon_min+lon_sec/60)/60);
		coordDone();
	    }
	};
	params = {
	    method: 'flickr.photos.getExif',
	    photo_id: photoid
	};
	url = 'http://flickr.com/services/rest/?' + sign(params);
	GM_xmlhttpRequest({
	    method: 'GET',
	    url: url,
	    headers: {
		'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey GeoRadar',
		'Accept': 'application/atom+xml,application/xml,text/xml'
	    },
	    onload: listener});
    } else coordDone();
}

function loadPhotos() {

    container.innerHTML = '';
    var radar = _ce('div');
    radar.style.width = '250px';
    radar.style.height = '250px';
    radar.style.padding = '0px 0px 0px 0px';
    radar.style.margin = '0px 0px 0px 0px';
    radar.style.display = 'inline';
    radar.style.border = 'solid 0px #000000';
    radar.style.overflow = 'hidden';
    var blank = radar.cloneNode(true);
    blank.style.border = '0px';
//    radar.innerHTML = '<img src="http://static.flickr.com/86/222763825_ad43c6d175_o.jpg" style="margin:0px" width="250" height="250" border="0" align="left" />';
    radar.innerHTML = '<img src="http://static.flickr.com/74/223454955_695950c335_o.gif" style="margin:0px" width="250" height="250" border="0" align="left" />';
    blank.innerHTML = '<img src="http://static.flickr.com/94/222893082_2925713b3b_o.gif" style="margin:0px" width="250" height="250" border="0" align="left" />';
    container.appendChild(radar);
    container.appendChild(blank);

    var url = 'http://maps.yuan.cc/api.php?method=flickr.search.nearby&lat=' +coord.lat+ '&lon=' +coord.lon;
    var headers = { 'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/Nearby Geotagged Photos', 'Accept': 'application/atom+xml,application/xml,text/xml' };
    GM_xmlhttpRequest({
	method: 'GET', url: url, headers: headers,
	onload: function(responseDetails) {
	    blank.innerHTML = '';
	    var lat=coord.lat, lon=coord.lon;
	    var PI = Math.PI;
	    var parser = new w.DOMParser();
	    var dom = parser.parseFromString(responseDetails.responseText, "application/xml");
	    var stat = dom.getElementsByTagName('rsp')[0].getAttribute('stat');
	    if( stat == 'ok' ) {
		var photos = dom.getElementsByTagName('photo');
		if(photos.length>1) {
		    var spot = _ce('div');
		    spot.style.position = 'absolute';
		    spot.style.zIndex = 1000;
		    spot.style.width = '0px';
		    spot.style.height = '0px';
		    spot.style.padding = '0px';
		    spot.style.margin = '0px';
		    spot.style.overflow = 'visible';
		    spot.style.display = 'inline';		    	    
		}

		var y = 1*photos[25].getElementsByTagName('longitude').item(0).firstChild.data;
		var x = 1*photos[25].getElementsByTagName('latitude').item(0).firstChild.data;
		var MaxR = Math.sqrt( (x-lat)*(x-lat)+(y-lon)*(y-lon));
		for(var i=1; i<26; i++) {
		    var id = photos[i].getAttribute('id');
		    var owner = photos[i].getAttribute('owner');
		    var secret = photos[i].getAttribute('secret');
		    var server = photos[i].getAttribute('server');
//		    var title = photos[i].getElementsByTagName('title').item(0).firstChild.data;
		    var img_s = 'http://static.flickr.com/' + server + '/' + id + '_' + secret + '_s.jpg';
		    var y = 1*photos[i].getElementsByTagName('longitude').item(0).firstChild.data;
		    var x = 1*photos[i].getElementsByTagName('latitude').item(0).firstChild.data;
		    var arc = Math.atan2(x-lat,y-lon);
		    var r = Math.sqrt( (x-lat)*(x-lat)+(y-lon)*(y-lon));
		    x = r*Math.cos(arc); x = x*110/MaxR; x = x-125;
		    y = r*Math.sin(arc); y = y*110/MaxR; y = 125-y;
		    dir = '';
		    if( -1/8*PI<=arc && arc<=1/8*PI ) dir = E;
		    if( 1/8*PI<=arc && arc<=3/8*PI ) dir = NE;
		    if( 3/8*PI<=arc && arc<=5/8*PI ) dir = N;
		    if( 5/8*PI<=arc && arc<=7/8*PI ) dir = NW;
		    if( 7/8*PI<=arc || arc<=-7/8*PI ) dir = W;
		    if( -7/8*PI<=arc && arc<=-5/8*PI ) dir = SW;
		    if( -5/8*PI<=arc && arc<=-3/8*PI ) dir = S;
		    if( -3/8*PI<=arc && arc<=-1/8*PI ) dir = SE;

		    var box = _ce('div');
		    box.style.width = '50px';
		    box.style.height = '50px';
		    box.style.padding = '0px';
		    box.style.margin = '0px';
		    box.style.display = 'inline';
		    var thumb = _ce('a');
		    thumb.title = arc;
		    thumb.href = 'http://www.flickr.com/photos/' +owner+ '/' + id +'/';
		    thumb.innerHTML = '<img src="' +img_s+ '" width="50" height="50" border="0" style="margin:0px" />';
		    box.appendChild(thumb);
		    blank.appendChild(box);

		    var _dir = _ce('div');
		    _dir.id = 'box'+i+'_dir';
		    _dir.style.position = 'absolute';
		    _dir.style.zIndex = 1000;
		    _dir.style.width = '0px';
		    _dir.style.height = '0px';
		    _dir.style.padding = '0px';
		    _dir.style.margin = '0px';
		    _dir.style.overflow = 'visible';
		    _dir.style.display = 'none';
		    _dir.innerHTML = '<img src="'+dir+'" style="position:relative;left:-18px;top:-2px;" />';
		    box.appendChild(_dir);

		    var _spot = spot.cloneNode(true);
		    radar.appendChild(_spot);
		    var point = _ce('img');
		    point.id = 'box'+i+'_img';
		    point.src = Green;
		    point.style.position = 'relative';
		    point.style.zIndex = 1000;
		    point.style.left = x+'px';
		    point.style.top = y+'px';
		    _spot.appendChild(point);
		    
		    box.id = 'box'+i;
		    box.addEventListener('mouseover', function() {
			_gi(this.id+'_img').style.zIndex = 2000;
			_gi(this.id+'_img').src = Red;
			_gi(this.id+'_dir').style.display = 'inline';
		    }, true);
		    box.addEventListener('mouseout', function() {
			_gi(this.id+'_img').style.zIndex = 1000;
			_gi(this.id+'_img').src = Green;
			_gi(this.id+'_dir').style.display = 'none';
		    }, true);		    		    
		}
	    }
	}
    });
}


function coordDone() {

    var photodiv = _gi('photoImgDiv' + photoid);
    container = _ce('div');
    container.style.width = '500px';
    container.style.border = '0px';
    container.style.margin = '0px';
    container.style.padding = '0px';

    var fetchphotos = _ce('a');
    fetchphotos.style.fontSize = '12px';
    fetchphotos.style.fontColor = '#00ff00';
    fetchphotos.style.textDecoration = 'none';
    fetchphotos.href = "javascript:;";
    fetchphotos.addEventListener('click', loadPhotos, true);
    //fetchphotos.innerHTML = '<img src="http://static.flickr.com/86/222763825_ad43c6d175_s.jpg" border="0" width="20" height="20" /> Turn on the radar';
    fetchphotos.innerHTML = '<img src="'+small_radar+'" border="0" width="20" height="20" /> <font color="#008800">TURN ON RADAR</font>';
    container.appendChild(fetchphotos);

    photodiv.parentNode.insertBefore(container, photodiv.nextSibling);
}

getCoord();

})();