/*
 * lfvr.js, version 1.8
 * A lightweight flickr viewer
 *
 * Copyright (C) 2005 CK Yuan (ckyuan@gmail.com)
 *
 * This script is a free software; you can use it at free charge.
 * Any comments and improvements are welcome. You can get a copy and
 * run at your own server after notifying me. The commercial use of 
 * this software is prohibited.
 */

var user,user_history,photo,stream,apiQueue,mapStr,mapPic,auth_contact;
var perPage=30, totalPages, totalPhotos, curPage=1, buffer_max=18,buffer_handler=null;
var photoset,photosetBox, photosetBoxStr, photosetBoxOpen=0;
var contact,contactBox, contactBoxStr,contactIconStr='', contactBoxOpen=0;
var groups,groupBox, groupBoxStr, groupBoxOpen=0;
var comments, commentStr, commentBox, commentBoxStr, commentBoxOpen=0;
var donationBox, donationBoxStr, donationBoxOpen=0;
var guestbookBox, guestbookBoxStr, guestbookBoxOpen=0;
var tags,tagBox, tagBoxStr, tagBoxOpen=0, tagAllStr;
var userinfoBox, userinfoBoxStr, userinfoBoxOpen=1;
var flickr_photoset_id = '';
var _haspages, _lastBg=null, _lastBox, _size='s',_vsize='-', _title, _gmap=0;
var _primary, _photoStream=1, _photoInfo=1, __photoInfo, _photoComments=1,__photoComments;
var streamStr=''; 
var login='', _contact=-1, _contact_count=0,_user,_usermore,_usertype=2,_userSort=0;
var getMoreContact=slidePlay=0;
var _mSiteName = 'LfVr - a Lightweight flickr Viewer';
var _mUsePrintLink='';
var GEOBLOGGERS_PROXY_URL = 'geobloggers.proxy.php', getNearBy='false', xmlhttp;
var _GMapURL = 'http://google.com/maps?file=js&hl=en';
var loading_photo = '/lfvr/loading_photo.gif';
var _maphacks = false;
var nav_div1, nav_div2, nav_br, nav_prev_text, nav_next_text;

var auth_contact = new Array();
var user_history = new Array();
var interestingness = new Object();
var tmp = new Array();
interestingness.photo = tmp;
var publicPhotos = new Object();
var tmp = new Array();
publicPhotos.photo = tmp;
var contactPhotos = new Object();
var tmp = new Array();
contactPhotos.photo = tmp;
var favorites = new Object(); ;
var tmp = new Array();
favorites.photo = tmp;
var recentPhoto = new Object();
var tmp = new Array();
recentPhoto.photo = tmp;
var searchResults = new Object();
var tmp = new Array();
searchResults.photo = tmp;
var mapInfo = new Object();
var fSearch = new Object();


var userArea = '<b>User Information</b><br /><form onSubmit="return searchUser()"><input id="screen" type=text size=16> <input id="searchbutton" type="button" value="Search" onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="searchUser()"></form>';
guestbookBoxStr = '<a href="javascript:;" onClick="showGuestbook(0)">- <b>Discuss</b></a><p>You are welcome to sign up the guestbook to let me know how you like LfVr. This is not mandatory. </p><p><a href="http://flickr.com/groups/topic/40901/" target="_blank">Signup my guestbook at flickr.</a><br /><a href="http://flickr.com/groups/flickr_tools/" target="_blank">Comments or Quesstions?</a></p>';
// guestbookBoxStr += '<script src="http://embed.technorati.com/linkcount" type="text/javascript"></script><a class="tr-linkcount" href="http://technorati.com/search/http%3A%2F%2Fwebdev.yuan.cc%2Flfvr%2F?sub=nscosmos">View blog reactions</a>';
donationBoxStr = '<a href="javascript:;" onClick="showDonation(0)">- <b>Donation</b></a><p>I am devoted to web programming for personal interests and running all services at home via DSL connection. If you like my work, you can donate to help me with the bills.  <form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input type="hidden" name="cmd" value="_s-xclick"> <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" border="0" name="submit" alt="Make payments with PayPal - it\'s fast, free and sec ure!"> <input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHPwYJKoZIhvcNAQcEoIIHMDCCBywCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMR YwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYBhena7x3NFZAOZwCka64nae5mKJVhchxFMYG3gMIySPzmaTrdhLLBhxGYUp1iujAkXqg4Oas96loyu9lV24IJmtBn05F9UD0LJfoV497/HEGR47Ei+Uk1Y1AUK5+FdSY0LV8hgZeqT0gd1CKHodLZqswyKkhonzmBD6jHHm7IJ4jELMAkGBSsOAwIaBQAwgbwGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIKPH1klI7TxmAgZi+9njL3q6pN6jrab59GsY/AmfNy1FekRVae5LwG+nbAx0TMRDUZ7M1BSbF+T6Q9YR9JRtyWu7tz4grvWEwxqsVPXC6JHqNsDuhxJadR6E5bt5+jDn9oTHc4hSs+o8z+bnTAqYcSN8GV7cOpjm7Wk8xFzaaZuGittuftZzNJDAdvAylPhwpMI5sPwWnqVOWv9mMbBsSiEKvSqCCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTA1MTAzMTE3MTYxNFowIwYJKoZIhvcNAQkEMRYEFETp8ECn/Vj5bfOpYiUC+SASGvooMA0GCSqGSIb3DQEBAQUABIGATNMUUdQNZiVhIVJbCt7Qfkjy6HUkYkMbUsWyWxVSQHofg5VO1bW7hfCjscARcveEyLRJ7neVaYhjTrYP71bgZO1wyrdFFEvj59j9E41MrljVYF7utE3ADCC0wsOW8MJN5wwMK9U+tnXL5LvCHUiOPpik+GPt6xcP04XLQWCG/bo=-----END PKCS7-----"></form></p>';

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 _IE4 = (document.all);

var handle_findUser = function (result,args)
{
    // args[0]: "true" for calling flickrAPI.people.getInfo
    // args[1]: "true" for calling flickrAPI.people.getPublicPhotos
    // args[2]: "true" for calling flickrAPI.photosets.getList(user.nsid);
    // args[3]: "true" for calling flickrAPI.tags.getListUserPopular(user.nsid,20);
    // args[4]: "true" for calling flickrAPI.contacts.getPublicList(user.nsid);
    // args[5]: "true" for calling flickrAPI.people.getPublicGroups(user.nsid);

    var nsid = (result.nsid)?result.nsid:result.id;
    user = new person(nsid, '', '', '', result.username, '', '', '', '', '', '', '');
    showPhotoSet(-1);
    showContact(-1);
    if( args[0] ) {
	showStatus('Loading ...', _gi('userinfo'));
	flickrAPI.people.getInfo(handle_people_getInfo, null, nsid);
    }
    if( args[1] ) {
	showStatus('Loading ' + result.username + '\'s recent photos ...', _gi('photos'));
	var args2 = new Array(recentPhoto, 'recent', 1, 'Public Photos',1);
	flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args2, nsid, '', perPage, 1);
    }
    if( args[2] ) {
	showStatus('Loading ' + result.username + '\'s photo sets ...', _gi('photoset'));
	flickrAPI.photosets.getList(handle_photosets_getList, null, nsid);
    }
    if( args[3] ) {
	showStatus('Loading ' + result.username + '\'s top 20 popular tags ...', _gi('phototag'));
	flickrAPI.tags.getListUserPopular(handle_tags_getListUserPopular, null, nsid, 20);
    }
    if( args[4] ) {
	showStatus('Loading ' + result.username + '\'s contacts ...', _gi('contact'));
	flickrAPI.contacts.getPublicList(handle_contacts_getPublicList, null, nsid);
    }
    if( args[5] ) {
	showStatus('Loading ' + result.username + '\'s groups ...', _gi('group'));
	flickrAPI.people.getPublicGroups(handle_people_getPublicGroups, null, nsid);
    }
    if( args[6] ) {
//	var url = 'http://flickr.com/recent_comments_feed.gne?id=' + user.nsid + '&format=rss_200';
	var url = 'http://api.flickr.com/services/feeds/activity.gne?id=' + user.nsid + '&format=rss_200';
	showStatus('Loading ' + result.username + '\'s recent comments ...', _gi('comment'));
	rssAPI.feeds.getItems(handle_rssAPI_feeds_getItems, null, url);
    }
    showStatus('', _gi('userinfo'));
}

var handle_urls_lookupUser = function (result,args)
{
    showPhotoSet(-1);
    showContact(-1);
    showStatus('Loading ...', _gi('userinfo'));
    flickrAPI.people.getInfo(handle_people_getInfo, null, result.nsid);
}

var handle_contact_getInfo = function (result,args)
{
    if( _contact >=0 ) {
	contact[_contact].iconserver = result.iconserver;
	contact[_contact].count = result.count;
	contact[_contact].ispro = result.ispro;
	contact[_contact].location = result.location;
	contact[_contact].realname = result.realname;
	contact[_contact].firstdate = result.firstdate;
	contact[_contact].firstdatetaken = result.firstdatetaken;
	contact[_contact].removabl = false;
	_contact--; _contact_count--;
	if ( _contact >= 0 && _contact_count > 0 ) {
	    showStatus('Got ' + contact[_contact].username + '\'s icon ..., ' + _contact_count + ' left',_gi('photos'));
	    if( _contact_count % 100 == 0 ) displayContacts(0);
	    flickrAPI.people.getInfo(handle_contact_getInfo, null, contact[_contact].nsid);
	} else {
	    getMoreContact = false;
	    displayContacts(2);
	}
//	showStatus('',_gi('photos'));
	return;
    }
}

var handle_people_getInfo = function(result,args) 
{
    var str = '', hit=false;
    userinfoBox = _gi('userinfo');

    user = new person(result.nsid, result.isadmin, result.ispro, result.iconserver, result.username, result.realname, result.location, result.photosurl, result.profileurl, result.firstdate, result.firstdatetaken, result.count);

    user.removable = false;
    for( var i=0; i<user_history.length; i++)
	if(user_history[i].nsid == user.nsid) {
	    hit = true;
	    user_history[i] = user;
	    user_history[i].removable = true;
	    user_history[i].del = history_del;
	    SetCookie('history'+i, user.nsid+','+user.username+','+user.iconserver+','+user.count,exp);
	}
    if( !hit ) {
	if( user_history.length >= 30 ) {
	    user_history.shift();
	    for( var i=0; i<user_history.length; i++)
		SetCookie('history'+i, user_history[i].nsid+','+user_history[i].username+','+user_history[i].iconserver+','+user_history[i].count,exp);
		
	}
	user_history[user_history.length] = user;
	user.removable = true;
	user.del = history_del;
	SetCookie('history'+(user_history.length-1), user.nsid+','+user.username+','+user.iconserver+','+user.count,exp);
	SetCookie('history_num', user_history.length,exp);
    }

    contactIconStr='';
    _contact=-1, _contact_count=0;
    delete contact;
    delete recentPhoto.photo;
    delete favorites.photo;
    recentPhoto.pages = 0;
    recentPhoto.total = 0;
    var tmp = new Array(user.count);
    recentPhoto.photo = tmp;
    var tmp = new Array();
    favorites.photo = tmp;

    _gi('screen').value = user.username;

    if( user.realname == null ) user.realname = '';
    if( user.location == null ) user.location = '';

    userinfoBox.innerHTML = userArea + namecard(user,-1,'website');
    showStatus('', _gi('userinfo'));
}

var handle_urls_lookupGroup = function (result,args)
{
    if( typeof(groups) != 'object' ) {
	groups = new Array(1);
	groups[0] = new Object();
	groups[0].nsid = result.id;
	groups[0].name = result.groupname;
	groups[0].flickr_url = 'http://flickr.com/groups/' + result.id + '/pool/';
    }
    gotoGroup(0,result.id);
}

var handle_interestingness_getList = function(result,args)
{
    var base = (result.page-1)*result.perpage;
    for(var i=1; i<result.photo.length; i++) {
        interestingness.photo[base+i-17] = result.photo[i];
    }

    interestingness.pages = result.pages;
    interestingness.total = result.total;
    interestingness.page = result.page;
    photo = interestingness;
    displayPhotos(_size,'Interesting Photos',' ',0);
    showStatus('', _gi('photos'));
}

var handle_photos_getRecent = function(result,args)
{
    var base = (result.page-1)*result.perpage;
    for(var i=1; i<result.photo.length; i++) {
        publicPhotos.photo[base+i-17] = result.photo[i];
    }

    publicPhotos.pages = result.pages;
    publicPhotos.total = result.total;
    publicPhotos.page = result.page;
    photo = publicPhotos;
    displayPhotos(_size,'Public Photos',' ',0);
    showStatus('', _gi('photos'));
}

var handle_photosets_getList = function (result,args)
{
    var str = '<a href="javascript:;" onClick="showPhotoSet(0)">- <b>Photo Sets</b></a><br />';

    photosetBox = _gi('photoset');
    photoset = result.photoset;
    for( var i=0; i < photoset.length; i++) {
	str += '<a href="javascript:;" onClick="showSet(' + i + ',\'' + photoset[i].id + '\')">' + photoset[i].title + '</a> ';
	photoset[i].owner = user.nsid;
    }
    photosetBoxStr = str;
    if( photosetBoxOpen == 1 ) showPhotoSet(1);
    showStatus('', _gi('photoset'));
}

var handle_tags_getListUserPopular = function (result,args)
{
    var str = '<a href="javascript:;" onClick="showTags(0)">-</a> <a href="javascript:;" onClick="showAllTags()"><b>Tags</b></a><br />';

    tagBox = _gi('phototag');
    tags = result;
    tags.text = 'tag';
    for( var i=0; i < tags.tag.length; i++) {
	str += '<a href="javascript:;" onClick="showTagPhotos(\''+user.nsid+'\',\''+tags.tag[i].name+'\')">' + tags.tag[i].name + '('+tags.tag[i].count+')</a> ';
    }
    str += '<br /><input id="tagsearchall" type="checkbox"><span> See all public photos</span>';
    str += '<br /><input id="tagsearch" type="text" size=18> <input type=button value="Tags Search" onClick="tagSearch();">';
    tagBoxStr = str;
    if( tagBoxOpen == 1 ) showTags(1);
    showStatus('', _gi('phototag'));
}

var handle_contacts_getList = function (result,args)
{
    var c = result.contacts;
    for( var i=0; i < c.length; i++) auth_contact[c[i].nsid] = c[i];
}

var handle_contacts_getPublicList = function (result,args)
{
    var str = '';

    contactBox = _gi('contactlist');
    contact = result.contact;
    _contact = contact.length-1;
    contactIconStr='';
    for( var i=0; i < contact.length; i++) {
	str += '<a href="javascript:;" onClick="gotoUser(\'' + contact[i].nsid + '\')">' + contact[i].username + '</a> ';
	if( contact[i].count == undefined ) contact[i].count =0;
    }
    contactBoxStr = str;
    if( contactBoxOpen == 1 ) showContact(1);
    showStatus('', _gi('contact'));
}

var handle_comments_getList = function (result,args)
{
    var str = '';

    var comments = result.comments;
    for( var i=0; i < comments.length; i++) {
        str += '<a href="javascript:;" onClick="gotoUser(\'' + contact[i].nsid + '\')">' + contact[i].username + '</a> ';
        if( contact[i].count == undefined ) contact[i].count =0;
    }
    contactBoxStr = str;
    if( contactBoxOpen == 1 ) showContact(1);
    showStatus('', _gi('contact'));
}

var handle_people_getPublicGroups = function (result,args)
{
    if( typeof(groups) != 'object' ) groups = new Array();
    var str = '<a href="javascript:;" onClick="showGroups(0)">- <b>Groups</b></a><br />';
//    str += '<input id="group_nsid" type="text" name="group_nsid" size="16">';
//    str += '<input type="button" value="Search Group" onClick="var gid=_gi(\'group_nsid\').value;gotoGroup(-1,gid)"><br />';

    groupBox = _gi('group');
    groups = result.group;
    for( var i=0; i < groups.length; i++) {
	str += '<a href="javascript:;" onClick="gotoGroup('+i+',\''+groups[i].nsid+'\')">' + groups[i].name + '</a> ';
	groups[i].flickr_url = 'http://flickr.com/groups/' + groups[i].nsid + '/pool/';
    }
    groupBoxStr = str;
    if( groupBoxOpen == 1 ) showGroups(1);
    showStatus('', _gi('group'));
}

var handle_photosets_getPhotos = function(result,args)
{
    var str='', primary;

    photoset[set_index].primary = result.primary;
    photoset[set_index].owner = result.owner;
    photoset[set_index].ownername = result.ownername;
    photo = new Object();
    var tmp = new Array();
    photo.photo = tmp;
    photo.flickr_url = 'http://flickr.com/photos/' + user.nsid + '/sets/'+ result.photoset_id + '/';
    for(var i=0; i<result.photo.length; i++) {
	photo.photo[i] = result.photo[i];
    }
    for( i=0; i < photo.photo.length; i++ ) {
	if( photoset[set_index].primary == photo.photo[i].id ) {
	    if( photoset[set_index].description  == null ) photoset[set_index].description = '';
	    if( user.nsid == photoset[set_index].owner ) 
		primary = '<table border=0><tr><td><img src="'+ photo.photo[i].img_m + '"></td><td>' + photoset[set_index].description + '</td></tr></table><br />';
	    else primary = '<table border=0><tr><td><img src="'+ photo.photo[i].img_m + '"></td><td><p><a href="javascript:;" onClick="gotoUser(\''+photoset[set_index].owner+'\')"><img src="http://flickr.com/buddyicons/' +photoset[set_index].owner+ '.jpg" width="48" height="48" /></a></p>' + photoset[set_index].description + '</td></tr></table><br />';
	}
    }
    displayPhotos(_size, photoset[set_index].title, primary,0);
    showStatus('', _gi('photos'));
}

var handle_getPhotoStream = function(result,args)
{
    // args[0] = stream instance
    // args[1] = stream text
    // args[2] = action: 1. displayPhotos, 2. displaySingle, 3. slideshow, 4... nothing
    // args[3] = param1 for action
    // args[4] = param2 for action

    var base = (result.page)?(result.page-1)*result.perpage:0;
    var stream = args[0];

//  alert(result.pages + ',' + result.total + ',' + result.page + ',' + result.perpage + ',' + base+ ',' + result.photo.length);
//  Flickr has 200 photos limit for free account
//  if( args[1] == 'recent' ) if( base>200 ) return;

    for(var i=0; i<result.photo.length; i++) {
	stream.photo[base+i] = result.photo[i];
	stream.photo[base+i].ownername = (result.photo[i].ownername)?result.photo[i].ownername:result.photo[i].username;
    }

    if( result.photo.length < result.perpage && result.page != result.pages ) {
	stream.pages = result.page;
	stream.total = (result.page-1)*result.perpage + result.photo.length;
    } else {
	if( !stream.pages ) stream.pages = result.pages;
	if( !stream.total ) stream.total = result.total;
    }
    stream.page = result.page;
//  alert(stream.pages + ',' + stream.total + ',' + stream.page + ',' + stream.perpage + ',' + base+ ',' + stream.photo.length);
    if( typeof(user) == 'object' ) {
	stream.owner = user.nsid;
	stream.ownername = user.username;
    }
    stream.text = args[1];
    if( stream.flickr_url == '' || stream.flickr_url == undefined ) 
	stream.flickr_url = 'http://flickr.com/photos/' + stream.owner + '/';
    if( typeof(stream.photo[stream.total-1]) != 'object' ) {
	stream.photo[stream.total-1] = stream.total;
    }
    if( stream.total < stream.photo.length ) {
	var k = stream.photo.length;
// alert(stream.photo.length + ',' + stream.total + ',' + k);
	for(var j=stream.total;j<k;j++) stream.photo.pop();
// alert(stream.photo.length);
    }
    photo = stream;
    showStatus('', _gi('photos'));

    if( args[2] == 1 ) displayPhotos(_size, args[3],' ', args[4]);
    if( args[2] == 2 ) displaySingle(args[3]);
    if( args[2] == 3 ) slideshow(args[3]);
}

var handle_rssAPI_feeds_getItems = function (result,args)
{
    var str='',re,description,author,tmp;

    commentBox = _gi('comment');
    commentBoxStr = '<a href="javascript:;" onClick="showComments(2,commentStr)">Comments on ' + user.username + '\' photos</a> (' +result.items.length+ ')';

//    comments = result.items;
    _title = 'Latest commented photos';
    comments = new Object();
    var tmp = new Array();
    comments.photo = tmp;
    comments.text = 'comment';
    comments.pages = 1;
    comments.page = 1;
    for( var i=0; i < result.items.length; i++) {
	re = /.*\((.*)\)/ig;
	author = result.items[i].author.replace(re, '$1');
	re = /(<a href=".*">)(.*)(<\/a> has posted a comment)/i;
	tmp = result.items[i].description.replace(re, '<a href="javascript:;" onClick="searchUser(\''+author+'\')"><b>$2</b>$3');
	re = /<a href="http:\/\/flickr.com\/photos\/.*\/(\d*)\/" (title=".*")><img/i;
	description = tmp.replace(re, '<a href="javascript:;" onClick="displaySingle('+i+')"><img');
	re = /(<p><a href=".*".*><img src=.*\/><\/a><\/p>)/i;
	tmp = re.exec(description);
	var imglink = tmp[1];
	description = description.replace(re,'');

	comments.photo[i] = new Object();
	comments.photo[i].owner = user.nsid;
	comments.photo[i].username = user.username;
	re = /<a href="http:\/\/www.flickr.com\/photos\/.*\/(\d*)\/" (title=".*")><img/i;
	tmp = re.exec(result.items[i].description);
	comments.photo[i].id = tmp[1];
	comments.photo[i].title = result.items[i].title;
	comments.photo[i].link = result.items[i].link;
	comments.photo[i].pubDate = result.items[i].pubDate;
	comments.photo[i].img_s = loading_photo;
	comments.photo[i].img_t = loading_photo;
	comments.photo[i].img_m = loading_photo;
	comments.photo[i].img   = loading_photo;
	comments.photo[i].img_b = loading_photo;
	comments.photo[i].img_o = loading_photo;
	str += '<div class="comment">';
	str += '<ul>' + imglink;
	str += '<b><a href="' + comments.photo[i].link + '">' + comments.photo[i].title + '</a></b><br />';
	str += 'On ' + comments.photo[i].pubDate;
	str += description;
	str += '</ul>';
	str += '</div><hr>';

	var photoinfo = function(result,args) {
	    var p = args[0];
	    p.id = result.id;
            p.owner = result.owner.nsid;
            p.ownername = result.owner.ownername;
            p.secret = result.secret;
            p.server = result.server;
            p.title = result.title;
            p.ispublic = result.visibility.ispublic;
            p.isfriend = result.visibility.isfriend;
            p.isfamily = result.visibility.isfamily;

            p.img_s = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_s.jpg';
            p.img_t = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_t.jpg';
            p.img_m = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_m.jpg';
            p.img = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'.jpg';
            p.img_b = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_b.jpg';
            p.img_o = 'http://static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_o.jpg';
            p.img_o = 'http://l.yimg.com/www.flickr.com/images/pulser2.gif';
	}
	var args = new Array(comments.photo[i]);
	if( comments.photo[i].id != '' ) flickrAPI.photos.getInfo(photoinfo, args, comments.photo[i].id);
    }
    commentStr = str;

    if( commentBoxOpen == 1 ) showComments(1);
    showStatus('', _gi('comment'));
}

function getPhotoById(id,owner) {

	photo = new Object();
	var tmp = new Array();
	photo.photo = tmp;
	photo.photo[0] = new Object();
	photo.photo[0].id = id;
	photo.photo[0].owner = owner;
	photo.photo[0].title = '';

	photo.photo[0].img_s = loading_photo;
	photo.photo[0].img_t = loading_photo;
	photo.photo[0].img_m = loading_photo;
	photo.photo[0].img   = loading_photo;
	photo.photo[0].img_b = loading_photo;
	photo.photo[0].img_o = loading_photo;
	displaySingle(0,_vsize,'\''+ id +'\'');
}

function showRecent() {
    if( recentPhoto.text ) {
	photo = recentPhoto;
	displayPhotos(_size,'Public Photos',' ',1);
	showStatus('', _gi('photos'));
    } else {
	showStatus('Loading user\'s recent photos ...', _gi('photos'));
	var args = new Array(recentPhoto, 'recent', 1, 'Public Photos',1);
	flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args, user.nsid, '', perPage, 1);
    }
}

function displayPhotos(size,title,primary,haspages) {

    var photobox = _gi('photos');
    var image, owner,str='', ptitle='',i,j,k;

    if( !photo || !photo.photo ) return;

    if( !haspages && haspages!=0 ) haspages = _haspages;
    else _haspages = haspages;
    if( haspages == 1 ) {
	str += pager();
	j = ( photo.page-1)*perPage;
	k = ( photo.page*perPage < photo.photo.length ) ? photo.page*perPage : photo.photo.length;
    } else {
	j=0;
	k = photo.photo.length;
    }
    if( size == undefined ) size = _size;
    str += '<div class="slide">';
    str += '<input type="button" class="button" onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changeImgSize(\'s\')" value="Square"> ';
    str += '<input type="button" class="button" onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changeImgSize(\'t\')" value="Thumbnail"> ';
    str += '<input type="button" class="button" onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changeImgSize(\'m\')" value="Small"> ';
    str += '<input type="button" class="button" onClick="slidePlay=2;slideshow(0)" value="Slideshow">';
    str += '</div>';
    str += '<img id="prefetch" width=' + (_gt('body')[0].clientWidth-60-200-60) + ' height=0 src="' +loading_photo+ '">';
    if( !title ) title = _title;
    if( !primary ) primary = _primary;
    _title = title;
    _primary = primary;
    for( i=j; i < k ; i++ ) {
	if( photo.photo[i].deleted ) continue;
	switch(size) {
	    case 's': image = photo.photo[i].img_s; ptitle = ''; break;
	    case 't': image = photo.photo[i].img_t; ptitle = ''; break;
	    case 'm': image = photo.photo[i].img_m; ptitle = photo.photo[i].title + '<br />'; break;
	    default: image = photo.photo[i].img_s; ptitle = ''; break;
	}
	var id = photo.photo[i].id;
	var secret = photo.photo[i].secret;
	var server = photo.photo[i].server;
//	var photo_url = 'http://flickr.com/photos/' + user.nsid + '/' + id 
	if( user == undefined || 
	    (photo.photo[i].owner != undefined && photo.photo[i].owner != user.nsid ) ) 
	    owner = '<br /><a href="javascript:;" onClick="gotoUser(\'' + photo.photo[i].owner + '\')">' + photo.photo[i].ownername + '</a>';
	else owner = '';
	str += '<p>' + ptitle + '<a href="javascript:;" onClick="displaySingle('+i+')">';
	if( size=='s' ) str += '<img src="'+ image +'" title="'+ photo.photo[i].title+'" width="75" height="75" />';
	else str += '<img src="'+ image +'" title="'+ photo.photo[i].title+'" />';
	str += '</a>' + owner + '</p>';
    }
    photobox.innerHTML = '<h4>' + title + '</h4>' + primary + str + officialURL(photo.flickr_url);
    showStatus('', _gi('photos'));
}

var showDesc = function(result,args) {

    var str = '', nsid='';
    var geotagged=false,lat='',lon='',geoAry,re,geostr='';
    var descBox = _gi('picdesc');
//    var sizeBox = _gi('sizediv');
    var originalsecret = result.originalsecret;
    var originalformat = result.originalformat;
    
    var image_s = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_s.jpg';
    var image_t = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_t.jpg';
    var image_m = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_m.jpg';
    var image = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '.jpg';
    var image_b = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_b.jpg';

    if( originalsecret != null ) {
	var image_o = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + originalsecret + '_o.' + originalformat;
	_gi('origimg').style.display = 'inline';
	_gi('origimg').onclick = function() {
	    _gi('pic').src = 'http://l.yimg.com/www.flickr.com/images/pulser2.gif';
	    _gi('pic').onload = function() {
		_gi('pic').src = image_o;
		_gi('pic').onload = null;
	    }
	    _vsize = 'o';
	}
	if(_vsize == 'o') {
	    _gi('pic').src = 'http://l.yimg.com/www.flickr.com/images/pulser2.gif';
	    _gi('pic').src = image_o;
	}
    } else image_o = '';
    var photo = args[0];
    var x = args[1];

    if( _gi('pic').src.match('loading_photo.gif') ) _gi('pic').src = image;
//    if( photo.photo[x].img_s.match('loading_photo.gif') ) {
	photo.photo[x].img_s = image_s;
	photo.photo[x].img_t = image_t;
	photo.photo[x].img_m = image_m;
	photo.photo[x].img = image;
	photo.photo[x].img_b = image_b;
	photo.photo[x].img_o = image_o;
//    }
    if( user == undefined || result.owner.nsid != user.nsid ) nsid = result.owner.nsid;
    else nsid = user.nsid;

    if( authenticated && result.isfavorite=='1' ) {
	_gi('faves').style.background = '#ff0084';
	photo.photo[x].isfavorite = true;
    } else photo.photo[x].isfavorite = false;
    photo.photo[x].description = result.description;

    str += '<p class="text"><a href="javascript:;" onClick="showPhotoInfo(0)"><b>- Photo Information</b></a></p>';
    str += 'Owner: <a href="javascript:;" onClick="gotoUser(\''+nsid+'\')"><img src="http://flickr.com/buddyicons/' +nsid+ '.jpg" width="24" height="24" /> '+ result.owner.username + '</a><br />';
    var d = new Date(1000*result.dates.posted);
    var postdate = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+' '+d.getHours()+':'+d.getMinutes()+':'+d.getSeconds();
    str += 'Taken on ' + result.dates.taken + '<br />';
    str += 'Posted on ' + postdate + '<br />';
    str += 'Comments: ' + result.comments + '<br />';
    if( result.visibility.ispublic == '1' ) str += 'This photo is public.<br />';
    if( result.visibility.isfriend == '1' && result.visibility.isfamily=='1' ) str += 'Friends and family can see this photo.<br />';
    if( result.visibility.isfriend == '0' && result.visibility.isfamily=='1' ) str += 'Family can see this photo.<br />';
    if( result.visibility.isfriend == '1' && result.visibility.isfamily=='0' ) str += 'Friends can see this photo.<br />';
    if( result.visibility.isfriend == '0' && result.visibility.isfamily=='0' && result.visibility.ispublic == '0' ) str += 'This photo is private.<br />';


    str += 'Tags: ';
    for( var i=0; i<result.tag.length; i++ ) {
        str += '<a href="javascript:;" onClick="showTagPhotos(\''+nsid+'\',\''+result.tag[i].raw+'\')">' +result.tag[i].raw +'</a> ';
//	str += '<br />' + result.tag[i].id + ',' + result.tag[i].raw + ',' + result.tag[i].text + ',' + result.tag[i].author + '<br />';

	if( result.tag[i].raw == 'geotagged' ) geotagged = true;
	re = /geo:lat=(.*)/ig;
	geoAry = re.exec( result.tag[i].raw );
	if( geoAry != null ) lat = geoAry[1];
	re = /geo:long?=(.*)/ig;
	geoAry = re.exec( result.tag[i].raw );
	if( geoAry != null ) lon = geoAry[1];
    }
    if( authenticated && auth_nsid == nsid ) {
	str += '<span id="added_tags"></span>';
	str += '<span id="add_tags" style="display:none">';
	str += '<input id="input_tags" type="text" size="16"><input type="button" value="Save" onClick="addPhotoTags(\'' +result.id+ '\')"><input type="button" value="Cancel" onClick="_gi(\'add_tags\').style.display=\'none\';">';
	str += '</span>';
	str += ' (<a href="javascript:;" onClick="_gi(\'add_tags\').style.display=\'inline\';">add tags</a>)';
    }
    if( geotagged && lat!='' && lon!='' ) {
	geotagged = true;
//	str += '<br />This photo is geotagged. <a href="http://www.geobloggers.com/index.cfm?lat=' + lat + '&lon=' + lon + '" target="_blank">See the photo at Geobloggers</a>.';
	str += '<br />This photo is geotagged. <a href="http://maps.yuan.cc/?service=flickr&photoid=' + result.id + '" target="_blank">See the photo at Yuan.CC Maps</a>.';
    } else geotagged = false;

    str += '<div id="context"></div><div id="favorers"></div><hr style="width:100%;height:1px" />';

    str += '<div id="edit_desc_div" style="display:none">';
    str += '<textarea id="edit_desc_input" rows="6" cols="40">' +result.description+ '</textarea><br />';
    str += '<input type="button" value="SAVE" onClick="savePhotoDesc(1,' +x+ ',\'' +result.id+ '\')"> ';
    str += '<input type="button" value="CANCEL" onClick="savePhotoDesc(0)">';
    str += '</div>';
    if( !authenticated || auth_nsid != nsid ) str += photo.photo[x].description;
    else str += '<div id="photo_desc" onMouseOver="this.style.background=\'#ffffd3\'" onMouseOut="this.style.background=\'#dddddd\'" onClick="editPhotoDesc(' +x+ ',\'' +id+ '\')">&nbsp;' + photo.photo[x].description + '</div>';

    descBox.innerHTML = str;
    if( geotagged ) {
	var w = _gi('photos').clientWidth-30;
	var h = _gi('photos').clientHeight-60;
	if( _gmap ) _gi('gmap').innerHTML = '<img width=' + w + ' height=' + h + ' src="' +loading_photo+ '">';
	mapPic = image_t;
	mapInfo.lat = lat;
	mapInfo.lon = lon;
	mapInfo.title = result.title;
	mapInfo.text = '';
	mapInfo.image = image_t;
	if( getNearBy == 'true' ) mapStr = 'lat=' +lat+ '&lon=' +lon+ '&maxRows=20';
	else mapStr = geoXML(lat,lon,result.title,'',image_t);
	_gi('gmapbutton').style.visibility = 'visible';
	if( _gmap ) initMap();
    } else {
	_gi('gmap').style.display = 'none';
	_gi('gmapbutton').style.display = 'none';
    }
    if( result.note.length > 0 ){
	var str = '';
	var _IE4=(document.all);
	var _notes = new Array();
	var photo_notes = _gi('photo_notes');

	for(var i=0; i<result.note.length; i++ ) {
	    var x = 1*result.note[i].x;
	    var y = 1*result.note[i].y;
	    var w = 1*result.note[i].w;
	    var h = 1*result.note[i].h;
	    var note_text = result.note[i].text;
	    if( nsid != result.note[i].author ) {
		note_text += '<br />- <a href="javascript:;" onClick="gotoUser(\'' +result.note[i].author+ '\')"><i>' + result.note[i].authorname + '</i></a>';
		var note_bgcolor = 'style="background-color:#d0fdaf;"';
	    } else note_bgcolor = 'style="background-color:#ffffd3;"';
	    str += '<div class="photo_note" id="photo_note_' +result.note[i].id+ '" style="left:' +(x+1)+ 'px; top:' +(y+1)+ 'px;"><div class="photo_note_box_div"><div class="photo_note_box_inner_div"><div class="photo_note_box_inner_inner_div"><div style="width:' +(w-4)+ 'px; height:' +(h-4)+ 'px;"></div></div></div></div><div class="photo_note_text_div" style="top:' +(h)+ 'px;"><table class="photo_note_text_table" ' +note_bgcolor+ ' cellpadding="0" cellspacing="0"><tr><td><span style="font-family:Arial,Helvetica,sans-serif;font-size:11px;color:#000;">' +note_text+ '</span></td></tr></table></div></div>';
	    _notes[_notes.length] = 'photo_note_'+result.note[i].id;
	}
	photo_notes.innerHTML = str;
	for(var i=0;i<result.note.length;i++) {
	    _n = _gi(_notes[i]);
	    _n.onmouseover = function() {
		_gi('photo_notes').style.visibility = 'visible';
		this.lastChild.style.display = 'block';
		return true;
	    }
	    _n.onmouseout = function() {
		if(!_IE4) this.lastChild.style.display = 'none';
	    }
	    if(_IE4) _n.lastChild.style.display = 'block';
	}
	_gi('photoImgDiv'+result.id).setAttribute('onMouseOver','showNoteBox()');
	_gi('photoImgDiv'+result.id).setAttribute('onMouseOut','hideNotes()');
    }

    var photo_id = result.id;
    var handle_getAllContexts = function (result,args) {
	str = 'Photoset: ';
	for(var i=0; i< result.set.length; i++) {
	    index = photoset.length;
	    photoset[index] = new Object();
	    photoset[index].primary = '';
	    photoset[index].title = result.set[i].title;
	    str += '<a href="javascript:;" onclick="showSet('+index+',\'' +result.set[i].id+ '\')">' +result.set[i].title+ '</a> ';
	}
	if( authenticated && auth_nsid == nsid ) 
	    str += '<span id="newaddedphotoset"></span><div id="select_set" style="display:none"></div> (<a href="javascript:;" onclick="selectSet(' +photo_id+ ')">add to set</a>)';
	str += '<br />Group: ';
	for(var i=0; i< result.pool.length; i++) {
	    index = groups.length;
	    groups[index] = new Object();
	    groups[index].name = result.pool[i].title;
	    groups[index].nsid = result.pool[i].id;
	    groups[index].flickr_url = 'http://flickr.com/groups/' + groups[index].nsid +'/';
	    str += '<a href="javascript:;" onClick="gotoGroup('+index+',\''+result.pool[i].id+'\')">' + result.pool[i].title + '</a> ';
	}
	if( _gi('context') ) _gi('context').innerHTML = str;
    }
    var args = new Array();
    flickrAPI.photos.getAllContexts(handle_getAllContexts, args, result.id);

    var handle_getFavorites = function (result, args) {
	var str = 'Favorers: ';
	for(var i=0; i<result.person.length; i++) {
	    var nsid = result.person[i].nsid;
	    var username = result.person[i].username;
	    str += '<a href="javascript:;" title="' +username+ '" onClick="gotoUser(\''+nsid+'\')"><img src="http://flickr.com/buddyicons/' +nsid+ '.jpg" width="24" height="24" /></a> ';
	}
	if( _gi('favorers') ) _gi('favorers').innerHTML = str;
    }
    flickrAPI.photos.getFavorites(handle_getFavorites, null, result.id,1,50);

    showStatus('', descBox, '#aaaaaa');
}

function selectSet(photo_id) {

    var i,str;

    _gi('select_set').style.display = 'inline';
    str = '<select id="set_list" onChange="addToSet(' +photo_id+ ')">';
    str += '<option>Select a photoset to add</option>';
    for(i=0; i<photoset.length; i++) {
	str += '<option value="' +photoset[i].id+ '">' +photoset[i].title+ '</option>';
    }
    str += '</select>';
    _gi('select_set').innerHTML = str;

}

function addToSet(photo_id) {

    var index, options = _gi('set_list').options;

    for(var i=0; i<options.length; i++) {
	if( options[i].selected ) {
	    set_id = options[i].value;
	    index = i;
	}
    }
    index--;
    _gi('select_set').style.display = 'none';

    var callback = function(result,args) {
	if( result.ok ) {
	    _gi('newaddedphotoset').innerHTML += '<a href="javascript:;" onclick="showSet('+index+',\'' +photoset[index].id+ '\')">' +photoset[index].title+ '</a> ';
	} else alert('Add to set failure');
    }
    flickrAPI.photosets.addPhoto(callback,null,set_id,photo_id);
}

function loadPhoto(pic) {

    _gi('pic').src = 'http://l.yimg.com/www.flickr.com/images/pulser2.gif';
    _gi('pic').onload = function() {
	_gi('pic').src = pic;
	_gi('pic').onload = null;
    }
}

/*
var getCntx =
function(result) {

    stream = { prev: result.prev, next: result.next};
    showStatus('Loading prev photo...', _gi('photostream'));
    flickrAPI.photos.getInfo(stream.prev.id, stream.prev.secret);
}

var showPrev =
function(result) {

    if( _gi('nextlink') && 
	_gi('nextlink').getAttribute('onClick') == 'loadPageBg' ) {
	showStatus('Loading next photo...', _gi('photostream'));
	flickrAPI.photos.getInfo(stream.next.id, stream.next.secret);
	return;
    }
    var str = '';
//    var image = 'http://photos'+ result.server + '.flickr.com/'+ result.id + '_' + result.secret + '.jpg';
//    var image_s = 'http://photos'+ result.server + '.flickr.com/'+ result.id + '_' + result.secret + '_s.jpg';
    var image = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '.jpg';
    var image_s = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_s.jpg';
    re = /(\w+)'(\w+)/g;
    result.title = str.replace( re, "$1$2"); 
    if( _gi('prevlink').getAttribute('onClick') == 'loadPageBg' ) {
	str += 'loadPageBg(1,' + result.id + ',\'' + result.title + '\',\'' + image + '\');';
	str += 'displaySingle(0,_vsize,\''+ result.id +'\',\''+ result.secret +'\')';
    } else str += 'displaySingle(-1,_vsize,\''+ result.id +'\',\''+ result.secret +'\')';
    _gi('prevlink').setAttribute('onClick',str);
    _gi('previmg').src = image_s;
//    _gi('prefetch').src = image;
    showStatus('Loading next photo...', _gi('photostream'));
    flickrAPI.photos.getInfo(stream.next.id, stream.next.secret);
}

var showNext =
function(result) {

    showStatus('');
    if( _gi('nextlink').getAttribute('onClick') != 'loadPageBg' ) {
	return;
    }
    var str = '';
//    var image = 'http://photos'+ result.server + '.flickr.com/'+ result.id + '_' + result.secret + '.jpg';
//    var image_s = 'http://photos'+ result.server + '.flickr.com/'+ result.id + '_' + result.secret + '_s.jpg';
    var image = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '.jpg';
    var image_s = 'http://static.flickr.com/'+ result.server + '/'+ result.id + '_' + result.secret + '_s.jpg';
    re = /(\w+)'(\w+)/g;
    result.title = str.replace( re, "$1$2"); 
    if( _gi('nextlink').getAttribute('onClick') == 'loadPageBg' ) {
	str += 'loadPageBg(-1,' + result.id + ',\'' + result.title + '\',\'' + image + '\');';
	str += 'displaySingle('+ (perPage-1) +',_vsize,\''+ result.id +'\',\''+ result.secret +'\')';
    } else str += 'displaySingle(-1,_vsize,\''+ result.id +'\',\''+ result.secret +'\')';
    _gi('nextlink').setAttribute('onClick',str);
    _gi('nextimg').src = image_s;
}
*/

function displaySingle(x,size,id,secret) {

    var photobox = _gi('photos');
    var photo_url,image_s,image_t,image_m,str='',pp=-1;
    var prefetch_nextimg='', prefetch_buffer='';
    var nsid, user_id;
    var w,h;

    clearInterval(buffer_handler);
    _gi('prefetch_buffer').innerHTML = '';
    if( !photo.photo[x].owner || photo.photo[x].owner == undefined ) {
	nsid = user.nsid;
	photo.photo[x].ownername = user.username;
    }
    else nsid = photo.photo[x].owner;

    if( x > photo.photo.length-1 ) {
	alert('No such photo');
	return;
    }
    if( !size ) size = _vsize;

    if( typeof(photo.photo[x]) != 'object' ) pp = (x-x%perPage)/perPage+1;
    if( x-1 >= 0 && typeof(photo.photo[x-1]) != 'object' ) pp = ((x-1)-(x-1)%perPage)/perPage+1;
    if( x+1 <= photo.photo.length-1 && typeof(photo.photo[x+1]) != 'object' ) pp = ((x+1)-(x+1)%perPage)/perPage+1;
    if( pp>-1 ) {
	showStatus('Loading new page...', _gi('photos'));
	args = new Array(photo, photo.text, 2, x);
	if(photo.text == 'recent') {
	    flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args, nsid, '', perPage, pp);
	}
	if(photo.text == 'interestingness') {
	    flickrAPI.interestingness.getList(handle_getPhotoStream, args, 'owner_name,icon_server',perPage,pp);
	}
	if(photo.text == 'favorites') {
	    flickrAPI.favorites.getList(handle_getPhotoStream, args, user.nsid,'owner_name,icon_server',perPage,pp);
	}
	if(photo.text == 'group') {
	    flickrAPI.groups.pools.getPhotos(handle_getPhotoStream, args, group_id,'','owner_name,icon_server',perPage,pp);
	}
	if(photo.text == 'tag') {
	    if( _gi('tagsearchall') && _gi('tagsearchall').checked ) user_id='';
	    else user_id = nsid;
	    args = new Array(_lastSearch[0], _lastSearch[1], 2, x);
	    flickrAPI.photos.search(handle_getPhotoStream, args, user_id, photo.tag,'any','','','','','','','owner_name,icon_server',perPage,pp);
	}
	if(photo.text == 'search') {
	    args = new Array(searchResults, photo.text, 1, 'Search Results', 1);
	    flickrAPI.photos.search(handle_getPhotoStream, args, fSearch.nsid, fSearch.tags,fSearch.tag_mode,'','','','','','','owner_name,icon_server',perPage,pp,fSearch.sort,fSearch.privacy_filter);
	}
	return;
    }

    if( x!= -1 ) {
	id = photo.photo[x].id;
	secret = photo.photo[x].secret;
    }
    photo.page = (x-x%perPage)/perPage+1;
    str += '<div id="edit_title_div" style="display:none">';
    str += '<input id="edit_title_input" type="text" size="60"> ';
    str += '<input type="button" value="SAVE" onClick="savePhotoTitle(1,' +x+ ',\'' +id+ '\')"> ';
    str += '<input type="button" value="CANCEL" onClick="savePhotoTitle(0)">';
    str += '</div>';
    if( !authenticated || auth_nsid != nsid ) str += '<h3>' + photo.photo[x].title + '</h3>';
    else str += '<h3 id="photo_title" onMouseOver="this.style.background=\'#ffffd3\'" onMouseOut="this.style.background=\'#f5f5f5\'" onClick="editPhotoTitle(' +x+ ',\'' +id+ '\')">' + photo.photo[x].title + '</h3>';

    // show user icon, only when display everyones' public photos
    if( user==undefined || user.nsid != photo.photo[x].owner && ( user==undefined || user.username==undefined || photo.photo[x].ownername!=user.username )) {
	str += '<p><a href="javascript:;" onClick="gotoUser(\'' + nsid + '\')">';
	str += '<img src="http://flickr.com/buddyicons/' +nsid+ '.jpg" width="48" height="48" /></a><br />';
	str += photo.photo[x].ownername + '</p>';
    }

    if( x == -1 || typeof(photo.photo[x]) != 'object' ) {
	str += '<input type="button" class="button" onClick="slidePlay=2;slideshow('+x+')" value="Slideshow">';
	str += '<br clear="all" />';
	photo_url = 'http://flickr.com/photos/' + nsid + '/' + id; 
	str += '<div><p class="pic"><a href=""><img id="pic" src="' +loading_photo+ '" title="'+ title + '" border=0 /></a></p></div>';
    } else {
	switch(size) {
	    case 's': image = photo.photo[x].img_s; postfix = '_s'; break;
	    case 't': image = photo.photo[x].img_t; postfix = '_t'; break;
	    case 'm': image = photo.photo[x].img_m; postfix = '_m'; break;
	    case '-': image = photo.photo[x].img;   postfix = '';   break;
	    case 'b': image = photo.photo[x].img_b; postfix = '_b'; break;
//	    case 'o': image = photo.photo[x].img_o; postfix = '_o'; break;
	    case 'o': image = 'http://l.yimg.com/www.flickr.com/images/pulser2.gif'; postfix = '_o'; break;
	    default : image = photo.photo[x].img;   postfix = '';   break;
	}
	str += '<div>';
	str += '<input type="button" class="button" onClick="loadPhoto(photo.photo['+x+'].img_s);_vsize=\'s\';" value="Square">';
	str += '<input type="button" class="button" onClick="loadPhoto(photo.photo['+x+'].img_t);_vsize=\'t\';" value="Thumbnail">';
	str += '<input type="button" class="button" onClick="loadPhoto(photo.photo['+x+'].img_m);_vsize=\'m\';" value="Small">';
	str += '<input type="button" class="button" onClick="loadPhoto(photo.photo['+x+'].img);_vsize=\'-\';" value="Medium">';
	str += '<input type="button" class="button" onClick="loadPhoto(photo.photo['+x+'].img_b);_vsize=\'b\';" value="Big">';
	str += '<input id="origimg" type="button" class="button" onClick="_gi(\'pic\').src=\'http://l.yimg.com/www.flickr.com/images/pulser2.gif\';_vsize=\'o\';" value="Orig" style="display:none">';
	if(authenticated && auth_nsid!=nsid) {
	    str += '<br />';
	    str += '<input type="button" class="button" id="faves" onClick="addToFaves('+x+', \''+id+'\')" value="Faves">';
	    str += '<input type="button" class="button" id="copy" onClick="checkPHPSession('+x+', \''+id+'\')" value="Copy">';
	}
	if(authenticated && auth_nsid==nsid) {
	    str += '<input type="button" class="button" id="rotate" onClick="_gi(\'rotate_img\').style.display=\'block\'" value="Rotate">';
	    str += '<input type="button" class="button" id="delete" onClick="deletePhoto('+x+', \''+id+'\')" value="Delete">';
	}
	str += '<input type="button" class="button" onClick="showHTML(\''+nsid+'\',\''+id+'\', \''+image+'\',\''+photo.photo[x].title+'\')" value="HTML">';
	str += '<input type="button" class="button" onClick="slidePlay=2;slideshow('+x+')" value="Slideshow">';
	str += '<input type="button" class="button" onClick="displayPhotos()" value="Photostream">';
	str += '<input id="gmapbutton" type="button" class="button" style="visibility:hidden;" onClick="initMap()" value="GMap">';
	str += '<br clear="all" />';
	str += '<div id="rotate_img" style="display:none">Rotate the photo: <input type="button" class="button" onClick="rotatePhoto('+x+', \''+id+'\',270)" value="Left"><input type="button" class="button" onClick="rotatePhoto('+x+', \''+id+'\',180)" value="Upside Down"><input type="button" class="button" onClick="rotatePhoto('+x+', \''+id+'\',90)" value="Right"></div>';
	str += '<div id="HTML_code"></div>';
	photo_url = 'http://flickr.com/photos/' + nsid + '/' + photo.photo[x].id; 
	if( document.location.href.match(/webdev.yuan.cc\/lfvr/) ) lfvr_url = 'http://webdev.yuan.cc/lfvr/photos/' + nsid + '/' + photo.photo[x].id; 
	if( document.location.href.match(/thirdhand.info\/lfvr/) ) lfvr_url = 'http://thirdhand.info/lfvr/photos/' + nsid + '/' + photo.photo[x].id;
	if( document.location.href.match(/flickr.tw\/lfvr/) )  lfvr_url = 'http://flickr.tw/lfvr/photos/' + nsid + '/' + photo.photo[x].id;
	str += '<div style="margin:5px 5px 2px 5px;padding:0px;">';
	str += '<div id="photo_notes" class="photo_notes"></div>';
	str += '<div id="photoImgDiv' +photo.photo[x].id+ '" class="photoImgDiv" style="display:inline;padding:2px;">';
	str += '<a href="' + photo_url + '" target="_blank">';
	str += '<img id="pic" src="'+ image +'" title="'+ photo.photo[x].title+'" border=0 onload="bufferring( '+x+' ,\''+postfix+'\',2)" /></a>';
	str += '</div></div>';
    }
    str += '<br clear="all">';

//  Build PhotoStream
    if( photo.photo.length > 1 ) {
	nav = _gi('photostream');

	if( !_gi('nav_br') ) {
	    nav_br = _ce('br');
	    nav_br.setAttribute('id','nav_br');
	    nav_br.setAttribute('clear','all');
	} else nav_br = _gi('nav_br');
	if( !_gi('nextlink') ) {
	    nav_div1 = _ce('span');
	    nav_div1.setAttribute('id','nav_div1');
//	    nav_div1.setAttribute('style','float:left;text-align: center; margin:5px');
	    nav_div1.style.display = 'inline';
	    var nav_next = _ce('a');
	    nav_next.setAttribute('id','nextlink');
	    nav_next.setAttribute('accesskey','+');
	    nav_next.href = 'javascript:;';
	    nav_div1.appendChild(nav_next);
//	    nav.appendChild(nav_div1);
	    _gi('nav_td1').appendChild(nav_div1);
	} else nav_next = _gi('nextlink');
	if( !_gi('nextimg') ) {
	    var nav_nextimg = _ce('img');
	    nav_nextimg.style.border = 0;
	    nav_nextimg.style.width = '75px';
	    nav_nextimg.style.height = '75px';
	    nav_nextimg.setAttribute('id','nextimg');
	    nav_next.appendChild(nav_nextimg);
	    nav_next.appendChild(_ce('br'));
	    nav_next_text = _ct('Next');
	    nav_next.appendChild(nav_next_text);
	} else nav_nextimg = _gi('nextimg');
	if( photo.text == 'recent' ) nav_next_text.data = 'Next';
	else nav_next_text.data = 'Prev';

	if( x>0 && x<photo.photo.length && typeof(photo.photo[x-1]) == 'object' ) {
	    nav_next.onclick = function() {displaySingle(x-1); }
	    nav_nextimg.src = photo.photo[x-1].img_s;
	} else if( x==0 ) {
	    nav_next.onclick = null;
	    if( photo.text == 'recent' ) nav_nextimg.src = '/lfvr/placeholder_last_photo.gif';
	    else nav_nextimg.src = '/lfvr/placeholder_first_photo.gif';
	} else {
	    nav_next.onclick = loadPageBg;
	    nav_nextimg.src = loading_photo;
	}

	if( !_gi('prevlink') ) {
	    nav_div2 = _ce('span');
	    nav_div2.setAttribute('id','nav_div2');
//	    nav_div2.setAttribute('style','text-align: center; margin:5px');
	    nav_div2.style.display = 'inline';
	    var nav_prev = _ce('a');
	    nav_prev.setAttribute('id','prevlink');
	    nav_prev.setAttribute('accesskey','-');
	    nav_prev.href = 'javascript:;';
	    nav_div2.appendChild(nav_prev);
//	    nav.appendChild(nav_div2);
	    _gi('nav_td2').appendChild(nav_div2);
	} else nav_prev = _gi('prevlink');
	if( !_gi('previmg') ) {
	    var nav_previmg = _ce('img');
	    nav_previmg.style.border = 0;
	    nav_previmg.style.width = '75px';
	    nav_previmg.style.height = '75px';
	    nav_previmg.setAttribute('id','previmg');
	    nav_prev.appendChild(nav_previmg);
	    nav_prev.appendChild(_ce('br'));
	    nav_prev_text = _ct('Prev');
	    nav_prev.appendChild(nav_prev_text);
	} else nav_previmg = _gi('previmg');
	if( photo.text == 'recent' ) nav_prev_text.data = 'Prev';
	else nav_prev_text.data = 'Next';

	if( x>=0 && x<photo.photo.length-1 && typeof(photo.photo[x+1]) == 'object' ) {
	    nav_prev.onclick = function() { displaySingle(x+1); }
	    nav_previmg.src = photo.photo[x+1].img_s;
	} else if( x==photo.photo.length-1 ) {
	    if( photo.text == 'recent' ) nav_previmg.src = '/lfvr/placeholder_first_photo.gif';
	    else nav_previmg.src = '/lfvr/placeholder_last_photo.gif';
	} else {
	    nav_prev.onclick = loadPageBg;
	    nav_previmg.src = loading_photo;
	}

	showPhotoStream(1,photo.text);
    }
//  End of PhotoStream

    str += '<div id="gmap"></div>';
    str += '<div id="panel"> </div>';
    str += '<div id="metapanel"></div>';
    str += '<div id="permalink"></div>';
    str += '<div id="printheader"></div>';
    str += '<div id="picdesc"></div>';
    str += '<div id="piccomments"></div>';

    if( login && login == user.email ) {
	str += 'Image URL: <input type="text" size=70 value="' + image + '"><br />';
	str += 'Photo URL: <input type="text" size=70 value="' + photo_url + '">';
    }
//    photobox.innerHTML = str + officialURL(photo_url) + prefetch_nextimg;
    photobox.innerHTML = str + officialURL(photo_url, lfvr_url);

    __photoInfo = function () {
	showStatus('Loading photo information ...', _gi('picdesc'));
	args = new Array(photo,x);
	flickrAPI.photos.getInfo(showDesc, args, id,secret);
    }

    __photoComments = function() {
	showStatus('Loading photo comments ...', _gi('piccomments'));
	args = new Array();
	args[0] = id;
	flickrAPI.photos.comments.getList(showComments_callback, args, id);
    }

    if( _photoInfo ) __photoInfo();
    else {
	_gi('gmapbutton').style.visibility = 'hidden';
	_gi('gmap').style.display = 'none';
	showPhotoInfo(0);
    }

    if( _photoComments ) __photoComments();
    else showPhotoComments(0);
}

var showComments_callback = function(results,args) {

    var str='';
    var box = _gi('piccomments');
    showStatus('', box, '#aaaaaa');

    var comments = results.comments;
    str += '<p class="text"><a href="javascript:;" onClick="showPhotoComments(0)"><b>- Photo Comments</b></a></p>';
    str += '<table>';
    for(var i=0;i<comments.length;i++) {
	username = comments[i].authorname;
	userpage = 'http://flickr.com/photos/' + comments[i].author;
	text = comments[i].comment;
	dt = new Date(1000*comments[i].datecreate);
	permalink = comments[i].permalink;

	str += '<tr valign="top"><td style="padding-right: 5px;">';
	str += '<a href="javascript:;" onClick="searchUser(\'' +username+ '\')"><img id="icon_' +comments[i].id+ '" src="http://flickr.com/buddyicons/' +comments[i].author+ '.jpg" width="48" height="48" align="left" /></a>';
	str += '</td><td><h4><a href="javascript:;" onClick="searchUser(\'' +username+ '\')">' +username+ '</a> &nbsp;';
	str += '<img id="pro_' +comments[i].id+ '" src="http://flickr.com/images/badge_pro.gif" width="20" height="12" alt="Pro User" style="vertical-align: bottom; border: none; display:none;" />&nbsp; says:</h4>';
	str += '<p class="text" style="text-align:left;">' +text+ '<br />';
	str += '<span class="PostDateTime">' +dt.toLocaleString()+ ' ( <a href="' +permalink+ '" class="PostLinks" target="_blank">permalink</a> )</span>';
	str += '</p><br /></td></tr>';
    }
    if( authenticated ) {
    str += '<tr valign="top"><td style="padding-right: 5px;" colspan="2">';
    str += '<div id="new_comment"><h4>Add your comment</h4>';
    str += '<textarea id="comment_text" cols="40" rows="4"></textarea><br />';
    str += '<input type="button" value="Post Comment" onClick="postComment(\'' +args[0]+ '\')">';
    str += '</div></td></tr>';
    }
    str += '</table>';
    box.innerHTML = str;
}

function showHTML(owner,photo_id, img,title) {

    var str = '<a href=&quot;http://www.flickr.com/photo.gne?id=' +photo_id+ '&quot; title=&quot;'+title+'&quot;><img src=&quot;'+img+'&quot; title=&quot;'+title+'&quot; alt=&quot;'+title+'&quot; /></a>';
    _gi('HTML_code').innerHTML = '<input type="text" size="90" value="'+str+'">';
}

function postComment(photo_id) {

    var comment = _gi('comment_text').value;
    var args = new Array();
    showStatus('Post comment ...', _gi('piccomments'));
    var callback = function() {
//	showStatus('',_gi('piccomments'));
	var args = new Array();
	args[0] = photo_id;
	flickrAPI.photos.comments.getList(showComments_callback, args, photo_id);
    }
    flickrAPI.photos.comments.addComment( callback, args, photo_id, comment);
}

function editPhotoTitle(index, photo_id) {

    showPhotoInfo(1);
    _gi('edit_title_div').style.display = 'block';
    _gi('edit_title_div').style.marginTop = '1em';
    _gi('edit_title_div').style.marginBottom = '1em';
    _gi('edit_title_input').value = photo.photo[index].title;
    _gi('photo_title').style.display = 'none';
}

function savePhotoTitle(flag, index, photo_id) {

    if(flag) {
	var title = escape(_gi('edit_title_input').value);
	var desc = escape(photo.photo[index].description);
	var title = _gi('edit_title_input').value;
	var desc = photo.photo[index].description;
	var callback = function(result) {
	    if( result.ok ) {
		photo.photo[index].title = _gi('edit_title_input').value;
		_gi('photo_title').innerHTML = _gi('edit_title_input').value;
	    }
	    showStatus('', _gi('photos'));
	}
	showStatus('Save photo title ...', _gi('photos'));
	flickrAPI.photos.setMeta(callback, null, photo_id,title,desc);
    }
    _gi('edit_title_div').style.display = 'none';
    _gi('photo_title').style.display = 'block';
}

function editPhotoDesc(index, photo_id) {

    _gi('edit_desc_div').style.display = 'block';
    _gi('edit_desc_div').style.marginTop = '1em';
    _gi('edit_desc_div').style.marginBottom = '1em';
    _gi('edit_desc_input').value = photo.photo[index].description;
    _gi('photo_desc').style.display = 'none';
}

function savePhotoDesc(flag, index, photo_id) {

    if(flag) {
	var title = photo.photo[index].title;
	var desc = _gi('edit_desc_input').value;
	var callback = function(result) {
	    if( result.ok ) {
		photo.photo[index].description = _gi('edit_desc_input').value;
		_gi('photo_desc').innerHTML = _gi('edit_desc_input').value;
	    }
	    showStatus('', _gi('picdesc'));
	}
	showStatus('Save photo description ...', _gi('picdesc'));
	flickrAPI.photos.setMeta(callback, null, photo_id,title,desc);
    }
    _gi('edit_desc_div').style.display = 'none';
    _gi('photo_desc').style.display = 'block';
}

function addPhotoTags(photo_id) {

    var tags = _gi('input_tags').value;

    var callback = function(result) {
	if(result.ok) {
	    _gi('added_tags').innerHTML += tags;
	    _gi('add_tags').style.display = 'none';
	} 
    }
    flickrAPI.photos.addTags(callback, null, photo_id,tags);
}

function fetch_done(x,postfix,b_size) {
    var el = _gi('pf_' +x);
    if(el) el.style.color = '#00ff00';
    photo.photo[x].loaded = true;
}

function bufferring(x,postfix,b_size) {
    var b,prefetch_buffer='',prefetch_nextimg='';

    if( _vsize == 'o' ) return;
    clearInterval(buffer_handler);
    photo.photo[x].loaded = true;
    for(var s=x-b_size;s<=x+b_size;s++) {
	if( photo.photo[s] != undefined ) {
	    eval( 'prefetch_img = photo.photo[s].img' + postfix );
	    if( s==x ) {
		prefetch_nextimg += '<img style="display:none" src="' + prefetch_img + '" />';
		prefetch_buffer += '<span id="pf_' +s+ '" style="color:#00AA00;font-size:1.5em;font-weight:bold;">.</span>';
	    } else {
		prefetch_nextimg += '<img style="display:none" src="' + prefetch_img + '" onLoad="fetch_done('+s+',\''+postfix+'\','+b_size+')" />';
		prefetch_buffer += '<span id="pf_' +s+ '" style="color:#FF0000">.</span>';
	    }
	}
    }
    _gi('prefetch_buffer').innerHTML = prefetch_buffer;
    b = _gi('buffer');
    if( !b ) {
	b = _ce('div');
	b.setAttribute('id','buffer');
	b.style.display = 'none';
	document.body.appendChild(b);
    }
    b.innerHTML = prefetch_nextimg;

    buffer_handler = setInterval('incr_buffer('+x+',"'+postfix+'",'+ b_size +')', 500);
}

function incr_buffer(x,postfix,b_size) {

    if( b_size*2 >= buffer_max ) {
	clearInterval(buffer_handler);
	return;
    }
    for(var i=x-b_size; i<=x+b_size; i++) {
	if( photo.photo[i] && !photo.photo[i].loaded ) return;
    }
    clearInterval(buffer_handler);
    if( b_size*2 < buffer_max ) bufferring(x,postfix,b_size+3);

}

function showPhotoStream(flag,order) {

    var nav = _gi('photostream');
    var nav_show = _gi('showstream');
    var nav_toggle = _gi('nav_toggle');

    if( !nav_div1 || !nav_div2 ) return;
    if( flag==0 ) {
	if( nav ) {
/*
	    if(nav_div1 && nav_div1.parentNode) nav_div1.parentNode.removeChild(nav_div1);
	    if(nav_div2 && nav_div2.parentNode) nav_div2.parentNode.removeChild(nav_div2);
*/
	    _gi('photostream_table').style.display = 'none';
	    _gi('prefetch_buffer').style.display = 'none';
	    nav_toggle.innerHTML = '+';
	    nav_toggle.onclick = function() { showPhotoStream(1,order); }
	}
	_photoStream=0;
    } else {
	if( nav ) {
/*
	    if( order == 'recent' ) {
		nav.appendChild(nav_div2);
		nav.appendChild(nav_div1);
		nav.appendChild(nav_br);
	    } else {
		nav.appendChild(nav_div1);
		nav.appendChild(nav_div2);
		nav.appendChild(nav_br);
	    }
*/
	    _gi('photostream_table').style.display = 'block';
	    _gi('prefetch_buffer').style.display = 'block';
	    nav_toggle.innerHTML = '-';
	    nav_toggle.onclick = function() { showPhotoStream(0,order); }
	}
	_photoStream=1;
    }
}

function showPhotoInfo(flag) {

    var box = _gi('picdesc');

    if( flag==0 ) {
	box.innerHTML = '<p class="text"><a href="javascript:;" onClick="showPhotoInfo(1)"><b>+ Photo Information</b></a></p>';
	_photoInfo=0;
    } else {
	_photoInfo=1;
	__photoInfo();
    }
}

function showPhotoComments(flag) {

    var box = _gi('piccomments');

    if( flag==0 ) {
	box.innerHTML = '<p class="text"><a href="javascript:;" onClick="showPhotoComments(1)"><b>+ Photo Comments</b></a></p>';
	_photoComments=0;
    } else {
	_photoComments=1;
	__photoComments();
    }
}

function officialURL(url, lfvr_url) {

    if( url == undefined ) return '';
    var str = '<img width=640 height=0 src="' +loading_photo+ '">';
    str += '<div style="float:right;margin:20px;">';
    if( lfvr_url ) str += '<a href="' +lfvr_url+ '">Link to this page</a>. ';
    str += 'See the <a href="' + url + '">official page in <font color="#0063DC">Flick</font><font color="#FF0084">r</font></a>. ';
    str += '</div>';
    return str;
}

function changeImgSize(size) {
    SetCookie('photo_size', size);
    _size = size;
    displayPhotos(_size);
}

function changeSet(x) {
    flickr_photoset_id = x.value;
    showStatus('Loading ' + user.username + '\'s photo set ...', _gi('photos'));
    flickrAPI.photosets.getPhotos(handle_photosets_getPhotos, null, flickr_photoset_id,'');
}

function changeBgcolor(x) {
    x.style.textDecoration = 'none';
}

function changeFont(x,flag) {
    if( flag=='in' ) {
	x.style.backgroundColor = '#ffffff';
    }
    if( flag=='out' ) {
	x.style.textDecoration = 'none';
	x.style.backgroundColor = '#e4e4e4';
    }
}

function searchUser(username) {

    var str = '';
    var screen;

    if( username ) screen = username;
    else screen = _gi('screen').value;
    if( screen == '__home__' ) screen = GetCookie('start_user');
    if( !screen ) return;

    showStatus('Searching user ' + screen + ' ...', _gi('userinfo'));
    var args = new Array(true, true, true, true, true, true, true);
    flickrAPI.people.findByUsername(handle_findUser, args, screen);

    return false;
}

function showPhotoSet(flag) {
    if( !photosetBox ) return;
    if( flag == 1 ) {
	photosetBox.innerHTML = photosetBoxStr;
	photosetBoxOpen = 1;
    }
    if( flag == 0 ) {
	photosetBox.innerHTML = '<a href="javascript:;" onClick="showPhotoSet(1)">+ <b>Photo Sets</b></a><br />';
	photosetBoxOpen = 0;
    }
    if( flag == -1 ) {
	if( photosetBoxOpen == 0 ) photosetBoxStr = '<a href="javascript:;" onClick="showPhotoSet(1)">+ <b>Photo Sets</b></a><br />';
	if( photosetBoxOpen == 1 ) photosetBoxStr = '<a href="javascript:;" onClick="showPhotoSet(0)">- <b>Photo Sets</b></a><br />';
	showPhotoSet(photosetBoxOpen);
    }
}

function showContact(flag) 
{
    if( !contactBox ) return;
    if( flag == 1 ) {
	contactBox.innerHTML = contactBoxStr;
	contactBoxOpen = 1;
	_gi('contactctr').innerHTML = '<a href="javascript:;" onClick="showContact(0)">-</a> <a href="javascript:;" onClick="displayContacts(0)"><b>Contacts</b></a><br />';
	_gi('contactreload').innerHTML = '<a href="javascript:;" onClick="reloadContact()">Reload</a>';
    }
    if( flag == 0 ) {
	_gi('contactctr').innerHTML = '<a href="javascript:;" onClick="showContact(1)">+</a> <a href="javascript:;" onClick="displayContacts(0)"><b>Contacts</b></a><br />';
	contactBox.innerHTML = '';
	contactBoxOpen = 0;
    }
    if( flag == -1 ) {
	contactBoxStr = '';
	showContact(contactBoxOpen);
    }
}

function showGroups(flag) 
{
    if( !groupBox ) return;
    if( flag == 1 ) {
	groupBox.innerHTML = groupBoxStr;
	groupBoxOpen = 1;
    }
    if( flag == 0 ) {
	groupBox.innerHTML = '<a href="javascript:;" onClick="showGroups(1)">+ <b>Groups</b></a><br />';
	groupBoxOpen = 0;
    }
    if( flag == -1 ) {
	groupBoxStr = '';
	if( groupBoxOpen == 0 ) groupBox.innerHTML = '<a href="javascript:;" onClick="showGroups(1)">+ <b>Groups</b></a><br />';
	if( groupBoxOpen == 1 ) groupBox.innerHTML = '<a href="javascript:;" onClick="showGroups(0)">- <b>Groups</b></a><br />';
    }
}

function showComments(flag, str) 
{
    if( !commentBox ) return;
    if( flag == 1 ) {
	commentBox.innerHTML = '<a href="javascript:;" onClick="showComments(0)">- <b>Comments</b></a><br />' + commentBoxStr;
	commentBoxOpen = 1;
    }
    if( flag == 0 ) {
	commentBox.innerHTML = '<a href="javascript:;" onClick="showComments(1)">+ <b>Comments</b></a><br />';
	commentBoxOpen = 0;
    }
    if( flag == -1 ) {
	commentBoxStr = '';
	if( commentBoxOpen == 0 ) commentBox.innerHTML = '<a href="javascript:;" onClick="showComments(1)">+ <b>Comments</b></a><br />';
	if( commentBoxOpen == 1 ) commentBox.innerHTML = '<a href="javascript:;" onClick="showComments(0)">- <b>Comments</b></a><br />';
    }
    if( flag == 2 ) {
	photo = comments;
	_gi('photos').innerHTML = str;
    }
}

function showGuestbook(flag) 
{
    if( !guestbookBox ) return;
    if( flag == 1 ) {
	guestbookBox.innerHTML = guestbookBoxStr;
	guestbookBoxOpen = 1;
    }
    if( flag == 0 ) {
	guestbookBox.innerHTML = '<a href="javascript:;" onClick="showGuestbook(1)">+ <b>Discuss</b></a><br />';
	guestbookBoxOpen = 0;
    }
    if( flag == -1 ) {
	guestbookBoxStr = '';
	if( guestbookBoxOpen == 0 ) guestbookBox.innerHTML = '<a href="javascript:;" onClick="showGuestbook(1)">+ <b>Discus</b></a><br />';
	if( guestbookBoxOpen == 1 ) guestbookBox.innerHTML = '<a href="javascript:;" onClick="showGuestbook(0)">- <b>Discus</b></a><br />';
    }
}

function showDonation(flag) 
{
    if( !donationBox ) return;
    if( flag == 1 ) {
	donationBox.innerHTML = donationBoxStr;
	donationBoxOpen = 1;
    }
    if( flag == 0 ) {
	donationBox.innerHTML = '<a href="javascript:;" onClick="showDonation(1)">+ <b>Donation</b></a><br />';
	donationBoxOpen = 0;
    }
    if( flag == -1 ) {
	donationBoxStr = '';
	if( donationBoxOpen == 0 ) donationBox.innerHTML = '<a href="javascript:;" onClick="showDonation(1)">+ <b>Donation</b></a><br />';
	if( donationBoxOpen == 1 ) donationBox.innerHTML = '<a href="javascript:;" onClick="showDonation(0)">- <b>Donation</b></a><br />';
    }
}

function displayContacts(flag, count) {

    var args;

    if( flag==0 && contact.length == 0 ) {
	_gi('photos').innerHTML = user.username + ' hasn\'t listed any contacts yet.';
	return;
    }
//    if( flag==0 && contactIconStr!='' ) {
    if( flag==0 ) {
	showStatus('',_gi('photos'));
	var url = 'http://flickr.com/people/' + user.nsid + '/contacts/';
	displayUsers( contactIconStr, contact, url);
	return;
    }
    if( flag==1 && _contact_count==0 || flag==0 && contactIconStr=='') {
	if( count > 0 ) _contact_count = count;
	else _contact_count = 5;
	getMoreContact = true;
	showStatus('Got ' + contact[_contact].username + '\'s icon ...',_gi('photos'));
	flickrAPI.people.getInfo(handle_contact_getInfo, null, contact[_contact].nsid);
    } else {
	contactIconStr = '';
	if( _contact >=0 ) {
	    contactIconStr += 'More <a href="javascript:;" onClick="displayContacts(1,1)">1</a>, <a href="javascript:;" onClick="displayContacts(1,5)">5</a>, <a href="javascript:;" onClick="displayContacts(1,10)">10</a>, <a href="javascript:;" onClick="displayContacts(1,20)">20</a>, <a href="javascript:;" onClick="displayContacts(1,50)">50</a>, <a href="javascript:;" onClick="displayContacts(1,100)">100</a> contacts...';
	    contactIconStr += ' (or <a href="javascript:;" onClick="displayContacts(1,' + contact.length + ')">all ' + contact.length + ' contacts</a>';
	    if( _contact > 100 ) contactIconStr += ', but very slow)';
	    else contactIconStr += ')';
	} else contactIconStr += 'All Contacts of ' + user.username + ': <br />';
	displayContacts(0);
    }
}

function compareCount(a, b) {
    return a.count - b.count;
}
function compareName(a, b) {
    var tmp = new Array(a.username,b.username);
    tmp.sort();
    if( tmp[0] == a.username ) {
	return 1;
    } else {
	return -1;
    }
}

function displayUsers(header,list, url,page) {

    var str='',str2='';
    var photoBox = _gi('photos');
    var tmplist = new Array();
    var pages = (list.length-list.length%perPage)/perPage+ ( (list.length%perPage>0)?1:0) ;

    if( page == undefined ) page = 1;
    j = (page==1) ? 0 : (page-1)*perPage;
    k = (list.length>page*perPage) ? page*perPage : list.length;
// alert(max + ',' + list.length);
//    for( var i=0; i<list.length; i++) tmplist[i] = list[i];
    for( var i=j; i<k; i++) tmplist[i-j] = list[i];
    switch(_userSort) {
	case 1: tmplist.sort(compareCount); break;
	case 2: tmplist.sort(compareName); break;
	default: break;
    }

    _userSort = 0;
    _user = list;
    _usermore = header;
    str2 += '<div class="sizediv">';
    str2 += '<input type="button" class="button" style="float:left;" onClick="_usertype=1;displayUsers(_usermore, _user)" value="List"> ';
    str2 += '<input type="button" class="button" style="float:left;" onClick="_usertype=2;displayUsers(_usermore, _user)" value="Icon"> ';
    str2 += '<input type="button" class="button" style="float:left;" onClick="_usertype=3;displayUsers(_usermore, _user)" value="Detail"> ';
    if( header != 'History' )
    str2 += '<input type="button" class="button" style="float:left;" onClick="showContactPhotos()" value="Photos"> ';
    str2 += '<input type="button" class="button" style="float:right;" onClick="_userSort=0;displayUsers(_usermore, _user)" value="Raw order"> ';
    str2 += '<input type="button" class="button" style="float:right;" onClick="_userSort=1;displayUsers(_usermore, _user)" value="Sort by count"> ';
    str2 += '<input type="button" class="button" style="float:right;" onClick="_userSort=2;displayUsers(_usermore, _user)" value="Sort by name"> ';
    str2 += '</div>';
    str2 += '<br clear="all" />';

    for( var i=tmplist.length-1; i>=0 && _usertype==1; i-- ) {
	if( tmplist[i].iconserver ) {
	    if( tmplist[i].removable )
		str += '[<a href="javascript:;" onClick="_user['+i+'].del('+i+')">X</a>] ';
	    str += '<a href="javascript:;" onClick="gotoUser(\'' + tmplist[i].nsid + '\')">' + tmplist[i].username + '</a>: ';
	    str += tmplist[i].count + ' photos';
	    if( tmplist[i].ispro == '1' ) str += ' <font style="color:#0063DC"><small><i><b>pro</b></i></small></font><br />';
	    else str += '<br />';
	} 
    }
    for( var i=tmplist.length-1; i>=0 && _usertype==2; i-- ) {
	if( tmplist[i].iconserver ) {
	    str += '<p><a href="javascript:;" onClick="gotoUser(\'' + tmplist[i].nsid + '\')">';
	    if( tmplist[i].iconserver > 0 ) 
		str += '<img src="http://static.flickr.com/' + tmplist[i].iconserver + '/buddyicons/' + tmplist[i].nsid + '.jpg" width="48" height="48" /></a> ';
	    else str += '<img src="http://flickr.com/images/buddyicon.jpg" width="48" height="48"></a> ';
	    str += '<br /><a href="javascript:;" onClick="gotoUser(\'' + tmplist[i].nsid + '\')">';
	    if( tmplist[i].ispro == '1' ) 
		str += '<font color="#0063DC"><i><b>' + tmplist[i].username + '</b></i></font>'; 
	    else str += tmplist[i].username;
	    str += '</a>';
	    if( tmplist[i].removable )
		str += ' [<a href="javascript:;" onClick="_user['+i+'].del('+i+')">X</a>]';
	    if( 1*tmplist[i].count > 0 )
		str += '<br />' + tmplist[i].count + ' photos';
	    str += '</p>';
	} 
    }
    for( var i=tmplist.length-1; i>=0 && _usertype==3; i-- )
	if( tmplist[i].iconserver ) str += namecard(tmplist[i],i);

    var str3 = '<br clear="all" />';
    photoBox.innerHTML = header + '<br /><br />' + str2 + str + str3 + officialURL(url) + str3;

    if( pages > 1 ) {
	var more = _ce('a');
	if( page < pages ) {
	    pp = page+1;
	    text = 'Next Page';
	} else {
	    pp = 1;
	    text = 'First Page';
	}
	more.href = 'javascript:;';
	more.onclick = function() {
	    displayUsers(header,list,url,pp);
	}
	more.innerHTML = text;
	photoBox.appendChild(more);
	photoBox.appendChild(_ct(' ( Page ' + page + ', Total ' +list.length+ ' users) ' ));
    }
}

function namecard(u,index,target) {

    var str='',fontstyle,cache;

    if( u.ispro == '1' ) fontstyle = '<font style="color:#0063DC;font-style:italic;font-weight:bold;">';
    else fontstyle = '<font>';
    if( u.realname == null ) u.realname = '';
    if( u.location == null ) u.location = '';
//    str += '<p style="text-align:left;">';
    str += '<table border=0 cellpadding=0><tr><td>';
    if( target == 'website' )
	 str += '<a href="http://flickr.com/photos/' + user.nsid + '/">';
    else str += '<a href="javascript:;" onClick="gotoUser(\'' + u.nsid + '\')">';
    if( u.iconserver > 0 ) str += '<img src="http://static.flickr.com/' +u.iconserver+ '/buddyicons/' + u.nsid + '.jpg" width="48" height="48" /></a> ';
    else str += '<img src="http://flickr.com/images/buddyicon.jpg"></a> ';
    str += '</td><td>';
    if( target == 'website' )
	 str += '<a href="http://flickr.com/photos/' + user.nsid + '/">' + fontstyle + user.username + '</font></a><br />' + user.realname;
    else str += '<a href="javascript:;" onClick="gotoUser(\'' + u.nsid + '\')">' + fontstyle + u.username + '</font></a><br />' + u.realname;
    if( u.ispro == '1' ) str += '<br />' + fontstyle + 'pro</font>';
    if( authenticated && auth_nsid != u.nsid ) {
	if( auth_contact[u.nsid] != undefined ) {
	    if( u.ispro == '1' ) str += ', My ';
	    else str += '<br />My ';
	    if( auth_contact[u.nsid].friend == '1' ) str += ' friend';
	    if( auth_contact[u.nsid].family == '1' ) str += ' family';
	    if( auth_contact[u.nsid].family == '0' && auth_contact[u.nsid].friend == '0' ) str += 'contact';
	} else {
	    if( u.ispro == '1' ) str += ', ';
	    else str += '<br /> ';
	    str += '<a href="javascript:;" onclick="addContact(\'' +u.nsid+ '\')">Add as a contact</a>';
	}
    }
    str += '<br /><a href="' + user.gmifurl + '"><small><i>GMiF</i></small></a> ' ;
    str += '<a href="javascript:;" onclick="profile(\'' +u.nsid+ '\')"><small><i>Profile</i></small></a>';
    str += '</td></tr></table>';
    if( u.location != '' ) str += u.location + '<br />\n';
    if( u.removable && index>=0 )
	str += '[<a href="javascript:;" onClick="_user['+index+'].del('+index+')">X</a>] ';
    str += u.count + ' photos&nbsp;&nbsp;&nbsp;';
    str += '<br />\n';
    if( u.firstdatetaken ) str += '<span style="font-size:9px;">First taken on ' + u.firstdatetaken + '<br />';
    if( u.firstdate ) {
	var d = new Date(1000*u.firstdate);
	var firstdate = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+' '+d.getHours()+':'+d.getMinutes()+':'+d.getSeconds();
	str += 'First post on ' + firstdate + '</span>'; 
    }
    str += '<br /><a href="javascript:;" onClick="setDefaultUser(\'' +u.username+ '\')">Set startup page</a>&nbsp;&nbsp;&nbsp;';
//    str += '<a href="javascript:;" onClick="searchPhotos()">Search photos</a><br />';
    if( GetCookie('flickr_cache') == '0' ) cache='';
    else cache = 'checked';
    str += ' <input id="cache1" type="checkbox" '+cache+' onClick="cacheSwitch(this)"><span style="font-size:9px;"> Enable Cache</span>';
//    str += '</p>\n';

    return str;
}

function addContact(id) {

    var photobox = _gi('photos');

    var w = photobox.style.width;
    var str = '<div><iframe width="100%" height="80%" src="http://flickr.com/people/' +id+ '/relationship/"></iframe></div>';
    photobox.innerHTML = str;
}

function profile(id) {

    var photobox = _gi('photos');

    var w = photobox.style.width;
    var str = '<div><iframe width="100%" height="80%" src="http://flickr.com/people/' +id+ '/"></iframe></div>';
    photobox.innerHTML = str;
}

function showTags(flag) {
    if( !tagBox ) return;
    if( flag == 1 ) {
	tagBox.innerHTML = tagBoxStr;
	tagBoxOpen = 1;
    }
    if( flag == 0 ) {
	tagBox.innerHTML = '<a href="javascript:;" onClick="showTags(1)">+</a> <a href="javascript:;" onClick="showAllTags()"><b>Tags</b></a><br />';
	tagBoxOpen = 0;
    }
    if( flag == -1 ) {
	tagBoxStr = '';
	if( tagBoxOpen == 0 ) tagBox.innerHTML = '<a href="javascript:;" onClick="showTags(1)">+</a> <a href="javascript:;" onClick="showAllTags()"><b>Tags</b></a><br />';
	if( tagBoxOpen == 1 ) tagBox.innerHTML = '<a href="javascript:;" onClick="showTags(0)">-</a> <a href="javascript:;" onClick="showAllTags()"><b>Tags</b></a><br />';
    }
}

function showAllTags() {
    var photobox = _gi('photos');
    var popular = _ce('div');
    var alltags = _ce('div');

    photobox.innerHTML = '';
    popular.setAttribute('style', 'line-height:1.2;padding:5px 30px 5px 30px;');
    popular.setAttribute('id', 'populartags');
    popular.innerHTML = ' Loading tags, please wait..... ';
    alltags.setAttribute('style', 'padding:5px 20px 5px 20px;');
    alltags.setAttribute('id', 'alltags');
    photobox.appendChild(popular);
    photobox.appendChild(alltags);

    showStatus('Loading user\'s all tags ...', _gi('photos'));
    var handle_getPopularTags = function (result,args) {
	var photobox = _gi('populartags');
	var str='<strong>Popular Tags</strong> <br /><center>';
	var max=0;
	tags = result;
	tags.text = 'tag';
	for( var i=0; i < tags.tag.length; i++) max = (max>(1*tags.tag[i].count)) ? max : 1*tags.tag[i].count;
	for( var i=0; i < tags.tag.length; i++) {
	    size = 1+1*tags.tag[i].count/max*3 + 'em';
	    str += '<a href="javascript:;" style="font-size:' + size + ';text-decoration:none;" title="' +tags.tag[i].count+ ' photos" onClick="showTagPhotos(\''+user.nsid+'\',\''+tags.tag[i].name+'\')">' + tags.tag[i].name + '</a> ... ';
	}
	photobox.innerHTML = str + '</center><hr>';
//	showStatus('', _gi('photos'));
    }
    var handle_getAllTags = function (result,args) {
	var photobox = _gi('alltags');
	tags = result;
	tags.text = 'tag';
	var str='<strong>All Tags</strong> <br />';
	for( var i=0; i < tags.tag.length; i++) {
	    if( i>0 && tags.tag[i].name[0] != tags.tag[i-1].name[0] ) str += '<br />';
	    str += '<a href="javascript:;" onClick="showTagPhotos(\''+user.nsid+'\',\''+tags.tag[i].name+'\')">' + tags.tag[i].name + '</a> ';
	}
	showStatus('', _gi('photos'));
	tagAllStr = str;
	photobox.innerHTML = tagAllStr;
    }
    flickrAPI.tags.getListUserPopular(handle_getPopularTags, null, user.nsid,50);
    flickrAPI.tags.getListUser(handle_getAllTags, null, user.nsid);
}

function gotoUser(nsid) {
    var args;

    showPhotoStream(0,'');
    showPhotoSet(-1);
    showContact(-1);
    showTags(-1);
    showGroups(-1);
    showComments(-1);
    showStatus('Searching user ...', _gi('userinfo'));
    flickrAPI.people.getInfo(handle_people_getInfo, null, nsid);
    showStatus('Loading user\'s recent photos ...', _gi('photos'));
    args = new Array(recentPhoto, 'recent', 1, 'Public Photos',1);
    flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args, nsid, '', perPage, 1);
    showStatus('Loading user\'s photo sets ...', _gi('photoset'));
    flickrAPI.photosets.getList(handle_photosets_getList, null, nsid);
    showStatus('Loading user\'s top 20 popular tags ...', _gi('phototag'));
    flickrAPI.tags.getListUserPopular(handle_tags_getListUserPopular, null, nsid, 20);
    showStatus('Loading user\'s contacts ...', _gi('contact'));
    flickrAPI.contacts.getPublicList(handle_contacts_getPublicList, null, nsid);
    showStatus('Loading user\'s groups ...', _gi('group'));
    flickrAPI.people.getPublicGroups(handle_people_getPublicGroups, null, nsid);
//    var url = 'http://flickr.com/recent_comments_feed.gne?id=' + nsid + '&format=rss_200';
    var url = 'http://api.flickr.com/services/feeds/activity.gne?id=' + nsid + '&format=rss_200';
    showStatus('Loading user\'s recent comments ...', _gi('comment'));
    rssAPI.feeds.getItems(handle_rssAPI_feeds_getItems, null, url);
}

function person(nsid, isadmin, ispro, iconserver, username, realname, location, photosurl, profileurl, firstdate, firstdatetaken, count) {
    this.nsid = nsid;
    this.isadmin = isadmin;
    this.ispro = ispro;
    this.iconserver = iconserver;
    this.username = username;
    this.realname = realname;
    this.location = location;
    this.photosurl = photosurl;
    this.profileurl = profileurl;
    this.firstdate = firstdate;
    this.firstdatetaken = firstdatetaken;
    this.count = count;

    var gmif = '' + photosurl;
    gmif = gmif.replace( /http:\/\/flickr.com\/photos\//, '');
    gmif = gmif.replace( /http:\/\/www.flickr.com\/photos\//, '');
//    if( document.location.hostname == 'webdev.yuan.cc' )
//	 gmif = document.location.protocol + '//flickr.yuan.cc/maps/' + gmif;
//    else gmif = document.location.protocol + '//' + document.location.host + '/maps/' + gmif;
    gmif = document.location.protocol + '//flickr.yuan.cc/maps/' + gmif;
    this.gmifurl = gmif;
}

function showSet(index,id) {
    set_index = index;
    set_id = id;
    showStatus('Loading ' + user.username + '\'s photo set ... ', _gi('photos'));
    flickrAPI.photosets.getPhotos(handle_photosets_getPhotos, null, id);
}

function showTagPhotos(user_id,tag) {

    if( _gi('tagsearchall') ) {
	if( _gi('tagsearchall').checked ) user_id='';
    }
    showStatus('Loading tag ' + tag + ' photos...', _gi('photos'));
    delete photo;
    photo = new Object();
    var tmp = new Array();
    photo.photo = tmp;
    photo.tag = tag;
    photo.owner = user_id;
    args = new Array(photo, 'tag', 1, 'Photos tagged with "'+photo.tag+'"', 1);
    _lastSearch = args;
    flickrAPI.photos.search(handle_getPhotoStream, args, user_id, tag, 'any','','','','','','','owner_name,icon_server',perPage,1);
}

function tagSearch() {
    var tags = _gi('tagsearch').value;
    tags = tags.replace(/\s+/ig, ',');
    tags = tags.replace(/^,|,$/ig, '');
    showTagPhotos(user.nsid,tags);
}

function gotoGroup(index,id) {

    if(index==-1) {		// Search group
	if( typeof(groups) != 'object' ) {
	    group_index = 0;
	    groups = new Array(1);
	    groups[0] = new Object();
	    groups[0].nsid = id;
	    groups[0].name = '';
	    groups[0].flickr_url = 'http://flickr.com/groups/' + id + '/pool/';
	} else {
	    group_index = groups.length;
	    groups[group_index] = new Object();
	    groups[group_index].nsid = id;
	    groups[group_index].name = '';
	    groups[group_index].flickr_url = 'http://flickr.com/groups/' + id + '/pool/';
	}
    } else group_index = index;
    group_id = id;
    showStatus('Loading group ...', _gi('photos'));
    if( typeof(groups[group_index].photo) == 'object' ) {
	delete groups[group_index].photo;
    }
    var tmp = new Array();
    groups[group_index].photo = tmp;
    groups[group_index].flickr_url = 'http://flickr.com/groups/' + groups[group_index].nsid + '/pool/';
    args = new Array(groups[group_index], 'group', 1, 'Group Photos<br /><br /><img src="http://flickr.com/buddyicons/' +group_id+ '.jpg" width="48" height="48" /> ' + groups[group_index].name, 1);
    flickrAPI.groups.pools.getPhotos(handle_getPhotoStream, args, group_id,'','owner_name,icon_server',perPage);
}

function showStatus(msg,highlight,color) {

    _gi('status').innerHTML=msg;
    if( highlight && msg != '' ) {
//	if( _lastBg == null)
	highlight.style.borderColor = '#f00';
    }
    if( highlight && msg == '' ) {
	if( color == undefined ) highlight.style.borderColor = '#ccddee';
	else highlight.style.borderColor = color;
    }
//    if( _lastBox && _lastBox != highlight ) {
//	_lastBg = null;
//	_lastBox.style.borderColor = '#ccddee';
//    }
//    _lastBox = highlight;
}

function pager() {

    if( photo.pages == 1 ) return '';

    var str = '<div id="page">Pages: ';
    var i;

    photo.page = 1*photo.page;
    if( photo.pages > 1 && photo.pages <= 10 ) {
	for(i=1; i<=photo.pages; i++) {
	    if( i==photo.page ) str += '<a href="javascript:;"><span style="background-color:#fff;"><b>' + i + '</b></span></a>';
	    else str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>';
	}
    } else if( photo.pages>10 && photo.page < 10 ) {
	for(i=1; i<=10; i++) {
	    if( i==photo.page ) str += '<a href="javascript:;"><span style="background-color:#fff;"><b>' + i + '</b></span></a>';
	    else str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>';
	}
	i = Math.round((10+1*photo.pages)/2);
	if( i != photo.pages ) str += '...<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>...';
	str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + photo.pages + ')"><b>' + photo.pages + '</b></span></a>';
    } else if( photo.pages>10 && photo.page>=10 && photo.page<(photo.pages-5) ) {
	str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' +1+ ')"><b>' + 1 + '</b></span></a>...';
	i = Math.round((photo.page-2)/2);
	str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>...';
	for(i=(photo.page-3); i<=(photo.page+3); i++) {
	    if( i==photo.page ) str += '<a href="javascript:;"><span style="background-color:#fff;"><b>' + i + '</b></span></a>';
	    else str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>';
	}
	i = Math.round((1*i+1*photo.pages)/2);
	str += '...<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>';
	str += '...<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + photo.pages + ')"><b>' + photo.pages + '</b></span></a>';
    } else if( photo.pages>10 && photo.page>=10 & photo.page>=(photo.pages-5) ) {
	i = Math.round((photo.page-2)/2);
	str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' +1+ ')"><b>' + 1 + '</b></span></a>...';
	str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' +i+ ')"><b>' + i + '</b></span></a>...';
	for(i=photo.page-3; i<=photo.pages; i++) {
	    if( i==photo.page ) str += '<a href="javascript:;"><span style="background-color:#fff;"><b>' + i + '</b></span></a>';
	    else str += '<a href="javascript:;"><span onMouseOver="changeFont(this,\'in\')" onMouseOut="changeFont(this,\'out\')" onClick="changePage(' + i + ')"><b>' + i + '</b></span></a>';
	}
    }
    str += "</div>";

    return str;
}

function changePage(x) {

    var args,user_id,text;

    photo.page = x;
    if( photo.photo[(x-1)*perPage] ) {
	switch(photo.text) {
	    case 'recent'  : text = 'Public Photos'; break;
	    case 'favorite': text = user.username + '\'s favorites'; break;
	    case 'group'   : text = 'Photos of group ' + groups[group_index].name; break;
	    case 'tag'     : text = 'Photos tagged with "'+photo.tag+'"'; break;
	    case 'search'  : text = 'Search Results'; break;
	}
	displayPhotos(_size, text, ' ', 1);
	return;
    }
    if( photo.text == 'recent' ) {
	showStatus('Loading new page ...', _gi('photos'));
	args = new Array(recentPhoto, photo.text, 1, 'Public Photos', 1);
	flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args, user.nsid, '', perPage, x);
    }
    if( photo.text == 'interestingness' ) {
	showStatus('Loading new interestingness page...', _gi('photos'));
	args = new Array(interestingness, photo.text, 1, 'Interesting Photos', 1);
	flickrAPI.interestingness.getList(handle_getPhotoStream, args, 'owner_name,icon_server',perPage,x);
    }
    if( photo.text == 'favorites' ) {
	showStatus('Loading new favorites page...', _gi('photos'));
	args = new Array(favorites, photo.text, 1, user.username + '\'s favorites', 1);
	flickrAPI.favorites.getList(handle_getPhotoStream, args, user.nsid,'owner_name,icon_server',perPage,x);
    }
    if( photo.text == 'group' ) {
	showStatus('Loading new group photo page...', _gi('photos'));
	if( typeof(groups[group_index].photo) != 'object' ) {
	    var tmp = new Array();
	    groups[group_index].photo = tmp;
	}
	args = new Array(groups[group_index], photo.text, 1, 'Photos of group ' + groups[group_index].name , 1);
	flickrAPI.groups.pools.getPhotos(handle_getPhotoStream, args, group_id,'','owner_name,icon_server',perPage,x);
    }
    if( photo.text == 'tag' ) {
	if( _gi('tagsearchall') && _gi('tagsearchall').checked ) user_id='';
	else user_id = photo.owner;
	showStatus('Loading new tagged photo page...', _gi('photos'));
//	args = new Array(photo, photo.text, 1, 'Photos tagged with "'+photo.tag+'"', 1);
	flickrAPI.photos.search(handle_getPhotoStream, _lastSearch, user_id, photo.tag,'any','','','','','','','owner_name,icon_server',perPage,x);
    }
    if( photo.text == 'search' ) {
	showStatus('Loading new searching results page...', _gi('photos'));
	args = new Array(searchResults, photo.text, 1, 'Search Results', 1);
	flickrAPI.photos.search(handle_getPhotoStream, args, fSearch.nsid, fSearch.tags,fSearch.tag_mode,'','','','','','','owner_name,icon_server',perPage,x,fSearch.sort,fSearch.privacy_filter);
    }
}

function showFavorites() {

    if( !user ) return;
    if( !favorites.photo.length ) {
	showStatus('Loading ' + user.username + '\'s favorite photos...', _gi('photos'));
	var args = new Array(favorites, 'favorites' , 1, user.username + '\'s favorites', 1);
	if( authenticated )
	    flickrAPI.favorites.getList(handle_getPhotoStream, args, user.nsid,'owner_name,icon_server',perPage,1);
	else
	    flickrAPI.favorites.getPublicList(handle_getPhotoStream, args, user.nsid,'owner_name,icon_server',perPage,1);
	return;
    }
    photo = favorites;
    displayPhotos(_size, user.username + '\'s favorites',' ',1);
}

function showInterestingness(reload) {

    var cache = GetCookie('flickr_cache');

    if( reload==1 ) {
	SetCookie('flickr_cache',0,exp);
//	_gi('cache').checked = false;
    }

//    if( !interestingness.photo.length ) {
	showStatus('Loading interesting photos...', _gi('photos'));
	var args = new Array(interestingness, 'interestingness' , 1, 'Interesting Photos', 1);
	flickrAPI.interestingness.getList(handle_getPhotoStream, args, 'owner_name,icon_server',perPage,1);
//	return;
//    }
//    photo = interestingness;
//    displayPhotos(_size, 'Interesting Photos',' ',1);
    if( reload==1 ) window.setTimeout('restoreCache('+cache+')', 2000);
}

function showPublicPhotos(reload) {

    var cache = GetCookie('flickr_cache');

    if( reload==1 ) {
	SetCookie('flickr_cache',0,exp);
//	_gi('cache').checked = false;
    }
    showStatus('Loading public photos...', _gi('photos'));
    flickrAPI.photos.getRecent(handle_photos_getRecent, null, 'owner_name,icon_server',2*perPage+17,1);
    if( reload==1 ) window.setTimeout('restoreCache('+cache+')', 2000);
}

function showContactPhotos() {

    var cache = GetCookie('flickr_cache');

    if( !user ) return;
    SetCookie('flickr_cache',0,exp);
//    _gi('cache').checked = false;
    showStatus('Loading contacts photos...', _gi('photos'));

    delete contactPhotos.photo;
    var tmp = new Array();
    contactPhotos.photo = tmp;

    var args = new Array(contactPhotos, 'contact', 1, user.username + ' contacts\' photos' , 0);
    flickrAPI.photos.getContactsPublicPhotos(handle_getPhotoStream, args, user.nsid, contact.length,GetCookie('just_friends'),GetCookie('single_photo'));
    window.setTimeout('restoreCache('+cache+')', 2000);

}

function restoreCache(x) {
//    if(x==0) _gi('cache').checked = false;
//    else _gi('cache').checked = true;
    SetCookie('flickr_cache',x,exp);
}

function reloadContact() {

    var cache = GetCookie('flickr_cache');

    SetCookie('flickr_cache',0,exp);
    showStatus('Reloading ' + user.username + '\'s contacts ...', _gi('contact'));
    flickrAPI.contacts.getPublicList(handle_contacts_getPublicList, null, user.nsid);
    SetCookie('flickr_cache',cache,exp);
}

function cacheSwitch(x) {
    if( x.checked ) SetCookie('flickr_cache',1,exp);
    if( !x.checked ) SetCookie('flickr_cache',0,exp);
    if( GetCookie('flickr_cache') == '0' ) {
	_gi('cache1').checked = false;
    } else {
	_gi('cache1').checked = true;
    }
}

function singlePhoto(x) {
    if( x.checked ) SetCookie('single_photo',1,exp);
    if( !x.checked ) SetCookie('single_photo',0,exp);
    if( GetCookie('single_photo') == '0' ) {
	_gi('single_photo').checked = false;
    } else {
	_gi('single_photo').checked = true;
    }
}

function justFriends(x) {
    if( x.checked ) SetCookie('just_friends',1,exp);
    if( !x.checked ) SetCookie('just_friends',0,exp);
    if( GetCookie('just_friends') == '0' ) {
	_gi('just_friends').checked = false;
    } else {
	_gi('just_friends').checked = true;
    }
}

function preferences() {

    var str;
    var photoBox = _gi('photos');
    var cache = GetCookie('flickr_cache');
    var startPage = GetCookie('start_page');
    var startUser = GetCookie('start_user');
    var photoSize = GetCookie('photo_size');
    var gmapLoc = GetCookie('gmap_location');
    var perPage = GetCookie('per_page');
   
    str  = '<h4>Cache</h4>';
    str += '<input id="cache1" type="checkbox" onClick="cacheSwitch(this)" checked>';
    str += ' Enable cache at LfVr proxy. Disable to load latest data from flickr, but with slower response.';

    str += '<h4>Home / Startup</h4>';
    str += '<input id="start1" type="radio" name="start" value="P1" onClick="startPage(this)">';
    str += ' Everyone\'s public photos<br />';
    str += '<input id="start2" type="radio" name="start" value="P2" onClick="startPage(this)">';
    str += ' Blank page<br />';
    str += '<input id="start3" type="radio" name="start" value="P3" onClick="startPage(this)">';
    str += ' Home: Photostream of user ';
    str += '<input id="defaultuser" type="text" onChange="setDefaultUser(this.value)"> (screen name)<br />';
//    str += '<input id="start4" type="radio" name="start" value="P4" onClick="startPage(this)">';
//    str += ' Entry Page<br />';

    str += '<h4>Default size of browsing photos</h4>';
    str += '<input id="size1" type="radio" name="psize" value="s" onClick="setSize(this)">';
    str += ' Square ';
    str += '<input id="size2" type="radio" name="psize" value="t" onClick="setSize(this)">';
    str += ' Thumbnail ';
    str += '<input id="size3" type="radio" name="psize" value="m" onClick="setSize(this)">';
    str += ' Small';

    str += '<h4>Contacts</h4>';
    str += '<input id="single_photo" type="checkbox" onClick="singlePhoto(this)" checked>';
    str += ' Only fetch one photo (the latest) per contact, instead of all photos in chronological order.<br />';
    str += '<input id="just_friends" type="checkbox" onClick="justFriends(this)" checked>';
    str += ' Only show photos from friends and family (excluding regular contacts)';

    str += '<h4>Google Maps</h4>';
    str += '<input id="gmap0" type="checkbox" onClick="showGmap(this)" checked>';
    str += ' Display Google Maps instead of photo itself if the photo is geotagged.<br />';
    str += '<input id="gmap1" type="radio" name="gmap" value="false" onClick="setGmap(this)">';
    str += ' Single Photo (Fast Map display) ';
    str += '<input id="gmap2" type="radio" name="gmap" value="true" onClick="setGmap(this)">';
    str += ' Nearby Photos (Slow Map display)';

    str += '<h4>Page</h4>';
    str += 'The number of photos per page ';
    str += '<select id="perpage" name="perpage" onChange="setPerPage(this.value)">';
    str += '<option value="30">30</option>';
    str += '<option value="40">40</option>';
    str += '<option value="50">50</option>';
    str += '<option value="60">60</option>';
    str += '<option value="70">70</option>';
    str += '<option value="80">80</option>';
    str += '<option value="90">90</option>';
    str += '<option value="100">100</option>';
    str += '</select>';

    photoBox.innerHTML = str;
    if( cache == '0' ) _gi('cache1').checked = false;
    if( GetCookie('single_photo')=='0') _gi('single_photo').checked = false;
    if( GetCookie('just_friends')=='0') _gi('just_friends').checked = false;
    if( GetCookie('gmap_show')=='0') _gi('gmap0').checked = false;
    else _gi('gmap0').checked = true;
    switch(startPage) {
	case 'P1': _gi('start1').checked = true; break;
	case 'P2': _gi('start2').checked = true; break;
	case 'P3': _gi('start3').checked = true; break;
	default  : _gi('start1').checked = true;
    }
    _gi('defaultuser').value = startUser;
    switch(photoSize) {
	case 's': _gi('size1').checked = true; break;
	case 't': _gi('size2').checked = true; break;
	case 'm': _gi('size3').checked = true; break;
	default : _gi('size1').checked = true;
    }
    switch(gmapLoc) {
	case 'false': _gi('gmap1').checked = true; break;
	case 'true' : _gi('gmap2').checked = true; break;
	default     : _gi('gmap1').checked = true;
    }
    switch(perPage) {
	case '30': _gi('perpage').selectedIndex = 0; break;
	case '40': _gi('perpage').selectedIndex = 1; break;
	case '50': _gi('perpage').selectedIndex = 2; break;
	case '60': _gi('perpage').selectedIndex = 3; break;
	case '70': _gi('perpage').selectedIndex = 4; break;
	case '80': _gi('perpage').selectedIndex = 5; break;
	case '90': _gi('perpage').selectedIndex = 6; break;
	case '100': _gi('perpage').selectedIndex = 7; break;
	default  : _gi('perpage').selectedIndex = 0;
    }
}

function startPage(x) {
    SetCookie('start_page', x.value, exp);
    if( x.value == 'P3' ) SetCookie('start_user', _gi('defaultuser').value, exp);
}

function setPerPage(x) {
    SetCookie('per_page', x);
    perPage = x;
    gotoUser(user.nsid);
}

function setDefaultUser(username) {
    if( !_gi('start3') ) SetCookie('start_page','P3',exp);
    SetCookie('start_user',username,exp);
    if( !username ) _gi('home').style.display = 'none';
    else _gi('home').style.display = 'inline';
}

function setSize(x) {
    SetCookie('photo_size', x.value, exp);
    _size = x.value;
}

function showGmap(x) {
    if( x.checked ) SetCookie('gmap_show',1,exp);
    if( !x.checked ) SetCookie('gmap_show',0,exp);
    if( GetCookie('gmap_show') == '0' ) {
	_gi('gmap0').checked = false;
	_gmap = 0;
    } else {
	_gi('gmap0').checked = true;
	_gmap = 1;
    }
}

function setGmap(x) {
    SetCookie('gmap_location', x.value, exp);
    getNearBy = x.value;
}

function slideshow(x) {

    if( slidePlay==0 ) return;
    if( slidePlay==1 ) slidePlay=0;

    var s=-1;
    if( typeof(photo.photo[x]) != 'object' ) s=x;
    if( typeof(photo.photo[(x+1)%photo.photo.length])!='object') s=(x+1)% photo.photo.length;
    if( s!=-1 ) {
	if(photo.text == 'recent') {
	    args = new Array(recentPhoto, photo.text, 3, 'Public Photos', 1);
	    flickrAPI.people.getPublicPhotos(handle_getPhotoStream, args, user.nsid, '', perPage, (s-s%perPage)/perPage+1);
	}
	if(photo.text == 'favorites') {
	    args = new Array(favorites, photo.text, 3, user.username + '\'s favorites', 1);
	    flickrAPI.favorites.getList(handle_getPhotoStream, args, user.nsid,'owner_name,icon_server',perPage,(s-s%perPage)/perPage+1);
	}
	return;
    }

    var str = '';
    var photoBox = _gi('photos');
    var image = photo.photo[x].img;
    var image2 = photo.photo[(x+1) % photo.photo.length].img;

    str = '<div style="text-align:center">';
    str += '<h3>' + photo.photo[x].title + '</h3>';
    str += '<span style="text-align:center">';
    str += '<a href="javascript:;" onClick="slidePlay=0;displaySingle('+x+')"><img src="'+ image +'" title="'+ photo.photo[x].title+'" /></a>';
    str += '</span>';
    str += '<br /><span style="text-align:center">'+(x+1)+' of '+photo.photo.length+'</span>';
    if( slidePlay==0 ) str += '<br /><br /><input type="button" class="button" onClick="slidePlay=2;slideshow('+x+');" value="Play">';
    if( slidePlay==2 ) str += '<br /><br /><input type="button" class="button" onClick="slidePlay=1;slideshow('+x+');" value="Stop">';
    str += '</div>';
    str += '<img width=0 height=0 src="' + image2 + '">';
    photoBox.innerHTML = str;
    x = (x+1) % photo.photo.length;
    if( slidePlay==2 ) window.setTimeout('slideshow('+x+')', 3000);
}

function init() {
 
    window_resize();
    var str,list,num,pattern;
    var startUser = GetCookie('start_user');
    _size = GetCookie('photo_size');
    if( _size == '' || _size == undefined ) _size = 's';
    getNearBy = GetCookie('gmap_location');

    if(authenticated) {
	_gi('login_status').innerHTML = 'Signed in Flickr as ' + auth_username + '&nbsp;&nbsp;&nbsp;<a href="javascript:;" onclick="signout()" style="font-family:Arial,Helvetica,sans-serif;font-size:11px">Sign out</a>';
	flickrAPI.contacts.getList(handle_contacts_getList, null);
    }

    if( document.location.href.match(/webdev.yuan.cc\/lfvr/) ) _gi('site').selectedIndex = 0;
    if( document.location.href.match(/thirdhand.info\/lfvr/) ) _gi('site').selectedIndex = 1;
    if( document.location.href.match(/flickr.tw\/lfvr/) ) _gi('site').selectedIndex = 2;

    if( !startUser ) _gi('home').style.display='none';
    guestbookBox = _gi('guestbook');
    donationBox = _gi('donation');

    if( GetCookie('flickr_cache') == '0' ) SetCookie('flickr_cache',0,exp);
    else SetCookie('flickr_cache',1,exp);
    if( GetCookie('single_photo') == '0' ) SetCookie('single_photo',0,exp);
    else SetCookie('single_photo',1,exp);
    if( GetCookie('just_friends') == '1' ) SetCookie('just_friends',1,exp);
    else SetCookie('just_friends',0,exp);
    if( GetCookie('gmap_show') == '1' ) {
	SetCookie('gmap_show',1,exp);
	_gmap = 1;
    } else {
	SetCookie('gmap_show',0,exp);
	_gmap = 0;
    }

    perPage = (GetCookie('per_page')) ? 1*GetCookie('per_page') : 30;
    SetCookie('per_page',perPage,exp);
    num = 1*GetCookie('history_num');
    pattern = /,/;
    for( var i=0; i<num; i++ ) {
	str = new String(GetCookie('history'+i));
	list = str.split(pattern);
	user_history[i] = new Object();
	user_history[i].nsid = list[0];
	user_history[i].username = list[1];
	user_history[i].iconserver = list[2];
	user_history[i].count = list[3];
	user_history[i].removable = true;
	user_history[i].del = history_del;
    }
//    showHistoryCookie();

    if( entryClass == 'photos' ) {
	if( entryPoint == '' || entryPoint == 'friends' ) showPublicPhotos(0);
	else {
	    showStatus('Searching user ...', _gi('userinfo'));
	    if(entryExtra == '' ) {
		var args = new Array(true, true, true, true, true, true, true);
		flickrAPI.urls.lookupUser(handle_findUser, args, 'http://flickr.com/photos/'+entryPoint );
	    } else if(entryExtra == 'sets' ) {
		photosetBoxOpen = 1;
		var args = new Array(true, true, true, true, true, true, true);
		flickrAPI.urls.lookupUser(handle_findUser, args, 'http://flickr.com/photos/'+entryPoint );
	    } else {
		var args = new Array(true, false, true, true, true, true, true);
		flickrAPI.urls.lookupUser(handle_findUser, args, 'http://flickr.com/photos/'+entryPoint );
		getPhotoById(entryExtra,entryPoint);
	    }
	}
	return;
    }
    if( entryClass == 'people') {
	if( entryPoint == '' ) showPublicPhotos(0);
	else {
	    var args = new Array(true, true, true, true, true, true, true);
	    flickrAPI.urls.lookupUser(handle_findUser, args, 'http://flickr.com/photos/'+entryPoint );
	}
	if( entryExtra == 'contacts' ) window.setTimeout('displayContacts(0)', 2000);
	return;
    }
    if( entryClass == 'groups' ) {
	if( entryPoint != '' && entryPoint != 'topic' ) {
	    flickrAPI.urls.lookupGroup(handle_urls_lookupGroup, null, 'http://flickr.com/groups/'+entryPoint+'/'+entryExtra );
	} else gotoUser(global_nsid);
	return;
    }
    goHome();
    initSearch();
}

function goHome() {

    var startUser = GetCookie('start_user');
    switch(GetCookie('start_page')) {
	case 'P1': showPublicPhotos(0); break;
	case 'P2': break;
	case 'P3': _gi('screen').value = startUser;
		   searchUser(); break;
	default: showPublicPhotos(0);
    }
}

// for debug use...
function showHistoryCookie() {

    var str = '';
    var x,i,j=0;
    var y = new Array();

    str += '# of History: ' + GetCookie('history_num') + '<br />';
    for(i=0; i<100; i++) {
	x = GetCookie('history'+i);
	str += i + ': ' + x + ' <br />'; 

	if( x != undefined ) {
	    y[y.length] = x;
	    str += i + '/' + j + ': ' + x + ' <br />'; 
	    j++;
	}

    }
    _gi('photos').innerHTML = str;

    for( var i=0; i<y.length; i++) SetCookie('history'+i, y[i] , exp);
    for( var i=y.length; i<100; i++) DeleteCookie('history'+i);
    SetCookie('history_num', y.length, exp);
}

var history_del = function(index) {

    for(var i=index+1;i<user_history.length;i++) {
	user_history[i-1] = user_history[i];
	SetCookie('history'+(i-1), user_history[i-1].nsid+','+user_history[i-1].username+','+user_history[i-1].iconserver+','+user_history[i-1].count,exp);
    }
    user_history.pop();
    DeleteCookie('history'+(i-1));
    SetCookie('history_num', user_history.length, exp);
    displayUsers('History', user_history);
}

function geoXML(lat,lng,title,text,img) {

var str;

str = '<?xml version="1.0"?>\n';
str += '<page>\n';
str += '<title>' + title + '</title>\n';
str += '<query></query>\n';
str += '<request></request>\n';
str += '<center lat="' +lat+ '" lng="' +lng+ '"/>\n';
str += '<span lat="0.017998" lng="0.027586"/>\n';
str += '<overlay panelStyle="sidepanel.xsl">\n';
str += '<location infoStyle="geocodeinfo-demo1.xsl" id="A">\n';
str += '<point lat="' +lat+ '" lng="' +lng+ '"/>\n';
str += '<icon image="http://maps.google.com/mapfiles/marker.png" class="local"/>\n';
str += '<info>\n';
str += '<title xml:space="preserve">\n';
str += '</title>\n';
str += '<address>\n';
str += '<line>' +text+ '</line>\n';
str += '</address>\n';
str += '<image>\n';
str += img + '\n';
str += '</image>\n';
str += '</info>\n';
str += '</location>\n';
str += '</overlay>\n';
str += '</page>\n';

return str;
}

function loadXMLDoc(url,mapApp) {

    if (window.XMLHttpRequest) {
	xmlhttp=new XMLHttpRequest();
	xmlhttp.onreadystatechange = function() {
	    if (xmlhttp.readyState==4) {
		if (xmlhttp.status==200) {
		    mapApp.loadXML(xmlhttp.responseText);
		    showStatus('', _gi('photos'));
		}
	    }
	}
	xmlhttp.open("GET",url,true);
	xmlhttp.send(null);
    } else if (window.ActiveXObject) {
	xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	if (xmlhttp) {
	    xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4) {
		    mapApp.loadXML(xmlhttp.responseText);
		}
	    }
	    xmlhttp.open("GET",url,true);
	    xmlhttp.send();
	}
    }
}

function _XMLHttpRequest(url,method,callback) {

    if (window.XMLHttpRequest) {
	xmlhttp=new XMLHttpRequest();
	xmlhttp.onreadystatechange = function() {
	    if (xmlhttp.readyState==4) {
		if (xmlhttp.status==200) {
		    callback(xmlhttp.responseText);
		}
	    }
	}
	xmlhttp.open(method,url,true);
	xmlhttp.send(null);
    } else if (window.ActiveXObject) {
	xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	if (xmlhttp) {
	    xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4) {
		    callback(xmlhttp.responseText);
		}
	    }
	    xmlhttp.open(method,url,true);
	    xmlhttp.send();
	}
    }
}

function initMap() {
    if( _maphacks ) initMapHacks();
    else initMapByAPI();
}

function initMapHacks() {

//    _loadscript(_GMapURL);
    showStatus('Loading Google Maps ...', _gi('photos'));

    var lat = mapInfo.lat;
    var lon = mapInfo.lon;
    var title = mapInfo.title;
    var text = mapInfo.text;
    var image = mapInfo.image;
    var img = _gi('pic').src;
    _gi('pic').src=loading_photo;
    _gi('pic').src=mapPic;
    _gi('gmap').style.display = 'block';
    _gi('gmap').style.width='95%';
    _gi('gmapbutton').value= 'Photo';
    _gi('gmapbutton').onclick = function () { closeMap(img); }

    myMapApp = new _MapsApplication(
	_gi("gmap"),
	_gi("panel"),
	_gi("metapanel"),
	_gi("permalink"),
	_gi("printheader"),
	createMapSpecs() );

    myMapApp.loadMap();
    myMapApp.map.setMapType(_SATELLITE_TYPE);
    myMapApp.map.centerAndZoom(new GPoint(lon,lat), 3);
    if( getNearBy=='true' ) {
	loadXMLDoc(GEOBLOGGERS_PROXY_URL+'?'+mapStr ,myMapApp);
    } else {
	myMapApp.loadXML(mapStr);
	showStatus('', _gi('photos'));
    }
}

function initMapByAPI() {

//    _loadscript(_GMapURL);
    var lat = mapInfo.lat;
    var lon = mapInfo.lon;
    var title = mapInfo.title;
    var text = mapInfo.text;
    var image = mapInfo.image;

    var height = document.defaultView.getComputedStyle(_gi('photos'),null).getPropertyValue('height');
    height = 1 * height.substring(0,height.indexOf('px')) - 60;
    height += 'px';
    showStatus('Loading Google Maps ...', _gi('photos'));
    var img = _gi('pic').src;
    _gi('pic').src=loading_photo;
    _gi('pic').src=mapInfo.image;
    _gi('gmap').style.display = 'block';
    _gi('gmap').style.width='95%';
    _gi('gmap').style.height=height;
    _gi('gmapbutton').value= 'Photo';
    _gi('gmapbutton').onclick = function () { closeMap(img); }

    var map = new GMap(_gi("gmap"));
//    map.setMapType(_SATELLITE_TYPE);
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.centerAndZoom(new GPoint(lon,lat), 3);

    var point = new GPoint(lon,lat);
    var marker = createMarker(point, title, image);
    map.addOverlay(marker);
    showStatus('', _gi('photos'));
}

function closeMap(img) {

    _gi('pic').src = img;
    _gi('gmap').style.display = 'none';
    _gi('gmap').style.width='0px';
    _gi('gmap').style.height='0px';
    _gi('gmapbutton').value= 'GMap';
    _gi('gmapbutton').onclick = function () { initMap(); }
}

function createMarker(point, str, image) {
  var marker = new GMarker(point);
  var html = str + '<br /><img src="' + image + '">';

  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });

  return marker;
}

function fnRecenter(lat,lon) {

    if( getNearBy == 'true' ) mapStr = 'lat=' +lat+ '&lon=' +lon+ '&maxRows=20';
    initMap();
}

// t.dump = function(a) {alert(a);} //debugging


function window_resize() {

    var div_right = _gi('right');
    var div_container = _gi('container');
    var wid = _gt('body')[0];

//  alert(wid.clientWidth);
    div_container.style.width = wid.clientWidth-30;
    div_right.style.width = wid.clientWidth-30-200-30;
}

function _loadscript(src) {

    var s = _ce('script'); 
    s.setAttribute('src', src); 
    document.body.appendChild(s);
}

function changeSite(site) {
    document.location = site.value;
}

function showNote(x) {
    _gi('photo_notes').style.visibility = 'visible';
}
function hideNotes() {
    _gi('photo_notes').style.visibility = 'hidden';
}
function showNoteBox() {
    _gi('photo_notes').style.visibility = 'visible';
}

function addToFaves(x,photoid) {

    if( photo.photo[x].isfavorite ) {
	var callback = function(result,args) {
	    if( result.ok ) {
		_gi('faves').style.background = '#ffffff';
		photo.photo[x].isfavorite = false;
	    } else alert('Remove Faves failed');
	}
	flickrAPI.favorites.remove(callback, null, photoid);
    } else {
	var callback = function(result,args) {
	    if( result.ok ) {
		_gi('faves').style.background = '#ff0084';
		photo.photo[x].isfavorite = true;
	    } else alert('Add to Faves failed');
	}
	flickrAPI.favorites.add(callback, null, photoid);
    }
}

function rotatePhoto(x,photoid,degrees) {

    if( photo.photo[x] ) {
	showStatus('Rotating photo...', _gi('photos'));
	var callback = function(result,args) {
	    showStatus('', _gi('photos'));
	    _gi('rotate_img').style.display='none';
	    if( result.ok ) {
		var secret = result.secret;
		var server = photo.photo[x].server;
		photo.photo[x].secret = secret;
		photo.photo[x].img_s = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'_s.jpg';
		photo.photo[x].img_t = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'_t.jpg';
		photo.photo[x].img_m = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'_m.jpg';
		photo.photo[x].img   = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'.jpg';
		photo.photo[x].img_b = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'_b.jpg';
		photo.photo[x].img_o = 'http://static.flickr.com/'+server+'/'+photoid+'_'+secret+'_o.jpg';
		_gi('pic').src= photo.photo[x].img;
	    } else alert('Photo rotation failed');
	}
	flickrAPI.photos.transform.rotate(callback, null, photoid, degrees);
    }
}

function deletePhoto(x,photoid) {

    if( photo.photo[x] ) {
	var callback = function(result,args) {
	    if( result.ok ) {
		photo.photo[x].deleted = true;
		displayPhotos();
//		changePage(1);
	    } else alert('Photo deletion failed');
	}
	var yes_or_no = confirm('Are you sure to delete this photo?');
	if( !yes_or_no ) return;
	var yes_or_no = confirm('This photo will be gone forever, go ahead?');
	if( !yes_or_no ) return;
	flickrAPI.photos._delete(callback, null, photoid);
    }
}

function copyPhoto(x,photoid) {

    var auth_div;

    showStatus('Copying to your Flickr ...', _gi('photos'));
    if( photo.photo[x].img_o != '' ) {
	var url = 'http://webdev.yuan.cc/lfvr/upload.php?title=' +photo.photo[x].title+ '&url=' + photo.photo[x].img_o;
    } else {
	var url = 'http://webdev.yuan.cc/lfvr/upload.php?title=' +photo.photo[x].title+ '&url=' + photo.photo[x].img;
    }
    var url = 'http://webdev.yuan.cc/lfvr/upload.php?title=' +photo.photo[x].title+ '&id=' + photo.photo[x].id;
    var callback = function(responseText) { 
	showStatus('', _gi('photos'));
//	alert(responseText);
    }
    _XMLHttpRequest(url,'GET',callback);
}

function checkPHPSession(x,photoid) {

    showStatus('Checking session ...', _gi('photos'));

    var url = "http://webdev.yuan.cc/lfvr/checksession.php?action=check";
    var callback = function(responseText) { 
	showStatus('', _gi('photos'));
//	alert('Check Session: ' + responseText);
	if( responseText == '1' ) {
	    copyPhoto(x,photoid);
	    return;
	}
	if( !_gi('auth_div') ) {
	    auth_div = _ce('div');
	    auth_div.id = 'auth_div';
	    auth_div.style.display = 'none';
//	    auth_div.style.width = '600px';
//	    auth_div.style.height = '300px';
	    document.body.appendChild(auth_div);
	} else auth_div = _gi('auth_div');
	auth_div.innerHTML = '<iframe src="http://webdev.yuan.cc/lfvr/checksession.php?action=auth" onload="copyPhoto('+x+',\'' +photoid+ '\')"></iframe>';
    }
    _XMLHttpRequest(url,'GET',callback);

}

function signout() {
    authenticated=false;
    auth_nsid='';
    auth_token='';
    auth_username='';
    auth_url='';
/*
    SetCookie("auth_nsid","", exp);
    SetCookie("auth_token","", exp);
    SetCookie("auth_username","", exp);
    SetCookie("auth_url","", exp);
    SetCookie("auth_flickr","", exp);
*/
    DeleteCookie("auth_nsid","", exp);
    DeleteCookie("auth_token","", exp);
    DeleteCookie("auth_username","", exp);
    DeleteCookie("auth_url","", exp);
    DeleteCookie("auth_flickr","", exp);
    _gi('login_status').innerHTML = '<a href="javascript:;" onClick="SetCookie(\'auth_flickr\',1,exp);document.location.reload();" style="font-family:Arial,Helvetica,sans-serif;font-size:11px">Sign in Flickr</a>';
}

function initSearch() {
    fSearch.dom = _ce('div');
    fSearch.dom.style.padding = '10px';
    var str = '<h4>Search User</h4>';
    str += '<input id="fsearch_screen" type=text size=16>';
    str += '<input type="button" value="Search User" onClick="searchUser(_gi(\'fsearch_screen\').value)">';
    str += '<span style="color:#888888;font-family:Arial,Helvetica,sans-serif;font-size:11px">';
    str += ' Search by user screen name, if you know it.</span>'; 

    str += '<h4>Search Photos</h4>';
    str += 'Owner: <input id="fsearch_nsid" type="text" size="16"> ';
    str += '<span class="sublink">';
    str += '<a href="javascript:;" onClick="_gi(\'fsearch_nsid\').value=\'\'">All users</a> ';
    str += '<a href="javascript:;" onClick="if(user&&user.nsid!=undefined) _gi(\'fsearch_nsid\').value=user.nsid">Current user</a></span><br />';
    str += 'Tags: <input id="fsearch_tags" type="text" size="40">&nbsp;&nbsp;';
    str += 'Tag mode: <select id="fsearch_tag_mode">';
    str += '   <option value="any">OR</option>';
    str += '   <option value="all">AND</option>';
    str += '</select><br />';
    str += 'Sort: <select id="fsearch_sort">';
    str += '   <option value="date-posted-desc">Latest posted first</option>';
    str += '   <option value="date-posted-asc">Oldest posted first</option>';
    str += '   <option value="date-taken-desc">Latest taken first</option>';
    str += '   <option value="date-taken-asc">Oldest taken first</option>';
    str += '   <option value="interestingness-desc">Most interesting first</option>';
    str += '   <option value="interestingness-asc">Least interesting first</option>';
    str += '</select><br />';
    str += 'Privacy: <select id="fsearch_privacy_filter">';
    str += '   <option value="1">public photos</option>';
    str += '   <option value="2">private photos visible to friends</option>';
    str += '   <option value="3">private photos visible to family</option>';
    str += '   <option value="4">private photos visible to friends & family</option>';
    str += '   <option value="5">completely private photos</option>';
    str += '</select>';
    str += '<br /><br /><input type="button" value="Submit" onClick="doSearch()">';

    str += '<h4>Search Groups</h4>';
    str += '<input id="fsearch_gnsid" type="text" size="16" value="NSID" onClick="if(this.value==\'NSID\') this.value=\'\'"> ';
    str += '<input type="button" value="Search Groups" onClick="var gid=_gi(\'fsearch_gnsid\').value;gotoGroup(-1,gid)"> ';
    str += '<span style="color:#888888;font-family:Arial,Helvetica,sans-serif;font-size:11px">Search by group nsid, if you know it.</span>'; 
    str += '<br />';
    str += '<input id="fsearch_group" type="text" size="30" value=""> ';
    str += '<input type="button" value="Search Groups" onClick="searchGroups(_gi(\'fsearch_group\').value)"> ';

    fSearch.dom.innerHTML = str;
}

function searchPhotos() {

    var photobox = _gi('photos');
    photobox.innerHTML = '';

    photobox.appendChild(fSearch.dom);
//    if( _gi('fsearch_nsid') && user && user.nsid != undefined ) _gi('fsearch_nsid').value = user.nsid;
}

function doSearch() {

    fSearch.nsid = _gi('fsearch_nsid').value;
    fSearch.tags = _gi('fsearch_tags').value;
    fSearch.tag_mode = _gi('fsearch_tag_mode').value;
    fSearch.sort = _gi('fsearch_sort').value;
    fSearch.privacy_filter = _gi('fsearch_privacy_filter').value;

    // args[0] = stream instance
    // args[1] = stream text
    // args[2] = action: 1. displayPhotos, 2. displaySingle, 3. slideshow, 4... nothing
    // args[3] = param1 for action
    // args[4] = param2 for action

    if(searchResults.photo) delete searchResults.photo;
    var tmp = new Array();
    searchResults.photo = tmp;
    searchResults.pages = 0;
    searchResults.total = 0;
    showStatus('Searching photos ...', _gi('photos'));
    args = new Array(searchResults, 'search', 1, 'Search Results',1);
    flickrAPI.photos.search(handle_getPhotoStream, args, fSearch.nsid, fSearch.tags,fSearch.tag_mode,'','','','','','','owner_name,icon_server',perPage,1,fSearch.sort,fSearch.privacy_filter);
}

function searchGroups(text) {

    var callback = function(result,args) {
	displayGroups(result.group, args[0]);
    }

    var args = new Array('Groups Search Results', text);
    showStatus('Searching groups ...', _gi('photos'));
    flickrAPI.groups.search(callback, args, text, 100,1);

}

function displayGroups(g, title) {

    var str = '';
    var photobox = _gi('photos');
    if( typeof(groups) != 'object' ) groups = new Array();
    for(var i=0; i<g.length; i++) {
	var index = groups.length;
	groups[index] = { nsid: g[i].nsid, name: g[i].name, eighteenplus: g[i].eighteenplus };
//	str += '<a href="javascript:;" onClick="gotoGroup(-1,\''+g[i].nsid+'\')">';
	str += '<a href="javascript:;" onClick="gotoGroup('+index+',\''+groups[index].nsid+'\')">';
	str += '<img src="http://flickr.com/buddyicons/' +g[i].nsid+ '.jpg" width="24" height="24" /> ';
	str += g[i].name + '</a>';
	str += '&nbsp;&nbsp;,&nbsp;<a href="http://flickr.com/groups/' +g[i].nsid+ '/" target="_blank">Flickr group page</a><br />';
    }
    photobox.innerHTML = '<div style="padding:10px"><h4>Groups Search Results</h4>' + str + '</div>';
    showStatus('', _gi('photos'));
}


var escape_utf8=function(_43) {
    if(_43===""||_43===null||_43===undefined) return '';
    _43=_43.toString();
    var _44="";
    for(var i=0;i<_43.length;i++) {
	var c=_43.charCodeAt(i);
	var bs=new Array();
	if(c>65536) {
	    bs[0]=240|((c&1835008)>>>18);
	    bs[1]=128|((c&258048)>>>12);
	    bs[2]=128|((c&4032)>>>6);
	    bs[3]=128|(c&63);
	} else {
	    if(c>2048) { 
		bs[0]=224|((c&61440)>>>12);
		bs[1]=128|((c&4032)>>>6);
		bs[2]=128|(c&63);
	    } else {
		if(c>128) {
		    bs[0]=192|((c&1984)>>>6);
		    bs[1]=128|(c&63);
		} else bs[0]=c;
	    }
	}
	if(bs.length>1) {
	    for(var j=0;j<bs.length;j++) {
		var b=bs[j];
		var hex=nibble_to_hex((b&240)>>>4)+nibble_to_hex(b&15);
		_44+="%"+hex;
	    }
	} else _44+=encodeURIComponent(String.fromCharCode(bs[0]));
    }
    return _44;
};

var nibble_to_hex= function(_50) {
    var _51 = "0123456789ABCDEF";
    return _51.charAt(_50);
};
