/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();/* usemedia.com . joes koppers . 12.2006 */
/* thnx for reading this code */


//extends js Date object with human readable formatting

Date.months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
Date.days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

Date.prototype.isValidDate = function()
{
	var valid = true;
	
	// ensure we have a Date object
	if( valid && ! this instanceof Date){
		valid = false;
	}
	
	// ensure it's a valid date
	if( valid && 'invalid date' === this.toString().toLowerCase() ){
		valid = false;		
	}

	return valid;
}

Date.prototype.format = function()
{
/*	pre-defined date formats: use (u) for US date order (dec 22, 2006)

	day					=> 'friday'
	shortday			=> 'fri'
	(u)date				=> '22/12/2006'
	(u)shortdate		=> '22/12/06'
	(u)humandate		=> '22 december 2006'
	(u)shorthumandate	=> '22 dec 2006'
	(u)shorterhumandate	=> '22 dec';
	(u)longhumandate	=> 'friday 22 december, 2006';
	time				=> '14:56'
	longtime			=> '14:56:23'
	(u)relative			=> 'x minutes ago', 'x hours x minutes ago', '1 day x hours ago', 'x days ago',
							prints regular (u)shorthumandate at 14+ days
							
	example: new Date().format('Current time and date: ','time',' on ','day',' ','humandate'); */						

	var day = this.getDay();
	var date = this.getDate();
	var month = this.getMonth()+1;
	var year = this.getFullYear();
	var h = this.getHours();
	var m = this.getMinutes(); if (m<10) m = '0'+m;
	var s = this.getSeconds(); if (s<10) s = '0'+s;

	var str = '';
	for (var i=0; i<arguments.length && this.isValidDate(); i++)
	{
		switch(arguments[i])
		{
			default: str+= arguments[i]; break; //non-format strings are printed
			case 'day': str+= ''+date; break;
			case 'month': str+= ''+month; break;
			case 'year': str+= ''+year; break;
			
			case 'shortday': str+= Date.days[day].substring(0,3); break;
			case 'date': str+= date+'/'+month+'/'+year; break;
			case 'udate': str+= month+'/'+date+'/'+year; break;
			case 'shortdate': str+= date+'/'+month+'/'+String(year).substr(2); break;
			case 'ushortdate': str+= month+'/'+date+'/'+String(year).substr(2); break;
			case 'humandate': str+= date+' '+Date.months[month-1]+' '+year; break;
			case 'uhumandate': str+= Date.months[month-1]+' '+date+', '+year; break;
			case 'shorthumandate': str+= date+' '+Date.months[month-1].substring(0,3)+' '+year; break;
			case 'ushorthumandate': str+= Date.months[month-1].substring(0,3)+' '+date+', '+year; break;
			case 'shorterhumandate': str+= date+' '+Date.months[month-1].substring(0,3)+' \''+String(year).substr(2); break;
			case 'ushorterhumandate': str+= Date.months[month-1].substring(0,3)+' '+date+', \''+String(year).substr(2); break;
			case 'longhumandate': str+= Date.days[day]+' '+date+' '+Date.months[month-1]+', '+year; break;
			case 'ulonghumandate': str+= Date.days[day]+' '+Date.months[month-1]+' '+date+', '+year; break;
			case 'time': str+= h+':'+m; break;
			case 'longtime': str+= h+':'+m+':'+s; break;
			case 'relative':
			case 'urelative':
				var now = new Date();
				var diff = now-this;
				if (diff<60000) diff = 0;
				var mins = Math.floor(diff/1000/60);
				var hrs = Math.floor(mins/60);
				var days = (hrs>now.getHours())? Math.floor((hrs)/24):0;

				if (days==0)
				{
					mins = mins-(hrs*60);
					hrs = hrs;
					if (hrs==0 && mins==0) str+= 'less than a minute ';
					else
					{
						if (hrs>0) str+= (hrs==1)? '1 hour ':hrs+' hours ';
						if (mins>0) str+= (mins==1)? '1 minute ':mins+' minutes ';
					}
				}
				else if (days==1)
				{
					str+= '1 day ';
					hrs = hrs - 24;
					if (hrs>0) str+= (hrs==1)? '1 hour ':hrs+' hours ';
				}
				else if (days<=14)
				{
					str+= days+' days ';
				}
				
				if (days>14)
				{
					str+= 'on ';
					str+= (arguments[i]=='relative')? date+' '+Date.months[month-1].substring(3,0)+' '+year:Date.months[month-1].substring(3,0)+' '+date+', '+year;
					str+= ' at '+h+':'+m;
				}
				else
				{
					str+= 'ago';
					if (days>1) str+= ' at '+h+':'+m;
				}
				break;
			case 'shortrelative':
				var now = new Date();
				var diff = now-this;
				if (diff<60000) diff = 0;
				var mins = Math.floor(diff/1000/60);
				var hrs = Math.floor(mins/60);
				var days = (hrs>now.getHours())? Math.floor((hrs)/24):0;

				if (days==0)
				{
					mins = mins-(hrs*60);
					hrs = hrs;
					if (hrs==0 && mins==0) str+= 'now ';
					else
					{
						if (hrs>0) str+= hrs + 'h';
						if (mins>0) str+= mins+'mins';
						str += ' ago';
					}
				}
				else if (days==1)
				{
					str+= '1 day ';
					hrs = hrs - 24;
					if (hrs>0) 
					{
						str +=hrs + 'h '; 
						
					}
					str+= 'ago';
				}
				else if (days<=14)
				{
					str+= days+' days ago';
				}
				
				if (days>14)
				{
					str+= 'on ';
					str+= date+'/'+month+'/'+String(year).substr(2);
					
				}
				break;
				
			//utils
			case 'tolower': str = str.toLowerCase(); break;
			case 'nonbreaking': str = str.replace(/ /g,'&nbsp;'); break;
		}
	}
	return str;
}
/**
*
*  MD5 (Message-Digest Algorithm)
*  http://www.webtoolkit.info/
*
**/
 
 var MD5 = function (string) {

	function RotateLeft(lValue, iShiftBits) {
		return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
	}

	function AddUnsigned(lX,lY) {
		var lX4,lY4,lX8,lY8,lResult;
		lX8 = (lX & 0x80000000);
		lY8 = (lY & 0x80000000);
		lX4 = (lX & 0x40000000);
		lY4 = (lY & 0x40000000);
		lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
		if (lX4 & lY4) {
			return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
		}
		if (lX4 | lY4) {
			if (lResult & 0x40000000) {
				return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
			} else {
				return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
			}
		} else {
			return (lResult ^ lX8 ^ lY8);
		}
 	}

 	function F(x,y,z) { return (x & y) | ((~x) & z); }
 	function G(x,y,z) { return (x & z) | (y & (~z)); }
 	function H(x,y,z) { return (x ^ y ^ z); }
	function I(x,y,z) { return (y ^ (x | (~z))); }

	function FF(a,b,c,d,x,s,ac) {
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};

	function GG(a,b,c,d,x,s,ac) {
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};

	function HH(a,b,c,d,x,s,ac) {
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};

	function II(a,b,c,d,x,s,ac) {
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};

	function ConvertToWordArray(string) {
		var lWordCount;
		var lMessageLength = string.length;
		var lNumberOfWords_temp1=lMessageLength + 8;
		var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
		var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
		var lWordArray=Array(lNumberOfWords-1);
		var lBytePosition = 0;
		var lByteCount = 0;
		while ( lByteCount < lMessageLength ) {
			lWordCount = (lByteCount-(lByteCount % 4))/4;
			lBytePosition = (lByteCount % 4)*8;
			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
			lByteCount++;
		}
		lWordCount = (lByteCount-(lByteCount % 4))/4;
		lBytePosition = (lByteCount % 4)*8;
		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
		lWordArray[lNumberOfWords-2] = lMessageLength<<3;
		lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
		return lWordArray;
	};

	function WordToHex(lValue) {
		var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
		for (lCount = 0;lCount<=3;lCount++) {
			lByte = (lValue>>>(lCount*8)) & 255;
			WordToHexValue_temp = "0" + lByte.toString(16);
			WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
		}
		return WordToHexValue;
	};

	function Utf8Encode(string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.charCodeAt(n);

			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}

		}

		return utftext;
	};

	var x=Array();
	var k,AA,BB,CC,DD,a,b,c,d;
	var S11=7, S12=12, S13=17, S14=22;
	var S21=5, S22=9 , S23=14, S24=20;
	var S31=4, S32=11, S33=16, S34=23;
	var S41=6, S42=10, S43=15, S44=21;

	string = Utf8Encode(string);

	x = ConvertToWordArray(string);

	a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

	for (k=0;k<x.length;k+=16) {
		AA=a; BB=b; CC=c; DD=d;
		a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
		d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
		c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
		b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
		a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
		d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
		c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
		b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
		a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
		d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
		c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
		b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
		a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
		d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
		c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
		b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
		a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
		d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
		c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
		b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
		a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
		d=GG(d,a,b,c,x[k+10],S22,0x2441453);
		c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
		b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
		a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
		d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
		c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
		b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
		a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
		d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
		c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
		b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
		a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
		d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
		c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
		b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
		a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
		d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
		c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
		b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
		a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
		d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
		c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
		b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
		a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
		d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
		c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
		b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
		a=II(a,b,c,d,x[k+0], S41,0xF4292244);
		d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
		c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
		b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
		a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
		d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
		c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
		b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
		a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
		d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
		c=II(c,d,a,b,x[k+6], S43,0xA3014314);
		b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
		a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
		d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
		c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
		b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
		a=AddUnsigned(a,AA);
		b=AddUnsigned(b,BB);
		c=AddUnsigned(c,CC);
		d=AddUnsigned(d,DD);
	}

	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);

	return temp.toLowerCase();
}
// ii.js
// defines global namespace
// and utility functions


// global namespace of entire lib
// utility functions are direct descendents
ii = {};

ii.views = {}; // contains view constructors
ii.items = {}; // contains item constructors

//ii.log_to_console = window.ii_log_to_console;
//ii.log_to_div = window.ii_log_to_div;
ii.logger_paused = false;
ii.logger_queue = [];

ii.init = function()
{
	// store browser options
	ii.browser = {
		safari: (navigator.userAgent.indexOf("Safari")!==-1)? true:false,
		opera: (navigator.userAgent.indexOf("Opera")!==-1)? true:false,
		windows: (navigator.userAgent.indexOf('Windows')!==-1)? true:false,
		msie: (navigator.userAgent.indexOf('MSIE')!==-1)? true:false,
		msie7: (navigator.userAgent.indexOf('MSIE 7')!==-1)? true:false
	}
}

/* global settings */
ii.set = {
  show_feedback: false,
  use_css_clock_blink: true
}


ii.assert = function(arg)
{
	if (!arg)
	{
		ii.error('Assertion failed');
	}
}

ii.dir = function(l) {
	if (window.console && window.console.dir)
		console.dir(l);
}

ii.log = function(l) {

    if(!window.ii_log_to_console){
        return;
    }

    if(ii.logger_paused === true){
        ii.logger_queue.push(l);
        return;
    }

    if(window['console']){

        if(console.log.apply){
            while(ii.logger_queue.length > 0){
                console.log.apply(console, ii.logger_queue.shift());
            }

            console.log.apply(console, arguments);
        }
        else {
            // IE 8
            while(ii.logger_queue.length > 0){
                console.log(ii.logger_queue.shift()[0]);
            }

            console.log(arguments[0]);
        }

    }
    else if(window.ii_log_to_div ){

        var div_console = document.getElementById('div_console');

        if(div_console){

            while(ii.logger_queue.length > 0){
                div_console.innerHTML += ii.logger_queue.shift() + '<br>';
            }

            div_console.innerHTML += l + '<br>';
        }
        else {

            div_console = document.createElement('div');

            div_console.setAttribute('id', 'div_console');

            div_console.style.position = 'fixed';
            div_console.style.background = 'white';
            div_console.style.zIndex = '99999999';
            div_console.style.bottom = '0px';
            div_console.style.right = '0px';
            div_console.style.width = '400px';
            div_console.style.height = '150px';
            div_console.style.overflow = 'auto';
            div_console.style.border = '1px solid red';

            div_console.innerHTML = l;

            document.body.appendChild(div_console);

            var open_console_button = ii.elm('div', {
                style: {
                    position: 'fixed',
                    bottom: '0px',
                    left: '0px',
                    background: 'blue',
                    color: 'white',
                    display: 'none'
                },
                onclick: function(){
                    div_console.style.display = 'block';
                    close_console_button.style.display = 'block';
                    this.style.display = 'none';
                }
            }, 'open console');

            document.body.appendChild(open_console_button);

            var close_console_button = ii.elm('div', {
                style: {
                    position: 'fixed',
                    bottom: '0px',
                    left: '0px',
                    background: 'blue',
                    color: 'white'
                },
                onclick: function(){
                    div_console.style.display = 'none';
                    open_console_button.style.display = 'block';
                    this.style.display = 'none';
                }
            }, 'close console');

            document.body.appendChild(close_console_button);

            var pause_console_button = ii.elm('div', {
                style: {
                    position: 'fixed',
                    bottom: '0px',
                    left: '75px',
                    background: 'green',
                    color: 'white'
                },
                onclick: function(){
                    if (this.innerHTML == 'console paused') {
                        ii.logger_paused = false;

                        while(ii.logger_queue.length > 0){
                            div_console.innerHTML += ii.logger_queue.shift()
                                + '<br>';
                        }

                        this.style.background = 'green';
                        this.innerHTML = 'pause console';
                    }
                    else {
                        ii.logger_paused = true;

                        this.style.background = 'red';
                        this.innerHTML = 'console paused';
                    }

                }
            }, 'pause console');

            document.body.appendChild(pause_console_button);

        }
    }
}

ii.error = function(l){
    if (console.error) 
        console.error(l);
    else {
        ii.log('err: ' + l);
        throw l;
    }
}


// performs an ajax query and evals results.
// params are key/values
// key is attached
ii.get = function(url,callback, params) {
	url = '/srv/' + url + '.php?';
	params = params || {};
	if (ii.login && ii.login.key)
		params.key = ii.login.key;

	for(var k in params)
		url += encodeURIComponent(k) + '=' + encodeURIComponent(params[k]) + '&';

	var request = new XMLHttpRequest();
	request.open('GET', url);
    
	request.onreadystatechange = function()
	{
		if (request.readyState == 4 && request.status==200)
		{
			
			if (0 && window.JSON)
			{
				try {
					var resp = JSON.parse(request.responseText);
				}
				catch(Exception)
				{
					ii.error('PHP ERROR: '+request.responseText);
					return;
				}
			}
			else
			{
				
				try {
					eval('var resp = ' + request.responseText);
					}
				catch(Exception)
				{
					
					ii.error('PHP ERROR: '+request.responseText);
					return;
				}
			}
			callback(resp);
		}
	}

	request.send(null);
	return request;
}

// performs an ajax query and puts result in target elm.
ii.getHtml = function(url,target, callback)
{
	url = 'html/' + url + '.php';
	var request = new XMLHttpRequest();
	request.open('GET', url);
    ii.log('gethtml: '+url);


	request.onreadystatechange = function()
	{
		if (request.readyState == 4 && request.status==200)
		{
			target.innerHTML = request.responseText;
			if (callback)
				callback(target);
		}
	}
	request.send(null);
	return request;
}

// performs an ajax request and caches the result
ii.loadDriver = function(name)
{
	if (!ii.drivers) ii.drivers = {};
	if (!ii.drivers[name])
	{
		ii.drivers[name] = ii.elm('div', { className:'driver' });
		ii.getHtml('Drivers'+name,ii.drivers[name] );
	}
	return ii.drivers[name];
}


// default hover images have X in there name
ii.onmouseoverbtn = function()
{
	this.src = this.src.replace(/([^X])\.png/, '$1X.png');
}
ii.onmouseoutbtn = function()
{
	this.src = this.src.replace(/X\.png/, '.png');
}

// create "tomtomtom's" from "tomtomtom"
ii.appendS = function(name)
{
	if (name.substr(name.length-1,1)=='s')
		return name+'\'';
	else
		return name+'\'s';
}

// conversions from typename/typeletter/typelabels
ii.typeletter = {
	user: 'u',
	account: 'u',
	trip: 't',
	comment: 'c',
	spot: 's',
	group: 'g',
	album: 'a',
	photo: 'p',
	poi: 'p',
	video: 'v',
	feed: 'f',
	thread: 'h'
};

ii.typename = {
	u: 'user',
	p: 'photo',
	v: 'video',
	t: 'trip',
	c: 'comment',
	g: 'group',
	s: 'spot',
	a: 'album',
	f: 'feed',
	h: 'thread'
}

ii.typector = {
	u: 'User',
	p: 'Photo',
	v: 'Video',
	t: 'Trip',
	c: 'Comment',
	g: 'Group',
	s: 'Spot',
	a: 'Album',
	f: 'Feed',
	h: 'Thread'
}

ii.typeplural = {
	u: 'People',
	p: 'Photos',
	v: 'Videos',
	t: 'Trips',
	c: 'Comments',
	s: 'Spots',
	g: 'Groups',
	a: 'Albums',
	f: 'Feed'
}
ii.typesingle = {
	u: 'Person',
	p: 'Photo',
	v: 'Video',
	t: 'Trip',
	c: 'Comment',
	s: 'Spot',
	g: 'Group',
	a: 'Album',
	f: 'Feed',
	user: 'Person',
	photo: 'Photo',
	video: 'Video',
	trip: 'Trip',
	comment: 'Comment',
	spot: 'Spot',
	group: 'Group',
	album: 'Album',
	feed: 'Feed'
}



/* ii.elm
 * utility function to create a new html-element
 * first param is element-name (TAG)
 * next param are children depending on type:
 * - object param is attritbutes
 * - string param is text-node
 * - html-element is child element
 *
 * eg: ii.elm('div', {style:{display:'none'}}, 'sample textcontent')
*/
ii.elm = function(elmname)
{

	var setatts = function(elm, atts)
	{
		for (var n in atts) {
            if (atts[n] instanceof Object && !(atts[n] instanceof Function)){
                setatts(elm[n], atts[n]);
            }
            else {
                if (ii.browser.msie) {
                    switch (n) {
                        case 'cssFloat':
                            elm.setAttribute('styleFloat', atts[n]);
                            break;
                        default:
                            try {
                                elm[n] = atts[n];
                            }
                            catch(e){
                                ii.log('cant set ' + n + ' to ' + atts[n]);
                                throw e
                            }
                            break;
                    }
                }
                else {
                    elm[n] = atts[n];
                }
            }
        }
	}

	var newelm = document.createElement(elmname);
	var args = ii.elm.arguments;

	for(var n=1; n < args.length; n++)
	{
		if (args[n] == undefined)
			ii.error('invalid parameter '+n+' to ii.elm');
		else if (args[n].nodeType)
			newelm.appendChild(args[n])
		else if (typeof(args[n]) == 'string')
			newelm.appendChild(document.createTextNode(args[n]));
		else
			setatts(newelm, args[n]);

	}
	return newelm;
}

// returns an img elment with specific src and dimensions
ii.pngImage = function(img, w, h) {

	var elm = document.createElement('img');
	elm.style.width = w + 'px';
	elm.style.height = h + 'px';
	elm.src = 'media/'+img;
	return elm;
}

ii.userLink = function(id, name)
{
	if (name=='Anonymous')
		return ii.elm('a', {className:'user'}, name);
	else
		return ii.elm('a', {className:'user', href:'#rel&item=u.'+id}, name);
}

ii.videoLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=v.'+id}, name);
}

ii.photoLink = ii.poiLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=p.'+id}, name);
}
ii.tripLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=t.'+id}, name);
}
ii.groupLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=g.'+id}, name);
}
ii.spotLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=s.'+id}, name);
}
ii.albumLink = function(id, name)
{
	return ii.elm('a', {href:'#rel&item=a.'+id}, name);
}

ii.setText = function(elm, newText)
{
	if (ii.browser.msie)
		elm.innerText = newText;
	else
		elm.textContent = newText;
}

ii.stopPropagation = function(ev) {

    if (ev) {
        // All incl. IE, will do nothing if browser doesn't support it.
        ev.cancelBubble = true;

        // Firefox and DOM specific.
        if (ev.stopPropagation) {
            ev.stopPropagation();
        }
    }
}

ii.formatDate = function(timestamp, format)
{
	var dt = new Date((parseInt(timestamp))*1000);
	return dt.format(format);
}

ii.formatDistance = function(dist)
{
	if (dist===undefined)
		return undefined;
	dist = parseInt(dist);
	return (dist < 2000 ? dist + ' m' : Math.round(dist/1000) + ' km');
}

ii.formatSpeed = function(s)
{
	if (s == undefined)
		return '';
	else
        // api returns values in m/s, so 1m/s * 1km/1000m * 3600s/h = 3.6km/h
		return Math.round(s * 3.6) + ' km/h';
}

ii.formatTimespan = function(t)
{
	if (t < 120)
		return t + ' secs';
	else if (t/60 < 240)
		return Math.round(t/60) + ' min';
	else
		return Math.round(t/3600) + ' hours';
}


ii.formatLocation = function(lat, lon, spotid, spotname, locname)
{
	if (spotname)
		return ii.elm('span',
				'@ ',
				spotLink(spotid, spotname),
				', ',
				ii.geoCode(lat, lon, locname)
			);
	else
		return ii.elm('span',
				'@ ',
				ii.geoCode(lat, lon, locname)
			);
}

ii.iframeDocument = function(iframe)
{
	if (iframe.contentDocument)     return iframe.contentDocument.documentElement;
	else if (iframe.contentWindow) return iframe.contentWindow.document.body;
	else if (iframe.document) return iframe.document;

}


/**
 * set a cookie to the given name and value for a period of days. if days is
 * less than zero, then cookie will be expired immediately, if it is 0 then it
 * will expire once the browser is exited. if days is not defined, it will be
 * set to 14 days.
 *
 * @param {Object} name  the name of the cookie
 * @param {Object} value the value of the named cookie
 * @param {Object} days  the number of days to expire the cookie in.
 */
ii.setCookie = function(name, value, days){

	var days = (days === undefined) ? 14 : days;
	var ms_in_day = 86400000; /* 24 * 60 * 60 * 1000 */

    if( days == 0 ){
        document.cookie = name+'='+value+'; path=/';
    }
    else {
        var cookie_expiration_date = new Date();
        cookie_expiration_date.setTime( cookie_expiration_date.getTime() + ( days * ms_in_day) );

        document.cookie = name+'='+value+'; expires='+cookie_expiration_date.toGMTString()+'; path=/';
    }
}

/**
 * get the value for the named cookie.
 *
 * @param {Object} name the name of the cookie to return the value of.
 */
ii.getCookieValue = function(name){
	// the return value
	var value = '';

	// make sure this document has cookies
	var cookies = document.cookie.split(';');
	if(cookies.length){
		var num_of_cookies = cookies.length;

		// loop through the cookies looking for the correct cookie name
		// 1. compare the names
		// 2. extract the value
		for(var i = 0; i < num_of_cookies; i++){
			var cookie = cookies[i];

			// 1.
			if( cookie.indexOf(name+'=') > -1 ){
				// 2.
				value = cookie.split(name+'=')[1];
				break;
			}
		}
	}

	return value;
}

/**
 * expire a cookie of a given name
 *
 * @param {Object} name the name of the cookie to expire
 */
ii.removeCookie = function(name){
	ii.setCookie(name,'',-1);
}

ii.selectItemBrowserTab = function(){

    if(ii.app.state.state.item && ii.app.state.state.item.indexOf('ME') > -1){
		document.getElementById('ii_menu_home').className = 'selected';
		document.getElementById('ii_menu_world').className = '';
    }
    else if (!ii.app.state.state.item)
	{
		document.getElementById('ii_menu_home').className = '';
		document.getElementById('ii_menu_world').className = 'selected';
    }
	else
	{
		document.getElementById('ii_menu_home').className = '';
		document.getElementById('ii_menu_world').className = '';
    }
}

/**
 * decode a javascript query string into a javascript object. eg:
 *
 * id=000001&name=andrew&action=add
 *
 * would return
 *
 * {id:'000001', name:'andrew', action:'add'}
 *
 * @param {Object} qs
 * @returns Object containing all params
 */
ii.decode_query_string = function(qs){
	var o = {};

	// trim the ? on the front if it exists.
	if(qs.substring(0,1).indexOf('?')>-1){
		qs = qs.substring(1);
	}

	// parse out the '&' and '='
	var qs_parts = qs.split('&');
	for(var i=0, len = qs_parts.length; i<len; i++){
		var kv = qs_parts[i].split('=');
		var k  = decodeURIComponent(kv[0]);
		var v  = decodeURIComponent(kv[1]);

		o[k] = v;
	}

	return o;
}

/**
 * encode a javascript object as query string in name=value pairs, without, the
 * '?' at the front.
 *
 * eg: {id:'000001', name:'andrew', action:'add'}
 *
 * would return
 *
 * id=000001&name=andrew&action=add
 *
 * @param {Object} qs_obj
 */
ii.encode_query_string = function(qs_obj){
	var qs = [];
	for(var k in qs_obj){
		qs.push(encodeURIComponent(k)+'='+encodeURIComponent(qs_obj[k]));
	}
	return qs.join('&');
}

// Sets a default text for an input or textarea
// that autohides on focus
ii.setDefaultText = function(elm, defaultText)
{
	if (!elm.hasFocus)
		elm.value = defaultText;
	elm.defaultText = defaultText;
	elm.style.color = '#707070';
	elm.onfocus = function()
	{
		if (this.value == defaultText)
			this.value = '';
		this.hasFocus = true;
	}

	elm.onblur = function()
	{
		if (this.value == '')
		{
			this.value = defaultText;
		}
		this.hasFocus = false;
	}
}

ii.getTextBoxValue = function(elm)
{
	if (!elm.defaultText || elm.value != elm.defaultText)
		return elm.value;
	else
		return '';
}

// use this to get an elm by cause ie7 doesn't support formelm.elmname
ii.getElmByName = function(form, name)
{
	if (false && !ii.browser.msie7)
		return form[name];
	else
	{
		for (var i=0;i<form.elements.length;i++)
		{
			var e = form.elements[i];
			if (e.getAttribute('name') == name)
				return e;
		}
	}

}

ii.createId = function() {
    return 'ii_id_'+Math.ceil(Math.random()*300000);
}

// transforms element (usually button)
// to a throbber
ii.startWaitButton = function(elm)
{
	elm.oldText = elm.value;
	elm.value = '  ';
	elm.className = (elm.className||'') + ' waiting';
	elm.blur();
	elm.disabled = true;
}


ii.endWaitButton = function(elm)
{
	elm.value = elm.oldText;
	elm.className = elm.className.replace('waiting','');
	elm.disabled = false;

}

ii.getMessageBox = function(options){
	// why no background-image?
    var message = options.message === undefined ? '' : options.message;
    var style = options.style === undefined ? {} : options.style;

    var message_box = ii.elm('div', {
            className: 'messagebox',
            style: style
        },
        ii.elm('span', message),
        ii.elm('img', {
            src: '/media/balloon_curve_SML.gif'
        })
    );

    return message_box;
}
ii.getMessageBox = function(options) {
    var message = options.message === undefined ? '' : options.message;
    var style = options.style === undefined ? {} : options.style;
	style.position = 'relative';
	style.maxWidth = '290px';
	style.marginTop = '86px';

    var message_box = ii.elm('div', {
            className: 'msgbox',
            style: style
        },
        ii.elm('div', message),
        ii.elm('img', {
            src: '/media/balloontip_discs.gif',
			style: {
				position: 'absolute',
				top: '-26px',
				left: '10px'
			}
        })
    );

    return message_box;
	//<div data-field="messagebox" data-editable="true" style="position:relative;" class="msgbox"><div>ddddsstestje test...sss</div><form style="display: none; "><textarea>ddddsstestje test...sss</textarea><input type="submit" value="Apply"><input type="reset" value="Cancel"></form><img src="/media/balloontip_discs.gif" style="position: absolute; top: -26px; left: 10px; "></div>
}

/**
 * perform actions that need done when the message box gain focus
 *   - replace the callout image.
 *
 * @param {Object} elm
 */
ii.handle_messagebox_focus = function(elm){

    elm.style.backgroundImage = 'none';
    elm.style.backgroundColor = 'white';

    var img_elm = elm.parentNode.getElementsByTagName('img')[0];
    img_elm.src = './media/balloon_curve_SMLX.gif';


    if (elm.setSelectionRange) {
        elm.setSelectionRange(0, elm.value.length);
    }
    else if(elm.createTextRange) {
        var range = elm.createTextRange();
        range.collapse(true);
        range.moveStart('character', 0);
        range.moveEnd('character', elm.value.length);
        range.select();
    }
}

/**
 * perform actions that need done when the message box loses focus:
 *   - replace the callout image.
 *
 * @param {Object} elm
 */
ii.handle_messagebox_blur = function(elm){

    elm.style.backgroundImage = 'url(media/tab_poi_bground.png)';
    elm.style.backgroundRepeat = 'repeat-x';

    var img_elm = elm.parentNode.getElementsByTagName('img')[0];
    img_elm.src = './media/balloon_curve_SML.gif';
}

/**
 * a function to handle adding event listeners to all browsers
 *
 * @param {Object} elm the element to have the listener attached to
 * @param {Object} type the type of event to listen for
 * @param {Object} fn the function to call when the event fires.
 */
ii.addEvent = function(elm, type, fn){
    // add an event listener to the elm depending on whether the browser
    // suports the dom[1], is internet explorer[2], or something else[3],
    // when the event fires the fn will be called.

    try {
        // 1.
        elm.addEventListener(type, fn, true);
    }
    catch(e){
        try {
            // 2.
            elm.attachEvent('on'+type, fn);
        }
        catch(e){
            // 3.
            elm['on'+type] = fn;
        }
    }
}

ii.autosizeTextArea = function()
{
   if ( this.scrollHeight > this.clientHeight )
         this.style.height = this.scrollHeight + "px";
}

/**
 * given a string then insert a href where necessary and append to the element
 * e and return resulting html. if e is undefined, then the resulting html is
 * returned, but not appended to the dom.
 *
 * the function recognized extern hrefs (http://google.com) and
 * internal hrefs (#item=u.9). For the internals, a name lookup is performed
 *
 * @param {String} s the string of text to insert href.
 * @param {Object} e the element to inser the string into.
 */
ii.text2href = function(s, e){
    var url_match = /https?:\/\/([-\w\.]+)+(:\d+)?(\/([\w\./_-]*(\?\S+)?(#\S+)?)?)?/;
    var intern_match = new RegExp("(?:https?:\\/\\/" + window.location.host + "\\/)?#(\\w+)=([\\w\\.%]*)(?:&(\\w+)=([\\w\\.%]*))*", "g");

    var elm = e || document.createElement('p');

	for(;;) {
		var url_m = url_match.exec(s);
		var int_m = intern_match.exec(s);

		// url match comes first?
		if (url_m!=null && (int_m == null || url_m.index < int_m.index))
		{
			// add the text before the url as text
			if (url_m.index > 0) {
				elm.appendChild(
						document.createTextNode(s.substr(0,url_m.index))
				);
			}
			// add the url as link
			elm.appendChild(ii.elm('a', {
					href: url_m[0],
					rel: 'nofollow',
					target: '_blank'
				},
				url_m[0]
			));
			s = s.substr(url_m.index + url_m[0].length);
		}
		// intern match comes first?
		else if (int_m!=null)
		{
			// add the text before the url as text
			if (int_m.index > 0) {
				elm.appendChild(
						document.createTextNode(s.substr(0,int_m.index))
				);
			}

			// we need to wrap this part in a function
			// to make link a local var, and allow it
			// to be used as closure in ii.get
			(function() {
				var link = ii.elm('a', { href: int_m[0] }, int_m[0]);

				var properNameFound =false;

				// if we have an item property, we're gonna find a proper name
				for (var n=1; n < int_m.length-1; n+=2)
				{
					if (int_m[n] == 'item')
					{
						ii.log('using item: ' + int_m[n+1]);
						var itm = int_m[n+1].split('.');
						if (itm.length!=2)
							break;
						var tp = ii.typename[itm[0]];
						var id = itm[1];
						ii.get('q-items-'+tp,
							function(resp) {
								if (resp.items.length==1) {
									ii.setText(link, resp.items[0].name);
									link.className = 'micro '+tp;
								}
							},
							{
								id: id,
								fields: 'basic'
							}
						);
						properNameFound = true;

					}
				}
				// if no name found, try "tab" param for name
				if (!properNameFound) {
					for (n=1; n < int_m.length; n+=2) {
						if (int_m[n] == 'tab') {
							ii.setText(link, int_m[n+1]);
						}
					}
				}
				// add the url as link
				elm.appendChild(link);
			})();


			s = s.substr(int_m.index + int_m[0].length);
		}
		else
			break; // no more matches
	}

    if(s){
        elm.appendChild(document.createTextNode(s));
    }

    return elm.innerHTML;
}


/**
 * removes leading and trailing white space from string s
 *
 * @param {Object} s
 */
ii.trim = function(s){
    if( typeof s == 'string'){
        s.replace('/^\s+|\s+$/g', '');
    }
    return s;
}


ii.obj2json = function(input) {
    if (input===undefined) return 'null'
    switch (input.constructor) {
      case String: return '"' + input + '"'
      case Number: return input.toString()
      case Array :
        var buf = []
        for (var i in input)
          buf.push(ii.obj2json(input[i]))
            return '[' + buf.join(',') + ']'
      case Object:
        var buf = []
        for (var k in input)
          buf.push('"'+ k + '":' + ii.obj2json(input[k]))
            return '{ ' + buf.join(',') + '} '
	  case Boolean:
		return input ? 'true' : 'false';
      default:
        return 'null'
    }
}

// pass the name of the parameter that will change
// default parameter is "page"
// You can also pass a function that will be invoked
// whenever the pagenr changes. The function param will
// be the pagenr
//
// Will create this.divs[0] and this.divs[1] containing pagers
ii.Pager = function(urlparam)
{
	if (urlparam instanceof Function)
		this.callback = urlparam;
	else
		this.urlparam = (urlparam || 'page');

	this.counter = ii.elm('span', {className: 'cnt'}, ' (...)');
	this.divs = [
	 	ii.elm('div', {className:'pager'}),
		ii.elm('div', {className:'pager'})
	];

}


// Callback function for ii.Query object that is invoked when the count
// changes. This will create/update the pager-divs
ii.Pager.prototype.countItems = function(start, count, total, pagesize)
{
	// set counter in header
	ii.setText(this.counter, ' ('+total+')');

	// get page nr and page range
	var page =   1+(start/pagesize);
	var pages = Math.ceil(total/pagesize);
	var p1 = Math.max(1,page - 5);
	var p2 = Math.min(pages,page + 5);
	if (p2 >= 10)
	{
		var p1 = Math.max(1,page - 4);
		var p2 = Math.min(pages,page + 4);
	}

	var that = this;
	function pagelink(pagenr, name)
	{
		var l = ii.elm('a', name);
		if (!that.urlparam)
		{
			l.href ='#rel';
			l.onclick = function() { that.callback(pagenr); };
		}
		else
			l.href = '#rel&'+that.urlparam+'='+pagenr;


		return l;
	}


	for(var t = 0; t < 2; t++)
	{
		var target = this.divs[t];
		while(target.firstChild)
			target.removeChild(target.firstChild);

		if (pages==1)
			continue;

		if (start > 0)
		{
			target.appendChild(pagelink(page-1, '<<'));
			target.appendChild(document.createTextNode(' | '));
		}
		for(var n=p1; n <= p2; n++)
		{
			if (page == n)
				target.appendChild(ii.elm('span', {className:'sel'}, n.toString()));
			else
				target.appendChild(pagelink(n,n.toString()));

			if (n<p2)
				target.appendChild(document.createTextNode(' | '));
		}
		if (start+count < total)
		{
			target.appendChild(document.createTextNode(' | '));
			target.appendChild(pagelink(1+page,'>>'));
		}

	}
}


ii.set_itempane_animate_speed = 80;
ii.set_itempane_animate_collapse_fact = 3;
ii.set_itempane_animate_expand_fact = 2;

ii.set_wait_before_status = 10000; //ms
ii.set_status_maxage = 10000; //ms
ii.set_interval_status = 6000; //ms


ii.app = {
    // has the map been initialized?
    initialized: false
};


// listener for status-display of item count
ii.app.statusDisplay = {
	counters: {photo:[0,0], video:[0,0], user:[0,0], trip:[0,0], spot:[0,0]},
	item: null,
	countItems: function(start, count, total, pagelen, type)
	{
        ii.log('counting '+type+' = '+total);
		this.counters[type] = [count,total];
		this.update();
	},

	getCount: function(name, label)
	{
		if (this.counters[name][1] == 0)
			return '';

		else if (this.counters[name][1] != this.counters[name][0])
			return  ('' + this.counters[name][0])
				+ ' of ' + this.counters[name][1] + ' ' +ii.typeplural[ii.typeletter[name]] 
				+ ', ';

		else if (this.counters[name][0] > 1)
			return  ('' + this.counters[name][0]) +  ' '+ ii.typeplural[ii.typeletter[name]] 
				+ ', ';

		else 
			return  ('' + this.counters[name][0]) + ' ' +ii.typesingle[ii.typeletter[name]] 
				+ ', ';
	},

	update: function()
	{
		var t = '';

		t += this.getCount('user');
		t += this.getCount('photo');
		t += this.getCount('video');
		t += this.getCount('trip');
		t += this.getCount('spot');

		if (t!='')
		{
			t = t.substr(0,t.length-2);
			if (ii.app.state.state.ll)
			{
				s = 'Showing in current Area: ' + t;

			}
			else
			{
				var s =	'Showing: ';
				if (this.item)
					s += this.item + ' ';
				s = 'Showing: ' + (this.item? this.item+' ':'')
					+ '<a href="javascript://viewAll" '
					+ 'onclick="ii.app.map.viewAll();">'
					+ t + ' world-wide' + '</a>';
			}
		}
		else if (this.item)
		{
			s = 'Showing: ' + this.item.substr(0,this.item.length-2);
		}
		else
			s = '';

		document.getElementById('ii_status_displaying').innerHTML = s;
	},
	reset: function(type, name)
	{
		if (!type)
			this.item = null;
		else if (type=='ME')
			this.item = 'You, ';
		else
			this.item = (ii.typesingle[type] + ' \''
					+ name + '\', ').toLowerCase();
		this.counters = {photo:[0,0], video:[0,0], user:[0,0], trip:[0,0], spot:[0,0]};
		this.update();
	}
};

function handleError(err) {
  alert('Failed to retrieve position');
	ii.log('error retrieving position ('+err.code+' '+err.message+')');
	var lb = document.getElementById('ii_lightbox');
	lb.style.display = 'none';
}

repeatLast = 0;
hasalerted = false;

function updatePos(pos) {
    if (!hasalerted)
    {
        hasalerted = true;
//        alert('Received position');
    }
	if (navigator.geolocation.type == 'FixedLocation')
		var locateMethod = 'IP Location';
	else
		var locateMethod = 'WiFi Location';

	if (repeatLast)
		window.clearTimeout(repeatLast);

    ii.log('invoking updatepos with watchid='+ii.watchId);
    
    if (ii.watchId===undefined)
        return;

	var coords = pos.coords;
	window.coords =
		{ lat:coords.latitude, lon:coords.longitude };


	ii.get(
		'p-new-loc',
		function() {
			if (!ii.app.isLocated)
			{
				ii.log('First time locating');
				ii.app.isLocated = true;
				function done() {
					ii.log('Done locating; zoomtodeep');
					ii.app.map.zoomToDeep(coords.latitude, coords.longitude,
						function() {
							ii.log('zooming');
							var lb = document.getElementById('ii_lightbox');
							lb.style.display = 'none';
							document.getElementById('ii_locatemebtn').style.display = 'block';
							ii.setText(document.getElementById('ii_locatemebtn'), locateMethod);

						}
					);
				}
				if (!ii.login)
				{
					ii.anonMe = {
						type: 'u',
						name: 'Anonymous',
						lat: window.coords.lat,
						lon: window.coords.lon,
						status: 'live'
					}
					ii.anonMe = new ii.items.User(ii.anonMe);
						ii.app.map.addItem(ii.anonMe);
					done();
					/*
					if (!ii.anonQuery)
					{
						ii.anonQuery = new ii.Query('user', {interval:15000}, {me:true});
						ii.anonQuery.addListener(ii.app.map);
					}
					ii.anonQuery.start();
					ii.log('adding anonuser');
					ii.anonQuery.addListener({addItem: done});
					ii.anonQuery.addListener({addItem: function(item) { ii.anonItem = item;} });
					*/
				}
				else
				{
					ii.login.query.doUpdate();
					done();
					window.setTimeout(function() {
						ii.login.item.jumpToCurrentPosition();
						
						}, 2000);
					
				}

			}
		},
		{ lat:coords.latitude, lon:coords.longitude }
	);


	repeatLast = window.setTimeout(function() {
		updatePos(pos); }, 1000 * 6);
}

ii.app.locateme = function() {
	if (ii.app.isLocated)
	{
		ii.log('already located, jumping');
		if (ii.login && ii.login.item)
		{
			ii.login.item.jumpToCurrentPosition();
			ii.app.map.zoomToDeep(ii.login.item.lat, ii.login.item.lon);
			ii.log('aa');
		}
		else if (ii.anonMe)
		{
			//ii.anonMe.jumpToCurrentPosition();
			ii.app.map.zoomToDeep(ii.anonMe.lat, ii.anonMe.lon);
		}
	}
	else if (navigator.geolocation)
	{
		ii.app.isLocated = false;
		// initiate lgightbox
		var lb = document.getElementById('ii_lightbox');
		lb.style.display = '';
		if (navigator.geolocation.type == 'FixedLocation')
			var locateMethod = 'ip';
		else
			var locateMethod = 'wifi';


		document.getElementById('ii_lightbox_ip').style.display
			 = (locateMethod == 'ip' ? '' : 'none');
		document.getElementById('ii_lightbox_wifi').style.display
			 = (locateMethod == 'wifi' ? '' : 'none');

		var options = {
			enableHighAccuracy: true,
			maximumAge: 0, //1000 * 30 /* 30 secs
			timeout: 24000
		}
		ii.log('Initializing watchPosition');

       ii.watchId = navigator.geolocation.watchPosition(updatePos, handleError, options);
       ii.log('Created watch: ' + ii.watchId + ' with type ' + navigator.geolocation.type);

	}
}

ii.app.uncenterActiveItem = function() {

	var isCentered = !!(document.getElementById('ii_centerbtn').className.indexOf('pressed') != -1)
	if (isCentered)
	{
		ii.app.centerActiveItem();
	}
}
ii.app.centerActiveItem = function() {
	
	var isCentered = !!(document.getElementById('ii_centerbtn').className.indexOf('pressed') != -1)
	ii.log('centerActiveItem invoked: ' + isCentered);

	ii.item.center(!isCentered);
	ii.stopPropagation();
}

ii.app.zoomMarquee = function() {
	var btn = document.getElementById('ii_zoommarqueebtn');
	if (btn.className.indexOf('pressed')>-1)
	{
		btn.className = btn.className.replace('pressed','');
		ii.app.map.zoomMarquee(false);
	}
	else
	{
		btn.className = btn.className + ' pressed';
		ii.app.map.zoomMarquee(true);
	}
}

ii.app.selectMap = function() {
	var btn = document.getElementById('ii_selectmapbtn');
	if (btn.className.indexOf('pressed')>-1)
	{
		btn.className = btn.className.replace('pressed','');
		ii.app.map.layerSelector(false);
	}
	else
	{
		btn.className = btn.className + ' pressed';
		ii.app.map.layerSelector(true);
	}
}

ii.app.setCenterButton = function(pressed) {
	document.getElementById('ii_centerbtn').className = 
		pressed ? 'pressed mapbutton' : 'mapbutton';
}

ii.app.init = function(){
	ii.log('APP INIT');

	ii.app.initClock();


	// if there is an item in the url we don't want to see the landing page.
	if( document.location.hash.indexOf('#') > -1
		&& document.location.hash.indexOf('Welcome') == -1)
	{
		ii.app.landing.remove();
	}

    // instatiate the state handler that monitors document.location and updates
	// the page upon updates, make sure this only happens once.
    if(ii.app.state === undefined){
      	ii.app.state = new ii.State();
        ii.app.state.init();
    }

    // note: ii_landing_page is removed from the dom after login from landing
    // page, hence, this will be false
    var viewLanding = document.getElementById('ii_landing_page') || false;

    if (ii.login || viewLanding === false)
	{
		// setup wait button
		ii.startWait = function(){
			var e = document.getElementById('ii_wait_icon');
			e.className = e.className.replace('waitoff', 'waiton');

			var e = document.getElementById('ii_active_item_label');
			e.className = e.className.replace('waitoff', 'waiton');
		}

		ii.stopWait = function(){
			var e = document.getElementById('ii_wait_icon');
			e.className = e.className.replace('waiton', 'waitoff');

			var e = document.getElementById('ii_active_item_label');
			e.className = e.className.replace('waiton', 'waitoff');
		}

		document.getElementById('landing_logo').style.display = 'none';
		// initialize various components
		ii.app.initScreenComponents();
		ii.app.initSearchBox();
		ii.app.initMap();
		ii.app.initMiniFeed();
		ii.app.initMouseEvents();
		ii.app.setWorldExpand();
		ii.app.initTipBalloon();


        ii.app.initialized = true;

		// clear initial item
		ii.app.applyState({item: ''}, {item: ''});


		if (window.ii_autologin)
		{
			ii.login = new ii.Login(
				ii.getCookieValue('id'),
				ii.getCookieValue('username'),
				ii.getCookieValue('key')
			);
			if (document.location.hash.indexOf('#') < 0)
				window.location='#item=ME.0';
		}
		else
			document.getElementById('ii_locatemebtn').style.display = 'block';

		if (ii.app.postInit)
			ii.app.postInit();
    }
    else {
        // not logged in, show landing...

        // hide screen elements
        document.getElementById('ii_pane_itemlist_container').style.display = 'none';
        document.getElementById('ii_status_explore_container').style.display = 'none';

		// the start/stop wait icons should not be displayed on the landing page
		// so define these to do nothing.
		ii.startWait = function(){};
		ii.stopWait  = function(){};

		// show landing page
        var target = document.getElementById('ii_landing_page');
		ii.app.landing.setup(target);
    }

	ii.app.setupWindowResize();

}

// create clock
ii.app.initClock = function()
{
	return;
	var prev = document.getElementById('ii_clock');
	if (prev)
		prev.parentNode.removeChild(prev);
    var clock = ii.createClock();
	
    document.getElementById('ii_header').appendChild(clock);
}

ii.app.initMouseEvents = function()
{
	var ii_search = document.getElementById('ii_search');
	var ii_itemlist = document.getElementById('ii_itemlist');
	var ii_menu = document.getElementById('ii_menu');
	var ii_center = document.getElementById('ii_centerbtn');
	var ii_zoommarquee = document.getElementById('ii_zoommarqueebtn');
	var ii_explorearea = document.getElementById('ii_lock_map');
	var ii_selectmapbtn = document.getElementById('ii_selectmapbtn');

	ii.addEvent(ii_search, 'mousedown', ii.stopPropagation);
	ii.addEvent(ii_menu, 'mousedown', ii.stopPropagation);

	ii.addEvent(ii_itemlist, 'mousemove', ii.stopPropagation);
	ii.addEvent(ii_search, 'mousemove', ii.stopPropagation);
	ii.addEvent(ii_menu, 'mousemove', ii.stopPropagation);

	ii.addEvent(ii_itemlist, 'dblclick', ii.stopPropagation);
	ii.addEvent(ii_search, 'dblclick', ii.stopPropagation);
	ii.addEvent(ii_menu, 'dblclick', ii.stopPropagation);
	
	ii.addEvent(ii_center, 'mousedown', ii.stopPropagation);
	ii.addEvent(ii_zoommarquee, 'mousedown', ii.stopPropagation);
	ii.addEvent(ii_explorearea, 'mousedown', ii.stopPropagation);
	ii.addEvent(ii_selectmapbtn, 'mousedown', ii.stopPropagation);
}

ii.app.initScreenComponents = function()
{
	// show the item browser
	document.getElementById('ii_pane_itemlist_container').style.display = 'block';

	// hide the explore bar
	document.getElementById('ii_status_explore_container').style.display = 'block';

	document.getElementById('ii_centerpane_container').style.visibility
		= 'hidden';
}

ii.app.initSearchBox = function()
{
	ii.app.searchBox = document.getElementById('ii_searchbox');

	document.getElementById('ii_searchform').onsubmit = function() {
		if (this.query.value == ''
				|| this.query.value == this.query.defaultText)
			return false;
		ii.app.state.setState({query: this.query.value});
		return false;
	}


}

ii.app.initMap = function()
{
	ii.app.map = new ii.Map(document.getElementById('ii_map'));
}

ii.app.initTipBalloon = function()
{
	var f = ii.getCookieValue('hide_balloon');
	if (f == 'true')
		return;

	var d = ii.elm('div', {className:'tipbox'});
	d.innerHTML = '<img src="media/tip_balloon_tip.png" />'
			+'<p><strong>Tip</strong></p>'
			+'<p>Press <strong>Locate Me</strong> to start sharing your <span class="live"><strong>Live</strong></span>'
			+' location stream</p>'
			+'<small><a id="hide_tipbox" href="#">close</a></small>'
			+'<small style="position:relative; top:-8px;" >Show balloon next time </small>'
			+'<form><input id="hide_tipbox_c" checked="checked" type="checkbox" /></form>';

	document.body.appendChild(d);
	document.getElementById('hide_tipbox').onclick = function() {
		d.style.display = 'none';
		return false;
	};
	document.getElementById('hide_tipbox_c').onclick = function() {
		ii.log(this.checked);
		if (this.checked)
			ii.removeCoookie('hide_balloon');
		else
			ii.setCookie('hide_balloon', 'true', 300);
		return false;
	}

}

ii.app.initMiniFeed = function()
{
	//Setup mini feed
	ii.app.statusQuery = new ii.Query('feed', {
		interval: ii.set_interval_status 
	}, {
		count: 1,
		maxage: ii.set_status_maxage / 1000
	});
	ii.app.statusQuery.addListener({
		addItem: function(item){

			ii.log('adding feed item');
			var vw = item.createView('SmallView');
			var s = document.getElementById('ii_status_explore_container');
			vw.div.style.background = 'white';
			vw.div.style.position = 'absolute';
			vw.div.style.top = '0px';
			vw.div.style.width = '100%';
			vw.div.style.marginLeft = '381px'; 
			vw.div.style.marginTop = '12px'; 
			vw.div.style.fontSize = '12px';

			s.appendChild(vw.div);

		}
	});
	window.setTimeout(function(){
		ii.app.statusQuery.start();
	}, ii.set_wait_before_status);
}

// called when the hash changes
ii.app.applyState = function(state, changedState){
    ii.log('APPLY');
    ii.dir(changedState);

	// event tracking
	if (changedState.tab)
		ii.tracker._trackEvent('Navigate', 'TabChange', changedState.tab);

	if (changedState.item)
		ii.tracker._trackEvent('Navigate', 'SelectItem', changedState.item);

	if (changedState.query)
		ii.tracker._trackEvent('Navigate', 'Search', changedState.query);

    if (ii.app.initialized === false && 
		((changedState.q === undefined && changedState.tab === undefined) 
		|| changedState.tab == '' || changedState.tab == 'Map'))
	{
        ii.app.init();
    }

    // pane change in browse-view is full change
    if ((!state.item || state.query) &&
			(changedState.pane != undefined || changedState.page != undefined))
        changedState.item = '' + state.item;

    // new full pane?
    if (changedState.item != undefined || changedState.query != undefined)
	{
        //ii.app.currentFilter = state.query;
		ii.startWait();

		ii.app.uncenterActiveItem();

		// stop previous content
		if (ii.itemQuery)
        {
            if (ii.login && ii.itemQuery == ii.login.query)
            {
                for (var vw=0; vw< ii.login.item.itemviews.length;vw++)
                {
                    ii.log('checking view:');
                    if (ii.login.item.itemviews[vw].temporary)
                    {
                        ii.login.item.removeView(ii.login.item.itemviews[vw]);
                        vw--;
                    }
                }
            }
            else
            {
                ii.itemQuery.stop();
            }
        }

     	var pane = document.getElementById('ii_itemlist');

        if (state.item == 'ME.0' && !ii.login)
		{
			// not logged in,
			// add login box
			var div = ii.Login.loginBox();
			pane.appendChild(div);
			var un = ii.getElmByName(div,'username');
			un.focus();

			//ensure removal:
			ii.itemQuery = { type:'user', stop: function() { pane.removeChild(div); } };

			ii.stopWait();

            ii.app.statusDisplay.reset();

            ii.setText(document.getElementById('ii_active_item_label'), 'Login');
		}
		else if (state.item == 'ME.0' && ii.login && !state.query)
		{
			var welcomeView;
			var browserView;
			var query = ii.login.query;
			if (ii.login.item)
			{
				welcomeView = ii.login.item.createView('MyWelcomeBox');
				browserView = ii.login.item.createView('MyItemBrowser', {map:ii.app.map});
                welcomeView.temporary = true;
                browserView.temporary = true;
				pane.appendChild(welcomeView.div);
				pane.appendChild(browserView.div);
				ii.stopWait();
				if (ii.login && ii.login.item && ii.login.item.lat)
				{
					ii.log('zooming to:'+ii.login.item.lat, ii.login.item.lon);
					ii.login.item.jumpToCurrentPosition();
					ii.app.map.zoomToDeep(ii.login.item.lat, ii.login.item.lon);
				} 
				else if (ii.app.isLocated && ii.anonMe)
				{
					ii.app.map.zoomToDeep(ii.anonMe.lat, ii.anonMe.lon);
				}
			}
			else
			{
				var listener = {
					addItem: function(item) {
						welcomeView = item.createView('MyWelcomeBox');
						browserView = item.createView('MyItemBrowser', {map:ii.app.map});
                        welcomeView.temporary = true;
                        browserView.temporary = true;
						pane.appendChild(welcomeView.div);
						pane.appendChild(browserView.div);
						item.jumpToCurrentPosition();
						ii.app.map.zoomToDeep(item.lat, item.lon);

						ii.stopWait();
					}
				}
				query.addListener(listener);
			}
			ii.itemQuery = ii.login.query;

            ii.setText(document.getElementById('ii_active_item_label'), 'Me');

		}
		else
		{
			if (!state.item || state.query)
				var s = ['g',1];
			else
				var s = state.item.split('.');

			var type = ii.typename[s[0]];
			if (!type) return;
			var id = s[1];


			var opts = {interval: ii.set_interval_largeitem};
			var params = {fields: 'full'};

			// world? get counts, otherwise get item-id
			if ((type=='group' && id==1) || state.query)
				opts.url = 'q-items-count';
			else
				params.id = id;

			if (state.query)
			{
				if (state.item == 'ME.0')
					params.user = ii.login.id;
				else if (state.item)
				{
					var typeletter = state.item.split('.')[0];
					var typeid = state.item.split('.')[1];

					params[ii.typename[typeletter]] = typeid;
				}
				params.query = state.query;
			}

			var query = new ii.Query(type, opts, params);
			var listener = {
				addItem: function(item) {

                    if (type=='group' && id==1) {
                        ii.setDefaultText(ii.app.searchBox, 'Search within World');
                        ii.app.statusDisplay.reset();
                        ii.setText(document.getElementById('ii_active_item_label'), 'World');
                    }
                    else {
                        ii.setDefaultText(ii.app.searchBox, 'Search within \''+item.name+'\'');
                        ii.app.statusDisplay.reset(type, item.name);
                        ii.setText(document.getElementById('ii_active_item_label'), ii.typesingle[item.type]);
                    }


					var vw = item.createView('LargeListItem');
					pane.appendChild(vw.div);

					var browser = (type=='group' && id==1
							? 'WorldItemBrowser'
							: 'ItemBrowser'
					);

					var vw = item.createView(browser, {map:ii.app.map,params:params});
					pane.appendChild(vw.div);

					ii.app.map.addItem(item, true);

                    ii.item = item; // TODO: rethink this
                    ii.itemView = vw;

                    ii.log("Setting global item reference");

					ii.stopWait();

				},
				hasItems: function(count) {
					ii.log('hasitem: '+count);

					if (count)
						return;
					if (type=='group' && id==1)
						return;

					pane.appendChild(ii.elm('p', {className:'results'},
						'This ',
						ii.typesingle[type],
						' no longer exists or its privacy is restricted for you.',
						ii.elm('p',
							ii.elm('a', {
								href:'javascript:history.back();'},
								'Go back ')
						)
					));
					ii.itemQuery = {
						stop: function() { pane.innerHTML ='' } 
					};
					ii.stopWait();
			   }
			}
			query.addListener(listener);
			query.start();
			ii.itemQuery = query;
		}

    }

	if (changedState.ll != undefined)
	{
		var elmMap = document.getElementById('ii_lock_map');

		if (state.ll == 'map')
		{
			elmMap.className = 'mapbutton pressed';

			window.ii_extramap_height = 0;
			window.onresize();
			ii.app.map.map.updateSize();
			ii.app.map.updateExtend(); // will convert ll to coords
		}
		else if (!state.ll)
		{
			ii.log('clearing explore mode');
			elmMap.href = '#rel&ll=map';
			elmMap.className = 'mapbutton';

			if (ii.item)
			{
				for(var n in ii.item.itemviews)
					if (ii.item.itemviews[n].setBounds)
						ii.item.itemviews[n].setBounds({
							lat1: '',
							lon1: '',
							lat2: '',
							lon2: ''
						});
			}
            ii.itemQuery.setQueryOpts({
                lat1: '',
                lon1: '',
                lat2: '',
                lon2: ''
            });
		}
		else
		{
			//ll are coords of extend
			elmMap.href = '#rel&ll=';
			elmMap.className = 'mapbutton pressed';

			ar = state.ll.split('x');
			if (ii.item)
			{
				for(var n in ii.item.itemviews)
					if (ii.item.itemviews[n].setBounds)
						ii.item.itemviews[n].setBounds({
							lat1: ar[1],
							lon1: ar[0],
							lat2: ar[3],
							lon2: ar[2]
						});
			}
			ii.itemQuery.setQueryOpts({
				lat1: ar[1],
				lon1: ar[0],
				lat2: ar[3],
				lon2: ar[2]
			});
		}
	}

    if (ii.app.SearchBox && ii.app.searchBox.value != state.query) {
        ii.app.searchBox.value = state.query;
        if (!state.query)
		{
			if (!ii.app.searchBox.hasFocus)
	            ii.app.searchBox.value = document.getElementById('ii_searchbox').defaultText;
			else
	            ii.app.searchBox.value = '';
            ii.app.searchBox.style.color = '#666666';

        }
    }
   	if (changedState.item!==undefined)
	{
		if (ii.app.state.state.item
				&& (ii.app.state.state.item != 'ME.0'
					|| ii.Login.isLoggedIn()))
		{
			var d = 'block';
			var f = '';
		}	
		else
		{
			var f = 'rightmost'
			var d = 'none';
		}

		document.getElementById('ii_btn_myfeed').className = f;
        document.getElementById('ii_btn_profile').style.display = d;

	;
	}
    // select the correct tabV
    var tab = state.tab ||
		(document.getElementById('ii_landing_page') ? 'Welcome' : 'Map');

	if (changedState.tab !== undefined)
	{
		var tabs = document.getElementById('ii_tabs').getElementsByTagName('a');
		for (var n=0; n < tabs.length; n++) {
            var isSelected = tab.indexOf(tabs[n].name.substr(4))==0;
            if (!isSelected && tabs[n].className.indexOf('selected')>=0)
                tabs[n].className = tabs[n].className.replace('selected','');
            else if (isSelected && tabs[n].className.indexOf('selected')<0)
                tabs[n].className += ' selected';
        }
	}

    // display the tab, it would be nice to only do this on changedState.tab or
    // subtab, however, when a pane changes (incl. page) the query gets removed
    // and the items with it, it would be nice if there was a way to keep
    // queries from pane to pane, and yet have items be automatically removed on
    // everything other than a page change.
    if( (changedState.item != undefined && (state.tab != undefined)) ||
         changedState.tab != undefined || changedState.subtab != undefined) {

		ii.log('loading tab: ' + tab);

        document.getElementById('ii_centerpane_container').style.visibility = (tab == 'Map' ? 'hidden' : 'visible');

        if (tab != 'Map') {
            // create and init static tab content
            ii.tabs.initTab(tab);
			if (ii.app.statusQuery)
				ii.app.statusQuery.pauseUpdate(true);
        }
		else
		{
			ii.tabs.cleanup();
			if (ii.app.statusQuery)
				ii.app.statusQuery.start();
		}
    }

    ii.selectItemBrowserTab();

    ii.app.refreshCenterPaneShadow();
}

ii.app.setWorldExpand = function() {
	var we = ii.getCookieValue('world_expand');
	if (!we) 
	{
		ii.itemExpand = {};
		ii.itemExpand['g.1.user'] = 
		ii.itemExpand['g.1.video'] = 
		ii.itemExpand['g.1.photo'] = true;
		return;
	}
	
	ii.itemExpand = {};

	var s = ['photo','user', 'video','trip','spot','group'];
	for(var k in s) 
		if (we.indexOf(s[k])>-1)
			ii.itemExpand['g.1.'+s[k]] = true;
		else
			ii.itemExpand['g.1.'+s[k]] = false;

}

ii.app.setupWindowResize = function(){
    window.onresize = function(){

        if (typeof(window.innerWidth) == 'number') {
            var h = window.innerHeight;
            var w = window.innerWidth;
        }
        else
            if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
                var h = document.documentElement.clientHeight;
                var w = document.documentElement.clientWidth;
            }


		var e = window.ii_extramap_height || 0;

		document.getElementById('ii_map').style.height = (h - 77 -40 + e) + 'px';

//        document.getElementById('ii_itemlist').style.height = (h - 85 - 78 + 6 -8) + 'px';
        document.getElementById('ii_pane_itemlist_container').style.height = (h - 85 - 78 + 6+77) + 'px';
        document.getElementById('ii_centerpane_scroller').style.minHeight = (h - 85 + 4)+'px';
        document.getElementById('ii_centerpane_scroller').style.maxHeight = (h - 85 + 4)+'px';
		document.getElementById('ii_centerpane').style.minHeight = (h-85+4-32)+'px';

        if (ii.map && ii.map.map) {
            var c = ii.map.map.controls;
            c[1].moveTo({
                x: Math.max(0, (w - cw) / 2) + 326 + 40,
                y: 15
            });
        }
		ii.app.refreshCenterPaneShadow();
    }

    window.onresize();
}


/**
 * refreshes the centerpane div shadow, based on the height of
 * ii_pane_itemlist_container (offset) height.
 */
ii.app.refreshCenterPaneShadow = function(){
	var pane_itemlist_container = document.getElementById('ii_pane_itemlist_container');
    if(pane_itemlist_container.style.display == 'none'){
        try {
            pane_itemlist_container = document.getElementById('ii_landing_page_container');
        }
        catch(e){
            // go ahead and use the pane_itemlist_container;
        }
    }

	var centerpane_container    = document.getElementById('ii_centerpane_container');

	var pic_height = pane_itemlist_container.offsetHeight;
	var cc_height  = centerpane_container.offsetHeight;

    var updated_left;
	var updated_bottomleft;
	updatedleft = updated_bottomleft = false;

	for( var i in pane_itemlist_container.childNodes ){
		var node = pane_itemlist_container.childNodes[i];
		if (node.nodeType != 1)
			continue;

		if (node.className.indexOf('chrome bottom') >-1) {
			node.style.display = 'none';

		}
	}

	for( var i in centerpane_container.childNodes ){
		// loop through the children of the centerpane container and do the
		// following:
		//  1. find a node that is an element node and matching the left
		//  2. update the top position of the found node.
        //  3. find a node that is an element node and matching the bottom left
		//  4. determine whether not to show the bottom left shadow.
		var node = centerpane_container.childNodes[i];

		// 1.
		if( updated_left === false                   &&
            1 /*Node.ELEMENT_NODE*/ == node.nodeType &&
            (node.className.indexOf('chrome left') > -1) ){

			// 2.
			if( cc_height > pic_height ){
				node.style.top = pic_height + 'px';
			}
			else{
				node.style.top = cc_height + 'px';
			}

            updated_left = true;

            if(updated_left === true && updated_bottomleft === true){
                break;
            }

		}

        // 3.
		if( updated_bottomleft === false             &&
            1 /*Node.ELEMENT_NODE*/ == node.nodeType &&
            (node.className.indexOf('chrome bottomleft') > -1) ){

            // 4.
            if( cc_height > pic_height ){
                node.style.visibility = 'visible';
            }
            else{
                node.style.visibility = 'hidden';
            }

            updated_bottomleft = true;

            if(updated_left === true && updated_bottomleft === true){
                break;
            }
        }

	}

	// get precise screen-height
	if (typeof(window.innerWidth) == 'number')
		var scr_height = window.innerHeight;
	else
		var scr_height = document.documentElement.clientHeight;

	// if the top of the itembrowser (=80) + it's height + height of
	// shadow (=10) exceeds screen height, hide bottom shadow
	if (pic_height+80+10 > scr_height)
		var disp_bottom = 'none';
	else
		var disp_bottom = '';

	for( var i in pane_itemlist_container.childNodes ){
		var node = pane_itemlist_container.childNodes[i];
		if (node.nodeType != 1)
			continue;

		if (node.className.indexOf('chrome bottom') >-1) {
			node.style.display = disp_bottom;

		}
	}

}




ii.Login = function(id, username, key)
{
	this.id = id;
	this.username = username;
	this.key = key;

	if (document.getElementById('ii_user_status_state'))
	{
//		document.getElementById('ii_user_status_state').innerHTML = 'Hi <a href="#rel&item=ME.0&pane=">' + this.username + '</a>! | '
		document.getElementById('ii_btn_logout').style.display='inline';
		document.getElementById('ii_btn_signup').style.display='none';
		document.getElementById('ii_btn_login').style.display='none';
		document.getElementById('ii_btn_add').style.display='block';
		document.getElementById('ii_btn_myinbox').style.display='block';
	}

	// we always need ourself
	if (!ii.Query) return;
	this.query = new ii.Query('user', {interval:10000}, {me:true,fields:'full'});
	this.query.start();

	if (ii.anonQuery)
	{
		ii.anonQuery.stop();
		ii.anonQuery = 0;
	}

	if (ii.anonMe) {
		ii.anonMe.remove();
	
	}

    // a view for the header status
	var that = this;

    this.query.addListener({
        addItem: function(item){
			that.item = item;
            item.createView('MyStatusState', {});
			that.setUnread();
			ii.app.map.addItem(item);

			document.getElementById('ii_locatemebtn').style.display 
				= ((item.status == 'live') ? 'none' : 'block');
			ii.setText(document.getElementById('ii_locatemebtn'), 
				'Locate Me');

        }
    });
	if (ii.tracker) ii.tracker._trackEvent('Session', 'Login', username);

    if (ii.watchId !== undefined)
    {
        ii.app.isLocated = false;
        ii.watchId = navigator.geolocation.clearWatch(ii.watchId);
        delete ii.watchId;
        ii.watchId = undefined;

    }
}

ii.Login.softLogout = function(){
	ii.get('s-logout', function(resp) {}, {soft:true});
}

ii.Login.prototype.logout = function(){

	window.location	= '#rel&item=&tab=';
	ii.get('s-logout', function(resp){

	    ii.removeCookie('id');
	    ii.removeCookie('username');
	    ii.removeCookie('key');

		delete ii.login;
		ii.app.state.refresh();
	});
	delete this.key;

    document.getElementById('ii_user_status_state').innerHTML = '';
	document.getElementById('ii_btn_logout').style.display='none';
	document.getElementById('ii_btn_signup').style.display='inline';
	document.getElementById('ii_btn_login').style.display='inline';
	document.getElementById('ii_btn_add').style.display='none';
	document.getElementById('ii_btn_myinbox').style.display='none';
    ii.log('stopping me-query');

	this.query.stop();
    ii.log('stopped me-query');

	ii.app.isLocated = false;

	ii.tracker._trackEvent('Session', 'Logout', this.username);

    if (ii.watchId !== undefined)
    {
        ii.app.isLocated = false;
        ii.watchId = navigator.geolocation.clearWatch(ii.watchId);
        delete ii.watchId;
        ii.watchId = undefined;

    }
	document.getElementById('ii_locatemebtn').style.display 
		= ('block');
	ii.setText(document.getElementById('ii_locatemebtn'), 
		'Locate Me');
}

ii.Login.prototype.updateAvatars = function()
{
	// for each view, with a div, update the imgs
	for(var n=0; n < this.item.itemviews.length; n++)
	{
		var vw = this.item.itemviews[n];
		var div = vw.div;
		if (!div && vw.details)
			div = vw.details.form;

		if (!div)
			continue;

		var imgs = div.getElementsByTagName('img');
		for (var m=0; m < imgs.length; m++)
		{
			if (/d-media/.test(imgs[m].src))
			{
				imgs[m].src += '&t=' + Math.random();
			}
		}
		if (div.style.backgroundImage &&
			/d-media/.test(div.style.backgroundImage))
		{
			ii.log('Reloading background-img');
			div.style.backgroundImage =
				div.style.backgroundImage.replace(')',
						'&t=' + Math.random()+')');
		}
	}
}

ii.Login.prototype.setUnread = function()
{
	var total = parseInt(this.item.unreadmsg)
		+ parseInt(this.item.unreadcmt);

	ii.log('setting unread: ' + total);
	var sp = ii.views.unreadIndicator(total);
	sp.id = 'ii_unread';

	var ur = document.getElementById('ii_unread');
	ur.parentNode.replaceChild(sp, ur);

	function setElm(id, count)
	{
		var ur = document.getElementById(id);
		if (ur && ur.parentNode)
		{
			var sp = ii.views.unreadIndicator(count);
			sp.id = id;
			ur.parentNode.replaceChild(sp, ur);
		}
	}
	setElm('ii_unread_msg', this.item.unreadmsg);
	setElm('ii_unread_cmt', this.item.unreadcmt);
	setElm('ii_unread_msg2', this.item.unreadmsg);
	setElm('ii_unread_cmt2', this.item.unreadcmt);

	if (total>0)
		var icon = 'favicon_notify.ico';
	else
		var icon = 'favicon.ico';

	document.getElementById('ii_favicon').innerHTML =
		'<link rel="shortcut icon" href="'+icon+'">';

}

ii.Login.isLoggedIn = function()
{
	return ii.login;
}

ii.Login.landingLoginBox = function()
{
	var loginBoxContainer = ii.elm('div', {
    		style: {
    			background: 'white',
    			left: '0px',
    			padding: '15px 16px 35px',
    			position: 'absolute',
    			top: '0px',
    			width: '294px',
    			zIndex: '999'
    		}
    	},
        ii.Login.loginBox({
            displayHeader: true,
            displayBorder: true,
            initOnSuccess: true
        })
    );

	return loginBoxContainer;
}

/**
 * the login box presented defined with the according options
 *
 * @param {Object} options an object defining the options for the loginbox
 */
ii.Login.loginBox = function(options)
{

    var options = (options !== undefined ? options : {});

	var error_p = ii.elm('p', { style:{color:'#FF0000', margin:'5px', position:'relative', textAlign:'center'}}, '');

	var username_input = ii.elm('input', { name:'username', style:{width:'100%'} } );
	var password_input = ii.elm('input', { name:'password', type:'password', style:{width:'100%'} } );
	var checkbox_input = ii.elm('input', { name:'remember_me', type: 'checkbox'});
	var login_button   = ii.elm('input', {type:'submit', value:'Log in', style:{margin:'0px', position:'absolute', right:'0px'}});

    var header = '';
    if(options.displayHeader && options.displayHeader !== false){
        header = ii.elm('h1', {style:{borderBottom:'solid 1px #b7b7b7', marginBottom:'20px', padding:'5px 0px'}}, 'Log in for bliin');
    }

	var forgetPasswordForm = ii.elm('form', {
				style: {
					display:'none',
					padding: '10px 25px 10px 11px',
					margin: '0px 0px 5px'
				},
				className:'forgotpassword',
				onsubmit:function(){
					if (!this.username.value && !this.email.value)
					{
						alert('Please enter your bliin-username or your email');
						return false;
					}

					ii.get('p-new-password', function(resp){},
						{
							username:this.username.value,
							email:this.email.value
						});
					alert('A new password has been send to your email address');
					form_fields.style.display = '';
					forgetPasswordForm.style.display='none';
					return false;
				}
			},
			ii.elm('p',
				'A new password will be generated and sent to your ',
				'email address. Type your email address or your bliin-username'
			),
			ii.elm('p',
				ii.elm('label',
					{style:{cssFloat:'left',styleFloat:'left',
						display:'block', width:'50px'}},
					'username:'
				),
				ii.elm('input', {style:{width:'160px',margin:'0px 1em'}, name:'username'})
			),
			ii.elm('p', '... or ...'),
			ii.elm('p',
				ii.elm('label',
					{style:{cssFloat:'left',styleFloat:'left',
						display:'block', width:'50px'}},
					'email:'
				),
				ii.elm('input', {style:{width:'160px',margin:'0px 1em'}, name:'email'})
			),
			ii.elm('input', {type:'submit',value:'Send',
				style:{cssFloat:'right', styleFloat:'right',
					margin:'0px 0px 1em 1em'}}),

			ii.elm('input', {type:'button',value:'Cancel',
				style:{cssFloat:'right', styleFloat:'right',
					margin:'0px 0px 1em 1em'},
				onclick:function() {

					form_fields.style.display = '';
					forgetPasswordForm.style.display='none';

				}}),
			ii.elm('div', {style:{clear:'both'}})
		);
    if(options.displayBorder && options.displayBorder !== false){
        forgetPasswordForm.style.border = 'solid 1px #b7b7b7';
	}

	var form_fields;

	var forgetPasswordLink = ii.elm('a', {
			href:'#rel',
			onclick:function() {
				{
					form_fields.style.display = 'none';
					forgetPasswordForm.style.display='';
				}
			}
		},
		'Forgot Password?');


    form_fields = ii.elm('div', {
            style:{
                margin:'0px 0px 5px',
                padding:'10px 25px 10px 11px',
                position:'relative'}
        },
		ii.elm('div', {style:{left:'0px', position:'absolute', top:'0px', width:'100%'}},
			error_p
		),
		ii.elm('p',
			ii.elm('label', {style:{display:'block', width:'100%'}}, 'Username'),
			username_input
		),
		ii.elm('p',
			ii.elm('label', {style:{display:'block', width:'100%'}}, 'Password'),
			password_input
		),
		ii.elm('p',
			checkbox_input,
			ii.elm('span', 'Remember Me')
		),
		ii.elm('p', {style:{position:'relative'}},
			forgetPasswordLink,
			forgetPasswordForm,
			login_button
		),
		ii.elm('p', {style:{padding:'5px 0px 0px'}},
			ii.elm('b', 'Need a login?'),
			ii.elm('br'),
			ii.elm('a', {href:"#rel&tab=Signup"}, 'Signup for an account ... it\'s free')
		)
	);

    if(options.displayBorder && options.displayBorder !== false){
        form_fields.style.border = 'solid 1px #b7b7b7';
    }

	var loginBox = ii.elm('form', {
            name:'ii_login_form'
        },
		header,
        form_fields,
		forgetPasswordForm
	);

	//loginBox.onmousedown = function(ev) { ii.stopPropagation(ev); };

	loginBox.onsubmit = function()
	{

		ii.Login.doLogin(
			username_input.value,
			password_input.value,
			function(login) {
				/* success */

				try {
					var error_text = document.createTextNode('');
					error_p.replaceChild(error_text, error_p.firstChild);
				}
				catch (err) {
					// no error, success
				}

				ii.login = login;

				if (checkbox_input.checked){

					ii.setCookie('id', ii.login.id, 365);
					ii.setCookie('username', ii.login.username, 365);
					ii.setCookie('key', ii.login.key, 365);
				}
                else {

                    ii.setCookie('id', ii.login.id, 0);
                    ii.setCookie('username', ii.login.username, 0);
                    ii.setCookie('key', ii.login.key, 0);
                }

				ii.app.landing.remove();

				// re-intialize to show the map
                if(options.initOnSuccess && options.initOnSuccess !== false){
    				ii.app.init();
					ii.app.state.setState({item:'ME.0'});
                }
                else {
                    ii.app.state.refresh();
                }


			},
			function(error) {
				/* fail */

				var error_text = document.createTextNode(error);
				try {
					error_p.replaceChild(error_text, error_p.firstChild);
				}
				catch (err) {
					error_p.appendChild(error_text);
				}
			}
		);

		return false;
	}

    return loginBox;
}



/* call without resp
   performs full login procedure
 */
ii.Login.doLogin = function(username, password, onSuccess, onFail, resp)
{

	if (!resp)
	{
	    // first step, get tempkey
        ii.get('s-getkey', function(resp) {
            ii.Login.doLogin(username, password, onSuccess, onFail, resp)
        }, {loginname: username});
    }
    else if (resp.tempkey){
        // use tempkey as seed for password-hash,
        var hash = MD5(password+resp.tempkey);

        ii.get('s-login', function(resp) {
            ii.Login.doLogin(username, password, onSuccess, onFail, resp)
        }, {loginname: username, password: hash});

        // ii.get('s-login', function(resp) { ii.Login.doLogin(username, password, onSuccess, onFail, resp); }, {loginname: username, password: password});
    }
	else if (resp.loginresult=='OK')
	{
		var login = new ii.Login(resp.id, username, resp.key);
		onSuccess(login);
	}
	else
	{
		onFail(resp.loginresult);
	}

}


/**
 * @author tomas
 * Defines ii.Time ctor
 *
 */


// creates and returns a clock element
ii.createClock = function()
{
	var pulse = false;
	var pulseElm = ii.elm('span', ':');
	var t1 = document.createTextNode('d1');
	var t2 = document.createTextNode('d2');


	function blink()
	{
		pulse = !pulse;
		pulseElm.style.visibility = (pulse ? '' : 'hidden');
	}


    if (ii.set.use_css_clock_blink)
        pulseElm.style.textDecoration = 'blink';
    else
        window.setInterval(blink, 1000);

	function clock()
	{
		var now = new Date();
		var h = now.getHours();
		var m = now.getMinutes(); if (m<10) m = '0'+m;
		t1.data = now.format('longhumandate') + ' ' + h;
		t2.data = m;
	}
	window.setInterval(clock, 60000);
	clock();

	return ii.elm('a',
		{id:'ii_clock', href: '#' },
        ii.elm('span', {className: 'clock'}, t1, pulseElm, t2)
    );
}

/* ii.map  */

ii.set_map_smooth_panning = false;
ii.set_expand_layerswitcher = true;

ii.Map = function(div, lat, lon, zoom)
{
    var ii_map = this;

	this.div = div;
	OpenLayers.ProxyHost="/v2/proxy.php?url=";

	var options = {
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326"),
            units: "m",
			numZoomLevels: 17,
			minZoomLevel: 2,
        	maxResolution: 30000, //15654.0339,
            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                                 20037508.34, 20037508.34),
			panMethod: OpenLayers.Easing.Linear.easeOut,
			panDuration: 10,
            eventListeners: {
                'moveend': function(){
                    if (ii.browser.msie) {
                        for (var name in ii_map.markerLayers) {
                            if ('tripLines' === name) {
                                var trip_lines_layer = ii_map.markerLayers[name];
                                ii.log('redrawing the vector feature layer');
                                trip_lines_layer.redraw();
                            }
                        }
                    }
                }
            },
            theme:'lib/OpenLayers-2.7/theme/bliin/style.css'
//			maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
//			maxResolution: 'auto'
        };

	var layers = [];
	this.layers=layers;

	this.map = new OpenLayers.Map (div , options );

	this.useTransform = true;


	if (window.ii_layer_Google)
	{
		// create Google Mercator layers
	    var gmap = new OpenLayers.Layer.Google(
    	    "Google Streets",
        	{'sphericalMercator': true, numZoomLevels: 16}
    	);
		var gsat = new OpenLayers.Layer.Google(
			"Google Satellite",
			{type: G_SATELLITE_MAP, numZoomLevels: 22 ,
			'sphericalMercator': true }
		);
		var ghyb = new OpenLayers.Layer.Google(
			"Google Hybrid",
			{type: G_HYBRID_MAP , 'sphericalMercator': true}
		);
		var gphy = new OpenLayers.Layer.Google(
            "Google Physical",
            {type: G_PHYSICAL_MAP , 'sphericalMercator': true,
			numZoomLevels: 15}
        );
		layers.push(gmap, gphy, gsat, ghyb);
	}
	if (window.ii_layer_VirtualEarth)
	{
		// create Virtual Earth layers
		var veroad = new OpenLayers.Layer.VirtualEarth(
			"Virtual Earth Roads",
			{'type': VEMapStyle.Road , 'sphericalMercator': true,
				minZoomLevel:4}
		);
		var veaer = new OpenLayers.Layer.VirtualEarth(
			"Virtual Earth Aerial",
			{'type': VEMapStyle.Aerial , 'sphericalMercator': true }
		);
		var vehyb = new OpenLayers.Layer.VirtualEarth(
			"Virtual Earth Hybrid",
			{'type': VEMapStyle.Hybrid , 'sphericalMercator': true }
		);
		layers.push(veroad, vehyb,veaer);
	}
	if (window.ii_layer_Yahoo)
	{
    	// create Yahoo layer
	    var yahoo = new OpenLayers.Layer.Yahoo(
        	"Yahoo Street",
			{ 'sphericalMercator': true }

    	);
    	var yahoosat = new OpenLayers.Layer.Yahoo(
        	"Yahoo Satellite",
			{'type': YAHOO_MAP_SAT , 'sphericalMercator': true }

	    );
    	var yahoohyb = new OpenLayers.Layer.Yahoo(
        	"Yahoo Hybrid",
	        {'type': YAHOO_MAP_HYB , 'sphericalMercator': true }
    	);
		layers.push(yahoo, yahoosat, yahoohyb);

	}

	if (window.ii_layer_Basic)
	{
		var ol_wms = new OpenLayers.Layer.WMS( "MetaCarta",
	                "http://labs.metacarta.com/wms/vmap0?",
					{ layers: 'basic' } );

	  	var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
	    	"http://t1.hypercube.telascience.org/cgi-bin/landsat7",
	    	{layers: "landsat7" });
		
		
		layers.push( ol_wms);

	}

	// add osm layers
	if (window.ii_layer_OpenStreetMap)
	{
		var osm = new OpenLayers.Layer.TMS(
			"OpenStreetMap (Mapnik)",
				"http://a.tile.openstreetmap.org/",
			{
				displayOutsideMaxExtent: true,
				type: 'png',
				maxResolution: 156543.0339,
				getURL: osm_getTileURL
			}
		);

		var osma = new OpenLayers.Layer.TMS(
			"OpenStreetMap (Tiles@H)",
			"http://tah.openstreetmap.org/Tiles/tile/",
			{
				type: 'png',
				displayOutsideMaxExtent: true,
				maxResolution: 156543.0339,
				getURL: osm_getTileURL
			}
		);

		var osml = new OpenLayers.Layer.TMS(
			"OpenStreetMap (linx)",
			"http://linx.bliin.com/tilecache.py/1.0.0/osm/",
			{
				type: 'png',
				displayOutsideMaxExtent: true,
				maxResolution: 156543.0339,
				getURL: osm_getTileURL
			}
		);
	
		var cdm = new OpenLayers.Layer.TMS(
			"Midnight Commander (CM)",
			"http://b.tile.cloudmade.com/8570b5222df659f2997f5348f024408d/999/256/",
			{
				type: 'png',
				displayOutsideMaxExtent: true,
				maxResolution: 156543.0339,
				getURL: osm_getTileURL
			}
		);

		var oam = new OpenLayers.Layer.WMS( "OpenAerialMap",
           	'http://openaerialmap.org/wms/',
			{layers: 'world', format: 'image/png' }
		);

		layers.push(osm, osml, cdm);
	}

	var blank = new OpenLayers.Layer.TMS("Hide Map", "http://bliin.com/", {
		displayOutsideMaxExtent: true,
		type: 'png',
		maxResolution: 156543.0339,
		getURL: function osm_getTileURL(bounds){
			return 'http://bliin.com/media/blank.png'		
		}
	});

	layers.push(blank);


	this.map.addLayers(layers);

	
	var ctl = new OpenLayers.Control.PanZoomBar();
	this.map.addControl(ctl);
	var ctlSw = new OpenLayers.Control.LayerSwitcher(
			{id:'layerSwitcher', activeColor:'white'});

    this.map.addControl(ctlSw);

	// set Midnight Commander as base-layer (comment out to restore to google)
	this.map.setBaseLayer(cdm);

	// expand layerswitcher
	this.layerBox = ctlSw;


//  show lat/lon on the map while moving the cursor
//    var ctlMP = new OpenLayers.Control.MousePosition();
//    this.map.addControl(ctlMP);
//    ctlMP.moveTo( {x:400, y:35 } );


	ctl.moveTo( {x:0,y:0});

	var c = this.map.controls;
	this.map.removeControl(c[1]);
	//c[1].moveTo( {x:400,y:15});

	this.zoomBox = new OpenLayers.Control.ZoomBox();
	this.map.addControl(this.zoomBox);
	
    var marker_options = {
        displayInLayerSwitcher: false
    }

    // The order of the these layers is importants.
    this.markerLayers = {};
	this.markerLayers['shadows'] = new OpenLayers.Layer.Markers("Shadows", marker_options );
    this.markerLayers['tripLines'] = new OpenLayers.Layer.Vector( "Trip lines", marker_options );
    this.markerLayers['poiThumbs'] = new OpenLayers.Layer.Markers( "POI thumbs", marker_options );
    this.markerLayers['userIcons'] =  new OpenLayers.Layer.Markers( "User icons", marker_options );
    this.markerLayers['userPopups'] = new OpenLayers.Layer.Markers( "User popups", marker_options );
    this.markerLayers['tripIcons'] = new OpenLayers.Layer.Markers( "Trip icons", marker_options );
    this.markerLayers['tripPopups'] = new OpenLayers.Layer.Markers( "Trip popups", marker_options );
    this.markerLayers['poiPopups'] = new OpenLayers.Layer.Markers( "POI popups", marker_options );
    this.markerLayers['spotIcons'] = new OpenLayers.Layer.Markers( "Spot icons", marker_options );
    this.markerLayers['spotPopups'] = new OpenLayers.Layer.Markers( "Spot popups", marker_options );



	for(var n in this.markerLayers)
	{
		this.map.addLayer(this.markerLayers[n]);
	}


    // Position the Layer Switcher Container
    ctlSw.div.style.top = '31px';
    ctlSw.div.style.left = '73px';

	ii.Map.setLayerSwitcherStyling(ctlSw);

	// explore mode event
	var that=this;
	this.map.events.register("moveend", this.map, function(e)
	{
		if (!ii.app) return;
		if (!ii.app.state) return;

		// if explore mode, update
		var ll = ii.app.state.state.ll;
		if (!ll)
			return;
		if (ll == 'items')
			; //window.location = ii.url({ll:''});
		else
		{
			that.updateExtend();
		}

	});

    this.div.onmousedown = function() { 
		if (!window.ii_centeredItem)
            return;
        if (window.ii_automoving)
            return;

		ii_centeredItem.center(false);
    }

	this.map.events.register("changebaselayer", this.map, function(e)
	{
		ii.setCookie('maplayer', that.map.baseLayer.name, 365);
	});

	var maplayer = ii.getCookieValue('maplayer');
	if (maplayer)
	{
		for(var n=0; n < this.map.layers.length; n++)
			if (this.map.layers[n].name == maplayer)
			{
				this.map.setBaseLayer(this.map.layers[n]);
			}
	}
	if (!this.div.clientHeight)
		this.div.style.height = '600px';
	// default zoom=2 latlon=30x0
	this.map.zoomTo(zoom||2);
	var mylatlon = this.getLatLon(lat||30, lon||0);
	this.map.setCenter(mylatlon);

	this.map.curZoom = this.map.getZoom();


}

function addWMS(name, url, layer)
{
	var wms = new OpenLayers.Layer.WMS( name, url,
				{ layers: layer });

	ii.app.map.map.addLayer(wms);
	ii.app.map.map.setBaseLayer(wms);
};

ii.Map.prototype.hideLayer = function() {
	this.layer = this.map.baseLayer;
	this.map.setBaseLayer(null);

}

ii.Map.prototype.zoomMarquee = function(active) {
	if (active)
		this.zoomBox.activate();
	else
		this.zoomBox.deactivate();
}

ii.Map.prototype.layerSelector = function(active) {
	if (active)
		this.layerBox.maximizeControl();
	else
		this.layerBox.minimizeControl();
}

ii.Map.prototype.addLowlandsLayer = function()
{
	var ll = new OpenLayers.Layer.TMS(
		"Lowlands",
			"http://linx.bliin.com/lowlands/",
		{
			displayOutsideMaxExtent: true,
			type: 'png',
		//	maxResolution: 156543.0339,
			getURL: ll_getTileURL,
			numZoomLevels: 22,
			maxZoomLevel: 22,
			isBaseLayer: false,
			displayInLayerSwitcher: false
		}
	);

	this.map.addLayer(ll);



}

/* static method to set styling on layer-switcher
   used by contructor and by minimap */
ii.Map.setLayerSwitcherStyling = function(control)
{
    // Layer Switcher Setup
    var layer_switcher_layers = control.layersDiv;
	layer_switcher_layers.style.paddingRight = '13px';
	layer_switcher_layers.style.marginLeft = '62px';
	layer_switcher_layers.style.marginTop = '4px';
    layer_switcher_layers.style.color='white';//'#b7b7b7';
	if (!ii.browser.msie)
		layer_switcher_layers.style.backgroundColor='inherit';

	layer_switcher_layers.style.backgroundImage = 'url(/media/single_alpha.png)';
    //layer_switcher_layers.style.backgroundColor='rgba(128, 176, 225, 0.85)';
 
    //layer_switcher_layers.style.backgroundColor='rgba(128, 176, 225, 0.85)';

    layer_switcher_layers.style.opacity='1';
    layer_switcher_layers.style.filter = 'alpha(opacity=100)';

    // The rounded corders
    var elms = control.div.getElementsByTagName('span');
    for(var i=0, length=elms.length; i<length; i++){
        var e = elms[i];

        if(e.style.backgroundColor=='white'){
            e.style.opacity='1';
            e.style.filter = 'alpha(opacity=100)';
			e.style.display = 'none';
        }
    }
    // The Base Layer Title Text
    var base_layer_title = layer_switcher_layers.getElementsByTagName('div')[0];
    base_layer_title.innerHTML = 'Select Map Provider';
    //base_layer_title.style.borderBottom='1px solid #b7b7b7';
    base_layer_title.style.color='white';//'#707070';
    base_layer_title.style.display='block';
    base_layer_title.style.fontSize='12px';
    base_layer_title.style.fontWeight='normal';
    base_layer_title.style.paddingBottom='3px';
    base_layer_title.style.textIndent='28px';

    // The Base Layer Labels -- also defined in bliin-ol.css
    var base_layer_container = layer_switcher_layers.getElementsByTagName('div')[1];
    base_layer_container.style.paddingLeft='0px';

	document.getElementById('OpenLayers_Control_MinimizeDiv').style.visibility = 'hidden';
	document.getElementById('OpenLayers_Control_MaximizeDiv').style.visibility = 'hidden';
}

ii.Map.prototype.updateExtend = function()
{
	// update state when map moves
	var bounds = this.map.getExtent();
	if (this.useTransform)
		bounds = bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
	var ar = bounds.toArray();
	var w = bounds.right - bounds.left;
	var h = bounds.top - bounds.bottom;
	bounds.left += w*.1;
	bounds.right -= w*.1;
	bounds.bottom += h*.1;
	bounds.top -= h*.1;
	window.location='#rel&ll='+bounds.toBBOX().replace(/,/g,'x');
}

// zoom out/in such that all items on map are visible
ii.Map.prototype.viewAll = function(items)
{

	var bounds = new OpenLayers.Bounds();
	var m= 0;
	if (items)
	{
		for(var n in items)
		{
			bounds.extend(this.getLatLon(items[n].lat,items[n].lon));
			m++;
		}
	}
	else
	{
		for(var n in this.markerLayers)
		{
            var b = this.markerLayers[n].getDataExtent();
			bounds.extend(this.markerLayers[n].getDataExtent());
			m++;
		}
	}
	if (m<=1) return; /* no items? do nothing */

	// we enlarge the bounds to ensure items are not covert by screen
	// components
	var w = (bounds.right-bounds.left);
	var h = (bounds.top-bounds.bottom);

    // no longer need margin cause map is no longer covered at edges
	//bounds.top += h*.2;
	//bounds.bottom -= h*.1;
	//bounds.left -= w*.67;
	//bounds.right += h*.1;
	this.map.zoomToExtent(bounds);
}



/* Zoom listeners are used by icons to update icon-size */
ii.Map.prototype.addZoomListener = function(obj, func)
{
	this.map.events.register("zoomend", obj, func);
}

ii.Map.prototype.removeZoomListener = function(obj, func)
{
	this.map.events.unregister("zoomend", obj, func);
}

ii.Map.prototype.getZoom = function()
{
	return this.map.getZoom() / this.map.getNumZoomLevels()
}

// used as callback for osm-layers to get tile url
function osm_getTileURL(bounds)
{
  var res = this.map.getResolution();

  var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
  var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
  var z = this.map.getZoom();
  var limit = Math.pow(2, z);

  if (y < 0 || y >= limit) {
      return OpenLayers.Util.getImagesLocation() + "404.png";
  } else {
      x = ((x % limit) + limit) % limit;
      return this.url + z + "/" + x + "/" + y + "." + this.type;
  }
}

function ll_getTileURL(bounds)
{
  var res = this.map.getResolution();

  var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
  var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
  var z = this.map.getZoom();
  if (this.map.baseLayer.name.indexOf('OpenStreet')==-1)
	  z+=2;
  var limit = Math.pow(2, z);
  if (z < 10 || y < 0 || y >= limit) {
	  return "http://linx.bliin.com/lowlands/blank.png";
  } else {
      x = ((x % limit) + limit) % limit;
      return this.url + z + "/" + x + "/" + y + "." + this.type;
  }
}

ii.Map.prototype.getLatLon = function(lat, lon)
{
	var ll = new OpenLayers.LonLat(lon, lat);
	if (this.useTransform)
	{
		ll = ll.transform(new OpenLayers.Projection("EPSG:4326"),
				new OpenLayers.Projection("EPSG:900913"));
	}
	return ll;
}

ii.Map.prototype.panTo = function(lat, lon)
{
	var ll = this.getLatLon(lat, lon);
	this.map.setCenter(ll);
}

// sets the center to specific lat lon, using specify pixel offset
// from actual center as center
ii.Map.prototype.setCenter = function(lat, lon, offsetx, offsety)
{
	this.offsetx = 0+offsetx;
	this.offsety = 0+offsety;
	var ll = this.getLatLon(lat, lon);
	if (offsetx || offsety)
	{
		var px = this.map.getLayerPxFromLonLat(ll);

		px.x -= offsetx;
		px.y -= offsety;
		ll = this.map.getLonLatFromLayerPx(px);
	}
	if (ii.set_map_smooth_panning)
		this.map.panTo(ll);
	else
		this.map.setCenter(ll);
}

// zoom to specific lat/lon
// offsetx/offsety define the pixel-offset from screen center to
// effective center
ii.Map.prototype.zoomTo = function(lat, lon, offsetx, offsety)
{

	var z = this.map.getZoom();
	var zoomstep = (this.map.getNumZoomLevels())/4*3;
	var newzoom = Math.min(
			this.map.getNumZoomLevels()-1,
			this.map.getZoom() + zoomstep
	);

	this.map.zoomTo(parseInt(newzoom));
	var ll = this.getLatLon(lat, lon);
	if (offsetx || offsety)
	{
		var px = this.map.getLayerPxFromLonLat(ll);

		px.x -= offsetx;
		px.y -= offsety;
		ll = this.map.getLonLatFromLayerPx(px);
	}
	//
	this.map.setCenter(ll);
}

// zoom to specific lat/lon at deep level
//
ii.Map.prototype.zoomToDeep = function(lat, lon, func)
{
	function f() {

		func();
		this.removeZoomListener(this, f);
	}
	if (func)
		this.addZoomListener(this,f);

	var ll = this.getLatLon(lat, lon);
	if (this.map.baseLayer.name.indexOf('Satel')!=-1)
		var z = 16;
	else
		var z = 14;
	var prevz = this.map.getZoom();
	if (z == prevz)
	{
		this.map.setCenter(ll);
		if (func)
			func();
	}
	else
		this.map.setCenter(ll, z);
}


/**
 * a function that will zoom to the extent defined by bottom_left and top_right.
 *
 * @param {Object} bottom_left a lon,lat in degrees
 * @param {Object} top_right a lon,lat in degrees
 */
ii.Map.prototype.zoomToExtent = function(bottom_left, top_right){

    var bl = this.getLatLon(bottom_left.lat, bottom_left.lon);
    var tr = this.getLatLon(top_right.lat, top_right.lon);

    this.map.zoomToExtent(new OpenLayers.Bounds(bl.lon, bl.lat, tr.lon, tr.lat));
    this.map.zoomOut();
}

ii.Map.prototype.addMarker = function(div, layerName, lat, lon, offsetX, offsetY)
{
	var marker = new OpenLayers.Marker.Div(this.map,
			this.getLatLon(lat, lon),
			div,
			new OpenLayers.Pixel(offsetX, offsetY));

	this.markerLayers[layerName].addMarker(marker);

	return marker;
}

ii.Map.prototype.removeMarker = function(marker, layerName)
{
	this.markerLayers[layerName].removeMarker(marker);
}

ii.Map.prototype.moveView = function(view, lat, lon)
{
	if (view == window.ii_centeredItem)
    {
        window.ii_automoving = 1;
        //view.marker.lock = true;
        this.setCenter(lat,lon,50,220);
        /*view.marker.lock = false;
        this.moveMarker(view.marker, lat,lon);
        if (view.shadowMarker)
            this.moveMarker(view.shadowMarker, lat, lon);
            */
        window.ii_automoving = 0;

    }
    else
    {
        this.moveMarker(view.marker, lat,lon);
        if (view.shadowMarker)
            this.moveMarker(view.shadowMarker, lat, lon);
    }
}

ii.Map.prototype.moveMarker = function(marker, lat, lon)
{
	marker.moveToLonLat(this.getLatLon(lat, lon));
}

ii.Map.prototype.addItem = function(item, selected)
{
	var result;
	if (item.type=='u')
	{
		var args = {map:this};
		item.createView('Icon', args);
		result = item.createView('IconPopup', {map: this, alwaysVisible: selected});
	}
	else if (item.type=='p' || item.type == 'v')
	{
		if (selected)
			result = item.createView('Popup', {map: this});
		else
			result = item.createView('Thumb', {map: this});
	}
	else if (item.type=='t')
	{

		result = item.createView('Icon', {map: this});
        result = item.createView('IconPopup', {map:this, alwaysVisible: selected});

		if (selected){
			result = item.createView('LineString', {map: this});
        }
	}
	else if (item.type =='s')
	{
		result = item.createView('Icon', {map: this});
        result = item.createView('IconPopup', {map:this, alwaysVisible: selected});
	}

	if (selected && (item.type == 'u' || item.type == 'p' 
		|| item.type == 'v' || item.type == 's'))
	{
		item.center(true);
		//this.map.zoomTo(14);
	}
	/*
	if (selected && (item.type=='p' || item.type == 'v'))

	{
		this.zoomTo(item.lat, item.lon, 0, 200);
        if (item.kind == 'video' || item.kind == 'stream')
            this.lockView(result);
	}
	else if (selected && item.type !='g' && item.type != 'a')
	{
		this.zoomTo(item.lat, item.lon, 0, 0);
	}
	*/
	return result;
}

ii.Map.prototype.addLineString = function(points, layerName)
{
	if (points.length<2)
		return 0;

	// define line style
	var style = {
    	strokeColor: "#FF9900",
        strokeWidth: 3
	}

	// convert to array of OpenLayers points
	var pts = [];
	for(var n=0; n < points.length; n++)
	{
		var pt = this.getLatLon(parseFloat(points[n].lat),parseFloat(points[n].lon));
		pt = new OpenLayers.Geometry.Point(pt.lon, pt.lat);
		pts.push(pt);
	}
	var ls = new OpenLayers.Geometry.LineString(pts);

	// create & add feature
	var feature = new OpenLayers.Feature.Vector(ls, null, style);
	this.markerLayers[layerName].addFeatures([feature]);
	return feature;

}

ii.Map.prototype.removeLineString = function(feature, layerName)
{
	this.markerLayers[layerName].destroyFeatures([feature]);
}



// creates a small map used to select a location
// params:
//  target: div to put map on
//  tabname: name of tab that is tested to remain active
//  needclick: if set, the user needs to click a location befor lat/lon is set
//      otherwise, geoip is used as default
//  onclick: callback when map is clicked
ii.Map.Minimap = function(params)
{
	var that = this;
	this.selectedLat = 0;
	this.selectedLon = 0;

	var target = params.target;
	var tabname = params.tabname;
	var onclick = params.onclick || function(){};

	// needed cause map destroy doesn't work.. (see below)
	target.innerHTML = '';

    if (!window.coords)
	// get location from ip
        ii.get('t-geoip', function(resp)
            {
                if (resp.lookupresult=='OK')
                {

                    if (that.selectedLat == 0 && that.selectedLon == 0)
                    {
                        that.map.setCenter(
                            new OpenLayers.LonLat(resp.lon, resp.lat), 5);
                        if (!params.needclick)
                        {
                            that.selectedLat = resp.lat;
                            that.selectedLon = resp.lon;
                        }
                    }
                }
            }
        );

	var zoom_control = new OpenLayers.Control.ZoomPanel();

	this.map = new OpenLayers.Map (target , {
		controls: [
			new OpenLayers.Control.Navigation(),
			zoom_control,
			new OpenLayers.Control.ArgParser(),
			new OpenLayers.Control.Attribution()
		],
		theme:'lib/OpenLayers-2.7/theme/bliin/style.css'
	} );

	var layers = [];
	// create Google Mercator layers
	var gmap = new OpenLayers.Layer.Google(
		"Google Streets"
	);
	var gsat = new OpenLayers.Layer.Google(
		"Google Satellite",
		{type: G_SATELLITE_MAP, numZoomLevels: 22  }
	);
	var ghyb = new OpenLayers.Layer.Google(
		"Google Hybrid",
		{type: G_HYBRID_MAP }
	);
	var gphy = new OpenLayers.Layer.Google(
		"Google Physical",
		{type: G_PHYSICAL_MAP }
	);
	layers.push(gmap, gphy, gsat, ghyb);

	this.markerLayer = new OpenLayers.Layer.Markers( "",
			{ displayInLayerSwitcher: false }
	);

	var marker = 0;

	that.map.addLayers(layers);
	that.map.addControl(zoom_control);
	that.map.addLayer(this.markerLayer);

	zoom_control.moveTo({x:10, y:10});

	var ctlSw = new OpenLayers.Control.LayerSwitcher(
			{id:'layerSwitcher', activeColor:'white'});

    this.map.addControl(ctlSw);

    // Position the Layer Switcher Container
    ctlSw.div.style.top = '10px';

	ii.Map.setLayerSwitcherStyling(ctlSw);

    if (window.coords)
    {
        this.map.setCenter(new OpenLayers.LonLat(
                window.coords.lon,window.coords.lat), 7);
		this.moveMarker(window.coords.lat, window.coords.lon);
		onclick();

    }
    else
    {
        that.map.setCenter(new OpenLayers.LonLat(4,20), 1);
    }


	that.map.events.register("click", that.map, function(e)
	{
		var ll = that.map.getLonLatFromPixel(e.xy);
		that.moveMarker(ll.lat, ll.lon);

		onclick();
	});

	// map needs update after scroll. no way to detect.
	var iv = window.setInterval(
		function()
		{
			if (ii.app.state.state.tab != tabname)
			{

				window.clearInterval(iv);

				// Weird behaviour of map.destroy
				// FIXME: Currenlt not removing AT ALL
				// Let's hope a user doesn't create to much
				// spots in one session
//				if (that.map && that.map.controls && that.controls[0])
//					that.map.destroy();

				// also map.destroy doens't seem to work correctly
				// events start doubling up  (FIXME)
				that.map = 0;
			}
			else
				that.map.updateSize();
		}, 500
	);
}

ii.Map.Minimap.prototype.setCenter = function(lat,lon)
{
	this.map.setCenter(new OpenLayers.LonLat(lon,lat), 13);
	this.moveMarker(lat, lon);
}

ii.Map.Minimap.prototype.moveMarker = function(lat,lon)
{
	if (this.marker)
	{
		this.markerLayer.removeMarker(this.marker);
		this.marker.destroy();
	}
	var size = new OpenLayers.Size(79,58);
	var offset = new OpenLayers.Pixel(-22,-55);
	var icon = new OpenLayers.Icon('media/spot_add_marker.png',size,offset);
	this.marker = new OpenLayers.Marker(new OpenLayers.LonLat(lon,lat),icon);
	this.markerLayer.addMarker(this.marker);

	this.selectedLat = lat;
	this.selectedLon = lon;

}




/* Augment OpenLayers with a Marker that displays a general div */
OpenLayers.Marker.Div = OpenLayers.Class(OpenLayers.Marker, {
   div: null,

	initialize: function(map, lonlat, div, offset) {

		this.map = map;
		this.lonlat = lonlat;
		this.div    = div;
		this.events = new OpenLayers.Events(this, this.div, null);
		this.offset = offset || new OpenLayers.Pixel(0,0);
			//this.setBorder(borderColor, borderWidth);
	},

	destroy: function() {

		OpenLayers.Marker.prototype.destroy.apply(this, arguments);
		this.div = null;
	},

	lock: function() {
		
	},

	unlock: function() {
	},

	moveToLonLat: function(lonlat) {
		this.lonlat = lonlat;

		this.px = this.map.getLayerPxFromLonLat(lonlat);

		if (this.div != null) {
				this.div.style.left = this.px.x+this.offset.x + 'px';
				this.div.style.top = this.px.y+this.offset.y + 'px';
		}
	},

	draw: function(px, sz) {
		this.div.style.left = px.x+this.offset.x + 'px';
		this.div.style.top = px.y+this.offset.y + 'px';
		return this.div;
	},

	onScreen:function() {
		var onScreen = false;
			if (this.map) {
					var screenBounds = this.map.getExtent();
					onScreen = screenBounds.containsBounds(this.bounds, true, true);
			}
			return onScreen;
	},

	display: function(display) {
			this.div.style.display = (display) ? "" : "none";
	},

	CLASS_NAME: "OpenLayers.Marker.Div"
});

ii.set_interval_factor = 1; // use to slow down or speed up all polling
ii.set_interval_default = 6000;
ii.set_full_refresh = 150;
ii.set_use_cache = false;

ii.Query = function(type, opts, queryOpts)
{
	this.type = type;
	this.items = { };
	this.queryOpts = { };
	this.fullrefresh = 0;

	// copy options
	this.paused = ((opts.paused!=undefined) ? opts.paused : 1);
	this.interval = opts.interval || ii.set_interval_default;
	this.url = opts.url || ('q-items-'+type);

	this.listeners = [];

	this.setQueryOpts(queryOpts); // the actual query objects

	//ii.log('creating %o from %o', this, arguments);
	//this.interval = 3000;
}


/* adds a listener
 * the listener object can have the following methods:
 *  addItem(item):
 *     invoked for all new items.
 *     should create and display a view of the item
 *
 *  itemsDone():
 *     invoked when the first batch of data is received
 *
 *  countItems(start,count,total,pagesize):
 *     invoked when the count changes to show/update a pager *
 *
 *  hasItems(hasItems):
 *     invoked when count becomes zero or more then zero
 */

ii.Query.prototype.addListener = function(listener)
{
	for(var n in this.items)
		if (listener.addItem)
			listener.addItem(this.items[n]);

	if (this.count && listener.itemsDone)
		listener.itemsDone(this.items);

	this.listeners.push(listener);
}


ii.Query.prototype.updateAll = function()
{
	for(var n in this.items)
		this.items[n].update(this.items[n]);
}

ii.Query.prototype.stop = function()
{
	// clear items
	for(id in this.items)
	{
		this.items[id].remove();
		delete this.items[id];
	}

    this.count = 0;
	this.queryOpts.lastmodified = 0;
	this.pauseUpdate(1);
}

ii.Query.prototype.start = function()
{
	// clear items
	for(id in this.items)
	{
		this.items[id].remove();
		delete this.items[id];
	}
	this.queryOpts.lastmodified = 0;
	this.pauseUpdate(0);
}

ii.Query.prototype.setQueryOpts = function(newOpts)
{
	if (newOpts)
	{
		for(var o in newOpts)
		{
			if (!newOpts[o] && this.queryOpts[o])
				delete this.queryOpts[o];
			else if (newOpts[o])
				this.queryOpts[o] = newOpts[o];
		}

		// remove all items; they might not apply with new opts
		/*for(id in this.items)
		{
			this.items[id].remove();
			delete this.items[id];
		}*/
		// this ensures recreation of the pager..
		delete this.count;
	}

	// clear cache
	this.queryOpts.lastmodified = 0;


	// clear old timer
	if (this.pollTimer)
	{
		window.clearTimeout(this.pollTimer);
		this.pollTimer = 0;
	}

	if (!this.paused)
		this.doDelayedUpdate();
}

ii.Query.prototype.pauseUpdate = function(pause)
{
	this.paused = pause;
    if (pause)
    {
        ii.log('Issuing pause update');
    }
	if (this.pollTimer)
	{
		window.clearTimeout(this.pollTimer);
		this.pollTimer = 0;
	}

	if (!this.paused)
		this.doDelayedUpdate();
}

ii.Query.prototype.doDelayedUpdate = function()
{
	var delay = Math.random()*300 + 0; // between 0 and 0.3 secs

	var that = this;
	this.pollTimer = window.setTimeout(function() { that.doUpdate() }, delay);
}

ii.Query.prototype.doUpdate = function(resp)
{

	if (this.paused) return; // this means this request is outdated.

	var that = this;

	// remove previous timer
	if (this.pollTimer)
	{
		window.clearTimeout(this.pollTimer);
		this.pollTimer = 0;
	}

	if (!resp)
	{
		if (this.request)
			this.request.abort();

		// Explore mode? no cache
		if (this.queryOpts.lat1 && this.queryOpts.lastmodified)
			delete this.queryOpts.lastmodified;

		this.request = ii.get(this.url, function(resp) { that.doUpdate(resp); }, this.queryOpts );
		return;
	}

	// Not Modified?
	if (resp.result == 'NM')
	{
		if (this.interval)
			this.pollTimer = window.setTimeout(function() { that.doUpdate(); }, this.interval * ii.set_interval_factor);

		return;
	}

    // an error in the db?
    if(resp.result == 'ERR'){
        ii.log('ERR - '+resp.msg+' : '+resp.dbmsg);
		ii.log('Last Query: ' + resp.lastsql.replace(/\t/, ' '));
        return;
    }

    // we have no items, but why?
    if( resp.items === undefined){
        ii.log('No Items - '+resp.result+' - '+resp.msg);
        return;
    }

	var dofullrefresh = (++this.fullrefresh % ii.set_full_refresh == 0);
	this.queryOpts.lastmodified = 0;

	var nodelete = {}; // maintain list of retrieved items, to remember what to delete
	for(var n=0; n < resp.items.length; n++)
	{
		var id = resp.items[n].id;
		ii.assert(id);
		nodelete[id] = 1;

		if (resp.items[n].modified > this.queryOpts.lastmodified && ii.set_use_cache)
		{

			this.queryOpts.lastmodified = resp.items[n].modified;
		}

		if (this.items[id])
		{
			// call update function if data is modified
			if (this.items[id].modified < resp.items[n].modified
				|| dofullrefresh)
			{
				this.items[id].update(resp.items[n]);
				ii.log('retieveData; updated:'+id);
			}

		}
		else
		{
			// new item,
			// call corresponding constructor

			resp.items[n].type = ii.typeletter[this.type];
			var ctor = ii.typector[resp.items[n].type];
			if (!ii.items[ctor])
				ii.log('Item type: ' + ctor + ' doesnt exist');
			var newItem = new ii.items[ctor](resp.items[n]);

			this.items[id] = newItem;
			//ii.log('retieveData; added:'+id);
			for(var m=0; m < this.listeners.length; m++)
				if (this.listeners[m].addItem)
					this.listeners[m].addItem(newItem);
		}
	}
	for(id in this.items)
	{
		if (!nodelete[id])
		{
			this.items[id].remove();
			delete this.items[id];
		}
	}

	for(var m=0; m < this.listeners.length; m++)
	{
		if (resp.count !== this.count && this.listeners[m].countItems )
		{
			this.listeners[m].countItems(this.queryOpts.start||0, resp.items.length, resp.count, this.queryOpts.count||5, this.type);

		}

		if (!this.firstTimeDone && this.listeners[m].itemsDone)
			this.listeners[m].itemsDone(this.items);

		if ((this.count === undefined || (this.count && !resp.count) || (!this.count && resp.count))
			&& this.listeners[m].hasItems)
		{
			this.listeners[m].hasItems(!!resp.count);
		}

	}

	this.count=resp.count||0;
	this.firstTimeDone = true;

	if (this.interval)
		this.pollTimer = window.setTimeout(function() { that.doUpdate(); }, this.interval * ii.set_interval_factor);

}



ii.app.landing = {};


// sets up the landingpage on the element given as param
ii.app.landing.setup = function(landingPage)
{
	// show/hide the tabs accordingly
	var tabs = document.getElementById('ii_header').getElementsByTagName('a');
	for(var i = 0, length = tabs.length; i < length; i++){
		var tab = tabs[i];

		switch(tab.name){
			case 'tab_Welcome':
				tab.className = 'selected leftmost rightmost';
				break;
			case 'tab_Map':
				tab.className = 'leftmost selected display_none';
				break;
			case 'tab_Feed':
				tab.className = 'hide';
				break;
			default:
				break;
		}
	}

	var login_box = ii.Login.landingLoginBox();

	var feed_browser = new ii.views.FeedBrowser({}, {}, {
		show_tabs: false,
		show_search: false,
		show_friends_checkbox: false,
		show_header: false,
		driver_name: 'Landing',
		onAvatarClick: function(){
			landingPage.style.display = 'none';
		},
		onDone: function(items){
			// refreshes the shadow around the landing page after the
			// feed items load.
			landingPage.style.height = landingPage.lastChild.offsetHeight+'px';
		},
		onUserNameClick: function(){
			landingPage.style.display = 'none';
		},
		onItemClick: function(){
			landingPage.style.display = 'none';
		},
		pager: function(page_number){
			var start = (page_number) ? (page_number-1) * 10 : 0;

			ii.landing_page_feed_browser.feed_query.setQueryOpts({start:start});
		}
	});

	ii.landing_page_feed_browser = feed_browser;

	function handle_tab_click(e){

		var banner = document.getElementById('landing_page_banner');
		var banner_a = banner.getElementsByTagName('a');

		for(var i=0, len=banner_a.length; i < len; i++){
			var a = banner_a[i];

			if(a.id.indexOf('tab') == -1){
				continue;
			}

			var img_div = document.getElementById(a.id.substr(0, a.id.length-4));

			if(e.id == a.id){
				a.className = img_div.className = 'selected';
			}
			else {
				a.className = img_div.className = '';
			}
		}
	}

	var landing_page_content = ii.elm('div', {
			style: {
				margin:'0px',
				padding:'0px',
				border:'0px'
			}
		},
		ii.elm('h1', {style:{marginBottom:'20px'}}, 'bliin ',
			ii.elm('span', {className:'live'}, 'YourLive!'),
			' \u00BA Always There'),
		ii.elm('div', {
				id: 'landing_page_banner'
			},
			ii.elm('div', {
					id: 'landing_live',
					className: 'selected'
				},
				ii.elm('div', {
						id: 'landing_live_overlay'
					},
					ii.elm('h1',
						ii.elm('span', {className:'live'}, 'Live!'),
						' locationstream sharing'
					),
					ii.elm('p', 'Find and follow your Friends in real-time via your phone and over the web. Share your ',
						ii.elm('span', {className:'live'},'Live!'),
						' locationstream without the fuzz of setting your location manually … you’re simply ',
						ii.elm('strong','Always There.')
					)
				)
			),
			ii.elm('div', {
					id: 'landing_share'
				},
				ii.elm('div', {
						id: 'landing_share_overlay'
					},
					ii.elm('h1', 'Instantly share experiences world wide'),
					ii.elm('p', 'Share your precious moments in geo-tagged media instantly, as you capture them. Create Trips of journeys and record them for playback later.')
				)
			),
			ii.elm('div', {
					id: 'landing_always'
				},
				ii.elm('div', {
						id: 'landing_always_overlay'
					},
					ii.elm('h1', 'Any handset, any OS, any carrier, anywhere'),
					ii.elm('p', 'A global service, independent of operating system, handset manufacturer or network carrier ... we are browser based: any PC and any Handset will do; ',
						ii.elm('strong', 'Anytime, Anywhere, Anyone!')
					)
				)
			),
			ii.elm('div', {
					id: 'landing_secure'
				},
				ii.elm('div', {
						id: 'landing_secure_overlay'
					},
					ii.elm('h1', 'You control... Peace of mind'),
					ii.elm('p', 'We work with experts and authorities to keep your data save and secure. The level of Privacy you want to enjoy on bliin is yours.')
				)
			),
			ii.elm('div', {
					id: 'landing_live_link_wrapper'
				},
				ii.elm('div', {
						className: 'landing_live_link_container',
						id: 'landing_live_link_signup_container'
					},
					ii.elm('img', {
						alt: 'next',
						src: './media/button_next.png'
					}),
					ii.elm('div', {
							className: 'landing_live_link'
						},
						ii.elm('a', {
								href: '#rel&tab=Signup'
							},
							'Sign up'
						)
					)
				),
				ii.elm('div', {
						className: 'landing_live_link_container',
						id: 'landing_live_link_entersite_container'
					},
					ii.elm('img', {
						alt: 'next',
						src: './media/button_next.png'
					}),
					ii.elm('div', {
							className: 'landing_live_link'
						},
						ii.elm('a', {
								href: '#rel&tab=Map'
							},
							'Enter Site'
						)
					)
				)
			),
			ii.elm('a', {
				id: 'landing_live_tab',
				className: 'selected',
				onclick: function(){
					handle_tab_click(this);
				}
			}),
			ii.elm('a', {
				id: 'landing_share_tab',
				onclick: function(){
					handle_tab_click(this);
				}
			}),
			ii.elm('a', {
				id: 'landing_always_tab',
				onclick: function(){
					handle_tab_click(this);
				}
			}),
			ii.elm('a', {
				id: 'landing_secure_tab',
				onclick: function(){
					handle_tab_click(this);
				}
			})
		),
		ii.elm('h1', {style:{margin:'20px 0px'}},
			ii.elm('span', {className:'live'}, 'Live!'),
			' Feed activity on bliin'),
		feed_browser.feed_div
	);

	var landing_page_content_container = ii.elm('div', {
		style: {
			background: 'white',
			left: '326px',
			padding: '15px 16px 35px',
			position: 'absolute',
			top: '0px',
			width: '635px',
			zIndex: '999'
		}},
		landing_page_content
	);

	// the login box
	landingPage.appendChild(login_box);

	// main content incl. feed
	document.getElementById('ii_centerpane_Welcome').appendChild(landing_page_content);
	document.getElementById('ii_centerpane_container').style.visibility
		= '';

	// refresh the shadow around the landing page.
	landingPage.style.height = landingPage.lastChild.offsetHeight+'px';

	document.getElementById('landing_logo').style.display = 'inline-block';
}



/**
 * remove the landing page and kill the fading timer if the exist in the
 * document.
 */
ii.app.landing.remove = function(){

    // kill the feed browser / query
    if( ii.landing_page_feed_browser ){
        if(ii.landing_page_feed_browser.feed_query){
            ii.landing_page_feed_browser.feed_query.stop();
        }
        delete ii.landing_page_feed_browser;
    }

    var tabs = document.getElementById('ii_header').getElementsByTagName('a');
    for(var i=0, length = tabs.length; i < length; i++){
        var tab = tabs[i];

        switch(tab.name){
            case 'tab_Welcome':
                tab.className = 'display_none';
                break;
            case 'tab_Map':
                tab.className = 'selected show leftmost';
                break;
            case 'tab_Feed':
                tab.className = 'show rightmost';
                break;
            default:
                break;
        }
    }

	// yank the landing page out of the doc, we dont need it anymore
    var landing_page = document.getElementById('ii_landing_page_container');
    if( landing_page ){
        landing_page.parentNode.removeChild( landing_page );
    }

    // hide the welcome landing page from the centerpane container.
    var welcome_page = document.getElementById('ii_centerpane_Welcome');
    if( welcome_page ){
        welcome_page.style.display = 'none';
    }
}

ii.set_status_duration = 1500;


// View object
ii.views.View = function(item) { }


// Initialize the div for the view,
// clones from template if there is any
ii.views.View.prototype.initDiv = function(viewtype)
{
	ii.assert(this.item); // must be set

	// find template
	var template_nm = ii.typename[this.item.type] + '_' + viewtype;
	var template = document.getElementById('ii_vw_' + template_nm);
    if (!template) {
        // try generic 
        var template_nm = viewtype;
        var template = document.getElementById('ii_vw_' + template_nm );
    }

    var that = this;
    function onload_internal() {
        // remember the datafields
        that.fields = [];
        var elms = that.div.getElementsByTagName('*');
        for (var n=0;n< elms.length; n++)
        {
            var field = elms[n].getAttribute('data-field');
            if (field)
                that.fields[field] = elms[n];
        }

        // default mouse handlers notify item
        that.div.onmouseover = function(){that.item.onmouseover()};
        that.div.onmouseout = function(){that.item.onmouseout()};

        if (that.onload)
            that.onload();
    }

	if (template)
	{
        this.div = template.cloneNode(true);
        this.div.id = ''; // must be removed, otherwise would be double
		var loadFromServer = template.getAttribute('data-loadFromServer');

        if (loadFromServer)
        {
            template.removeAttribute('data-loadFromServer');
            ii.log('load from server');
            ii.getHtml(template_nm,
                template,
                function() {
                    that.div.innerHTML = template.innerHTML;
                    onload_internal();
                }
            );
        }
        else
        {

            onload_internal();
        }
	}
	else
	{
		// no template,
		// initiate empty div
		this.div = ii.elm('div', {className: 'view'});
        onload_internal();
	}

}
ii.views.generic = {};

ii.views.generic.TabAbout = function(item) {
    ii.log('TabAbout Constructor');
    this.item = item; // not used
    this.initDiv('TabAbout');
}

ii.views.generic.TabAbout.prototype = new ii.views.View();

ii.views.generic.GenericView = function(item, viewname) {
    ii.log('GenericView Constructor');
    this.item = item; // not used
    this.initDiv(viewname);
}

ii.views.generic.GenericView.prototype = new ii.views.View();

// default update, fills elements with data-field attribute.
// finds fillField_fieldname functions for custom filling
ii.views.View.prototype.update = function()
{
	for (var field in this.fields)
	{
		var elm = this.fields[field];

		// does this field have a custom fill function
		if (this['fillField_'+field])
		{
			//ii.log('using fillfunction: '+field);
			this['fillField_'+field](elm);
			continue;
		}
			//ii.log('not using fillfunction: '+field);

		switch(field)
		{
			case 'author':
				elm.innerHTML ='';
				elm.appendChild(
						ii.userLink(this.item.userid, this.item.author)
				);
				break;

			case 'link':
				if (this.item.name == 'Anonymous')
					elm.removeAttribute('href');
				else
					elm.href = '#rel&item='+this.item.type+'.'+this.item.id;
				break;

			case 'thumb_large':
				elm.src = '/srv/d-media.php'
						+ '?entitytype=' + ii.typename[this.item.type]
						+ '&entityid=' + this.item.id
						+ '&width=120&height=90'
						+ '&style=center'
						+ '&marker=commentcount';
				break;

			case 'thumb':
				elm.src = '/srv/d-media.php'
						+ '?entitytype=' + ii.typename[this.item.type]
						+ '&entityid=' + this.item.id
						+ '&width=64&height=48'
						+ '&style=center'
						+ '&marker=commentcount';
				break;
			case 'authorthumb':
				elm.src = '/srv/d-media.php?entitytype=user&entityid='
						+ this.item.userid +'&width=48&height=36';
				break;

			case 'authorthumb_large':
				elm.src = '/srv/d-media.php?entitytype=user&entityid='
						+ this.item.userid +'&width=64&height=48';
				break;

			case 'stopped':
			case 'created':
				elm.innerHTML ='';
				elm.appendChild(document.createTextNode(
						ii.formatDate(this.item[field], 'relative')));
				break;

			case 'location':
				elm.innerHTML ='';
				elm.appendChild(document.createTextNode(this.item.locname));
				if (this.item.distance) {
					elm.appendChild(ii.elm('small', ' @ ' + 
                               ii.formatDistance(this.item.distance)));
                }

				break;

			case 'description':
				elm.innerHTML = '';
				ii.text2href(this.item.description || 'No description', elm)
				break;

			case 'timespan':
				elm.innerHTML = ii.formatTimespan(this.item.timespan);
				break;

			case 'content':
                elm.innerHTML = '';
				if (this.item.content !== undefined)
				{
					ii.text2href(this.item.content || 'No content', elm)
				}
				else
				{
					elm.innerHTML = '';
					var cnts = [];
					function add(cls, count, lbl)
					{
						if (!count) return;
						var s = '' + count + ' ' + lbl + (count>1 ? 's' : '');
						cnts.push(ii.elm('span', {className:'micro '+cls}, s));
					}
					if (this.item.friends) add('friend', this.item.friends, 'Friend');
					if (this.item.photos) add('photo', this.item.photos, 'Photo');
					if (this.item.videos) add('video', this.item.videos, 'Video');
					if (this.item.trips) add('trip', this.item.trips, 'Trip');
					if (this.item.spots) add('spot', this.item.spots, 'Spot');
					if (this.item.albums) add('album', this.item.albums, 'Album');
					if (this.item.groups) add('group', this.item.groups, 'Group');
					if (this.item.members) add('user', this.item.members, 'Member');

					for (var n=0; n < cnts.length; n++)
					{
						if (n>0)
							elm.appendChild(document.createTextNode(', '));
						elm.appendChild(cnts[n]);

					}
					if (cnts.length==0)
						ii.setText(elm,'None');
				}

				break;

			case 'messagebox':
				var isEditable = elm.getAttribute('data-editable');
				var isEditing = elm.getAttribute('data-editing');
				if (isEditing === 'true') return;
				elm.innerHTML = '';
				elm.className = 'msgbox';
				var content = ii.elm('div');
				if (this.item.message)
					ii.text2href(this.item.message, content);
				else
					content = ii.elm('div', ii.elm('em', 'No message yet'));

				elm.appendChild(content);

				if (isEditable)
				{
					var edit = ii.elm('textarea',
									this.item.message);

					var item = this.item;
					var submit = function() {
						item.message = edit.value;
						content.style.display = 'block';
						form.style.display = 'none';
						elm.setAttribute('data-editing', 'false');
						ii.get('p-upd-profile', function(resp){}, 
							{message: item.message});

						item.update(item);
						return false;
					}
					var reset = function() {
						content.style.display = 'block';
						form.style.display = 'none';
						elm.setAttribute('data-editing', 'false');
					}
					var form = ii.elm('form',
							{ onsubmit: submit, onreset: reset },
							{ style: { display: 'none' }},
							edit,
							ii.elm('input', {type:'submit', value:'Apply'}),
							ii.elm('input', {type:'reset', value:'Cancel'})
					);

					edit.onkeyup = ii.autosizeTextArea;
					elm.appendChild(form);

					content.onclick = function() {
						content.style.display = 'none';
						form.style.display = 'block';
						edit.focus();
						edit.style.height = edit.scrollHeight + "px";
						elm.setAttribute('data-editing', 'true');
					}
				}


				elm.appendChild(ii.elm('img', {src: '/media/balloontip_discs.gif', style: {
					position:'absolute',
					top:'-26px', left:'10px'}} ));
				break;

			case 'zoomto':
				var item = this.item;
				elm.onclick = function(ev) {
					ii.stopPropagation(ev);
					item.zoomto();
				}
				if (elm.tagName.toLowerCase() == 'img')
					var img = elm;
				else
					var img = elm.getElementsByTagName('img')[0];
				img.onmouseover = ii.onmouseoverbtn;
				img.onmouseout  = ii.onmouseoutbtn;
				break;

			case 'status':
				elm.innerHTML='';
				elm.appendChild(this.item.getLiveStatusElement());
				break;

			case 'distance':

				var distance_value = 'Unknown';
				if(this.item.distance !== undefined){
					distance_value = ii.formatDistance(this.item.distance);
				}

				elm.innerHTML ='';
				elm.appendChild(document.createTextNode(distance_value));
				break;

            case 'postedin':
                elm.innerHTML = '';
                for(var n=0; n < postedIn.length; n++)
                {
                    var pi = postedIn[n];
                    if (n >0)
                        elm.appendChild(document.createTextNode(', '));

                    if (pi.type == 'album')
                    {
                        var link = '#rel&item='+ii.typeletter[pi.parenttype]+'.'
                            +pi.parentid+'&pane=album.'+pi.id;
                        var name = pi.parentname + ' (' + pi.name + ')';
                        var type='album';
                    }
                    else if (pi.type == 'group' && pi.id==1)
                    {
                        var link = '#rel&item=';
                        var name = pi.name;
                        var type = 'world';
                    }
                    else if (pi.type == 'group' && pi.name == 'Friends')
                    {
                        var link = '#rel&item=u.' + pi.parentid + '&pane=friends';
                        var name = ii.appendS(pi.parentname) + ' Friends';
                        var type = 'friends';
                    }
                    else
                    {
                        var link = '#rel&item='+ii.typeletter[pi.type]+'.'+pi.id;
                        var name = pi.name;
                        var type = pi.type;
                    }

                    elm.appendChild(ii.elm('a', {className: type, href:link}, name));

                }
                if (postedIn.length == 0)
                {
                    // private
                    elm.appendChild(ii.elm('a', {className: 'private'}, 'Private'));
                }
                break;


			default:

				if (this.item[field] !== undefined)
				{
					elm.innerHTML ='';
					elm.appendChild(document.createTextNode(''+this.item[field]));
				}
				break;
		}
	}
   
}

ii.views.View.prototype.removeQueries = function() {
	if (this.queries)
		for (var n in this.queries)
			this.queries[n].stop();
}

ii.views.View.prototype.remove = function() {
	this.removeQueries();
}


// specialized view ListItem
// overrides mouseover
// note that we're not using hover, cause we also
// want to highlight if we're hovering another view of 
// this item
ii.views.ListItem = function() { }
ii.views.ListItem.prototype = new ii.views.View;

ii.views.ListItem.prototype.onmouseover = function() {
	this.div.className = this.div.className.replace('nosel','dosel');
}

ii.views.ListItem.prototype.onmouseout = function() {
	this.div.className = this.div.className.replace('dosel','nosel');
}


// specialized Mappable view,
// adds methods to add to map, and autoremoves from map
// also implements centering.
ii.views.Mappable = function() {}
ii.views.Mappable.prototype = new ii.views.View;

ii.views.Mappable.prototype.addToMap = function(layer,offsetX,offsetY)
{
    this.layer = layer;
	this.marker = this.map.addMarker(
			this.div,
			layer,
			this.item.lat, this.item.lon,
			offsetX, offsetY);
}

ii.views.Mappable.prototype.addShadowToMap = function(img,width,height,
		offsetX,offsetY)
{
	this.shadowDiv = ii.pngImage(img, width, height);
	this.shadowDiv.className = 'marker shadow';

	this.shadowMarker = this.map.addMarker(this.shadowDiv, 'shadows',
			this.item.lat, this.item.lon,
			offsetX, offsetY);
}

ii.views.Mappable.prototype.center = function()
{
	ii.app.setCenterButton(this.item.centered);

	if (this.item.centered)
	{
		ii.log('centered');
		this.centerOffsetY = this.centerOffsetY || 0;

		window.ii_centeredItem = this.item;


		this.prevparent = this.div.parentNode;
		this.div.style.position = 'static'; // ignore top/left

		if (this.shadowMarker)
		{
			this.prevShadowParent = this.shadowDiv.parentNode;
			this.shadowDiv.style.position = 'static'; // ignore top/left
			var cont = ii.elm('div', {style: {
					position:'absolute',
					left: (this.shadowMarker.offset.x) + 'px',
					top: (this.shadowMarker.offset.y + this.centerOffsetY) + 'px'
					}}, this.shadowDiv);

			this.tempShadowContainer = cont;
			document.getElementById('ii_centereditem_container')
				.appendChild(cont);

		}
		
		var cont = ii.elm('div');
		cont.style.position = 'absolute';
		cont.style.left = (this.marker.offset.x) + 'px';
		cont.style.top = (this.marker.offset.y + this.centerOffsetY) + 'px';
		cont.appendChild(this.div);
		this.tempContainer = cont;

		document.getElementById('ii_centereditem_container').appendChild(cont);
		window.ii_extramap_height = this.centerOffsetY * 2;
		window.onresize();
		this.map.map.updateSize();
			
		this.map.setCenter(
				this.item.displayLat||this.item.lat, 
				this.item.displayLon||this.item.lon);//,
//				0, this.centerOffsetY);
				
	}
	else
	{
		ii.log('uncentered');
		this.move();
		this.prevparent.appendChild(this.div);
		this.div.style.position = 'absolute';
		
		document.getElementById('ii_centereditem_container').removeChild(
				this.tempContainer);

		if (this.prevShadowParent)
		{
			this.shadowDiv.style.position = 'absolute';
			this.prevShadowParent.appendChild(this.shadowDiv);
		
			document.getElementById('ii_centereditem_container').removeChild(
				this.tempShadowContainer);
		}

		var om = document.getElementById('ii_map_OpenLayers_Container');
		ii.log(om.style.left);
		if (om.style.left.indexOf('e') > 0)
		{
			om.style.left = om.style.top = '0px';
		}
		//window.ii_extramap_height = 0;
		//window.onresize();
		//this.map.map.updateSize();

	}
}


ii.views.Mappable.prototype.remove = function()
{
	//if (this.item.centered) this.item.center(false);
	this.removeQueries();
	this.removeFromMap();
}

ii.views.Mappable.prototype.removeFromMap = function()
{
	this.map.removeMarker(this.marker,this.layer);
	if (this.shadowDiv)
		this.shadowDiv.parentNode.removeChild(this.shadowDiv);
	if (this.shadowMarker)
		this.map.removeMarker(this.shadowMarker,'shadows');
}

ii.views.Mappable.prototype.move = function()
{
	if (this.item.centered)
	{
		this.map.panTo(
				this.item.displayLat || this.item.lat, 
				this.item.displayLon || this.item.lon);
	}
	else
	{
		this.map.moveMarker(
				this.marker, 
				this.item.displayLat || this.item.lat, 
				this.item.displayLon || this.item.lon);
		if (this.shadowMarker)
			this.map.moveMarker(
					this.shadowMarker, 
					this.item.displayLat || this.item.lat, 
					this.item.displayLon || this.item.lon);
	}
}

// specilized ActionLinks View,
// provides functions to create actions
ii.views.ActionLinks = function() {}
ii.views.ActionLinks.prototype = new ii.views.View;


/* generate link-element and hidden div for status display
 * used for LargeListItem views
 */
ii.views.ActionLinks.prototype.statusDiv = function()
{
	// status shows result of action
	this.statusMsg = ii.elm('div', ' ',{style:{margin:'4px 16px'}} );
	this.statusDiv = ii.elm('div',
			{style:{display:'none'}, className:'live'},
			this.statusMsg, ii.elm('hr'));
	return this.statusDiv;
}

ii.views.ActionLinks.prototype.setStatus = function(status, duration)
{
	ii.setText(this.statusMsg, status);
	this.statusDiv.style.display = 'block';
	var that = this;
	window.setTimeout(function()
		{
			 ii.setText(that.statusMsg, '');
			 that.statusDiv.style.display = 'none';

		},
		duration || ii.set_status_duration
	);
}
ii.views.ActionLinks.prototype.clearStatus = function()
{
	ii.setText(this.statusMsg, '');
	this.statusDiv.style.display = 'none';
}

/* generate link-element and hidden div for adding 
 * or dropping friendship 
 */
ii.views.ActionLinks.prototype.addFriendLink = function()
{
	var friendLink = ii.elm('a', {href: 'javascript://setfriend()'},
		this.item.isfriend==1 ? '[Drop Friend]' : '[Add Friend]');

	var that = this;
	friendLink.onclick = function()
	{
		that.clearStatus();
		if (!ii.login)
		{
			alert('You must be logged in to make friends');
			return;
		}
		if (friendLink.innerHTML.indexOf('Add')>-1)
		{
			that.setStatus('Adding user to Friends');
			ii.get('p-new-friend',
				function(resp) {
					that.setStatus('Added user to Friends');
					friendLink.innerHTML = '[Drop Friend]';
				},
				{friendid: that.item.id  }
			);
		}
		else
		{
			that.setStatus('Removing user from Friends');
			ii.get('p-del-friend',
				function(resp) {
					that.setStatus('Removed user from Friends');
					friendLink.innerHTML = '[Add Friend]';
				},
				{friendid: that.item.id  }
			);
		}
	}

	return friendLink; 

}

/* generate link-element and hidden div for commenting
 * used for LargeListItem views
 */
ii.views.ActionLinks.prototype.postCommentLink = function()
{
	var commentLink = ii.elm('a', {href: 'javascript://comment()'},
		(this.item.type=='u'?'[Send Message]' : '[Post Comment]'));

	var that = this;
	commentLink.onclick = function()
	{
		that.clearStatus();
		if (!ii.login)
		{
			if (that.item.type == 'u')
				alert('You must be logged in to send a Message');
			else
				alert('You must be logged in to post a Comment');

			return;
		}

		if (that.commentDiv.style.display=='block')
			that.commentDiv.style.display= 'none';
		else
		{
			ii.log('displaying commentdiv');
			that.commentDiv.style.display= 'block';
			that.commentArea.focus();
		}
		ii.app.refreshCenterPaneShadow();
	}
	return commentLink;
}


ii.views.ActionLinks.prototype.postCommentDiv	= function()
{
	this.commentArea = ii.elm('textarea', {style:{width:'100%' },  rows:3});
	this.commentDiv = ii.elm('form',
		{style: {display:'none'}},
		this.commentArea,
		ii.elm('input', {type:'submit', value:'post',style:{display:'block', cssFloat:'right'}}),
		ii.elm('hr',{style:{clear:'right'}}));

	this.commentDiv.onmousedown = ii.stopPropagation;
	this.commentDiv.onmousemove = ii.stopPropagation;


	var that = this;
	this.commentDiv.onsubmit = function() {
		ii.log('sending msg');
		ii.get('p-new-comment',
			function(resp) {
				if (that.item.type=='u')
					that.setStatus('Message sent');
				else
					that.setStatus('Comment posted');
				ii.log('msg sent: ' + resp.result);
			},
			{
				entitytype: ii.typename[that.item.type],
				entityid: that.item.id,
				content: that.commentArea.value }
		);
		that.setStatus('Sending...');
		that.commentArea.value = '';
		this.style.display = 'none';
		return false;
	}
	return this.commentDiv;

}


ii.views.ActionLinks.prototype.postInLink = function()
{
	var postInLink = ii.elm('a', {href: 'javascript://postIn()'}, '[Post In]');

	if (!ii.login)
	{
		postInLink.onclick = function()
		{
			alert('You must be logged in to post this item '
					+ 'in your collections');

		}
	}
	else if (this.item.userid != ii.login.id && !this.item.ispublic)
	{
		postInLink.onclick = function()
		{
			alert('You are not allowed to post this item in your collections'
				+ ' because it is not public.');
		}
	}
	else
	{
		var that = this;
		postInLink.onclick = function()
		{
			if (that.postInDiv.style.display == 'block')
			{
				that.postInDiv.style.display = 'none';
			}
			else
			{
				that.postInDiv.style.display = 'block';

				that.postInLoadMySets();

			}
			ii.app.refreshCenterPaneShadow();
		}
	}
	return postInLink;
}

ii.views.ActionLinks.prototype.postInDiv = function()
{
	this.postInSelect = ii.elm('select', {
		className:'postedIn',
		multiple:'yes',
		size:'8',
        style: {
            width: '150px'
        }
	});
	var select = this.postInSelect;

	var submitbtn = ii.elm('input', {
				type:'submit',
				value:'Save'
			});

	var that = this;

	function submit()
	{
		ii.startWaitButton(submitbtn);

		var opts_sel = [0];
		var opts = select.getElementsByTagName('option');
		for(var n=0; n < opts.length; n++)
			if (opts[n].selected)
				opts_sel.push(opts[n].value);

		ii.get('p-upd-'+ii.typename[that.item.type],
				function(resp)
				{
					ii.endWaitButton(submitbtn);
					ii.log('updating sets: ' + resp.result);
					that.postInDiv.style.display = 'none';
					if (resp.partialSuccess)
					{
						that.setStatus('Some changes were not made '
							+ 'because that would change the item\'s '
							+ 'security settings' , 10);
					}


					ii.app.itemQuery.doUpdate();

				},
				{
					id:that.item.id,
					sets:opts_sel.join(',')
				}
		);

		return false;
	}


	this.postInDiv = ii.elm('form',
			{
				className: 'postIn',
				style: {
					display:'none'
				},
				onsubmit:submit,
				onmousedown: ii.stopPropagation,
				onmousemove: ii.stopPropagation
			},
			ii.elm('p',
				'Post this ',
				ii.typesingle[this.item.type],
				' in your Collections'
			),
			ii.elm('p',
				{className: 'note'},
				ii.typesingle[this.item.type],
				' inherits the Collection\'s Privacy'
			),
			ii.elm('p',
				{className: 'header'},
				'My Collections'
			),
            ii.elm('div', {
                    style: {
                        marginBottom: '10px',
                        position: 'relative',
                        width: '100%'
                    }
                },
			    select,
                submitbtn
            ),
			ii.elm('p',
				{className: 'footer'},
				'Control Click (PC) or Apple Click (Mac) to select ',
				'multiple Collections. Read our ',
				ii.elm('a', {href: '#rel&tab=HelpFAQ&q=postin'}, 'FAQ'),
				' for help on the Post In feature.'
			)

	);

	return this.postInDiv;
}

ii.views.ActionLinks.prototype.postInLoadMySets = function()
{
	this.postInSelect.innerHTML = '';

	// fill left select box with postin
	var strPostedIn = '';
	var isprivate = (this.item.postedin.length==0)
	var opt =ii.elm('option',
		{
				className: 'private',
				value: 0
		}, 'Private'
	);

	if (isprivate)
		opt.selected = 'selected';
	this.postInSelect.appendChild(opt);

	for(var n=0; n< this.item.postedin.length; n++)
	{
		var type = this.item.postedin[n].type;
		var id = this.item.postedin[n].id;
		var name = this.item.postedin[n].name;
		if (type=='trip')
			continue;// no trips in list
		if (type=='group' && id==1)
			type = 'world';
		if (type=='group' && name=='Friends')
			type='friends';
		var opt = ii.elm('option',
			{
				className: type,
				value:id,
				selected: 'selected'

			},
			name);

		this.postInSelect.appendChild(opt);
		strPostedIn += '_' + this.item.postedin[n].id + '_';

	}
	var that = this;
	var myset = ii.get('q-mysets',
		function(resp)
		{
			for(var n=0; n < resp.items.length; n++)
			{
				//already in left listbox ?
				if (strPostedIn.indexOf('_'+resp.items[n].id+'_')>=0)
					continue;
				var type = resp.items[n].type;
				var id = resp.items[n].id;
				var name = resp.items[n].name;
				if (type=='group' && id==1)
					type = 'world';
				if (type=='group' && name=='Friends')
					type='friends';
				var opt = ii.elm('option',
					{
						className: type,
						value:id
					},
					name);

				that.postInSelect.appendChild(opt);
			}
		}, {}
	);
}

ii.views.ActionLinks.prototype.visitLink = function()
{
	var res = ii.elm('a', {href: 'javascript://visit()'}, '[Visit Spot]');
    var that = this;

	res.onclick = function()
	{
		if (!ii.login)
		{
			alert('You must be logged in to visit a Spot');
			return;
		}

		that.setStatus('Visiting ... ');
		ii.get('p-upd-profile', function(resp)
			{
				that.setStatus('You are now visiting ' + that.item.name);

			},
			{
				spotid: that.item.id
			}
		)


	}
    return res;
}


ii.views.ActionLinks.prototype.joinLink = function() 
{
    var item = this.item;

 	var typename = ii.typesingle[this.item.type];

	this.joinLink = ii.elm('a', {href: 'javascript://join()'},
			'[Join ' + typename + ']');
	this.leaveLink = ii.elm('a', {href: 'javascript://leave()'},
			'[Leave ' + typename + ']');
	var joinLink = this.joinLink;
	var leaveLink = this.leaveLink;

    var span = ii.elm('span', this.joinLink, ' ', this.leaveLink);

	function setShowHide()
	{
		joinLink.style.display = (
			(!ii.login || (item.canjoin==0) || item.ismember == 'owner' || item.ismember == 'member')
			? 'none' : '');

		leaveLink.style.display = (
			(!ii.login || item.ismember != 'member')
			? 'none' : '');
	}
	setShowHide();
    var that = this;

	function doJoinLeave(url, ismember, text)
	{
		that.setStatus('Updating ... ');
		ii.get(url,
			function(resp)
			{
				item.ismember = ismember;
				setShowHide();
				that.setStatus(typename + ' ' + text);
			},
			{
				entitytype: 'user',
				entityid: ii.login.id,
				setid: item.id
			}
		);
	}

	joinLink.onclick = function()
	{
		doJoinLeave('p-new-link', 'member', 'joined');
	}

	leaveLink.onclick = function()
	{
		doJoinLeave('p-del-link', 'none', 'left');
	}

    return span ;
}

ii.views.ItemList = function() {}
ii.views.ItemList.prototype = new ii.views.View;


ii.views.ItemList.prototype.addSearchHeader = function(query)
{
	this.query = query;

}

// Sets up a header for the itembrowser.
// args:
//  dataField: the fieldname to be used for the count
//  label: the header-label
//  paneLink: The 'pane' param for the onclick link
//  icon: The className used to add a micro-icon
ii.views.ItemList.prototype.addHeader = function(args)
{
	// create count element as data-field
	var count = ii.elm('span', ''+this.item[args.dataField]);
	this.fields[args.dataField] = count;
	var hasItems = (this.item[args.dataField] > 0);

	var waiting = ii.elm('img', {src:'/media/throbber.gif',style:{
			display:'none', cssFloat:'right',
			position:'relative', top:'5px',
			width:'16px', height:'16px'}});

	var items = ii.elm('div', {className:'items'});

	if (this.query) args.filter.query = this.query;
	var query = new ii.Query(args.type, {interval: 10000}, args.filter);

	function setpage(pagenr)
	{
		query.firstTimeDone = false;
		waiting.style.display = '';
		query.setQueryOpts({start: (pagenr-1) * 5});
	}

	var div;
	var pager = new ii.Pager(setpage);
	var hasClicked = false;
	query.addListener(pager);

	query.setQueryOpts({fields:'basic,locname,distance,count,content',count:'5'});

	query.addListener(
		{
			addItem: function(item) {
			var vw = item.createView('ListItem');
	  		items.insertBefore(vw.div, items.firstChild);
		},
		itemsDone: function(items) {
			waiting.style.display = 'none';
			if (hasClicked)
			{
				var cont = document.getElementById('ii_itemlist');
				if (cont.scrollHeight > cont.clientHeight)
				{
					var e = window.ii_extramap_height;
					window.ii_extramap_height = 0;
					window.onresize();
					div.scrollIntoView(true);
					window.ii_extramap_height = e;
					window.onresize();
				}
			}
			hasClicked = false;
            if (args.ondone) args.ondone();
		}
	});
	query.addListener(ii.app.map);
    query.addListener(ii.app.statusDisplay);

	ii.itemExpand = ii.itemExpand || {};
	var browserId = this.item.type +'.'+this.item.id+'.'+args.type;
	var expand = ii.itemExpand[browserId];
	if (expand === undefined) expand = args.expand;
	if (expand && hasItems)
	{
		waiting.style.display = 'block';
		query.start();
	}

	var hdr = ii.elm('div',
				{className:'hdr', href:'#rel'},
				ii.elm('div', {className: 'arrow'}),
				waiting,
				args.label + ' ' ,
				ii.elm('span', {className:'cnt'},'(', count, ')')
			);
	var state = (expand && hasItems) ? 'expanded ' : 'collapsed ';
	div = ii.elm('div', {className:'item_browser '+state+args.type 
		+ ' '+(hasItems?'':'noitems')},
			hdr,
			pager.divs[0],
			items,
			pager.divs[1],
			ii.elm('div', {className: 'ftr'})
		);

	var that = this;
	hdr.onclick = function() {
		if (that.item[args.dataField]> 0)
		{
			if (div.className.indexOf('expanded') >= 0)
			{
				div.className = div.className.replace('expanded','collapsed')
                ii.app.statusDisplay.counters[args.type][1] = 0;
                ii.app.statusDisplay.update();
				query.stop();
				waiting.style.display = 'none';
				ii.itemExpand[browserId] = false;
				
			}
			else
			{
				div.className = div.className.replace('collapsed','expanded')
				waiting.style.display = '';
				hasClicked = true;
				query.firstTimeDone = false;
				query.start();
				ii.itemExpand[browserId] = true;
			}
			if (browserId.match(/^g.1/))
			{
				var s = ['photo','user', 'video','trip','spot','group'];
				var m = '';
				for(var k in s) 
					if (ii.itemExpand['g.1.'+s[k]]) 
						m += s[k] + '.';
				ii.setCookie('world_expand', m, 30);
				ii.log('setting cookie:'+m);

			}
		}
	}

	// save waiting element and header inside query
	query.waiting = waiting;

	this.div.appendChild(div);
	this.queries.push(query);

	this.div.onmouseover = function(){};
	this.div.onmouseout = function(){};
}

ii.views.ItemList.prototype.setBounds = function(bounds) {
	ii.log('BOUNDS:'+bounds);
	for (var n = 0; n < this.queries.length; n++)
	{
		this.queries[n].setQueryOpts(bounds);
		this.queries[n].setQueryOpts({start: (1-1) * 5});
		if (this.queries[n].paused) continue;
		this.queries[n].firstTimeDone = false;
		this.queries[n].waiting.style.display = '';
	}
}

/* specilized view to display feed */
ii.views.TabFeed = function() {}
ii.views.TabFeed.prototype = new ii.views.View;

ii.views.TabFeed.prototype.initFeed = function()
{
    var browser_options = browser_options || {
        show_friends_checkbox: false,
        show_search: false,
        show_tabs: true,
		show_header: true,
		driver_name: 'feed'
    };

    var query_properties = {
        interval: 10000
    };
    var query_url_parameters = { 
        count: 10,
        entitytype: ii.typename[this.item.type],
        entityid: this.item.id,
	    fields:'basic,locname,count,tt'
    };
    if (this.item.type=='g' && this.item.id==1)
    {
        delete query_url_parameters.entitytype;
        delete query_url_parameters.entityid;
		if (ii.app.state.state.subtab && ii.app.state.state.subtab != 'all')
			query_url_parameters.entitytype = ii.app.state.state.subtab ;
    }
	if (this.item.type=='v' || this.item.type=='p')
		query_url_parameters.entitytype = 'poi';

    var feed_query = new ii.Query('feed', query_properties, query_url_parameters);
	this.queries = [ feed_query ];

    var feed_pager = this.createPager(function(page) {
			feed_query.setQueryOpts({start:(page-1)*10}); } );

    var feed_items_div = ii.elm('div', {style:{cssFloat:'left', width:'455px'}});

    feed_query.addListener(feed_pager);

    feed_query.addListener({
        addItem: function(item){

            view = item.createView('ListItem');

			feed_items_div.insertBefore(view.div, feed_items_div.firstChild);
		},
        itemsDone: function(items){
            if( browser_options.onDone ){
                browser_options.onDone(items);
            }
            else {
                ii.app.refreshCenterPaneShadow();
            }
        }
    });


    this.feed_query = feed_query;

    this.feed_div = ii.elm('div');
    this.div.appendChild(this.feed_div);

	if (browser_options.show_header)
	    this.feed_div.appendChild(this.createHeader(query_url_parameters));

    if(browser_options.show_tabs && browser_options.show_tabs === true){
		if (ii.app.state.state.subtab)
			// use selected subtab
            var selected_subtab = ii.app.state.state.subtab;
		else if (ii.app.state.state.pane)
			// default to opened pane
            var selected_subtab = ii.app.state.state.pane;
		else
			// no pane & no subtab => select all
			var selected_subtab = 'all';

		ii.tabs.feed = {

			subtab_labels: {
				all: 'All',
				user: 'People',
				poi: 'Photos',
				trip: 'Trips',
				comment: 'Comments',
				spot: 'Spots',
				group: 'Groups',
				album: 'Albums'
			}
		}
		var selected_subtab_label = ii.typeplural[ii.typeletter[selected_subtab]] || 'All';
		ii.log('adding tabs');

        this.feed_div.appendChild(this.createTabHeader(selected_subtab_label, 'All', 'Comments', 'People', 'Photos', 'Trips', 'Spots', 'Groups'));
    }


    feed_query.start();

    if(browser_options.show_search && browser_options.show_search === true){
        this.feed_div.appendChild(this.createSearchInput());
    }

    if(browser_options.show_friends_checkbox && browser_options.show_friends_checkbox === true){
        this.feed_div.appendChild(ii.elm('div',
            {style:{
                borderBottom: 'solid 1px #b7b7b7',
                position:'relative'
            }},
            feed_pager.divs[0],
            ii.elm('div',
                {style:{
                    textAlign:'right'
                }},
                ii.elm('input', {type:'checkbox'}),
                ii.elm('span', 'Friends Only')
            )
        ));
    }
    else {
        this.feed_div.appendChild(ii.elm('div',
            {style:{
                borderBottom: 'solid 1px #b7b7b7',
                padding: '7px 0px',
                position:'relative'
            }},
            feed_pager.divs[0]
        ));
    }





    this.feed_div.appendChild(ii.elm('div',
        {style:{
            width:'100%',
            overflow:'hidden'
        }},
        feed_items_div,
		ii.loadDriver( 'Feed')

    ));
    this.feed_div.appendChild(ii.elm('div',
        {style:{
            padding:'15px 0px',
            position:'relative'
        }},
        feed_pager.divs[1]
    ));
}


ii.views.TabFeed.prototype.createHeader = function(options){

    var options = (options === undefined) ? {} : options;

    var header = ii.elm('h1', {
            style: {
                border: '0px'
            }
        }
    );

    if (this.item.type !== 'g' || this.item.id !== 1) {

        if( this.item)
		{
			var txt = ii.typesingle[this.item.type]
				+ ' Feed: ' + this.item.name;
			header.appendChild(document.createTextNode(txt));
        }
    }
	else
	{
		header.appendChild(document.createTextNode('Global '));
		header.appendChild(ii.elm('span', {className:'live'}, 'Live!'));
		header.appendChild(document.createTextNode(' Feed'));

	}


    return header;
}

ii.views.TabFeed.prototype.createPager = function(pager_callback){

    var pager;
    if (pager_callback instanceof Function){
        pager = new ii.views.Pager(pager_callback);
    }
    else {
        pager = new ii.views.Pager('tpage');
    }

    for(var i = 0, length = pager.divs.length; i < length; i++){
        pager.divs[i].style.position = 'absolute';
        pager.divs[i].style.left     = '0px';
        pager.divs[i].style.bottom   = '0px';
    }

    return pager;
}

ii.views.TabFeed.prototype.createTabHeader = function(selectedTab){
	var subtab_entities = {
		'All': 'all',
		'People': 'user',
		'Photos': 'photo',
		'Trips': 'trip',
		'Comments': 'comment',
		'Spots': 'spot',
		'Groups': 'group',
		'Albums': 'album'
	};

    var subtabs = ii.elm('div', {className:'subtabs'});

    // only generate sub tabs if this is not an item
	for(var n=1; n < arguments.length && !ii.app.state.state.item; n++)
	{
		var tabName = arguments[n];
		if (tabName == selectedTab)
			var tab = ii.elm('a', {className:'selected'}, arguments[n]);
		else
			var tab = ii.elm('a', {href:'#rel&subtab='+subtab_entities[arguments[n]]}, arguments[n]);

		subtabs.appendChild(tab);

	}

    // wrap the subtabs in a div to ensure the subtabs div is cleared.
	return ii.elm('div', {style:{width:'100%', overflow:'hidden'}}, subtabs);
}

ii.views.TabFeed.prototype.createSearchInput = function(){

    var default_search_value = 'Type search'

    var search_form = ii.elm('form',
        ii.elm('input',{
            id:'feed_search',
            name:'search',
            onblur: function(){
                if(this.value == ''){
                    this.value = default_search_value;
                    this.style.color = '#666666';
                }
                this.hasFocus = false;
            },
            onfocus: function(){
                if(this.value == default_search_value){
                    this.value = '';
                }
                this.style.color = 'black';
                this.hasFocus = true;
            },
            onkeyup: function(){
                if(ii.app.applyFilterTimer){
                    window.clearTimeout(ii.app.applyFilterTimer);
                }

                ii.app.applyFilterTimer = window.setTimeout(function(){
                   window.location = '#rel&query=' + document.getElementById('feed_search').value;
                }, 500);
            },
            style:{
                color:'#666666',
                margin:'20px 0px 10px',
                width:'60%'
            },
            value:default_search_value
        })
    );

    return search_form;

}

ii.views.TabFeed.prototype.setPage = function(page){
    this.feed_query.setQueryOpts({start:(page-1)*this.feed_query.queryOpts.count})
}


/* specialized Details Tab View */
ii.views.TabDetails = function() {}
ii.views.TabDetails.prototype = new ii.views.View;

/* fills the static fields that are common */
ii.views.TabDetails.prototype.initFields = function()
{
	if (this.fields.author)
	{
		this.fields.author.appendChild(
				ii.elm('img', {src: '/srv/d-media.php?entitytype=user' +
					'&entityid='+this.item.userid+'&width=60&height=45',
					style:{cssFloat:'right'}})
		);
		this.fields.author.appendChild(
				ii.userLink(this.item.userid, this.item.author)
		);
	}

	if (this.fields.photo)
		this.fields.photo.appendChild(
				ii.elm('img', {src: '/srv/d-media.php?entitytype=' +
                    ii.typename[this.item.type] +
					'&entityid='+this.item.id+'&width=288&height=218'
			    })
        );

	if (this.fields.info_form)
	{
		if (this.fields.info_form.name)
			this.fields.info_form.name.value = this.item.name;

		if (this.fields.info_form.description)
			this.fields.info_form.description.value = this.item.description;
	}
}

ii.views.TabDetails.prototype.update = function() {
    ii.log('***updating');

    ii.views.View.prototype.update.call(this);
};

ii.views.TabDetails.prototype.initForm = function(form_prefix, onsubmit)
{
	// owner is userid field except for user. Then it's id
	var ownerid = (this.item.type == 'u' ? this.item.id : this.item.userid);

	var form = this.fields[form_prefix+'_form'];
    ii.log('Initializing form : '+form_prefix+'_form (='+form+')');
	var actionbar = this.fields[form_prefix+'_actionbar'];
	var editbtn = this.fields[form_prefix+'_editbtn'];
	var cancelbtn = this.fields[form_prefix+'_cancelbtn'];

	this.setEditMode(form, false);

	if (ii.login && (ii.login.id == ownerid || ii.login.isAdmin))
	{
		actionbar.style.display = '';

		var that = this;

		// set edit & cancel buttons
		editbtn.onclick =
			function() {
				that.setEditMode(form, true);
			}

		cancelbtn.onclick =
			function() {
				that.setEditMode(form, false);
			}
		form.onsubmit = onsubmit;
	}
	else
	{
		ii.log('Setting up ' + form_prefix + '_actionbar');
		actionbar.style.display = 'none';
	}

	this.setupDelete(form_prefix);

}

ii.views.TabDetails.prototype.setEditMode = function(form, editMode)
{
	if (editMode)
		form.className = form.className.replace('viewmode', 'editmode');
	else
		form.className = form.className.replace('editmode', 'viewmode');
}

ii.views.TabDetails.prototype.setupDelete = function(prefix)
{
	var type = this.item.type;
	var id = this.item.id;
	var deleteBtn  = this.fields[prefix+'_deletebtn'];
	if (!deleteBtn)
		return;

	var showButton = (!this.item.ismember || this.item.ismember == 'owner');
	deleteBtn.style.display = (showButton ? '' : 'none');

	ii.log('type:'+this.type);
	deleteBtn.onclick = function()
	{
		var txt = 'Are you sure you want to delete this '
				+ ii.typesingle[type] + '?';
		if (!confirm(txt))
			return;
		ii.startWaitButton(deleteBtn);
		type = ii.typename[type].replace('spot','set').replace('group','set')
				.replace('photo','poi').replace('video','poi');
		ii.get('p-del-'+type,
			function(resp)
			{
				ii.endWaitButton(deleteBtn);
				ii.app.state.setState({item:'ME.0'});

			},
			{
				id: id
			}
		);

	}

}


ii.views.TabDetails.prototype.addComments = function()
{
	var div = this.fields.commentlist;
	ii.log('comments : ' + div);
	if (!div) return;

    div.innerHTML = '';
	var filter = { count:100, type:'comment' };
	var type = ii.typename[this.item.type].replace('group','set')
		.replace('album','set').replace('spot','set');

	filter['entitytype'] = type;
	filter['entityid'] = this.item.id;
	var query = new ii.Query('thread', {interval:15000},
			filter);

	query.addListener({
		addItem: function(item)
		{
			var view = item.createView('TabView',
				{
					title: 'Comments',
                    args: {
                        deleteMethod: 'remove',
						parentQuery: query

                    }
				});
			div.appendChild(view.div);
		},
		itemsDone: function(items)
		{
		}

	});
	query.start();

	this.queries.push(query); // remember for later removal
}

ii.views.TabDetails.prototype.addUsers = function()
{
	var div = this.fields.userlist;
	if (!div) return;

    div.innerHTML = '';

	var filter = {fields:'basic,count, locname,content'};
	var type = ii.typename[this.item.type].replace('group','set')
		.replace('album','set').replace('spot','set');

	filter[type] = this.item.id;
	var query = new ii.Query('user', {interval:15000},
			filter);

	query.addListener({
		addItem: function(item)
		{
			var vw = item.createView('ListItem', {});
            vw.div.style.backgroundColor = 'transparent';

			vw.div.className += ' wide';
            div.appendChild(vw.div);
		}
	});
    query.start();
	this.queries.push(query); // remember for later removal
}

ii.views.TabDetails.prototype.addPhotos = function()
{
	var div = this.fields.photolist;
	if (!div) return;

    div.innerHTML = '';

	var filter = {count:24, fields:'basic,count'};
	var type = ii.typename[this.item.type].replace('group','set')
		.replace('album','set').replace('spot','set');
	filter[type] = this.item.id;
	var query = new ii.Query('photo', {interval:15000},
			filter);

	query.addListener({
		addItem: function(item)
		{
			var vw = item.createView('Details', {});
            div.appendChild(vw.div);
//			div.insertBefore(vw.div, div.firstChild);
		}
	});
	var pager = new ii.views.Pager(
			function onchange(pagenr) {
				query.setQueryOpts({start:(pagenr-1)*filter.count});
			});
	query.addListener(pager);

	var pdiv = this.fields.photolist_pager;
	pdiv.innerHTML = '';
	pdiv.appendChild(pager.divs[0]);

	var that = this;
	// hide entire footer if no pager, (no line)
	query.addListener({
		countItems: function(start, count, total, pagesize) {

			var showFooter = (count<total);
			pdiv.style.display = (showFooter ? 'block' : 'none');

			if (total == 0)
			{
				var nm = ii.typesingle[that.item.type];
				var elm = ii.elm('span','This '+nm+' contains no Photos yet. ',
					'Use the [Post In] link to Post a Photo in a '+nm+'. ',
					'Read our ',
					ii.elm('a', {href:'#rel&tab=HelpFAQ&q=postin_what'}, 'FAQ'),
					' for help on the Post In feature.');
				div.appendChild(elm);
			}
		}
	});

	this.queries.push(query); // remember for later removal
    query.start();

}


ii.views.TabDetails.prototype.addVideos = function()
{
	var div = this.fields.videolist;
	if (!div) return;

    div.innerHTML = '';

	var filter = {count:24, fields:'basic,count'};
	var type = ii.typename[this.item.type].replace('group','set')
		.replace('album','set').replace('spot','set');
	filter[type] = this.item.id;
	var query = new ii.Query('video', {interval:15000}, filter);

	query.addListener({
		addItem: function(item)
		{
			var vw = item.createView('Details', {});
            div.appendChild(vw.div);
//			div.insertBefore(vw.div, div.firstChild);
		}
	});
	var pager = new ii.views.Pager(
			function onchange(pagenr) {
				query.setQueryOpts({start:(pagenr-1)*filter.count});
			});
	query.addListener(pager);

	var pdiv = this.fields.videolist_pager;
	pdiv.innerHTML = '';
	pdiv.appendChild(pager.divs[0]);

	var that = this;
	// hide entire footer if no pager, (no line)
	query.addListener({
		countItems: function(start, count, total, pagesize) {

			var showFooter = (count<total);
			pdiv.style.display = (showFooter ? 'block' : 'none');

			if (total == 0)
			{
				var nm = ii.typesingle[that.item.type];
				var elm = ii.elm('span','This '+nm+' contains no Videos yet. ',
					'Use the [Post In] link to Post a Videos in a '+nm+'. ',
					'Read our ',
					ii.elm('a', {href:'#rel&tab=HelpFAQ&q=postin_what'}, 'FAQ'),
					' for help on the Post In feature.');
				div.appendChild(elm);
			}
		}
	});

	this.queries.push(query); // remember for later removal
    query.start();

}



ii.set_absolute_url_delay = 400;
ii.set_state_polling_interval = 150;


ii.State = function(){};

ii.State.prototype.init = function() {

	this.seq = Math.random();
	this.state = {};
    this.hash = {}; //document.location.hash;

    /** a history object that holds the users item browser navigation */
    this.history = new History();
    /** a boolean defining whether the user is navigating w/ the item brwsr */
    this.history_nav = false;

	var that = this;

    // for IE we need the iframe State trick
    if (ii.browser.msie) {
        var frame = document.createElement("iframe");
        frame.id = "ii-state-frame";
        frame.style.display = "none";
        document.body.appendChild(frame);
        this.writeFrame("");

        // IE
        if ("onpropertychange" in document && "attachEvent" in document) {

            document.attachEvent("onpropertychange", function () {
                if (event.propertyName == "location") {
                    that.check();
                }
            });

        }
    }


	// poll for changes of the hash
    if ('onhashchange' in window) {
        window.onhashchange = function() {
            that.check();
        }
        window.setTimeout(function() { that.check(); }, 50);
    }
    else
    {
    	window.setInterval(function () { that.check() }, ii.set_state_polling_interval);
    }//6644005
// roebie v ostadestraat 153 : 20:00
};

ii.State.prototype.check = function () {
	var h = document.location.hash;
	if (h != this.hash) {
		this.changeHash(h);
	}
}


ii.State.prototype.getHash = function () {
	return document.location.hash;
}

ii.State.prototype.writeFrame = function (s) {
    var f = document.getElementById("ii-state-frame");
    var d = f.contentDocument || f.contentWindow.document;
    d.open();
    d.write("<script>window._hash = '" + s + "'; window.onload = parent.ii.app.state.syncHash;<\/script>");
    d.close();
}

ii.State.prototype.syncHash =	function () {
	var s = this._hash;
	if (s != document.location.hash) {
		document.location.hash = s;
	}
}

ii.State.prototype.updateAbsoluteLocation = function(newhash, replaceUrl)
{

	if (this.updateLocTimer)
		window.clearTimeout(this.updateLocTimer);

	var that = this;
    this.updateLocTimer = window.setTimeout(function(){
        that.hash = newhash;

        if (replaceUrl) {
            window.location.replace(that.hash);
        }
        else {
            window.location = that.hash;
        }
    }, ii.set_absolute_url_delay);

}

// setAutoStates
// adds state changes that are infered from other state-changes
ii.State.prototype.setAutoStates = function(newStates)
{
	if (newStates.ll=='map' && this.state.item)
		newStates.item = '';

	if (newStates.item!=undefined && newStates.pane == undefined)
		newStates.pane = '';

	if (newStates.query!=undefined || newStates.pane!=undefined){
		newStates.page = '';
		newStates.tab = '';
		newStates.tpage = '';
	}

	// search clears pane
	if (newStates.query!= undefined && newStates.query!='')
		newStates.pane = '';

	// clear search when opening item
	if (newStates.item!=undefined)
		newStates.query = '';

	// close explore mode when opening item
	if (newStates.item!=undefined && newStates.item!='')
		newStates.ll = '';

	// reset pagenr when moving map in explore mode
	if (newStates.ll!=undefined && newStates.ll!='map')
		newStates.page = '';

	if (newStates.tab!=undefined)
		newStates.subtab = '';

	// close question when changing tab
	if (newStates.q==undefined && newStates.tab!=undefined)
		newStates.q='';

	if (newStates.subtab!=undefined)
		newStates.tpage = '';
}


// Updates the state
// the second param is set to true if invoked by a hash change
// causing the absolute url to replace the current one
ii.State.prototype.setState = function(newStates, replaceUrl)
{
	var changedStates = {};

	this.setAutoStates(newStates);

	var newhash = this.createHash(newStates);
	this.updateAbsoluteLocation(newhash, replaceUrl);

	for (var n in newStates)
	{
		var old = (this.state[n] ? this.state[n] : '');
		if (old != newStates[n])
		{
			this.state[n] = newStates[n];
			changedStates[n] = newStates[n];
		}
	}

	// apply if not empty
	for(var n in changedStates)
	{
		ii.app.applyState(this.state, changedStates);//(oldsq > this.state.sq));
		break;
	}

    // to aid user navigation, we try to save location (newhash) of the state
    // (changedStates) to history
    this.add_location_to_history(changedStates, newhash);
}

ii.State.prototype.createHash = function(args)
{
	// clone current hash
	var newhash = {};
	for(var key in this.state)
		newhash[key]=this.state[key];
		// apply args
	for(var key in args)
		newhash[key] = args[key];
	var hash = '#';
	for(n in newhash)
		if (newhash[n])
			hash += encodeURIComponent(n) + '=' + encodeURIComponent(newhash[n]) + '&';

	if (hash.length>1)
		return hash.substr(0,hash.length-1)
	else
		return '#';
}

ii.State.prototype.changeHash =	function(newHash)
{
	this.hash = newHash;
	var newStates = {};
	var stateseq = newHash.substr(1).split('&');
	for(var n=0; n < stateseq.length; n++)
	{
		var statekv = stateseq[n].split('=');
		if (statekv.length==2)
			newStates[statekv[0]] = statekv[1];
		else if (statekv.length==1 && statekv[0]=='rel')
			newStates[statekv[0]] = 1; // 'rel' means rel=1
	}

	if (newStates.rel)
	{
		delete newStates.rel;
		this.setState(newStates, true);
		return;
	}

	var changedStates = {};

	// remove and change states
	for(var n in this.state)
	{
		var newStateVal = '';
		for(var m in newStates)
		{
			if (n == m)
			{
				newStateVal = newStates[m];
				break;
			}
		}
		if (this.state[n] != newStateVal)
			changedStates[n] = newStateVal;

	}

	// add states
	for(var n in newStates)
	{
		var found = 0;
		for(var m in this.state)
		{
			if (n==m)
			{
				found=1;
				break;
			}
		}
		if (!found)
			changedStates[n] = newStates[n];
	}

	this.state = newStates;

	// apply if not empty
	for(var n in changedStates)
	{
		ii.app.applyState(this.state, changedStates);//(oldsq > this.state.sq));
		break;
	}

    // if we get an absolute state hash (eg: bookmark), we try to save location
    // of the state (changedStates) to history
    this.add_location_to_history(changedStates, this.createHash(newStates));
}

// refresh the state, or only one param of the state
ii.State.prototype.refresh = function(param)
{
	if (!param)
		var changed = this.state;
	else
	{
		var changed = {};
		changed[param] = this.state[param];
	}
	ii.app.applyState(this.state, changed);
}


/**
 * saves absolute urls (location) that result from an action in the item browser
 *
 * This saves locations so that we can navigate accordingly with the < and >
 * buttons in the item browser.
 *
 * It is also upto the action that changes the location to set the
 * this.history_nav flag if the location should not be added to the history.
 * This method will always turn off the this.history_nav flag before exiting.
 *
 * @param {Object} state the changed state
 * @param {Object} location the absolute url
 */
ii.State.prototype.add_location_to_history = function(state, location){

    // check if this state change is for the item browser? if so then save in
    // history, we check the history_nav because we don't want to
    // modify history if the user is navgiating via item browser.
    if( this.history_nav === false &&
       ( state.item !== undefined || state.query !== undefined ||
         state.pane !== undefined || state.page !== undefined) ){

        this.history.append(location);
    }

    // always ensure that the history nav flag is false because from this point
    // forward the user may or may not navigate the site with the item browser
    this.history_nav = false;
}

/**
 * move to the next location in history
 */
ii.State.prototype.next = function(){
    this.history_nav = true;
    var location = this.history.get_next_location();

    if ('string' == typeof location && '' !== location && location !== this.hash.toString()) {
        window.location = location;
    }
}

/**
 * handle the onmouseover event on history navigation for next
 * @param {Object} e
 */
ii.State.prototype.next_onmouseover = function(e){
    if(this.history.get_current_index() < this.history.length()-1){
        e.src='media/arrow_rightX.png';
    }
}

/**
 * move to the prev location in history
 */
ii.State.prototype.prev = function(){
    this.history_nav = true;
    var location = this.history.get_prev_location();

    if('string' == typeof location && '' !== location && location !== this.hash.toString()){
        window.location = location;
    }
}

/**
 * handle the onmouseover event on history navigation for prev
 * @param {Object} e
 */
ii.State.prototype.prev_onmouseover = function(e){
    if(this.history.get_current_index() > 0){
        e.src='media/arrow_leftX.png';
    }
}

/**
 * A General History object that can be used to manage the next(forward) and
 * prev(back) actions. Originally developed with the item browser
 * navigation in mind, however this is more general and can potentially serve
 * other purposes.
 *
 * The History object acts similar to a LIFO queue when populating with data.
 * However, elements are pushed AND instead of popping elements, a current index
 * is maintained.  When a branch at the current index occurs, then all
 * elements following the branch are popped off before another element is pushed
 * onto the queue.
 */
History = function(){
    this.queue = [];
    this.current_index = this.queue.length-1;
}

/**
 * public methods of the History object
 */
History.prototype = {

    /**
     * append a location to the history
     *
     * @param {Object} location
     * @return this history object, making the append method chainable
     */
    append: function(location){
        // never want the first entry to be empty
        if(this.queue.length == 0 && location == ''){
            return;
        }

        // pop off the locations that will be lost due to branching during
        // navigation
        while(this.current_index > -1 && this.current_index < this.queue.length-1){
            var s = this.queue.pop();
        }

        // add the new location
        this.queue.push(location);
        this.current_index = this.queue.length-1;

        return this;
    },

    /**
     * current location in history that is being viewed by the user.
     */
    get_current_index: function(){
        return this.current_index;
    },

    /**
     * get the location in the history of position i
     *
     * @param {Object} i
     */
    get_location_at_index: function(i){
        var location = null;
        try{
            location = this.queue[i];
        }
        catch(e){
            // invalid location
        }
        return location;
    },

    /**
     * get the next location
     */
    get_next_location: function(){
        var location = this.queue[this.queue.length-1] || '';

        if(this.current_index < 0 && this.queue.length > 0){
            this.current_index = 0;
            location = this.queue[this.current_index];
        }
        else if(this.current_index < this.queue.length-1){
            this.current_index = this.current_index + 1;
            location = this.queue[this.current_index];
        }

        return location;
    },

    /**
     * get the previous location
     */
    get_prev_location: function(){
        var location = this.queue[0] || '';

        if(this.current_index > this.queue.length-1){
            this.current_index = this.queue.length-1;
            location = this.queue[this.current_index];
        }
        else if(this.current_index > 0){
            this.current_index = this.current_index - 1;
            location = this.queue[this.current_index];
        }

        return location;
    },

    /**
     * return the current history as a queue;
     */
    get_queue: function(){
        return this.queue;
    },

    /**
     * returns the number of elements in the current history
     */
    length: function(){
        return this.queue.length;
    },

    /**
     * replaces the location at element index i with the location passed into
     * replace
     *
     * @param {Object} i
     * @param {Object} location
     */
    replace: function(i, location){
        this.queue.splice(i,1,location);
    },

    /**
     * converts the history object to a string.
     */
    toString: function(){
        var sb = [];
        sb.push('current_index='+this.current_index+'\n');
        for(var i=0, length = this.queue.length; i<length; i++){
            sb.push('queue['+i+']='+this.queue[i]+'\n');
        }
        return sb.join('');
    }
}
/**
 * @author tomas
 */
ii.tabs = {};

// cleans up queries associate with active tab
ii.tabs.cleanup = function()
{
	if (ii.app.currentTabView)
	{
		if (ii.app.currentTabView.item && 
            ii.app.currentTabView.item.hasView(ii.app.currentTabView))
			ii.app.currentTabView.item.removeView(ii.app.currentTabView);
		else if (ii.app.currentTabView.remove)
			ii.app.currentTabView.remove();
		ii.app.currentTabView = 0;
	}

}

// loads a tab
// itemQuery can be passed to load dynamic data from a view
ii.tabs.initTab = function(tabname)
{
	ii.log('init tab: '+tabname );
	ii.tabs.cleanup();

    var viewname = 'Tab' + tabname;

    var container = {
        addItem: function(item)
        {
            ii.app.currentTabView = item.createView(viewname, {});
            document.getElementById('ii_centerpane')
                .appendChild(ii.app.currentTabView.div)
        }
    }
    if (tabname.indexOf('Add')>=0
            || tabname.indexOf('Inbox')>=0)
        ii.login.query.addListener(container);
    else if (ii.itemQuery && ii.itemQuery.addListener)
        ii.itemQuery.addListener(container);
	else
	{
		var item = new ii.items.Item();
		item.init({type:'u'});
		container.addItem(item);
		document.getElementById('ii_centerpane_Welcome').style.display = 
			(tabname == 'Welcome' ? '' : 'none');
	}
}


ii.tabs.init_HelpFAQ = function()
{
	// see if we need to go to a specific question
	if (ii.app.state.state.q)
	{
		var anchors = document.getElementById('ii_help_FAQ').
				getElementsByTagName('a');

		for(var n=0; n <anchors.length; n++)
		{
			if (anchors[n].name == 'rel&q='+ii.app.state.state.q)
			{

				//scroll into view; must schedule to allow finishing rendering
				var a = anchors[n];

				window.setTimeout(function() {
					ii.log('scrolling into view:');
					ii.log(a);
					a.scrollIntoView();
				}, 100);
			}
		}
	}

}

ii.views.generic.TabSignup = function(item) {
    ii.log('Signup Constructor');
    this.item = item; // not used
    this.initDiv('TabSignup');
}

ii.views.generic.TabSignup.prototype = new ii.views.View();

ii.views.generic.TabSignup.prototype.onload = function() 
{
    var dr = this.fields.driver;
	dr.innerHTML = '';
	dr.appendChild(ii.loadDriver('Signup1'));

	var form = this.fields.form;
	window.ii_signup_params = window.ii_signup_params || {};
    for(var n in window.ii_signup_params)
        if (form[n])
            form[n].value = window.ii_signup_params[n];

	form.onsubmit = function()
	{
		// this time, only try the results

		ii.startWaitButton(this.save);

		// setup paramters
		var fields = {
			username: form.username.value,
			password: form.password.value,
			captcha: form.captcha.value,
			email: form.email.value,
			mobile: form.cellphone.value,
			sex: form.sex.value,

			tryonly: true
		};

		// birthday only if correct
		if (form.birthyear.value>0 && form.birthmonth.value>0 && form.birthdom.value>0)
        {
			fields.birthday = form.birthyear.value.concat(
				'-', form.birthmonth.value,
				'-', form.birthdom.value);
            window.ii_signup_params.birthyear = form.birthyear.value;
            window.ii_signup_params.birthmonth = form.birthmonth.value;
            window.ii_signup_params.birthdom = form.birthdom.value;
        }

        for(var n in fields)
            window.ii_signup_params[n] = fields[n];
        

		// remove existing errors
		var divs = form.getElementsByTagName('div');
		for(var n=0; n< divs.length; n++)
		{
			ii.log('found div with class: ' + divs[n].className);
			if (divs[n].className.match('error'))
				divs[n].parentNode.removeChild(divs[n]);
		}
		// locally test matching passwords
		if (form.password.value != form.retypepassword.value)
		{
			var error = ii.elm('div', {className:'error'}, 'passwords don\'t match');
			form.retypepassword.parentNode.appendChild(error);
			return false;
		}

		// issue signup
		ii.get('s-signup', function(resp)
		{
			ii.endWaitButton(form.save);
			if (resp.signupresult != 'OK')
			{
				// failure
				var target;
				if (resp.target)
					target = form[resp.target];
				if (!target)
					target = form.captcha;

				var error = ii.elm('div', {className:'error'}, resp.signupresult);
				form[resp.target].parentNode.appendChild(error);
				ii.log(resp.signupresult);
			}
			else
			{
				window.location = '#rel&tab=Signup2';
			}

		}, fields);

		return false;

	}

}

ii.views.generic.TabSignup2 = function(item) {
    ii.log('Signup Constructor');
    this.item = item; // not used
    this.initDiv('TabSignup2');
}

ii.views.generic.TabSignup2.prototype = new ii.views.View();

ii.views.generic.TabSignup2.prototype.onload = function() 
{

	var networks = this.fields.networks;
	networks.innerHTML = '';
	var networkEdit = ii.views.networkEdit([]);
	networks.appendChild(networkEdit);

	var dr = this.fields.driver;
	dr.innerHTML = '';
	dr.appendChild(ii.loadDriver('Signup2'));

	var form = this.fields.form;
	form.skip.onclick = function()
	{
		window.location = '#rel&tab=Signup3';
	}

	form.save.onclick = function()
	{
		ii.startWaitButton(this);

		// clear iframe for image result
		var doc = ii.iframeDocument(document.getElementById('ii_iframe'));
        try{
            doc.innerHTML = '';
        }catch(e){
            // do nothing, the above is not needed in IE
        }

		// check image upload result
		function checkResult()
		{
			ii.endWaitButton(form.save);
			var doc = ii.iframeDocument(document.getElementById('ii_iframe'));
			if (!doc.innerHTML.match('"result"'))
			{
				if (ii.app.state.state.tab == 'Signup2') // still on this page?
					window.setTimeout(checkResult, 250);
			}
			else
			{
				var regex = /"mediaid":(\d+)/;
				var res = regex.exec(doc.innerHTML);
				if (res)
				{
					window.ii_signup_params.mediaid = 0+res[1];
				}
				window.location = '#rel&tab=Signup3';
			}
		}
		window.ii_signup_params.fullname = form.fullname.value;
		window.ii_signup_params.message = form.msgbox.value;
		window.ii_signup_params.website = form.website.value;
		window.ii_signup_params.homecountry = form.homecountry.value;
		window.ii_signup_params.homecity = form.homecity.value;
		window.ii_signup_params.networks = ii.views.networksGet(networkEdit);

		checkResult(); // start polling avatar upload
	}

}

ii.views.generic.TabSignup3 = function(item) {
    this.item = item; // not used
    this.initDiv('TabSignup3');
}

ii.views.generic.TabSignup3.prototype = new ii.views.View();

ii.views.generic.TabSignup3.prototype.onload = function() 
{
	var dr = this.fields.driver;
	dr.innerHTML = '';
	dr.appendChild(ii.loadDriver('Signup3'));

	var form = this.fields.form;

	form.onsubmit = function() {
		window.location = '#rel&tab=Signup4';
		return false;
	}

	form.save.onclick = function()
	{
		if (form.privacy[0].checked)
			window.ii_signup_params.visibility = 'public';
		if (form.privacy[1].checked)
			window.ii_signup_params.visibility = 'friends';
		if (form.privacy[2].checked)
			window.ii_signup_params.visibility = 'private';
	}
}


ii.views.generic.TabSignup4 = function(item) {
    this.item = item; // not used
    this.initDiv('TabSignup4');
}

ii.views.generic.TabSignup4.prototype = new ii.views.View();

ii.views.generic.TabSignup4.prototype.onload = function() 
{
	var dr = this.fields.driver;
	dr.innerHTML = '';
	dr.appendChild(ii.loadDriver('Signup4'));

    var form = this.fields.form;

    var that = this;
	var selectedSpot = 0;

	var map = new ii.Map.Minimap(
		{
			target: this.fields.minimap,
			tabname: 'Signup4',
			onclick: onclickmap
		}
	);

	var lm = this.fields.locateme;
	if (!navigator.geolocation)
		lm.style.display = 'none';
	else
	{
		lm.onclick = function() {
			ii.startWaitButton(lm);
			navigator.geolocation.getCurrentPosition(function(position) {
				map.setCenter(position.coords.latitude, position.coords.longitude);
				that.fields.name_spot.style.display = 'block';
				that.fields.selected_spot.style.display = 'none';

		selectedSpot = 0;
				ii.endWaitButton(lm);
			}, function() {
				ii.endWaitButton(lm);
				that.fields.locateme_err.style.display = 'inline';
		  });

		}
	}


	function onclickmap(){
        that.fields.name_spot.style.display = 'block';
        that.fields.selected_spot.style.display = 'none';

		selectedSpot = 0;
	}

	// onclick for spot-listitem
	function onClickSpot(view)
	{
		// 'this' will be the view

		ii.log('selected item:' + view.item.name);
        that.fields.name_spot.style.display = 'none';

		// show active spot below map
        var elm = that.fields.selected_spot;
		elm.style.display = 'block';
		elm.innerHTML = '';
		elm.appendChild( document.createTextNode('You positioned yourself on: '
					+ view.item.name)
		);

		// set the marker
		map.moveMarker(view.item.lat, view.item.lon);
		view.highlighted = true;
		selectedSpot = view.item.id;
	}

	// onclick for search spot button
	form.searchspot_btn.onclick = function()
	{
		that.fields.searchspot_result.innerHTML='';
		if (ii.qrySearchSpots)
		{
			ii.qrySearchSpots.stop();
		}
		var qry = form.searchspot_txt.value;
		ii.qrySearchSpots = new ii.Query('spot',
				{interval:60000},
				{query:qry,fields:'basic.count'}
		);

		ii.qrySearchSpots.addListener({addItem:
			function(item) {
				var vw = item.createView('ListItem',
					{onclick:onClickSpot});

				var res = that.fields.searchspot_result;
				res.insertBefore(vw.div, res.firstChild);
			},
			countItems: function(start,count, total)
			{
				ii.log('found: '+total + ' items');
				if (total == 0)
				{
                    that.fields.searchspot_result
						.innerHTML='No spots found matching ' + qry;
				}

			}
		});
		ii.qrySearchSpots.start();
	}

	var form4 = form;
	form4.save.onclick = function()
	{
		window.ii_signup_params.spotid = selectedSpot;
		window.ii_signup_params.spotname = form4.spotname.value;
		form4.onsubmit();
	}

	form4.skip.onclick = function()
	{
		form4.onsubmit();
	}


	form4.onsubmit = function()
	{
		ii.startWaitButton(this.save);

		//Perform acutal signup
		window.ii_signup_params.tryonly = false;

		if (map.selectedLat || map.selectedLon)
		{
			window.ii_signup_params.spotlat = map.selectedLat;
			window.ii_signup_params.spotlon = map.selectedLon;
		}

		// issue signup
		ii.get('s-signup', function(resp)
		{
			ii.endWaitButton(form4.save);

			if (resp.signupresult != 'OK')
			{
				// shouldn't happen.
				// everything is checked by now
				var error = ii.elm('div', {className:'error'}, 'Signup error. Please try again');
				form4.spotname.parentNode.appendChild(error);
				ii.log(resp.signupresult);
			}
			else
			{

				ii.login = new ii.Login(resp.id, window.ii_signup_params.username, resp.key);
				ii.app.state.setState({item:'ME.0'});
				ii.app.state.setState({tab:'Signup5'});
				ii.app.state.refresh('item');
				ii.tabs.clear_Signup();
			}

		}, window.ii_signup_params);


		return false;
	}
}

ii.views.generic.TabSignup5 = function(item) {
    this.item = item; // not used
    this.initDiv('TabSignup5');
}

ii.views.generic.TabSignup5.prototype = new ii.views.View();

ii.views.generic.TabSignup5.prototype.onload = function() 
{

	ii.setText(this.fields.username, ii.login.username);
	ii.login.query.addListener({addItem:function (item) {
		this.fields.mailto.innerHTML = item.uploademail;
		this.fields.mailto.href = 'mailto:'+item.uploademail;
	}});
	this.fields.vcard.href = '/srv/t-vcard-upload.php?key='
		+ ii.login.key;
	ii.setText(this.fields.vcard, '[Download '
		+ ii.login.username
		+' vCard]');

}

/**
 * @author tomas
 *
 */




// pass the name of the parameter that will change
// default parameter is "page"
// You can also pass a function that will be invoked
// whenever the pagenr changes. The function param will
// be the pagenr
//
// Will create this.divs[0] and this.divs[1] containing pagers
ii.views.Pager = function(urlparam)
{
	if (urlparam instanceof Function)
		this.callback = urlparam;
	else
		this.urlparam = (urlparam || 'page');

	this.counter = ii.elm('span', {className: 'cnt'}, ' (...)');
	this.divs = [
	 	ii.elm('div', {className:'pager'}),
		ii.elm('div', {className:'pager'})
	];

}


// Callback function for ii.Query object that is invoked when the count
// changes. This will create/update the pager-divs
ii.views.Pager.prototype.countItems = function(start, count, total, pagesize)
{
	// set counter in header
	ii.setText(this.counter, ' ('+total+')');

	// get page nr and page range
	var page =   1+(start/pagesize);
	var pages = Math.ceil(total/pagesize);
	var p1 = Math.max(1,page - 5);
	var p2 = Math.min(pages,page + 5);
	if (p2 >= 10)
	{
		var p1 = Math.max(1,page - 4);
		var p2 = Math.min(pages,page + 4);
	}

	var that = this;
	function pagelink(pagenr, name)
	{
		var l = ii.elm('a', name);
		if (!that.urlparam)
		{
			l.href ='#rel';
			l.onclick = function() { that.callback(pagenr); };
		}
		else
			l.href = '#rel&'+that.urlparam+'='+pagenr;


		return l;
	}


	for(var t = 0; t < 2; t++)
	{
		var target = this.divs[t];
		while(target.firstChild)
			target.removeChild(target.firstChild);

		if (pages==1)
			continue;

		if (start > 0)
		{
			target.appendChild(pagelink(page-1, '<<'));
			target.appendChild(document.createTextNode(' | '));
		}
		for(var n=p1; n <= p2; n++)
		{
			if (page == n)
				target.appendChild(ii.elm('span', {className:'sel'}, n.toString()));
			else
				target.appendChild(pagelink(n,n.toString()));

			if (n<p2)
				target.appendChild(document.createTextNode(' | '));
		}
		if (start+count < total)
		{
			target.appendChild(document.createTextNode(' | '));
			target.appendChild(pagelink(1+page,'>>'));
		}

	}
}

ii.views.ItemBrowser = function(pane,args)
{
	var div = ii.elm('div');


	pane.query.setQueryOpts({fields:'basic,distance,count,details,postedin'});

	pane.query.addListener({addItem: function(item) {
		var vw = item.createView('ListItem');
	  	div.insertBefore(vw.div, div.firstChild);
		if (args.onItemClick)
		{
			vw.div.onclick = function() { args.onItemClick(item); };
		}
	}});

	// are we active pane
	var isOpen = (pane.id == args.pane);

	if (isOpen)
		var link = '#rel&pane=';
	else
		var link = '#rel&pane='+pane.id; // open on click

	if (pane.inverseOpen)
		isOpen = !isOpen;

	pane.query.setQueryOpts({count: (isOpen ? 10 : 'none') });
	if (!isOpen)
		pane.query.interval *= 5;

	if (args.page)
	{
		pane.query.setQueryOpts({start:(args.page-1)*10});
	}

	var pager = new ii.views.Pager();
	var hdr = ii.elm('div', {className:'hdr'}, ii.elm('a',{href:link}, pane.label, pager.counter));
	if (!pane.label)
		hdr.style.display='none';

	if (isOpen)
		this.div = ii.elm('div', {className: 'item_browser ' + pane.type} ,hdr, pager.divs[0], div, pager.divs[1]);
	else
		// ignore pagers
		this.div = ii.elm('div', {className: 'item_browser ' + pane.type} ,hdr, div);

	if (isOpen)
		pane.query.addListener(ii.app.statusDisplay);

	pane.query.addListener(pager);

	pane.query.addListener({countItems:function(start,length,total) {
			ii.log('done with total: '+total);
			if (total == 0 && pane.nocontent)
				div.appendChild(
					ii.elm('p', {className: 'results' },
						pane.nocontent
					)
				);

			}
		});

	this.query = pane.query;
	this.query.start();

}


// Creates a header for the itembrowser, with a count
ii.views.addHeader = function(div, name, pane, type, count)
{
    var elm = 
		ii.elm('div', {className:'item_browser '+type},
		ii.elm('a',
			{className:'hdr', href:'#rel&pane='+pane},
			name+' ' ,
			ii.elm('span', {className:'cnt'},'(', ''+count, ')')));
	div.appendChild(elm);
    return elm;
}

/**
 * create a feed browser
 *
 * the browser_options are
 *    show_friends_checkbox   default true
 *    show_search             default true
 *    show_tabs               default true
 *    driver_name             name of the driver pane to show (default=feed)
 *    onAvatarClick           a custom onclick event that fires BEFORE the
 *                            avatar onclick event fires
 *    onDone                  a custom onDone handler to fire AFTER all items
 *                            have been loaded
 *    onItemClick             a custom onclick event that fires BEFORE the item
 *                            onclick event fires.
 *    onUserNameClick         a custom onClick event that fires BEFORE the
 *                            username onclick event fires.
 *    pager                   a custom pager to use.
 *
 * @param {Object} query_properties
 * @param {Object} query_url_parameters
 * @param {Object} tabs_and_header if true (default), render the tabs and header


 * 8 pos, 4 states = 16 bits * 10 pos for target = 10 * 65565
 */
ii.views.FeedBrowser = function(query_properties, query_url_parameters, browser_options){

    var browser_options = browser_options || {
        show_friends_checkbox: true,
        show_search: true,
        show_tabs: true,
		show_header: true,
		driver_name: 'feed'
//      onAvatarClick: function(){},
//      onDone: function(){},
//      onUserNameClick: function(){},
//      onItemClick: function(){},
//      pager: function(){},
    };

    if( ! query_properties.interval ){
        query_properties.interval = 10000; // 10 seconds
    }

    if( ! query_url_parameters.count ){
        query_url_parameters.count = 10;
    }

    var feed_query = new ii.Query('feed', query_properties, query_url_parameters);

    var feed_pager = this.createPager(browser_options.pager);

    var feed_items_div = ii.elm('div', {style:{cssFloat:'left', width:'455px'}});

    feed_query.addListener(feed_pager);

    feed_query.addListener({
        addItem: function(item){

            var view;

            // loop through the browser_options and pass any function onto the
            // view for custom display.
            var options;
            for(var k in browser_options){
                if(browser_options[k] instanceof Function){
                    options = options || {};
                    options[k] = browser_options[k];
                }
            }

            if( options !== undefined ){
                view = item.createView('ListItem', options);
            }
            else{
                view = item.createView('ListItem');
            }

			feed_items_div.insertBefore(view.div, feed_items_div.firstChild);
		},
        itemsDone: function(items){
            if( browser_options.onDone ){
                browser_options.onDone(items);
            }
            else {
                ii.app.refreshCenterPaneShadow();
            }
        }
    });


    this.feed_query = feed_query;

    this.feed_div = ii.elm('div');

	if (browser_options.show_header)
	    this.feed_div.appendChild(this.createHeader(query_url_parameters));

    if(browser_options.show_tabs && browser_options.show_tabs === true){
		if (ii.app.state.state.subtab)
			// use selected subtab
            var selected_subtab = ii.app.state.state.subtab;
		else if (ii.app.state.state.pane)
			// default to opened pane
            var selected_subtab = ii.app.state.state.pane;
		else
			// no pane & no subtab => select all
			var selected_subtab = 'all';

		var selected_subtab_label = ii.tabs.feed.subtab_labels[selected_subtab];
		ii.log('adding tabs');

        this.feed_div.appendChild(this.createTabHeader(selected_subtab_label, 'All', 'Comments', 'People', 'Photos', 'Trips', 'Spots', 'Groups'));
    }

	feed_query.setQueryOpts({fields:'basic,locname,count',subtab:selected_subtab});

    feed_query.start();

    if(browser_options.show_search && browser_options.show_search === true){
        this.feed_div.appendChild(this.createSearchInput());
    }

    if(browser_options.show_friends_checkbox && browser_options.show_friends_checkbox === true){
        this.feed_div.appendChild(ii.elm('div',
            {style:{
                borderBottom: 'solid 1px #b7b7b7',
                position:'relative'
            }},
            feed_pager.divs[0],
            ii.elm('div',
                {style:{
                    textAlign:'right'
                }},
                ii.elm('input', {type:'checkbox'}),
                ii.elm('span', 'Friends Only')
            )
        ));
    }
    else {
        this.feed_div.appendChild(ii.elm('div',
            {style:{
                borderBottom: 'solid 1px #b7b7b7',
                padding: '7px 0px',
                position:'relative'
            }},
            feed_pager.divs[0]
        ));
    }





    this.feed_div.appendChild(ii.elm('div',
        {style:{
            width:'100%',
            overflow:'hidden'
        }},
        feed_items_div,
		ii.loadDriver(browser_options.driver_name || 'Feed')

    ));
    this.feed_div.appendChild(ii.elm('div',
        {style:{
            padding:'15px 0px',
            position:'relative'
        }},
        feed_pager.divs[1]
    ));
}

ii.views.FeedBrowser.prototype.createHeader = function(options){

    var options = (options === undefined) ? {} : options;

    var header = ii.elm('h1', {
            style: {
                border: '0px'
            }
        }
    );

    if(options.item !== undefined && options.item !== ''){

        if( ii.item)
		{
			var txt = ii.typesingle[ii.item.type]
				+ ' Feed: ' + ii.item.name;

			header.appendChild(document.createTextNode(txt));

        }
    }
	else
	{
		header.appendChild(document.createTextNode('Global '));
		header.appendChild(ii.elm('span', {className:'live'}, 'Live!'));
		header.appendChild(document.createTextNode(' Feed'));

	}


    return header;
}

ii.views.FeedBrowser.prototype.createPager = function(pager_callback){

    var pager;
    if (pager_callback instanceof Function){
        pager = new ii.views.Pager(pager_callback);
    }
    else {
        pager = new ii.views.Pager('tpage');
    }

    for(var i = 0, length = pager.divs.length; i < length; i++){
        pager.divs[i].style.position = 'absolute';
        pager.divs[i].style.left     = '0px';
        pager.divs[i].style.bottom   = '0px';
    }

    return pager;
}

ii.views.FeedBrowser.prototype.createTabHeader = function(selectedTab){

    var subtabs = ii.elm('div', {className:'subtabs'});

    // only generate sub tabs if this is not an item
	for(var n=1; n < arguments.length && !ii.app.state.state.item; n++)
	{
		var tabName = arguments[n];
		if (tabName == selectedTab)
			var tab = ii.elm('a', {className:'selected'}, arguments[n]);
		else
			var tab = ii.elm('a', {href:'#rel&subtab='+ii.tabs.feed.subtab_entities[arguments[n]]}, arguments[n]);

		subtabs.appendChild(tab);

	}

    // wrap the subtabs in a div to ensure the subtabs div is cleared.
	return ii.elm('div', {style:{width:'100%', overflow:'hidden'}}, subtabs);
}

ii.views.FeedBrowser.prototype.createSearchInput = function(){

    var default_search_value = 'Type search'

    var search_form = ii.elm('form',
        ii.elm('input',{
            id:'feed_search',
            name:'search',
            onblur: function(){
                if(this.value == ''){
                    this.value = default_search_value;
                    this.style.color = '#666666';
                }
                this.hasFocus = false;
            },
            onfocus: function(){
                if(this.value == default_search_value){
                    this.value = '';
                }
                this.style.color = 'black';
                this.hasFocus = true;
            },
            onkeyup: function(){
                if(ii.app.applyFilterTimer){
                    window.clearTimeout(ii.app.applyFilterTimer);
                }

                ii.app.applyFilterTimer = window.setTimeout(function(){
                   window.location = '#rel&query=' + document.getElementById('feed_search').value;
                }, 500);
            },
            style:{
                color:'#666666',
                margin:'20px 0px 10px',
                width:'60%'
            },
            value:default_search_value
        })
    );

    return search_form;

}

ii.views.FeedBrowser.prototype.setPage = function(page){
    this.feed_query.setQueryOpts({start:(page-1)*this.feed_query.queryOpts.count})
}

/* generate link-element and hidden div for status display
 * used for LargeListItem views
 */
ii.views.StatusElms = function()
{
	// status shows result of action
	this.statusMsg = ii.elm('div', ' ',{style:{margin:'4px 16px'}} );
	this.statusDiv = ii.elm('div',
			{style:{display:'none'}, className: 'live' },
			this.statusMsg, ii.elm('hr'));
}

ii.views.StatusElms.prototype.setStatus = function(status, duration)
{
	ii.setText(this.statusMsg, status);
	this.statusDiv.style.display = 'block';
	var that = this;
	window.setTimeout(function()
		{
			 ii.setText(that.statusMsg, '');
			 that.statusDiv.style.display = 'none';

		},
		duration || ii.set_status_duration
	);
}
ii.views.StatusElms.prototype.clearStatus = function()
{
	ii.setText(this.statusMsg, '');
	this.statusDiv.style.display = 'none';
}

// returns an element linking to other networks
ii.views.networkDisplay = function(networks)
{
	if (!networks.length)
		return ii.elm('span', {className:'networks'}, 'None');

	var elm = ii.elm('span', {className:'networks'});
	for(var n = 0; n < networks.length; n++)
	{
		var url = ii.views.user.networks[networks[n].community].url;
		url = url.replace('$nick', networks[n].nickname);
		elm.appendChild(ii.elm('a',
					{ href: url, target: '_blank' },
					networks[n].community));

		if (n < networks.length -1)
			elm.appendChild(document.createTextNode(', '));
	}

	return elm;
}


// returns an element for editing links to other networks
ii.views.networkEdit = function(networks)
{
	// create first network-selector div
	var sel = ii.elm('select');
	sel.appendChild(ii.elm('option', {value:''}, 'Select a network'));

	// get options from global-var (defined in iiItemUser)
	for(var n in ii.views.user.networks)
	{
		sel.appendChild(ii.elm('option', {value:n}, n));
	}

	var ndiv = ii.elm('div',
			sel,
			ii.elm('input'),
			ii.elm('img',
				{
					src: '/media/button_clear.png' ,
					className: 'close',
					style: { display: 'none' }
				}
			),
			ii.elm('form') /* network-specific settings */

	);

	var elm = ii.elm('div', {className:'edit_networks'});

	function appendElm(community, nickname, settings)
	{
		var div = ndiv.cloneNode(true);
		// create new box
		var select = div.firstChild;
		var input = select.nextSibling;
		var img = input.nextSibling;
		var set= img.nextSibling;

		if (community)
		{
			select.value = community;
			if (ii.views.user.networks[community].fillSettingsDiv)
				ii.views.user.networks[community].fillSettingsDiv(set,settings);

		}

		if (nickname)
			input.value = nickname;

		img.onmouseover = ii.onmouseoverbtn; // not cloned
		img.onmouseout = ii.onmouseoutbtn; // not cloned
		img.onclick = function() {
			this.parentNode.parentNode.removeChild(this.parentNode);
		}



		var selclick = function() {
			ii.log('testing');
			if (this.value)
			{
				// set default text
				if (ii.getTextBoxValue(this.nextSibling) == '')
				{
					var helptext = ii.views.user.networks[this.value].helpText;
					if (!helptext)
						helptext = 'Enter your ' + this.value + ' username';
					ii.setDefaultText(this.nextSibling, helptext);
				}
			set.innerHTML = '';
			if (ii.views.user.networks[this.value].fillSettingsDiv)
				ii.views.user.networks[this.value].fillSettingsDiv(set,settings);
			}

			if (this.parentNode.nextSibling)
				return; // not the last one? ignore
			if (!this.value)
			{
				if (ii.getTextBoxValue(this.nextSibling.value) == '')
					ii.setDefaultText(this.nextSibling, '');
				return; // no community selected
			}

			// unhide clear button
			this.nextSibling.nextSibling.style.display = '';

			appendElm();
		};

		if (ii.browser.safari)
			select.onchange = selclick;
		else
			select.onclick = selclick;

		elm.appendChild(div);
		return div;
	}

	for(var n = 0; n < networks.length; n++)
	{
		var newelm = appendElm(networks[n].community, networks[n].nickname,
				networks[n].settings);

		// unhide clear btn
		newelm.firstChild.nextSibling.nextSibling.style.display='';
	}
	ii.log('testing appenndelm');

	appendElm();

	return elm;
}


// wraps the networks from a network_edit box into string for server
ii.views.networksGet = function(elm)
{
	var result = [];
	var selects = elm.getElementsByTagName('select');
	for (var n=0; n < selects.length; n++)
	{
		var community = selects[n].value;
		var nick = ii.getTextBoxValue(selects[n].nextSibling);
		var set = selects[n].nextSibling.nextSibling.nextSibling;

		if (!community || !nick)
			continue;

		var id = { nickname: nick, community: community };

		if (ii.views.user.networks[community].getSettings)
		{
			id.settings = ii.views.user.networks[community].getSettings(set);
		}
		result.push(id);
	}
	return ii.obj2json(result);
}

ii.views.fillPostInDropDown = function(elm,options)
{
	options = options || {};
	options.groupsOnly = options.groupsOnly || false;

	var myset = ii.get('q-mysets',
		function(resp)
		{

			elm.innerHTML='';
			elm.appendChild(
					ii.elm('option',
						{
							className: 'private',
							value: 0
						}, 'Private'
					)
				);
			for(var n=0; n < resp.items.length; n++)
			{
				var type = resp.items[n].type;
				var id = resp.items[n].id;
				var name = resp.items[n].name;
				if (type=='group' && id==1)
					type = 'world';
				if (type=='group' && name=='Friends')
					type='friends';
				var opt = ii.elm('option',
					{
						className: type,
						value:id
					},
					name);
				if (options.groupsOnly && (type=='album' || type=='spot'))
					continue;


				elm.appendChild(opt);
				if (type=='world' && !options.value)
					opt.selected = true;
				else if (options.value == id)
					opt.selected = true;
			}
		}, {}
	);

}

// returns an element with a counter, used for unread msgs/comments
ii.views.unreadIndicator = function(count)
{
	if (count == 0)
		return ii.elm('span','');
	else if (count < 10)
		return ii.elm('span', {className:'unread sd'}, ''+count);
	else
	{
		ii.log('count=' + count);
		return ii.elm('span', {className:'unread dd'}, ''+count);
	}
}


/* generate link-element and hidden div for commenting
 * used for LargeListItem views
 */
ii.views.CommentElms = function(entitytype, entityid, statusElms)
{
	var commentArea = ii.elm('textarea', {cols:30, rows:3});

	var commentDiv = ii.elm('form',
		{style: {display:'none'}},
		commentArea,
		ii.elm('input', {type:'submit', value:'post'}),
		ii.elm('hr'));

	commentDiv.onmousedown = ii.stopPropagation;
	commentDiv.onmousemove = ii.stopPropagation;

	this.commentDiv = commentDiv;

	this.commentLink = ii.elm('a', {href: 'javascript://comment()'},
		(entitytype=='user'?'[Send Message]' : '[Post Comment]'));
	this.commentLink.onclick = function()
	{
		statusElms.clearStatus();
		if (!ii.login)
		{
			if (entitytype == 'user')
				alert('You must be logged in to send a Message');
			else
				alert('You must be logged in to post a Comment');

			return;
		}

		if (commentDiv.style.display=='block')
			commentDiv.style.display= 'none';
		else
		{
			ii.log('displaying commentdiv');
			commentDiv.style.display= 'block';
			commentArea.focus();
		}
		ii.app.refreshCenterPaneShadow();
	}

	commentDiv.onsubmit = function() {
		ii.log('sending msg');
		ii.get('p-new-comment',
			function(resp) {
				if (entitytype=='user')
					statusElms.setStatus('Message sent');
				else
					statusElms.setStatus('Comment posted');
				ii.log('msg sent: ' + resp.result);
			},
			{entitytype: entitytype, entityid: entityid, content: commentArea.value }
		);
		statusElms.setStatus('Sending...');
		commentArea.value = '';
		this.style.display = 'none';
		return false;
	}


}

// UNUSED
ii.views.SafElms = function(entitytype, entityid, statusElms)
{
	var safArea = ii.elm('textarea', {cols:60, rows:6});
	this.safLink = ii.elm('a', {href: 'javascript://sendAFriend()'}, '[send Friend]');
}


ii.views.VisitElms = function(item, statusElms)
{
	this.visitLink = ii.elm('a', {href: 'javascript://visit()'}, '[Visit Spot]');

	this.visitLink.onclick = function()
	{
		if (!ii.login)
		{
			alert('You must be logged in to visit a Spot');
			return;
		}

		statusElms.setStatus('Visiting ... ');
		ii.get('p-upd-profile', function(resp)
			{
				statusElms.setStatus('You are now visiting ' + item.name);

			},
			{
				spotid: item.id
			}
		)


	}
}


// Creates an object with two anchor elements
// this.joinLink and this.leaveLink
// These are action-links that will join or leave a group
// the statusElms param must be a ii.views.StatusElms object
ii.views.JoinElms = function(item, entitytype, entityid, statusElms)
{
 	var typename = ii.typesingle[entitytype];

	this.joinLink = ii.elm('a', {href: 'javascript://join()'},
			'[Join ' + typename + ']');
	this.leaveLink = ii.elm('a', {href: 'javascript://leave()'},
			'[Leave ' + typename + ']');
	var joinLink = this.joinLink;
	var leaveLink = this.leaveLink;

	function setShowHide()
	{
		joinLink.style.display = (
			(!ii.login || (item.canjoin==0) || item.ismember == 'owner' || item.ismember == 'member')
			? 'none' : '');

		leaveLink.style.display = (
			(!ii.login || item.ismember != 'member')
			? 'none' : '');
	}
	setShowHide();

	function doJoinLeave(url, ismember, text)
	{
		statusElms.setStatus('Updating ... ');
		ii.get(url,
			function(resp)
			{
				item.ismember = ismember;
				setShowHide();
				statusElms.setStatus(typename + ' ' + text);
			},
			{
				entitytype: 'user',
				entityid: ii.login.id,
				setid: item.id
			}
		);
	}

	joinLink.onclick = function()
	{
		doJoinLeave('p-new-link', 'member', 'joined');
	}

	leaveLink.onclick = function()
	{
		doJoinLeave('p-del-link', 'none', 'left');
	}
}


ii.views.PostInElms = function(item, entitytype, entityid, statusElms)
{
	if (!ii.login
		|| (item.userid != ii.login.id && item.ispublic==0))
	{
		this.postInLink = ii.elm('span');
		this.postInDiv = ii.elm('span');
		return;
	}
	else ii.log('post in allowed');


	this.postInLink = ii.elm('a', {href: 'javascript://postIn()'}, '[Post In]');

	var select = ii.elm('select', {
		className:'postedIn',
		multiple:'yes',
		size:'8',
        style: {
            width: '150px'
        }
	});

	var submitbtn = ii.elm('input', {
				type:'submit',
				value:'Save'
			});

	var that = this;

	function submit()
	{
		ii.startWaitButton(submitbtn);

		var opts_sel = [0];
		var opts = select.getElementsByTagName('option');
		for(var n=0; n < opts.length; n++)
			if (opts[n].selected)
				opts_sel.push(opts[n].value);

		ii.get('p-upd-'+entitytype,
				function(resp)
				{
					ii.endWaitButton(submitbtn);
					ii.log('updating sets: ' + resp.result);
					that.postInDiv.style.display = 'none';
					if (resp.partialSuccess)
					{
						statusElms.setStatus('Some changes were not made '
							+ 'because that would change the item\'s '
							+ 'security settings' , 10);
					}


					ii.app.currentPane.itemQuery.doUpdate();

				},
				{
					id:item.id,
					sets:opts_sel.join(',')
				}
		);

		return false;
	}


	this.postInDiv = ii.elm('form',
			{
				className: 'postIn',
				style: {
					display:'none'
				},
				onsubmit:submit,
				onmousedown: ii.stopPropagation,
				onmousemove: ii.stopPropagation
			},
			ii.elm('p',
				'Post this ',
				ii.typesingle[entitytype],
				' in your Collections'
			),
			ii.elm('p',
				{className: 'note'},
				ii.typesingle[entitytype],
				' inherits the Collection\'s Privacy'
			),
			ii.elm('p',
				{className: 'header'},
				'My Collections'
			),
            ii.elm('div', {
                    style: {
                        marginBottom: '10px',
                        position: 'relative',
                        width: '100%'
                    }
                },
			    select,
                submitbtn
            ),
			ii.elm('p',
				{className: 'footer'},
				'Control Click (PC) or Apple Click (Mac) to select ',
				'multiple Collections. Read our ',
				ii.elm('a', {href: '#rel&tab=HelpFAQ&q=postin_what'}, 'FAQ'),
				' for help on the Post In feature.'
			)

	);

	var loadMySets = function()
	{
		select.innerHTML = '';

		// fill left select box with postin
		var strPostedIn = '';
		var isprivate = (item.postedin.length==0)
		var opt =ii.elm('option',
			{
					className: 'private',
					value: 0
			}, 'Private'
		);

		if (isprivate)
			opt.selected = 'selected';
		select.appendChild(opt);

		for(var n=0; n< item.postedin.length; n++)
		{
			var type = item.postedin[n].type;
			var id = item.postedin[n].id;
			var name = item.postedin[n].name;
			if (type=='trip')
				continue;// no trips in list
			if (type=='group' && id==1)
				type = 'world';
			if (type=='group' && name=='Friends')
				type='friends';
			var opt = ii.elm('option',
				{
					className: type,
					value:id,
					selected: 'selected'

				},
				name);

			select.appendChild(opt);
			strPostedIn += '_' + item.postedin[n].id + '_';

		}
		var myset = ii.get('q-mysets',
			function(resp)
			{
				for(var n=0; n < resp.items.length; n++)
				{
					//already in left listbox ?
					if (strPostedIn.indexOf('_'+resp.items[n].id+'_')>=0)
						continue;
					var type = resp.items[n].type;
					var id = resp.items[n].id;
					var name = resp.items[n].name;
					if (type=='group' && id==1)
						type = 'world';
					if (type=='group' && name=='Friends')
						type='friends';
					var opt = ii.elm('option',
						{
							className: type,
							value:id
						},
						name);

					select.appendChild(opt);
				}
			}, {}
		);
	}

	this.postInLink.onclick = function()
	{
		if (that.postInDiv.style.display == 'block')
		{
			that.postInDiv.style.display = 'none';
			return;
		}
		that.postInDiv.style.display = 'block';

		loadMySets();

		ii.app.refreshCenterPaneShadow();
	}

}

ii.views.SendAFriendElms = function(item, entitytype, entityid, statusElms) {

    if (!ii.login || item.ispublic==0)
    {
        this.sendAFriendLink = ii.elm('span');
        this.sendAFriendDiv = ii.elm('span');
        return;
    }

    var sendAFriendElms = this;

    var to_msg = 'Select or type Friends names or type email addresses';

    var to_textarea = ii.elm('textarea', {
            onfocus: function(){
                if(ii.trim(this.value) == to_msg){
                    this.value = '';
                }
            },
            onblur: function(){
                if(ii.trim(this.value) == ''){
                    this.value = to_msg;
                }
            }
        },
        to_msg
    );
    var msg_textarea = ii.elm('textarea');

    var friends = ii.elm('select', {
            onchange: function(){
				var txt = to_textarea.value;

                if(txt.indexOf(this.options[this.selectedIndex].text) > -1){
                    // do nothing, it's already in the list.
                }
                else if(to_msg === txt){
                    to_textarea.value = this.options[this.selectedIndex].text;
                }
                else {
                    to_textarea.value = txt + ', ' + this.options[this.selectedIndex].text;
                }

                // go back to the default after each selection
                this.options[0].selected = true;
            },
            style: {
                border: 'none',
                marginLeft: '10px'
            }
        },
        ii.elm('option', {value:'-1'}, 'My Friends')
    );

    ii.get('q-items-user', function(resp){
            for( var n = 0, len = resp.items.length; n < len; n++){
                var option = ii.elm('option', resp.items[n].name);
                friends.appendChild(option);
            }
        },
        {
            count: 100,
            friendof: ii.login.id,
			order: 'name'
        }
    );

    this.sendAFriendDiv = ii.elm('div', {
            style: {
                borderBottom: '1px solid #b7b7b7',
                display: 'none',
                margin: '12px 16px 8px',
                padding: '0px 0px 12px'
            }
        },
        ii.elm('form', {
                className: 'sendAFriend',
                onsubmit:function(){

                    if( to_textarea.value != to_msg ){

                        ii.get('p-new-message',
                            function(resp) {
                                statusElms.setStatus('Message sent');
                            },
                            {entitytype: 'user', entityid: to_textarea.value, content: msg_textarea.value }
                        );
                        statusElms.setStatus('Sending to Friend...');

                        // hide
                        this.parentNode.style.display = 'none';

                        // and reset;
                        to_textarea.value = to_msg;
                        msg_textarea.value = msg_textarea.defaultValue;
                    }


                    return false;
                },
                onmousedown: ii.stopPropagation,
                onmousemove: ii.stopPropagation
            },
            ii.elm('div', {className:'safTxtHeader'}, 'To:', friends),
            to_textarea,
            ii.elm('div', {className:'safTxtHeader'}, 'Message:'),
            msg_textarea,
            ii.elm('div', {
                    style: {
                        overflow: 'hidden',
                        width: '100%'
                    }
                },
                ii.elm('input', {
                        style: {
                            display: 'block',
                            cssFloat: 'right',
                            margin: '0px'
                        },
                        type: 'submit',
                        value: 'Send Message'
                    }
                )
            )
        )
    );


    this.sendAFriendLink = ii.elm('a', {
            href: 'javascript://sendAFriend()',
            onclick: function(){
                if(sendAFriendElms.sendAFriendDiv.style.display == 'block'){
                    sendAFriendElms.sendAFriendDiv.style.display = 'none';
                }
                else {
                    sendAFriendElms.sendAFriendDiv.style.display = 'block';

                    // populate the text area, here because there is a delay
                    // in populating the ii.login.item after page refresh or
                    // direct access.
                    var username = ii.login.username || '';
                    var fullname = ii.login.item.fullname || '';
					if (fullname)
						fullname = ' (' + fullname + ')';

                    var msg = 'Hi There!\n' +
                              'Checkout this ' + ii.typesingle[item.type] +
							   ' on bliin: ' +
                              'http://' + window.location.host + '/#item=' +
                              item.type + '.' + item.id +
							  '\n\nRegards,';

                    msg_textarea.value = msg;
                }

                ii.refreshCenterPaneShadow();
            }
        },
        '[Send to Friend]'
    );
}

ii.views.postedInLinks = function(postedIn)
{
	var res = ii.elm('span', {className: 'postedIn'});
	for(var n=0; n < postedIn.length; n++)
	{
		var pi = postedIn[n];
		if (n >0)
			res.appendChild(document.createTextNode(', '));

		if (pi.type == 'album')
		{
			var link = '#rel&item=a.'+pi.id;
			var name = pi.parentname + ' (' + pi.name + ')';
			var type='album';
		}
		else if (pi.type == 'group' && pi.id==1)
		{
			var link = '#rel&item=';
			var name = pi.name;
			var type = 'world';
		}
		else if (pi.type == 'group' && pi.name == 'Friends')
		{
			var link = '#rel&item=u.' + pi.parentid + '&pane=friends';
			var name = ii.appendS(pi.parentname) + ' Friends';
			var type = 'friends';
		}
		else
		{
			var link = '#rel&item='+ii.typeletter[pi.type]+'.'+pi.id;
			var name = pi.name;
			var type = pi.type;
		}

		res.appendChild(ii.elm('a', {className: type, href:link}, name));

	}
	if (postedIn.length == 0)
	{
		// private
		res.appendChild(ii.elm('a', {className: 'private'}, 'Private'));
	}
	return res;
}




ii.items.Item = function() {};

ii.items.Item.prototype.init = function(itm)
{
		// attach properies of itm to this
	for(var p in itm)
	{
		this[p] = itm[p];
	}

	// maintain a list of view for this item
	this.itemviews = [];

}

// called when new data comes in
ii.items.Item.prototype.update = function(itm)
{
	ii.log('item.update ' + this.id);

	// default when new data comes in is to
	// update fields & update views
	for(var p in itm)
		this[p] = itm[p];

	// update each view
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n].update)
			this.itemviews[n].update();
}

ii.items.Item.prototype.remove = function()
{
	// remove it from all views
	while(this.itemviews.length > 0)
	{
		this.removeView(this.itemviews[0])
	}
}

ii.items.Item.prototype.center = function(centered)
{
	if (this.centered && centered) return;
	if (!this.centered && !centered) return;
	this.centered = (this.centered ? false : true);
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n].center)
			this.itemviews[n].center();
}

ii.items.Item.prototype.onmouseover = function()
{
	// show popup, highlight listitem
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n].onmouseover)
			this.itemviews[n].onmouseover();
}

ii.items.Item.prototype.onmouseout = function()
{
	// hide popup, unhighlight listitem
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n].onmouseout)
			this.itemviews[n].onmouseout();
}

ii.items.Item.prototype.zoomto = function()
{
	ii.app.map.zoomTo(this.lat, this.lon, 0, 0);
}
ii.items.Item.prototype.hasView = function(view)
{
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n] == view)
		{
			return true;
		}
    return false;

}

ii.items.Item.prototype.removeView = function(view)
{
	var index = -1;
	// find index
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n] == view)
		{
			index = n;
			break;
		}

	if (index==-1)
	{

        ii.dir(this);
        ii.log('view');
        ii.dir(view);
		ii.error('Removing non existent view');
		return;
	}

	// remove div from parent
	if (view.div)
	{
		var parent = view.div.parentNode;
		if (parent)
		{
			parent.removeChild(view.div);
		}
	}

	// container needs a custom remove func?
	if (view.remove)
		view.remove();

	this.itemviews.splice(index,1);

}


ii.items.Item.prototype.createView = function(viewtype, args)
{

	var itemtype = ii.typename[this.type];

	if (!ii.views[itemtype])
		ii.error('itemtype ' + itemtype + ' has no views');

    var ctor = ii.views[itemtype][viewtype];

    // see if we have a generic contructor
    if (!ctor)
    {
        ii.log('using generic item' );
        var ctor = ii.views.generic[viewtype];
        ii.log('used generic item' );
    }

    if (!ctor)
    {
        ii.log('using generic view');
        var ctor = ii.views.generic.GenericView;
        var view = new ctor(this, viewtype);
    }
    else
    {
        if (args)
            var view = new ctor(this, args);
        else
            var view = new ctor(this);
    }

    //if (!ctor)
	//	ii.error(' Item ' + itemtype + ', view ' + viewtype + ' doesn t exist');


	this.itemviews.push(view);

	return view;
}

ii.set_interval_user_feed = 3000;
ii.set_interval_user_albums = 5000;
ii.set_interval_user_friends = 5000;
ii.set_interval_user_groups = 10000;
ii.set_interval_user_photos = 15000;
ii.set_interval_user_spots = 15000;
ii.set_interval_user_trips = 15000;


/* local settings */
ii.set_user_animate_step = 200; //  in ms
ii.set_user_blink_on = 1400; //  in ms
ii.set_user_blink_off = 200; //  in ms


ii.assert(ii.items);
ii.assert(ii.views);

ii.views.user = {};

/* defines user & its views */


/* networks a user can be in */
ii.views.user.networks = {
'MySpace': 		{ url: 'http://www.myspace.com/$nick' },
'LinkedIn':		{ url: 'http://www.linkedin.com/in/$nick' },
'Flickr':		{ url: 'http://www.flickr.com/photos/$nick/' },
'Hyves':		{ url: 'http://$nick.hyves.nl' },
'Twitter':		{ url: 'http://www.twitter.com/$nick' },
'Delicious':	{ url: 'http://del.icio.us/$nick' },
'Last.fm':		{ url: 'http://www.last.fm/user/$nick' },
'Qik':			{ url: 'http://qik.com/$nick' },
'YouTube':		{ url: 'http://www.youtube.com/$nick' }
};

/*
ii.views.user.networks['Qik'].fillSettingsDiv = function(div, settings)
{
	eval('settings = '+settings);
	settings = settings || {};
	div.appendChild(
			ii.elm('div', {style: {padding:'0px 0px 10px 0px',
								borderBottom:'1px solid #cccccc'}},
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'getQiks',
						checked:settings.getQiks}),
					ii.elm('label', 'Post your Qiks on bliin ')
						
				)));
}
ii.views.user.networks['Qik'].getSettings = function(frm)
{

	var set = {};
	var chks = frm.getElementsByTagName('input');
	for(var n in chks)
	{
		if (chks[n].type == 'checkbox')
			set[chks[n].name] = chks[n].checked ? true : false;
		else
			set[chks[n].name] = chks[n].value;
	}
	return set;

}
*/
ii.views.user.networks['YouTube'].fillSettingsDiv = function(div, settings)
{
	eval('settings = '+settings);
	settings = settings || {};
	div.appendChild(
			ii.elm('div', {style: {padding:'0px 0px 10px 0px',
								borderBottom:'1px solid #cccccc'}},
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'getVideos',
						checked:settings.getVideos}),
					ii.elm('label', 'Post your YouTube videos on bliin ')
						
				)));
}
ii.views.user.networks['YouTube'].getSettings = function(frm)
{

	var set = {};
	var chks = frm.getElementsByTagName('input');
	for(var n in chks)
	{
		if (chks[n].type == 'checkbox')
			set[chks[n].name] = chks[n].checked ? true : false;
		else
			set[chks[n].name] = chks[n].value;
	}
	return set;

}
/*
ii.views.user.networks['Twitter'].fillSettingsDiv = function(div, settings)
{
	eval('settings = '+settings);
	settings = settings || {};
	settings.password = settings.password || '';
	div.appendChild(
			ii.elm('div', {style: {padding:'10px 0px',
								borderBottom:'1px solid #cccccc'}},
				ii.elm('label', 'Your Twitter Password:'),
				ii.elm('input', {type:'password',
					name:'password',
					value:''+settings.password,
					style:{position:'relative',left:'2px'}})
			)
	);
	div.appendChild(ii.elm('img', {style:{display:'block',padding:'10px 0px'},
				src: '/media/bliin2twitter.png'}));

	div.appendChild(
			ii.elm('div', {style: {padding:'0px 0px 10px 0px',
								borderBottom:'1px solid #cccccc'}},
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'sendLive',
						checked:settings.sendLive}),
					ii.elm('label', 'Tweet your bliin ',
						ii.elm('span', {className:'live'}, 'Live!'))
				),
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'sendStatus',
						checked:settings.sendStatus}),
					ii.elm('label', 'Tweet your bliin Status Message')
				),
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'sendPhoto',
						checked:settings.sendPhoto}),
					ii.elm('label', 'Tweet your bliin Photo Posts')
				),
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'sendTrip',
						checked:settings.sendTrip}),
					ii.elm('label', 'Tweet your bliin Trip Recordings')
				)
			)
	);
	div.appendChild(ii.elm('img', {style:{display:'block',padding:'10px 0px'},
				src: '/media/twitter2bliin.png'}));
	div.appendChild(
			ii.elm('div', {style: {padding:'0px 0px 10px 0px',
								marginBottom: '10px',
								borderBottom:'1px solid #cccccc'}},
				ii.elm('div',
					ii.elm('input', {type:'checkbox', name:'getStatus',
						checked:settings.getStatus}),
					ii.elm('label', 'bliin your Tweets (Status Messages)')
				)
			)
	);

}

ii.views.user.networks['Twitter'].getSettings = function(frm)
{

	var set = {};
	var chks = frm.getElementsByTagName('input');
	for(var n in chks)
	{
		if (chks[n].type == 'checkbox')
			set[chks[n].name] = chks[n].checked ? true : false;
		else
			set[chks[n].name] = chks[n].value;
	}
	return set;

}
*/
/* user constructor, initializes animation time  and creates position */
ii.items.User = function(itm) {

	this.init(itm);

	this.lat = parseFloat(this.lat);
	this.lon = parseFloat(this.lon);

	// if no previous pos is known, use current
	this.displayLat = parseFloat(this.lastlat) || this.lat;
	this.displayLon = parseFloat(this.lastlon) || this.lon;

	this.blink = 0;

	// create a timer for animation and blinking
	if (this.status =='live')
	{
		var that = this;
		this.animationTimer = window.setInterval(function() { that.updatePos(); }, ii.set_user_animate_step + (Math.random()*50)-25 );
	}
	else
		this.animationTimer = 0;

}

ii.items.User.prototype = new ii.items.Item;

ii.items.User.prototype.update = function(itm)
{
	for(var p in itm)
		this[p] = itm[p];

	this.lat = parseFloat(this.lat);
	this.lon = parseFloat(this.lon);

	var correctPos = (this.lat==this.displayLat && this.lon==this.displayLon);

	if ((!correctPos || this.status=='live') && !this.animationTimer)
	{
		var that = this;
		this.animationTimer = window.setInterval(function() { that.updatePos(); }, ii.set_user_animate_step);
	}
	else if ((correctPos && this.status !='live') && this.animationTimer)
	{
		window.clearInterval(this.animationTimer);
		this.animationTimer = 0;
	}


	// update each view
	for(var n=0; n < this.itemviews.length; n++)
		if (this.itemviews[n].update)
			this.itemviews[n].update();

	// set unread-messages icon
	if (ii.login && ii.login.id==itm.id)
		ii.login.setUnread();
}

ii.items.User.prototype.showPopup = function(showAlways)
{
	this.popupAlwaysVisible = showAlways;

	for(var n=0; n < this.itemviews.length; n++)
	{
		if (this.itemviews[n].onmouseout)
			this.itemviews[n].onmouseout();
	}
}

ii.items.User.prototype.jumpToCurrentPosition = function(){
	this.displayLat = this.lat;
	this.displayLon = this.lon;
	this.updatePos();
}


/* creates an icon for this item */
ii.views.user.Icon = function(item, args)
{
	this.item = item;
	this.color = args.color;
	this.map = args.map;
	var iconurl = item.getIconUrl(this.map.getZoom(), args.color);

	this.div = ii.elm(
		'div',
		{className:'marker'},
		ii.elm('img', {src: iconurl.url})
	);

	if (this.item.status == 'live')
		this.div.style.zIndex = 200;
	else
		this.div.style.zIndex = 100;

	this.div.onmouseover = function(){ item.onmouseover(); };
	this.div.onmouseout = function(){ item.onmouseout(); };
	this.div.onclick = function() {
		if (window.ii_popup_z)
			item.popup_z = window.ii_popup_z++
		item.popupAlwaysVisible = true;
		item.onmouseover();
	}


	this.addToMap('userIcons', -iconurl.size/2, -iconurl.size/2);

	this.map.addZoomListener(this, this.update);

	//HACK: we don't want a double icon for login
	if (ii.login && item != ii.login.item && item.id == ii.login.id
		&& ii.login.id != 34750)
		this.div.style.display = 'none';
}

ii.views.user.Icon.prototype = new ii.views.Mappable;

ii.views.user.Icon.prototype.blink = function(blink)
{
	this.div.style.visibility = (blink ? '' : 'hidden');
}

ii.views.user.Icon.prototype.remove = function()
{
	this.map.removeZoomListener(this, this.update);
	this.removeFromMap();
}


ii.views.user.Icon.prototype.update = function()
{
	var newicon = this.item.getIconUrl(this.map.getZoom(), this.color);

	if (this.div.firstChild.src != newicon.url)
	{
		if (this.item.status == 'live')
			this.div.style.zIndex = 200;
		else
			this.div.style.zIndex = 100;

		this.div.firstChild.src = newicon.url;
		this.marker.offset.x =
			this.marker.offset.y = -newicon.size/2;
		this.move();
	}
}


/* called from animation timer. Implements smooth movement and blinking */
ii.items.User.prototype.updatePos = function()
{
	if (this.status == 'live')
	{
		// blinking
		if (this.blink == (ii.set_user_blink_on/ ii.set_user_animate_step))
		{
			// hide all icons
			for(var n=0; n < this.itemviews.length; n++)
				if (this.itemviews[n].blink)
					this.itemviews[n].blink(0);

		}
		else if (this.blink >=
			((ii.set_user_blink_off+ii.set_user_blink_on)/ ii.set_user_animate_step))
		{
			// show all icons
			for(var n=0; n < this.itemviews.length; n++)
				if (this.itemviews[n].blink)
					this.itemviews[n].blink(1);
			this.blink=0;
		}
		this.blink++;
	}

	// smoothed moving

	if ((Math.abs(this.displayLat - this.lat) < 0.000001)
			&& Math.abs(this.displayLon - this.lon) < 0.000001)
	{
		// if we're not live, clear the timer
		if (this.status!='live')
		{
			window.clearInterval(this.animationTimer);
			this.animationTimer = 0;
		}

		return;
	}
	if (this.status == 'live')
	{
		this.displayLat += 0.01 * (this.lat - this.displayLat);
		this.displayLon += 0.01 * (this.lon - this.displayLon);
	}
	else
	{
		this.displayLat += 0.1 * (this.lat - this.displayLat);
		this.displayLon += 0.1 * (this.lon - this.displayLon);
	}


	// move in all views with movetofunc
	for(var n=0; n < this.itemviews.length; n++)
	{
		if (this.itemviews[n].move)
			this.itemviews[n].move(this.displayLat, this.displayLon);
	}

}



/* sets the marker-icon url, based on heading, zoomLevel and status */

ii.items.User.prototype.getIconUrl = function(zoom, color) {
	var url = 'icon_user/';
	if (color == 'green')
		url += 'live/';
	else if (color == 'blue')
		url += 'trip/'
	else if (this.status != 'live')
		url += 'idle/';
	else
		url += 'live/';

	var w = (zoom<=.3 ? 16 : (zoom <= .6 ? 24 : 32));

	url += w + '/';

	if (this.status != 'live')
	{
		var icon = 0;
	}
	else
	{
		//get heading based on previous screen position
		var dx = Math.abs(this.lon-this.displayLon);
		var dy = -Math.abs(this.lat-this.displayLat);
		if (dy==0)
		{
			var c = (this.lon>this.displayLon)? 90:270; //going straight east or west
		}
		else
		{
			var c = Math.atan(dx/-dy) * (360/(2*Math.PI)); //in degrees
		}

		//transform to 0-360 degrees, with N=0, E=90, S=180, W=270
		if (this.lon>this.displayLon && this.lat<this.displayLat) c = 180 - c;
		if (this.lon<this.displayLon && this.lat<this.displayLat) c = 180 + c;
		if (this.lon<this.displayLon && this.lat>this.displayLat) c = 360 - c;

		//there are 12 icons = steps of 30 degree on circle
		var icon = Math.round(c/30) * 30;
		if (icon==360) icon=0;
	}
	url += icon + '.png';

	return {url:'/media/'+url, size:w};
}

/**
 * @param {Object} options options for the code
 */
ii.items.User.prototype.getLiveStatusElement = function()
{
    var status = '';
    var classname = 'lastseen';
    var sb = [];

    switch(this.status){
        case 'lastloc':
            status = document.createTextNode('Last seen ' + ii.formatDate(this.locmodified,'shortrelative'));
            break;
        case 'idle':
			var spotname = ii.spotLink(this.spotid, this.spotname);
			spotname.className = 'spot micro';

            status = ii.elm('span', 'Last seen at ', spotname, ' ',
				ii.formatDate(this.locmodified,'shortrelative'));
            break;
        case 'live':
            classname = '';

    		if (parseInt(this.speed) ){
                status = ii.elm('span', ii.elm('span', {className:'live'}, 'Live!'), ' travelling ' + Math.round(parseInt(this.speed)*3.6) + ' km/h');
            }
    		else{
                status = ii.elm('span', {className:'live'}, 'Live!');
            }
            break;
        default:
            status = document.createTextNode('Unknown');
            break;
    }

    return ii.elm('span', {className: classname}, status);
}

ii.views.user.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.user.TabFeed.prototype = new ii.views.TabFeed();


ii.views.user.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.user.TabDetails.prototype = new ii.views.TabDetails;

ii.views.user.TabDetails.prototype.onload = function() 
{
    var that = this;

	this.initFields();

    // fill fields of info form
	if (ii.login)
	{
		var form = this.fields.info_form;
		form.action = '/srv/p-upd-profile.php?key='+ii.login.key;
		form.fullname.value = this.item.fullname;
		form.homecountry.value = this.item.homecountry;
		form.homecity.value = this.item.homecity;
		form.sex.value = this.item.sex;
		form.birthdayofmonth.value = ii.formatDate(this.item.birthday, 'day');
		form.birthmonth.value = ii.formatDate(this.item.birthday, 'month');
		form.birthyear.value = ii.formatDate(this.item.birthday, 'year');


		// fill fields of networks form
		form = this.fields.networks_form;
		this.fields.networks_edit.innerHTML = '';
		this.fields.networks_edit.appendChild(ii.views.networkEdit(this.item.networks));
	}


    if (ii.login && ii.login.id == this.item.id)
    {
        this.fields.subtabs.style.display = '';
        this.initForm('networks', function() { return that.submitNetworks(); });
        this.initForm('info', function() { return that.submitInfo(); });
    }
    else
    {
        this.fields.subtabs.style.display = 'none';
        this.initForm('networks', function() { return false; } );
        this.initForm('info', function() { return false;});
    }

	this.update();

}

ii.views.user.TabDetails.prototype.fillField_networks = function(elm)
{
    elm.innerHTML = '';
    elm.appendChild(ii.views.networkDisplay(this.item.networks));
}

ii.views.user.TabDetails.prototype.fillField_website = function(elm)
{
    elm.innerHTML='';
    var website = this.item.website;
    if (!/http/.test(website))
        website = 'http://' + website;
    elm.appendChild(
            ii.elm('a',
                {
                    target: '_blank',
                    href: website
                },
                this.item.website
            )
    );
}
ii.views.user.TabDetails.prototype.fillField_birthday = function(elm)
{
    if (this.item.birthday == 0)
        ii.setText(elm, 'Unknown');
    else
        ii.setText(elm, ii.formatDate(this.item.birthday, 'humandate'));
}

ii.views.user.TabDetails.prototype.fillField_sex = function(elm)
{
    if (this.item.sex=='m')
        ii.setText(elm, 'Male');
    else if (this.item.sex=='f')
        ii.setText(elm, 'Female');
    else
        ii.setText(elm, 'Unknown');
}
ii.views.user.TabDetails.prototype.fillField_totallivetime = function(elm)
{
    if (this.item.livetime)
        ii.setText(elm, ii.formatTimespan(this.item.livetime));
    else
        ii.setText(elm, 'None');
}

ii.views.user.TabDetails.prototype.fillField_totaltravelled = function(elm)
{
    if (this.item.livemeters)
        ii.setText(elm, ii.formatDistance(this.item.livetime));
    else
        ii.setText(elm, 'None');
}

ii.views.user.TabDetails.prototype.submitInfo = function()
{
    var form = this.fields.info_form;

    ii.startWaitButton(form.savebtn);
    // set birthday as one param through hidden input
    form.birthday.value = form.birthyear.value.concat(
            '-', form.birthmonth.value,
            '-', form.birthdayofmonth.value);


    var that = this;
    var doc = ii.iframeDocument(document.getElementById('ii_iframe'));
    doc.innerHTML = ''; //clear previous result

    // check upload result
    function checkResult()
    {
        var doc = ii.iframeDocument(document.getElementById('ii_iframe'));
        ii.log('checking result...');
        if (doc.innerHTML.match('"result"'))
        {
            that.setEditMode(form, false);
            ii.endWaitButton(form.savebtn);
            ii.login.query.doUpdate();
            ii.login.updateAvatars();
            return;
        }
        window.setTimeout(checkResult, 250);
    }
    checkResult();
    return true;
}

ii.views.user.TabDetails.prototype.submitNetworks = function()
{
    var that = this;
    var form = this.fields.networks_form;

    ii.startWaitButton(form.savebtn);

    var params = {
        id: this.item.id,
        website: form.website.value,
        networks: ii.views.networksGet( this.fields.networks_edit)

    }
    ii.get('p-upd-profile',
        function(resp) {
            that.setEditMode(form, false);
            ii.endWaitButton(form.savebtn);
            ii.login.query.doUpdate();
        },
        params
    );
    return false;
}

ii.views.user.TabDetailsSettings = function(item)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetailsSettings');
}

ii.views.user.TabDetailsSettings.prototype = new ii.views.TabDetails;

ii.views.user.TabDetailsSettings.prototype.onload = function() 
{
	this.setupAccount();
	this.setupPrivacy();
	this.setupPassword();
	this.setupDelete();
//	this.setupMapType(item);

}

ii.views.user.TabDetailsSettings.prototype.setupAccount = function()
{
    var form = this.fields.account_form;
	// Account form, set values
	ii.setText(this.fields.name, this.item.name);

    form.email.value = '' + this.item.email;
    form.phone.value = '' + this.item.phone;

    ii.log('EMAIL: '+this.item.email);

	ii.setText( this.fields.upload_email, this.item.uploademail);

    var result = this.fields.account_result;
    result.style.display='none';

	// set account form behaviour
	form.onsubmit = function() {
		var f = this;
		ii.startWaitButton(f.savebtn);

		var params = {
			email: f.email.value,
			phone: f.phone.value
		};
		ii.get('p-upd-profile',
				function(resp)
				{
					ii.endWaitButton(f.savebtn);
					ii.login.query.doUpdate();
					result.style.display='block';
					window.setTimeout(function() {
                            result.style.display='none';
						},
						3000
					);

				},
				params
		);
		return false;

	}
}

ii.views.user.TabDetailsSettings.prototype.setupPrivacy = function()
{
	// visiblity fill in
	var vis = document.getElementById('ii_details_user_settings_visible');
	ii.views.fillPostInDropDown(vis, {groupsOnly:true, value: this.item.visibility});

	// set privacy form behaviour
	var form1 = document.getElementById('ii_settings_privacy_form');
	form1.onsubmit = function() {
		var f = this;
		ii.startWaitButton(f.savebtn);

		var params = {
			visibility: vis.value
		};
		ii.get('p-upd-profile',
				function(resp)
				{
					ii.endWaitButton(f.savebtn);
					ii.login.query.doUpdate();
					document.getElementById('ii_settings_visibility_result')
						.style.display='block';
					window.setTimeout(function() {
						document.getElementById('ii_settings_visibility_result')
							.style.display='none';
						},
						3000
					);

				},
				params
		);
		return false;

	}
}



ii.views.user.TabDetailsSettings.prototype.setupPassword = function()
{
	// change password form behaviour
	var form = this.fields.password_form;
    var error = this.fields.password_error;
    var result = this.fields.password_result;

	var section = form;
	var btn = this.fields.change_password;
    var cancel = form.cancelbtn;

	cancel.onclick = function() { section.style.display = 'none'; }
	ii.setText(error, '');

	btn.onclick = function() {
		section.style.display = 'block';
	}
	form.onsubmit = function() {
		var f = this;
		if (f.password.value != f.password2.value)
		{
			ii.setText(error, 'Passwords are not identical');
			return false;
		}
		else
			ii.setText(error, '');
		ii.startWaitButton(f.savebtn);

		var params = {
			password: f.password.value
		};
		ii.get('p-upd-profile',
				function(resp)
				{
					ii.endWaitButton(f.savebtn);
					if (resp.result != 'OK')
					{
						ii.setText(error, resp.msg);
					}
					else
					{
						ii.login.query.doUpdate();

						result.style.display='block';
						window.setTimeout(function() {
							result.style.display='none';
							section.style.display = 'none';
							},
							3000
						);
					}

				},
				params
		);
		return false;

	}

}

ii.views.user.TabDetailsSettings.prototype.setupDelete = function()
{
	// delete account form behaviour
	console.dir(this.fields);
	var submit = document.getElementById('ii_settings_delete_submit');
	var section = this.fields.delete_account_;
	var btn = this.fields.delete_account;
	var cancel = document.getElementById('ii_settings_delete_cancel');

	cancel.onclick = function() { section.style.display = 'none'; }

	console.log(cancel);
	btn.onclick = function() {
		section.style.display = 'block';
	}

	submit.onclick = function() {
		ii.startWaitButton(btn);
		ii.get('p-del-user',
				function(resp) {
					if (resp.result == 'ERR')
						alert('error deleting your accounr');
					else
					{
						ii.endWaitButton(btn);
						alert('Your account has been deleted. The page will reload');
						window.location = 'http://bliin.com';
						window.location.reload(true);
					}


				}
		);
	}

}


/* ListItem*/

ii.views.user.ListItem = function (item) {
	this.item = item;
	if (item.name == 'Anonymous')
	{
		this.div = ii.elm('div');
		return;
	}

	this.initDiv('ListItem');

	this.div.onclick = function() {
		ii.app.state.setState({item:'u.'+item.id})
	};

	this.update();
}
ii.views.user.ListItem.prototype = new ii.views.ListItem;


/* LargeListItem */

ii.views.user.LargeListItem = function(item) {

	this.item = item;
	this.initDiv('LargeListItem');

	// setup action links
	var links = item.createView('ActionLinks');
	this.div.appendChild(links.div);

	this.update();

}
ii.views.user.LargeListItem.prototype = new ii.views.View;

ii.views.user.ActionLinks = function(item) {
	this.item = item;
	this.initDiv();

	this.div = ii.elm('div',
		ii.elm('div', {className: 'listitem_links'},
			this.postCommentLink(),
			' ',
			this.addFriendLink()
		),
		this.postCommentDiv(),
		this.postInDiv(),
		this.statusDiv()
	);

	this.update();
}

ii.views.user.ActionLinks.prototype = new ii.views.ActionLinks;

ii.views.user.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

	this.addHeader( {
		type: 'photo',
		label: ii.appendS(item.name)+ ' Photos',
		dataField: 'photos',
		filter: {user: this.item.id},
		expand: true
	});

	this.addHeader( {
		type: 'video',
		label: ii.appendS(item.name)+ ' Videos',
		dataField: 'videos',
		filter: {user: this.item.id}
	});

	this.addHeader( {
		type: 'user',
		label: ii.appendS(item.name)+ ' Friends',
		dataField: 'friends',
		filter: {friendof: this.item.id}
	});

	this.addHeader( {
		type: 'album',
		label: ii.appendS(item.name)+ ' Albums',
		dataField: 'albums',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Albums yet. ')
	});

	this.addHeader( {
		type: 'trip',
		label: ii.appendS(item.name)+ ' Trips',
		dataField: 'trips',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Trips yet. ')
	});
	this.addHeader( {
		type: 'spot',
		label: ii.appendS(item.name)+ ' Spots',
		dataField: 'spots',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Spots yet. ')
	});
	this.addHeader( {
		type: 'group',
		label: ii.appendS(item.name)+ ' Groups',
		dataField: 'groups',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Groups yet. ')
	});
	this.update();

}

ii.views.user.ItemBrowser.prototype = new ii.views.ItemList;


ii.views.user.IconPopup = function(item, args)
{
	this.item = item;
	this.map = args.map;
	if (item.popupAlwaysVisible == undefined)
		item.popupAlwaysVisible = args.alwaysVisible;

	this.initDiv('IconPopup');

	var that = this;
	this.fields.closebtn.onmouseover = ii.onmouseoverbtn;
	this.fields.closebtn.onmouseout  = ii.onmouseoutbtn;
	this.fields.closebtn.onclick =  function() { 
		item.popupAlwaysVisible = false; 
		//that.div.style.visibility='hidden';
		//that.shadowDiv.style.visibility='hidden';
		that.div.style.display = 'none';
		that.shadowDiv.style.display = 'none';
	}


	this.update();

	this.addToMap('userPopups', -58, -124);
	this.addShadowToMap('user_info_shadow.png', 208, 60, -28, -71);

	this.onmouseout();
}

ii.views.user.IconPopup.prototype = new ii.views.Mappable;

ii.views.user.IconPopup.prototype.onmouseout = function()
{
	//this.div.style.visibility =
	//	this.shadowDiv.style.visibility = 
	//		(this.item.popupAlwaysVisible ? '' : 'hidden');
	this.div.style.display =
		this.shadowDiv.style.display = 
			(this.item.popupAlwaysVisible ? '' : 'none');

}

ii.views.user.IconPopup.prototype.onmouseover = function()
{
	this.div.style.visibility =
		this.shadowDiv.style.visibility = '';
	this.div.style.display =
		this.shadowDiv.style.display = '';
}


ii.views.user.Details = function(item, args)
{
    var location_name = ii.geoCode(item.lat, item.lon);

    var author_p = ii.elm('p', {
            className: 'clear_wrapper'
        },
        ii.userLink(item.id, item.name),
        ' ',
        item.getLiveStatusElement(),
        ' @ ',
        location_name
    )

    var status_div = '';
    if(item.message && item.message != ''){

        status_div = ii.elm('div', {
                className: 'content_background clear_wrapper'
            },
            ii.elm('p',
                item.message
            )
        );
    }

    var userid = args.userid;

    var checkbox_visibility = 'hidden';
    if((ii.login && (ii.login.id == userid) || ii.login.id == item.userid)){
        checkbox_visibility = 'visible';
    }

    this.div = ii.elm('div', {
            className: 'group_user_wrapper clear_wrapper'
        },
        ii.elm('input', {
                type: 'checkbox',
                className: 'checkbox',
                style: {
                    visibility: checkbox_visibility
                }
            }
        ),
        ii.elm('img', {
                src: '/srv/d-media.php?width=64&height=48&entitytype=user&entityid=' + item.id
            }
        ),
        ii.elm('div', {
                className: 'content_wrapper'
            },
            author_p,
            status_div
        )
    );
}
/**
 * @author tomas
 */


ii.assert(ii.views.user); // iiItemUser should be included first



ii.views.user.TabMyInbox = function(item, args)
{
    this.item = item;
    this.initDiv('TabMyInbox');
}

ii.views.user.TabMyInbox.prototype = new ii.views.View();

ii.views.user.TabMyInbox.prototype.onload = function() 
{
	var that = this;

	var pagesize = 10;
    this.query = new ii.Query('thread', {interval:10000}, {count:pagesize, type:'message'});
	this.queries = [this.query];

    var query = this.query;

	document.getElementById('ii_btn_myinbox').href = '#rel&tab=MyInbox';
	// add pager to header
	function changePage(pagenr)
	{
		query.setQueryOpts({start:pagesize*(pagenr-1)});
	}
	var pager = new ii.views.Pager(changePage);
	this.fields.pager.appendChild(pager.divs[0]);
	this.query.addListener(pager);


	this.fields.searchform.onsubmit = function() {
		query.setQueryOpts({query:ii.getElmByName(this, 'query').value,start:0});
		return false;
	}

	function onUpdateNeeded(fullUpdate)
	{
		if (fullUpdate)
		{
			query.start();
		}
		else
			query.doUpdate();
		ii.login.query.doUpdate();
	}
	var cont = this.fields.threads;

	this.query.addListener({
		addItem: function(item)
			{
				var vw = item.createView('TabView', {
					startCollapsed: true,
					deleteMethod: 'remove',
					parentQuery: query });
				cont.appendChild(vw.div);

			},
			hasItems: function(hasItems)
			{
				if (ii.getTextBoxValue(ii.getElmByName(that.fields.searchform,'query')) == '')
				{
					var showSearch = (hasItems);
					that.fields.noresults.style.display = 'none';
				}
				else
				{
					var showSearch = true;
					that.fields.noresults.style.display = (!hasItems ? '' : 'none');

				}
				that.fields.nocontent.style.display = (!showSearch ? '' : 'none');
				that.fields.searchform.style.display = (showSearch ? '' : 'none');
				that.fields.loading.style.display = 'none';
			}
	});
	this.query.start();

}

ii.views.user.TabMyInboxComments = function(item, args)
{
    this.item = item;
    this.initDiv('TabMyInboxComments');
}

ii.views.user.TabMyInboxComments.prototype = new ii.views.View();

ii.views.user.TabMyInboxComments.prototype.onload = function() 
{
	var that = this;

	var pagesize = 10;
    this.query = new ii.Query('thread', {interval:10000}, {count:pagesize, type:'comment'});

    var query = this.query;

	document.getElementById('ii_btn_myinbox').href = '#rel&tab=MyInboxComments';

	// add pager to header
	function changePage(pagenr)
	{
		query.setQueryOpts({start:pagesize*(pagenr-1)});
	}
	var pager = new ii.views.Pager(changePage);
	this.fields.pager.appendChild(pager.divs[0]);
	this.query.addListener(pager);


	this.fields.searchform.onsubmit = function() {
		query.setQueryOpts({query:ii.getElmByName(this, 'query').value,start:0});
		return false;
	}

	function onUpdateNeeded(fullUpdate)
	{
		if (fullUpdate)
		{
			query.start();
		}
		else
			query.doUpdate();
		ii.login.query.doUpdate();
	}
	var cont = this.fields.threads;

	this.query.addListener({
		addItem: function(item)
			{
				var vw = item.createView('TabView', {
					startCollapsed: true,
					deleteMethod: 'remove',
					addLink: true,
					title: item.name,
					parentQuery: query});
				cont.appendChild(vw.div);

			},
		hasItems: function(hasItems)
			{
				if (ii.getTextBoxValue(ii.getElmByName(that.fields.searchform,'query')) == '')
				{
					var showSearch = hasItems;
					that.fields.noresults.style.display = 'none';
				}
				else
				{
					var showSearch = true;
					that.fields.noresults.style.display = (!hasItems ? '' : 'none');

				}
				that.fields.nocontent.style.display = (!showSearch ? '' : 'none');
				that.fields.searchform.style.display = (showSearch ? '' : 'none');
				that.fields.loading.style.display = 'none';
			}
	});
	this.query.start();

}



ii.views.user.MyWelcomeBox = function(item)
{
	this.item = item;
	this.initDiv('MyWelcomeBox');
	this.update();
}
ii.views.user.MyWelcomeBox.prototype = new ii.views.View;

ii.views.user.MyItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

	this.addHeader( {
		type: 'user',
		label: 'My Friends',
		dataField: 'friends',
		filter: {friendof: this.item.id},
		expand: true
	});

	this.addHeader( {
		type: 'photo',
		label: 'My Photos',
		dataField: 'photos',
		filter: {user: this.item.id}
	});


	this.addHeader( {
		type: 'video',
		label: 'My Videos',
		dataField: 'videos',
		filter: {user: this.item.id}
	});


	this.addHeader( {
		type: 'album',
		label: 'My Albums',
		dataField: 'albums',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Albums yet. ')
	});

	this.addHeader( {
		type: 'trip',
		label: 'My Trips',
		dataField: 'trips',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Trips yet. ')
	});
	this.addHeader( {
		type: 'spot',
		label: 'My Spots',
		dataField: 'spots',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Spots yet. ')
	});
	this.addHeader( {
		type: 'group',
		label: 'My Groups',
		dataField: 'groups',
		filter: {user: this.item.id},
		noContentMsg: ii.elm('span','This User has no Groups yet. ')
	});
	this.update();

}

ii.views.user.MyItemBrowser.prototype = new ii.views.ItemList;



ii.views.user.MyItemCounter = function(item,args)
{
	this.item = item;
	this.subItemsets = [];


	this.div = ii.elm('div');

	this.update();

	// must do after processing cause caller must store this obj first
	window.setTimeout(function(){args.onDone();},0);
}

ii.views.user.MyItemCounter.prototype.update = function()
{
	this.div.innerHTML='';

	for(var n=0; n < this.item.albums.length; n++)
		ii.views.addHeader(this.div,
				this.item.albums[n].name,
				'album.'+this.item.albums[n].id,
				'album', this.item.albums[n].count);
	ii.views.addHeader(this.div, 'My Friends', 'friends', 'friends', this.item.friends);
	ii.views.addHeader(this.div, 'My Photos & Videos', 'allphotos', 'poi', this.item.pois);
	ii.views.addHeader(this.div, 'My Trips', 'alltrips', 'trip', this.item.trips);
	ii.views.addHeader(this.div, 'My Spots', 'spots', 'spot', this.item.spots);
	ii.views.addHeader(this.div, 'My Groups', 'groups', 'group', this.item.groups);
	ii.views.addHeader(this.div, 'All My Photos', 'allphotos', 'photo', this.item.pois);
	ii.views.addHeader(this.div, 'All My Trips', 'alltrips', 'trip', this.item.trips);

}


ii.views.user.TabAddPhoto = function(item, args)
{
    this.item = item;
    this.initDiv('TabAddPhoto');
}

ii.views.user.TabAddPhoto.prototype = new ii.views.View();

ii.views.user.TabAddPhoto.prototype.onload = function(item, args)
{
	var form = this.fields.form;
	form.key.value = ii.login.key;
	form.tz_offset.value = (new Date()).getTimezoneOffset();
	ii.log('timezone:'+form.tz_offset.value);

	//ii.iframeDocument(uploadPhotoDone).innerHTML = '';
	var uploadPhotoDone = document.getElementById('ii_iframe');
	ii.iframeDocument(uploadPhotoDone).innerHTML = '';

	ii.setText(this.fields.error, '');
	form.name.value = '';
	form.description.value = '';

	var button = form.submitbtn;
    var that = this;
	function checkUploadDone()
	{

        var uploadPhotoDone = document.getElementById('ii_iframe');
		if (ii.iframeDocument(uploadPhotoDone) &&
			ii.iframeDocument(uploadPhotoDone).innerHTML.indexOf('result')>0)
		{
			ii.endWaitButton(button);
			var resp = ii.iframeDocument(uploadPhotoDone).innerHTML;
			var result = /"result":\s*"([^"]+)"/.exec(resp);
			result = result[1];

			if (result == 'OK')
			{
				var newid = /"newid":\s*([0-9]+)/.exec(resp);
				newid = newid[1];
				ii.log('upload successfull: newid='+newid);
				window.location = '#rel&item=p.'+newid;

			}
			else
			{
				var msg = /"msg":\s*"([^"]+)"/.exec(resp);
				msg = msg[1];
				ii.log('error uploading: '+ msg);
				ii.setText(that.fields.error,
						'Error: ' + msg);
			}
		}
		else
		{
            ii.log('AddPhoto check upload done again');
			if (ii.app.state.state.tab == 'AddPhoto')
				window.setTimeout(checkUploadDone, 1000);
			else
				ii.endWaitButton(button);
		}
	}

	// fill Post In options
	var postIn = this.fields.postin;
	ii.views.fillPostInDropDown(postIn);

	form.onsubmit = function()
	{
        ii.setText(that.fields.error, '');
		ii.startWaitButton(button);
		checkUploadDone();
		return true;
	}
}


ii.views.InviteUsers = function(options)
{
	options = options || {};
	options.buttonText = options.buttonText || 'Finish';

	var selLeft = ii.elm('select',
			{
				className:'postedIn',
				multiple:'yes',
				size:'9'
			}
		);
	var selRight = ii.elm('textarea', {rows:'8'});


	// function to move a selected friend to the right
	function toRight() {
		var opts = selLeft.getElementsByTagName('option');
		for(var n=0; n < opts.length; n++)
			if (opts[n].selected)
			{
				opts[n].selected = '';
				if (selRight.value.indexOf(opts[n].textContent||opts[n].innerText)>=0)
					continue;
				var t = ''+ selRight.value;

				if (t)
					t += ', ';
				t += opts[n].textContent || opts[n].innerText;
				selRight.value = t;
			}
	}


	var table = ii.elm('div',
			ii.elm('div', {style:{cssFloat:'left'}},
				ii.elm('h3', 'My Friends'),
				selLeft
			),
			ii.elm('div', {style:{cssFloat:'left'}},
				ii.elm('input', {type:'button',
					style:{width:'70px', marginTop:'50px'},
					value:'Post in >>', onclick:toRight}
				)
			),
			ii.elm('div', {style:{cssFloat:'left'}},
				ii.elm('h3', 'Members'),
				selRight
			),
			ii.elm('div', {style: {clear:'both'}})


		);


	ii.get('q-items-user',
			function(resp) {
				for (var n = 0; n < resp.items.length; n++)
				{
					var opt = ii.elm('option',
						{className: 'people' },
						resp.items[n].name);
					selLeft.appendChild(opt);
				}
			},
			{ order:'name', friendof: ii.login.id, count:100 }
	);

	// remember this, cause parent will create waitbutton
	this.submitbtn = ii.elm('input',
			{type:'submit', 'value':options.buttonText});

	// remember this for value-extraction onsubmit
	this.members = selRight;

	// there can be only one!
	var inv = document.getElementById('ii_invite_section');
	if (inv)
		inv.parentNode.removeChild(inv);

	// remember this for hide/show form parent
	this.div = ii.elm('div',
			{id:'ii_invite_section',className: 'cp_s invite', style:{display:'none'}},
			ii.elm('h2', {className: 'cp_sh'}, 'Invite Members'),
			ii.elm('div', {className: 'cp_sc'},
				ii.elm('p', 'Invite Members from your Friends Group '
					+ 'or by typing usernames'),
				table,
				ii.elm('div', {className: 'buttonbar'},
					this.submitbtn))
	);
}

ii.views.user.TabAddAlbum = function(item, args)
{
    this.item = item;
    this.initDiv('TabAddAlbum');
}

ii.views.user.TabAddAlbum.prototype = new ii.views.View;

ii.views.user.TabAddAlbum.prototype.onload = function() 
{
    ii.log('AddAlbum onload');

	var form = this.fields.form;

	ii.setDefaultText(form.albumname, 'Enter a name');
	ii.setDefaultText(form.description, 'Enter a description');

	form.visible.value = 'all';

	var invite = new ii.views.InviteUsers();
	this.fields.invite.appendChild(invite.div);


	function onSecurityChanged()
	{
		// when visible=members
		// hide submit, and show invite-pane
		var m = (this.value == 'members');
		invite.div.style.display = (m ? '' : 'none');
		form.submitbtn.style.display = (m ? 'none' : '');
	};

    form.visible.onclick = form.visible.onkeyup
        = form.visible.onchange = onSecurityChanged;

	onSecurityChanged();

	this.fields.error.innerHTML = '';
    var that = this;

	form.onsubmit = function()
	{
		var btn = this.submitbtn;

		ii.startWaitButton(btn);
		ii.startWaitButton(invite.submitbtn);

		that.fields.error.innerHTML = '';

		var params = {
				type: 'album',
				name: ii.getTextBoxValue(this.albumname),
				description: ii.getTextBoxValue(this.description),
				invite: 'me',
				post: 'me',
				visible: this.visible.value
			}

		if (this.visible.value == 'members')
			params.members = invite.members.value;

		ii.get('p-new-set',
			function(resp)
			{
				ii.endWaitButton(btn);
				ii.endWaitButton(invite.submitbtn);
				if (resp.result=='OK')
				{
					ii.log('Album created');
					//item.albums.push({id:resp.newid, name:params.name, count:0});
					that.item.update(that.item);
					window.location = '#rel&item=ME.0';
				}
				else
				{
					ii.setText(
						that.fields.error,
						resp.msg
					);
				}
			},
			params
		);
		return false;
	}
}


ii.views.user.TabAddGroup = function(item, args)
{
    this.item = item;
    this.initDiv('TabAddGroup');
}

ii.views.user.TabAddGroup.prototype = new ii.views.View();

ii.views.user.TabAddGroup.prototype.onload = function()
{
    var join_section = this.fields.join_s;
    var detail_section = this.fields.detail_s;
    var invite = new ii.views.InviteUsers();

	this.fields.invite.appendChild(invite.div);

    join_section.style.display = 'none';
    detail_section.style.display = 'none';

	this.fields.error.innerHTML = '';

    var frmName = this.fields.form_name;
	var frmAdd = this.fields.form_add;


	frmAdd.visible.value =
		frmAdd.invite.value =
		frmAdd.post.value = 'all';

	ii.setDefaultText(frmName.groupname, 'Enter a name');
	ii.setDefaultText(frmAdd.description, 'Enter a description');

    var that = this;

	frmName.onsubmit = function() {
		if (ii.getTextBoxValue(this.groupname) == '')
		{
			that.fields.error.innerHTML
				= 'Please enter a name';
			return false;
		}

		that.fields.error.innerHTML = '';

		var query = this.groupname.value;
		ii.get('q-items-group',
				function(resp) {
					if (!resp.items.length)
					{
						join_section.style.display = 'none';
						return;
					}
					join_section.style.display = 'block';
					that.fields.groups.innerHTML ='';
					that.fields.searchterm.textContent = query;

					for(var n=0; n < resp.items.length; n++)
					{
						resp.items[n].type='g';
						var itm = new ii.items.Group(resp.items[n]);
                        itm.onmouseover = function(){};
                        itm.onmouseout  = function(){};
						var view = itm.createView('ListItem');
						view.div.style.backgroundColor = 'transparent';
						that.fields.groups
							 .appendChild(view.div);


					}
				},
				{ query: this.groupname.value, order:'name' }
		);

		detail_section.style.display = 'block';
		return false;
	}

    frmAdd.onsubmit = function() {
		var btn = this.submitbtn;
		ii.startWaitButton(btn);
		ii.startWaitButton(invite.submitbtn);
		var params = {
			type:'group',
			name:frmName.groupname.value,
			description:this.description.value,
			invite:this.invite.value,
			post:this.post.value,
			visible:this.visible.value
		}
		if (invite.div.style.display != 'none')
			params.members = invite.members.value;

		ii.get('p-new-set',
			function(resp)
			{
				ii.endWaitButton(btn);
				ii.endWaitButton(invite.submitbtn);
				if (resp.result=='OK')
				{
					ii.log('Group created');
					window.location = '#rel&item=g.'+resp.newid;
				}
				else
				{
					ii.setText(
						that.fields.error,
						resp.msg
					);
				}
			},
			params
		);
    	return false;
    }


	// if any security = members, invite-box should show
	function onSecurityChange()
	{
		var show = false;
		var sels = frmAdd.getElementsByTagName('select');
		for (var n=0; n < sels.length; n++)
			if (sels[n].value=='members')
				show = true;
		frmAdd.submitbtn.style.display = (show ? 'none': '');
		invite.div.style.display = (show ? '' : 'none');
		ii.log('showing invite: '+show);
	}

	onSecurityChange();

	var sels = frmAdd.getElementsByTagName('select');
	for (var n=0; n < sels.length; n++)
		sels[n].onclick = sels[n].onchange = sels[n].onkeyup = onSecurityChange;

}

ii.views.user.TabAddSpot = function(item, args)
{
    this.item = item;
    this.initDiv('TabAddSpot');
}

ii.views.user.TabAddSpot.prototype = new ii.views.View();

ii.views.user.TabAddSpot.prototype.onload = function()
{
    var join_section = this.fields.join_s;
    var detail_section = this.fields.detail_s;
    var invite = new ii.views.InviteUsers();

	this.fields.invite.appendChild(invite.div);

    join_section.style.display = 'none';
    detail_section.style.display = 'none';

	this.fields.error.innerHTML = '';
	this.fields.error2.innerHTML = '';

    var frmName = this.fields.form_name;
	var frmAdd = this.fields.form_add;

	ii.setDefaultText(frmName.spotname, 'Enter a name');

	frmAdd.visible.value =
		frmAdd.invite.value =
		frmAdd.post.value = 'all';

	ii.setDefaultText(frmAdd.description, 'Enter a description');


	var mapelm = this.fields.minimap;
	var that = this;

	frmName.onsubmit = function() {
		if (ii.getTextBoxValue(this.spotname) == '')
		{
			that.fields.error.innerHTML = 'Please enter a name';
			return false;
		}

		that.fields.error.innerHTML = '';
		that.fields.error2.innerHTML = '';

		var query = this.spotname.value;
		ii.get('q-items-spot',
			function(resp) {
				if (!resp.items.length)
				{
					join_section.style.display = 'none';
					return;
				}
				join_section.style.display = 'block';
				that.fields.spots.innerHTML ='';
				that.fields.searchterm.textContent = query;
				for(var n=0; n < resp.items.length; n++)
				{
					resp.items[n].type='s';
					var itm = new ii.items.Spot(resp.items[n]);
					itm.onmouseover = function(){};
					itm.onmouseout  = function(){};
					var view = itm.createView('ListItem');
					view.div.style.backgroundColor = 'transparent';
					that.fields.spots
						 .appendChild(view.div);


				}
			},
			{ query: this.spotname.value }
		);

		detail_section.style.display = 'block';
		that.map = new ii.Map.Minimap({
				target: mapelm,
				tabname: 'AddSpot',
				needclick: true
		});
		return false;
	}

    frmAdd.onsubmit = function() {
		if (that.map.selectedLat == 0 && that.map.selectedLon == 0)
		{
			that.fields.error2
				.innerHTML = 'Please click a location on the map';
			return false;
		}
		that.fields.error2.innerHTML = '';

		var btn = this.submitbtn;
		ii.startWaitButton(btn);
		ii.startWaitButton(invite.submitbtn);

		var params = {
			type:'spot',
			name:frmName.spotname.value,
			description:ii.getTextBoxValue(this.description),
			invite:this.invite.value,
			post:this.post.value,
			visible:this.visible.value,
			lat: that.map.selectedLat,
			lon: that.map.selectedLon
		}
		if (invite.div.style.display != 'none')
			params.members = invite.members.value;

		ii.get('p-new-set',
			function(resp)
			{
				ii.endWaitButton(btn);
				ii.endWaitButton(invite.submitbtn);
				if (resp.result=='OK')
				{
					ii.log('Spot created');
					window.location = '#rel&item=s.'+resp.newid;
				}
				else
				{
					ii.setText(
						document.getElementById('ii_addspot_error2'),
						resp.msg
					);
				}

			},
			params
		);
    	return false;
    }


	// if any security = members, invite-box should show
	function onSecurityChange()
	{
		var show = false;
		var sels = frmAdd.getElementsByTagName('select');
		for (var n=0; n < sels.length; n++)
			if (sels[n].value=='members')
				show = true;
		frmAdd.submitbtn.style.display = (show ? 'none': '');
		invite.div.style.display = (show ? '' : 'none');
	}

	onSecurityChange();

	var sels = frmAdd.getElementsByTagName('select');
	for (var n=0; n < sels.length; n++)
		sels[n].onclick = sels[n].onkeyup = sels[n].onchange = onSecurityChange;

}


ii.views.user.MyStatusState = function(item, args){
	this.item = item;

   	this.statusElm = ii.elm('span');


	var target = document.getElementById('ii_user_status_state');
    target.parentNode.replaceChild(
			ii.elm('span',
				{ id: 'ii_user_status_state' },
				'Hi ',
				ii.elm('a', {href:'#rel&item=ME.0&pane='}, ii.login.username),
				'! ',
				this.statusElm,
				' | '),
			target
	);
	this.update();
}


ii.views.user.MyStatusState.prototype.update = function()
{
	var newStatus = this.item.getLiveStatusElement();
	this.statusElm.parentNode.replaceChild(
			newStatus,
			this.statusElm
	);
	this.statusElm = newStatus;
}
ii.set_interval_photo_popup_comments = 10000;
ii.set_interval_photo_commenters = 10000;

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.photo = {};


ii.items.Photo = function(itm) {
	this.init(itm);

	this.lat = parseFloat(this.lat);
	this.lon = parseFloat(this.lon);

}


ii.items.Photo.prototype = new ii.items.Item;


ii.items.Photo.prototype.hideFromMap = function(hide)
{
    for(var n=0; n < this.itemviews.length;n++){
        if (this.itemviews[n].map){

            var itemview = this.itemviews[n];

            itemview.marker.div.style.visibility = (hide ? 'hidden' : 'visible');
            itemview.shadowMarker.div.style.visibility = (hide ? 'hidden' : 'visible');

        }
    }
}

// override zoomto, since we also want to create a large popup
// when zooming to

ii.items.Photo.prototype.zoomto = function()
{
	if (ii.activePopup)
	{
		for(var n=0; n < ii.activeItem.itemviews.length; n++)
			if (ii.activeItem.itemviews[n] == ii.activePopup)
			{
				ii.activeItem.removeView(ii.activePopup);
				break;
			}
	}
	// adding to map with second param true, wlll
	// create a large item and zoomto automatically
	ii.activePopup = ii.app.map.addItem(this, true);
	ii.activeItem = this;
}

// move to another photo next/prev from user
// or next prev from collection
ii.items.Photo.prototype.moveRelative = function(dir, tab)
{
    ii.log('moverel ' + tab);
	if (ii.last_active_setid)
	{
		var relid = ii.last_active_setid;
		var reltype = 'set';
	}
	else
	{
		var relid = this.userid;
		var reltype = 'user';
	}

	ii.get('q-relative-id',
		function(resp) {

			ii.app.state.setState({item:'p.'+resp.id});
            ii.app.state.setState({tab: tab});
		},
		{
			entitytype:'photo',
			entityid:this.id,
			relid:relid,
			reltype:reltype,
			reldir:dir
		}
	);
}
ii.items.Photo.prototype.setPrevNextButtons = function(prevbtn, nextbtn, tab)
{
    var that = this;

	if( !ii.last_active_setid)
	{
		prevbtn.title = prevbtn.alt =
			'Previous Photo by: ' + this.author;
		nextbtn.title = nextbtn.alt =
			'Next Photo by: ' + this.author;
	}
	else
	{
		for(var i=0, len=this.postedin.length; i<len; i++)
		{
			if (item.postedin.id == ii.last_active_setid)
			{
				var tpname = ii.typesingle[this.postedin[i].type];
				prevbtn.title = prevbtn.alt =
					'Previous Photo in ' + tpname +': ' +
					this.postedin[i].name;
				nextbtn.title = prevbtn.alt =
					'Next Photo in ' + tpname +': ' +
					this.postedin[i].name;
				break;
			}
		}
	}
	prevbtn.onclick = function() { that.moveRelative('prev', tab); }
	prevbtn.onmouseover = ii.onmouseoverbtn;
	prevbtn.onmouseout = ii.onmouseoutbtn;

	nextbtn.onclick = function() { that.moveRelative('next', tab); }
	nextbtn.onmouseover = ii.onmouseoverbtn;
	nextbtn.onmouseout = ii.onmouseoutbtn;

}

/* ListItem*/

ii.views.photo.ListItem = function (item) {
	this.item = item;

	this.initDiv('ListItem');

	this.div.onclick = function() {
		ii.app.state.setState({item:'p.'+item.id})
	};

	this.update();
}
ii.views.photo.ListItem.prototype = new ii.views.ListItem;


/* LargeListItem */

ii.views.photo.LargeListItem = function(item) {

	this.item = item;
	this.initDiv('LargeListItem');

	// setup action links
	var links = item.createView('ActionLinks');
	this.div.appendChild(links.div);

	this.update();

}
ii.views.photo.LargeListItem.prototype = new ii.views.View;

ii.views.photo.LargeListItem.prototype.fillField_postedin = function(elm)
{
	var newPostedInLinks =  ii.views.postedInLinks(this.item.postedin);
	elm.innerHTML = '';
	elm.appendChild(newPostedInLinks);
}

/*
 * Details. small view of photo in Details tab of group/spot
 */
ii.views.photo.Details = function(item, args)
{
	this.item = item;
	this.initDiv('Details');
	this.update();

}
ii.views.photo.Details.prototype = new ii.views.View;

/* Thumb. Small marker on map */

ii.views.photo.Thumb = function(item, args)
{
	this.map = args.map;
	this.item = item;

	this.initDiv('Thumb');

	var that = this;

	var size=80;
	var a = item.aspectratio;
	var w = (a>1)? size:Math.floor(a*size);
	var h = (a>1)? Math.floor(size/a):size;
	var th = Math.min(Math.round(.25*w),20); //anchor tip
	var tw = Math.min(Math.round(.3*w),30);


	// z-index based on lat
	// max z-index limited by safari 16 000 000
	// 16 000 000 is used for mouseover-item
	// factor 80000 will create large range not passing 1600000
	this.zIndex = Math.round((90-item.lat)*80000);
	this.div.style.zIndex = this.zIndex;

	var url = '/srv/d-media.php?border=0&entitytype=photo&entityid='
		+this.item.id+'&width='+w+'&height='+h;

	this.fields.thumb.style.width = w+'px';
	this.fields.thumb.style.height = h+'px'
	this.fields.thumb.appendChild(ii.elm('img', {src:url}));

	this.fields.zoomto.style.top = (h+4-16) + 'px';

	// anchor
	this.fields.anchor.style.marginLeft =
		(4+Math.round((w/2)-(tw/2)))+'px';

	this.update();

	// add item to map
	this.addToMap('poiThumbs', -((w/2) + 4), -(h + 8 + th));
	this.addShadowToMap('media_shadow.png', 140, 100, -48, -105);

	this.div.onclick = function() { ii.app.state.setState({item:'p.'+item.id})};

	// HACK: reenlarge thumb when this is already selected item
	// we see that this item is selected because it was retrieved
	// with fields=full
	var itm = ii.app.state.state.item;
	if (itm && itm == 'p.'+item.id)
	{
		var that = this;
		this.div.onclick = function()
		{
			item.removeView(that);
			args.map.addItem(item, true);
		}
	}
}
ii.views.photo.Thumb.prototype = new ii.views.Mappable;

ii.views.photo.Thumb.prototype.onmouseover = function() {
	this.div.style.zIndex = 16000000;
}

ii.views.photo.Thumb.prototype.onmouseout = function() {
	this.div.style.zIndex = this.zIndex;
}


/* Popup */


ii.views.photo.Popup = function(item, args)
{
	this.item = item;
	this.map = args.map;
    this.item = item;

	this.initDiv('Popup');

	var that = this;
	var size=400;
	var a = item.aspectratio;
	var w = (a>1)? size:Math.floor(a*size);
	var h = (a>1)? Math.floor(size/a):size;

	var th = Math.min(Math.round(.25*w),20);
	var tw = Math.min(Math.round(.3*w),30); //anchor tip

	this.centerOffsetY = (h + th + 10)/2;


	this.div.onmousedown = ii.stopPropagation;
	this.div.onmouemove =  ii.stopPropagation;
	this.div.onclick    =  ii.stopPropagation;
	this.div.ondrag     =  ii.stopPropagation;
	this.div.ondblclick =  ii.stopPropagation;

	var commentQuery = this.commentQuery = new ii.Query('comment',
				{interval:ii.set_interval_photo_popup_comments},
				{poi:item.id, count:100}
	);

	this.fields.imgcont.style.width = w+'px';
	this.fields.imgcont.style.height = h+'px';

	this.fields.img.src = '/srv/d-media.php?entitytype=poi&entityid='
			+this.item.id+'&width='+w+'&height='+h;
	this.fields.anchor.style.marginLeft = (12+Math.round((w/2)-(tw/2)))+'px';

	this.fields.zoom.style.top = (h+10-20)+'px';
	this.fields.zoom.onmouseover = ii.onmouseoverbtn;
	this.fields.zoom.onmouseout = ii.onmouseoutbtn;
	this.fields.zoom.onclick = function() {
		that.map.zoomTo(item.lat, item.lon, 0, 200)
	};

	this.fields.close.style.left = (w-21-8)+'px';
	this.fields.close.onmouseover = ii.onmouseoverbtn;
	this.fields.close.onmouseout = ii.onmouseoutbtn;
	this.fields.close.onclick = function() {
		ii.app.uncenterActiveItem();
		that.item.removeView(that);
		that.map.addItem(that.item);
	};

	this.fields.commenttab.style.width = (w-34)+'px';
	this.fields.commenttab.style.maxHeight = (h-63)+'px';
	this.fields.commenttab.ondrag = ii.stopPropagation;
	this.fields.commenttab.onmousemove = ii.stopPropagation;

	this.fields.infobtn.onclick = function()
	{
		that.fields.commentbtn.className = 'tab';
		that.fields.commenttab.style.display = 'none';

		this.className = 'tab sel';
		that.fields.infotab.style.display = '';
	}

	this.fields.commentbtn.onclick = function()
	{
		that.fields.infobtn.className = 'tab';
		that.fields.infotab.style.display = 'none';

		this.className = 'tab sel';
		that.fields.commenttab.style.display = '';
		commentQuery.start();
	}

    this.item.setPrevNextButtons(this.fields.prevbtn, this.fields.nextbtn);
	this.fields.prevbtn.style.left = (w/3-21-10)+'px';
	this.fields.nextbtn.style.left = (w*2/3-21-15)+'px';

	if (ii.browser.safari)
	{
		this.fields.commentbtnsin.style.marginTop = '5px';
		this.fields.commenttext.style.position = 'relative';
	}

	this.fields.commenttext.style.width = (w-44)+'px';

	this.fields.bottombar.style.top = (h+10-20-18)+'px';

	this.fields.commentform.onclick = ii.stopPropagation;
	this.fields.commentform.onmousedown = ii.stopPropagation;
	this.fields.commentform.onsubmit = function() {
		ii.get('p-new-comment',
			function(resp) {
				that.fields.commentform.style.display = 'none';
				that.fields.commenttext.value = '';

				ii.setText(that.fields.commentlink,
					'Comments '
					+ (that.item.comments ?
						' ('+(1+parseInt(that.item.comments))+')' : '')
				);
				that.commentQuery.start();
			},
			{
				entitytype: 'poi',
				entityid: that.item.id,
				content: that.fields.commenttext.value
			}
		);
		return false;


	}
	this.fields.commentform.onreset = function()
	{
		that.fields.commentform.style.display = 'none';
		that.fields.commenttext.value = '';
	}

	this.fields.addcommentbtn.onclick = function()
	{
		ii.log('onclick');
		if (!ii.login)
		{
			alert('You must be logged in to post a comment');
		}
		else
		{
			that.fields.commentform.style.display = 'block';
			
			that.fields.commenttext.focus();
		}
	}

	this.fields.infotab.style.width = (w-34)+'px';
	this.fields.infotab.style.maxHeight = (h-63)+'px';
	this.fields.infotabcontent.style.width = (w-34 -73) + 'px';

	this.update();

	this.addToMap('poiPopups', -((w/2) + 10), -(h + 20 + th));
	this.addShadowToMap('media_shadow.png', 520, 400, -200, -392);

	this.commentQuery.addListener( {
		addItem: function(item)
		{
			var vw = item.createView('TabView');
        	that.fields.commentlist.insertBefore(vw.div,
				that.fields.commentlist.firstChild);

		}}
	);
}
ii.views.photo.Popup.prototype = new ii.views.Mappable;


// comment count is dynamic
ii.views.photo.Popup.prototype.fillField_commentbtn = function(elm)
{
	ii.setText(elm, 'Comments '
			+ (this.item.comments ? ' ('+this.item.comments+')' : ''));
}

ii.views.photo.Popup.prototype.onmouseover = function() {
	this.fields.overlay.style.display='';
}

ii.views.photo.Popup.prototype.onmouseout = function() {

    var form = this.fields.commentform;
	ii.log(form);
    if( ! (form && form.style.display == 'block') ){
        // only turn off display if there is no form displayed.
    	this.fields.overlay.style.display='none';
    }
}


ii.views.photo.ActionLinks = function(item) {
	this.item = item;
	this.initDiv();

	var centerbtn = ii.elm('span');

	this.div = ii.elm('div',
        centerbtn,
		ii.elm('div', {className: 'listitem_links'},
			this.postInLink(),
			' ',
			this.postCommentLink()
		),
		this.postCommentDiv(),
		this.postInDiv(),
		this.statusDiv()
	);

	this.update();
}

ii.views.photo.ActionLinks.prototype = new ii.views.ActionLinks;


ii.views.photo.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');


	this.addHeader( {
		type: 'user',
		label: 'Commenters',
		dataField: 'commenters',
		filter: {commentedonid: this.item.id, commentedontype: 'poi'},
		noContentMsg: ii.elm('span','This Photo has no Commenters yet. ',
			'Use the [Post Comment] link to be the first to Comment. ',
			'Read our ',
			ii.elm('a', {href:'#rel&tab=HelpFAQ&q='}, 'FAQ'),
			' for help on the Post Comment feature.'),
		expand: true
	});

	this.update();

	//window.setTimeout(function() { args.onDone()},0); // legacy to be removed
	//this.subItemsets = []; //legacy to be removed
}

ii.views.photo.ItemBrowser.prototype = new ii.views.ItemList;

ii.views.photo.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.photo.TabFeed.prototype = new ii.views.TabFeed();

ii.views.photo.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.photo.TabDetails.prototype = new ii.views.TabDetails;

ii.views.photo.TabDetails.prototype.onload = function() 
{
	this.addComments();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-poi',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}

    this.fields.photo_large.appendChild(
			ii.elm('img', {src: '/srv/d-media.php?style=center&width=428&height=321&entitytype=poi&entityid=' + this.item.id})
	);

    this.item.setPrevNextButtons(this.fields.prev, this.fields.next, 'Details');

	this.initFields();

	this.initForm('info', onsubmit);

	this.update();

}

ii.set_interval_video_popup_comments = 10000;
ii.set_interval_video_commenters = 10000;
ii.set_use_livestream = false;

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.video = {};


ii.items.Video = function(itm) {
	this.init(itm);

	this.lat = parseFloat(this.lat);
	this.lon = parseFloat(this.lon);

}


ii.items.Video.prototype = new ii.items.Item;


ii.items.Video.prototype.hideFromMap = function(hide)
{
    for(var n=0; n < this.itemviews.length;n++){
        if (this.itemviews[n].map){

            var itemview = this.itemviews[n];

            itemview.marker.div.style.visibility = (hide ? 'hidden' : 'visible');
            itemview.shadowMarker.div.style.visibility = (hide ? 'hidden' : 'visible');

        }
    }
}

// override zoomto, since we also want to create a large popup
// when zooming to

ii.items.Video.prototype.zoomto = function()
{
	if (ii.activePopup)
	{
		for(var n=0; n < ii.activeItem.itemviews.length; n++)
			if (ii.activeItem.itemviews[n] == ii.activePopup)
			{
				ii.activeItem.removeView(ii.activePopup);
				break;
			}
	}
	// adding to map with second param true, wlll
	// create a large item and zoomto automatically
	ii.activePopup = ii.app.map.addItem(this, true);
	ii.activeItem = this;
}

// move to another video next/prev from user
// or next prev from collection
ii.items.Video.prototype.moveRelative = function(dir, tab)
{
    ii.log('moverel ' + tab);
	if (ii.last_active_setid)
	{
		var relid = ii.last_active_setid;
		var reltype = 'set';
	}
	else
	{
		var relid = this.userid;
		var reltype = 'user';
	}

	ii.get('q-relative-id',
		function(resp) {

			ii.app.state.setState({item:'v.'+resp.id});
            ii.app.state.setState({tab: tab});
		},
		{
			entitytype:'video',
			entityid:this.id,
			relid:relid,
			reltype:reltype,
			reldir:dir
		}
	);
}
ii.items.Video.prototype.setPrevNextButtons = function(prevbtn, nextbtn, tab)
{
    var that = this;

	if( !ii.last_active_setid)
	{
		prevbtn.title = prevbtn.alt =
			'Previous Video by: ' + this.author;
		nextbtn.title = nextbtn.alt =
			'Next Video by: ' + this.author;
	}
	else
	{
		for(var i=0, len=this.postedin.length; i<len; i++)
		{
			if (item.postedin.id == ii.last_active_setid)
			{
				var tpname = ii.typesingle[this.postedin[i].type];
				prevbtn.title = prevbtn.alt =
					'Previous Video in ' + tpname +': ' +
					this.postedin[i].name;
				nextbtn.title = prevbtn.alt =
					'Next Video in ' + tpname +': ' +
					this.postedin[i].name;
				break;
			}
		}
	}
	prevbtn.onclick = function() { that.moveRelative('prev', tab); }
	prevbtn.onmouseover = ii.onmouseoverbtn;
	prevbtn.onmouseout = ii.onmouseoutbtn;

	nextbtn.onclick = function() { that.moveRelative('next', tab); }
	nextbtn.onmouseover = ii.onmouseoverbtn;
	nextbtn.onmouseout = ii.onmouseoutbtn;

}

/* ListItem*/

ii.views.video.ListItem = function (item) {
	this.item = item;

	this.initDiv('ListItem');

	this.div.onclick = function() {
		ii.app.state.setState({item:'v.'+item.id})
	};

	this.update();
}
ii.views.video.ListItem.prototype = new ii.views.ListItem;


/* LargeListItem */

ii.views.video.LargeListItem = function(item) {

	this.item = item;
	this.initDiv('LargeListItem');

	// setup action links
	var links = item.createView('ActionLinks');
	this.div.appendChild(links.div);

	this.update();

}
ii.views.video.LargeListItem.prototype = new ii.views.View;

ii.views.video.LargeListItem.prototype.fillField_postedin = function(elm)
{
	var newPostedInLinks =  ii.views.postedInLinks(this.item.postedin);
	elm.innerHTML = '';
	elm.appendChild(newPostedInLinks);
}

/*
 * Details. small view of video in Details tab of group/spot
 */
ii.views.video.Details = function(item, args)
{
	this.item = item;
	this.initDiv('Details');
	this.update();

}
ii.views.video.Details.prototype = new ii.views.View;

/* Thumb. Small marker on map */

ii.views.video.Thumb = function(item, args)
{
	this.map = args.map;
	this.item = item;

	this.initDiv('Thumb');

	var that = this;
	ii.log('creating thumb for video');

	var size=80;
	var a = item.aspectratio;
	var w = (a>1)? size:Math.floor(a*size);
	var h = (a>1)? Math.floor(size/a):size;
	var th = Math.min(Math.round(.25*w),20); //anchor tip
	var tw = Math.min(Math.round(.3*w),30);


	// z-index based on lat
	// max z-index limited by safari 16 000 000
	// 16 000 000 is used for mouseover-item
	// factor 80000 will create large range not passing 1600000
	this.zIndex = Math.round((90-item.lat)*80000);
	this.div.style.zIndex = this.zIndex;

	var url = '/srv/d-media.php?border=0&entitytype=video&entityid='
		+this.item.id+'&width='+w+'&height='+h;

	this.fields.thumb.style.width = w+'px';
	this.fields.thumb.style.height = h+'px'
	this.fields.thumb.appendChild(ii.elm('img', {src:url}));

	this.fields.zoomto.style.top = (h+4-16) + 'px';

	// anchor
	this.fields.anchor.style.marginLeft =
		(4+Math.round((w/2)-(tw/2)))+'px';

	this.update();

	// add item to map
	this.addToMap('poiThumbs', -((w/2) + 4), -(h + 8 + th));
	this.addShadowToMap('media_shadow.png', 140, 100, -48, -105);

	this.div.onclick = function() { ii.app.state.setState({item:'v.'+item.id})};

	// HACK: reenlarge thumb when this is already selected item
	// we see that this item is selected because it was retrieved
	// with fields=full
	var itm = ii.app.state.state.item;
	if (itm && itm == 'p.'+item.id)
	{
		var that = this;
		this.div.onclick = function()
		{
			item.removeView(that);
			args.map.addItem(item, true);
		}
	}
}
ii.views.video.Thumb.prototype = new ii.views.Mappable;

ii.views.video.Thumb.prototype.onmouseover = function() {
	this.div.style.zIndex = 16000000;
}

ii.views.video.Thumb.prototype.onmouseout = function() {
	this.div.style.zIndex = this.zIndex;
}

/* Popup */

ii.views.video.Popup = function(item, args)
{
	this.item = item;
	this.map = args.map;

	this.initDiv('Popup');

	var that = this;
	var size=400;
	var a = item.aspectratio;
    var w = 425;
    var h = 319;

	var th = Math.min(Math.round(.25*w),20);
	var tw = Math.min(Math.round(.3*w),30); //anchor tip

	this.centerOffsetY = (h + th + 10)/2;

	this.div.onmousedown = ii.stopPropagation;
	this.div.onmousemove = ii.stopPropagation;
	this.div.onclick    =  ii.stopPropagation;
	this.div.ondrag     =  ii.stopPropagation;
	this.div.ondblclick =  ii.stopPropagation;

	var commentQuery = this.commentQuery = new ii.Query('comment',
				{interval:ii.set_interval_video_popup_comments},
				{poi:item.id, count:100}
	);

	this.fields.imgcont.style.width = w+'px';
	this.fields.imgcont.style.height = h+'px';

	this.fields.img.src = '/srv/d-media.php?entitytype=video&entityid='
			+this.item.id+'&width='+w+'&height='+h;
	
	this.fields.anchor.style.marginLeft = (12+Math.round((w/2)-(tw/2)))+'px';

	// actual img
	ii.log('kind='+item.kind);
	if (ii.set_use_livestream && item.kind == 'stream')
	{
		var vid = ii.elm('div');
		this.fields.img.parentNode.replaceChild(vid, this.fields.img);
		var uid = item.description.substr(5);
		var html = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0" width="425" height="319" id="qikPlayer" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="true" /><param name="movie" value="http://qik.com/swfs/qikPlayer4.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#333333" /><param name="FlashVars" value="rssURL=http://qik.com/video/'+uid+'.rss&autoPlay=true" /><embed src="http://qik.com/swfs/qikPlayer4.swf" quality="high" swliveconnect="true" id="iii" bgcolor="#333333" width="425" height="319" name="qikPlayer" align="middle" allowScriptAccess="sameDomain" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" FlashVars="rssURL=http://qik.com/video/'+uid+'.rss&autoPlay=true"></embed></object>';
		vid.innerHTML = html;
		ii_active_vid_view = this;
		ii_active_vid_user = item.userid;
		this.item.displayLat = parseFloat(item.lat);
		this.item.displayLon = parseFloat(item.lon);
		this.streamTimer = window.setInterval(function() {streamTimer();}, 15000);
	}
	else if (item.kind == 'youtube')
	{
		var vid = ii.elm('div', {id:'ii_video_cont'});
		this.fields.img.parentNode.replaceChild(vid, this.fields.img);
		//item.orgid= 'http://www.youtube.com/v/TIf_kxxJrjg?f=user_uploads&amp;app=youtube_gdata';
		var uid = item.orgid + '&enablejsapi=1&playerapiid=ytplayer';
		ii.log('UID='+uid);
		var attributes = {
			id:"myytplayer",
			name:"myytplayer"
		}

		var params = {
			allowfullscreen:"true",
			allowscriptaccess:"always",
			wmode: 'transparent'
		}
		window.setTimeout(function() {

			swfobject.embedSWF(uid, "ii_video_cont", "425", "319", "8", null, null, params, attributes);
		},0);
		ii_active_vid_view = this;
		ii_active_vid_user = item.userid;
		this.item.displayLat = parseFloat(item.lat);
		this.item.displayLon = parseFloat(item.lon);
/*
		var html = '<object width="425" height="319">'
		  +'<param name="movie" value="'+uid+'"></param>'
		  +'<param name="allowFullScreen" value="true"></param>'
		  +'<param name="allowScriptAccess" value="always"></param>'
		  +'<embed src="'+uid+'" '
		  +'type="application/x-shockwave-flash" '
    	  +'allowscriptaccess="always" '
    	  +'width="425" height="319" '
		  +'allowfullscreen="true"></embed></object>';

		vid.innerHTML = html;
		ii_active_vid_user = item.userid;
		this.item.displayLat = parseFloat(item.lat);
		this.item.displayLon = parseFloat(item.lon);
		this.streamTimer = window.setInterval(function() {streamTimer();}, 15000);
*/
//		ii_active_vid_view = this;
	}
	else if (item.kind == 'video')
	{
		var vid = ii.elm('div', {id:'ii_video_cont'});
		this.fields.img.parentNode.replaceChild(vid, this.fields.img);
		var uid = item.description.substr(5);
			var x = {file:'http://www.youtube.com/v/QX9bjyMZCnc?f=user_uploads&amp;app=youtube_gdata'};
		var flashvars = {
			playlistfile: 'http://gdata.youtube.com/feeds/api/users//uploads',
			
			autostart:"true"
		}

		var params = {
			allowfullscreen:"true",
			allowscriptaccess:"always",
			wmode: 'transparent'
		}

		var attributes = {
			id:"player2",
			name:"player2"
		}




		window.setTimeout(function() {

			swfobject.embedSWF("/lib/mediaplayer/player.swf", "ii_video_cont", "425", "319", "9.0.115", false, flashvars, params, attributes);
		},0);

		ii_active_vid_user = item.userid;
		ii_active_vid_start = item.created;
		ii_active_vid_state = 'start';
		ii_active_vid_view = this;
		this.item.displayLat = parseFloat(item.lat);
		this.item.displayLon = parseFloat(item.lon);
		//vid.innerHTML = html;
	}


	this.update();

	this.addToMap('poiPopups', -((w/2) + 10), -(h + 20 + th));
	this.addShadowToMap('media_shadow.png', 520, 400, -200, -392);

	this.commentQuery.addListener( {
		addItem: function(item)
		{
			var vw = item.createView('TabView');
        	that.fields.commentlist.insertBefore(vw.div,
				that.fields.commentlist.firstChild);

		}}
	);
}
ii.views.video.Popup.prototype = new ii.views.Mappable;


// comment count is dynamic
ii.views.video.Popup.prototype.fillField_commentbtn = function(elm)
{
	ii.setText(elm, 'Comments '
			+ (this.item.comments ? ' ('+this.item.comments+')' : ''));
}


ii.views.video.Popup.prototype.onmouseover = function() {
	//this.fields.overlay.style.display='';
}

ii.views.video.Popup.prototype.onmouseout = function() {

}


ii.views.video.ActionLinks = function(item) {
	this.item = item;
	this.initDiv();

	this.div = ii.elm('div',
		ii.elm('div', {className: 'listitem_links'},
			this.postInLink(),
			' ',
			this.postCommentLink()
		),
		this.postCommentDiv(),
		this.postInDiv(),
		this.statusDiv()
	);

	this.update();
}

ii.views.video.ActionLinks.prototype = new ii.views.ActionLinks;


ii.views.video.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');


	this.addHeader( {
		type: 'user',
		label: 'Commenters',
		dataField: 'commenters',
		filter: {commentedonid: this.item.id, commentedontype: 'poi'},
		noContentMsg: ii.elm('span','This Video has no Commenters yet. ',
			'Use the [Post Comment] link to be the first to Comment. ',
			'Read our ',
			ii.elm('a', {href:'#rel&tab=HelpFAQ&q='}, 'FAQ'),
			' for help on the Post Comment feature.'),
		expand: true
	});

	this.update();

	//window.setTimeout(function() { args.onDone()},0); // legacy to be removed
	//this.subItemsets = []; //legacy to be removed
}

ii.views.video.ItemBrowser.prototype = new ii.views.ItemList;

ii.views.video.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.video.TabFeed.prototype = new ii.views.TabFeed();

ii.views.video.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.video.TabDetails.prototype = new ii.views.TabDetails;

ii.views.video.TabDetails.prototype.onload = function() 
{
	this.addComments();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-poi',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}

    this.fields.photo_large.appendChild(
			ii.elm('img', {src: '/srv/d-media.php?style=center&width=428&height=321&entitytype=poi&entityid=' + this.item.id})
	);

    this.item.setPrevNextButtons(this.fields.prev, this.fields.next, 'Details');

	this.initFields();

	this.initForm('info', onsubmit);

	this.update();

}
var player = null; 
ii.views.video.Popup.prototype.prevcenter = ii.views.Mappable.prototype.center;
ii.views.video.Popup.prototype.center = function() {

	this.prevcenter();
	//ii_active_vid_forcepos = ii_active_vid_position;
	
	return;
	window.setTimeout(function() {
		ii.log('Setting pos to '+oldpos);
		player = document.getElementById('player2');
		player.sendEvent("SEEK", oldpos); }, 500
	);
}

function onYouTubePlayerReady(playerId) {
	ytplayer = document.getElementById("myytplayer");
	if (ii_active_vid_view.timer)
	{
		ii.log('video restarted at '+ii_active_vid_view.currentPos);
		var pos = parseInt(ii_active_vid_view.currentPos);
		window.setTimeout(function() {
			ytplayer = document.getElementById("myytplayer");
			//ytplayer.seekTo(2, true);
			ytplayer.seekTo(pos, true);
		}, 400);
		return;
	}
	ytplayer.playVideo();

	ii.log('video started');
	function checkDuration() {
		var d = ytplayer.getDuration();
		if (d == 0)
			window.setTimeout(checkDuration, 250);
		else 
			ii_active_vid_view.loadPoints(d);
	}
	checkDuration();
}

ii.views.video.Popup.prototype.loadPoints = function(duration, resp)
{
	var that = this;
    ii_active_vid_state = 'loading';
    if (!resp)
    {
        ii.log('Loading points');
        var params = { user: this.item.userid, 
                     start: this.item.created-8,
                     end: parseInt(duration) + parseInt(this.item.created)
                    };
        ii.get('q-points', function(rsp) { 
				that.loadPoints(duration, rsp); }, params);
        return;
    }

    this.points = resp.points;
	console.log('points loaded: '+resp.points.length);
	if (this.points.length<2) return;
	
	this.timer = window.setInterval(function() { that.tracker(); }, 1000);

}

ii.views.video.Popup.prototype.tracker = function() {
	ytplayer = document.getElementById("myytplayer");
	if (!ytplayer.getCurrentTime) return;
	var time = ytplayer.getCurrentTime();
	if (time>1)
		this.currentPos = time;
	var search = parseFloat(time) + parseFloat(this.item.created);
	ii.log('Searching '+time+', '+search);

	for(var n=0; n < this.points.length; n++)
	{
		if (parseFloat(this.points[n].loctime) > search)
		{
			if (n==0)
			{
				lat = this.points[n].lat;
				lon = this.points[n].lon;
			}
			else
			{
				var lat1 = this.points[n-1].lat;
				var lon1 = this.points[n-1].lon;
				var lat2 = this.points[n  ].lat;
				var lon2 = this.points[n  ].lon;
				var progr = search - parseFloat(this.points[n-1].loctime);
				var tot = parseFloat(this.points[n].loctime) -
					this.points[n-1].loctime;
				progr /= tot;
				lat1=parseFloat(lat1);
				lon1=parseFloat(lon1);
				lat2=parseFloat(lat2);
				lon2=parseFloat(lon2);

				lat = lat1 + (lat2 - lat1) * progr;
				lon = lon1 + (lon2 - lon1) * progr;
			}
			break;
		}
	}
//        ii.log('time:%o, search='+search+', lat='+lat+', lon='+lon+', progr='+progr , obj);
	if (!lat && !lon) return;

	ii.log('moving to '+lat+'x'+lon);
	this.item.displayLat = lat;
	this.item.displayLon = lon;


//        ii.set_map_smooth_panning =true;
	this.move();
}

ii.views.video.Popup.prototype.remove = function() {
	this.removeQueries();
	this.removeFromMap();

	ii.log('Removing timer: '+this.timer);
	if (this.timer)
		window.clearInterval(this.timer);
}

function startTracker(obj) {
    //player.removeModelListener("TIME","startTracker");
    loadPoints(obj.duration);

}
function timeTracker(obj) { 
    if (ii_active_vid_state == 'start')
        loadPoints(obj.duration);
    else if (ii_active_vid_state == 'loading')
        return;
    /*else if (ii_active_vid_state > 0)
    {
        ii_active_vid_state++;
        if (ii_active_vid_state>2)
            ii_active_vid_state = 0;
    }*/
	else if (window.ii_active_vid_forcepos)
	{
		var oldpos = ii_active_vid_forcepos;
		window.setTimeout(function() {
			ii.log('Setting pos to '+oldpos);
			player.sendEvent("SEEK", oldpos); }, 10);
		ii_active_vid_forcepos = 0;
	}
    else
    {
        var lat;
        var lon;
        ii_active_vid_state++;
        // find point in ii_active_vid_points
		ii_active_vid_position = obj.position;
        var search = parseFloat(obj.position) + parseFloat(ii_active_vid_start) + 12;
        for(var n=0; n < ii_active_vid_points.length; n++)
        {
            if (parseFloat(ii_active_vid_points[n].loctime) > search)
            {
                if (n==0)
                {
                    lat = ii_active_vid_points[n].lat;
                    lon = ii_active_vid_points[n].lon;
                }
                else
                {
                    var lat1 = ii_active_vid_points[n-1].lat;
                    var lon1 = ii_active_vid_points[n-1].lon;
                    var lat2 = ii_active_vid_points[n  ].lat;
                    var lon2 = ii_active_vid_points[n  ].lon;
                    var progr = search - parseFloat(ii_active_vid_points[n-1].loctime);
                    var tot = parseFloat(ii_active_vid_points[n].loctime) -
                        ii_active_vid_points[n-1].loctime;
                    progr /= tot;
                    lat1=parseFloat(lat1);
                    lon1=parseFloat(lon1);
                    lat2=parseFloat(lat2);
                    lon2=parseFloat(lon2);

                    lat = lat1 + (lat2 - lat1) * progr;
                    lon = lon1 + (lon2 - lon1) * progr;
                }
                break;
            }
        }
//        ii.log('time:%o, search='+search+', lat='+lat+', lon='+lon+', progr='+progr , obj);
        if (!lat && !lon) return;

        ii_active_vid_view.item.displayLat = lat;
        ii_active_vid_view.item.displayLon = lon;


//        ii.set_map_smooth_panning =true;
		ii_active_vid_view.move();
        //ii_active_vid_view.map.moveView(ii_active_vid_view, ii_active_vid_view.item.displayLat, ii_active_vid_view.item.displayLon);
  //      ii.set_map_smooth_panning =false;

        return;
    }
}

function playerReady(thePlayer) 
{ 
    ii.log('Player ready: Adding listeners::' + thePlayer.id);
    //player = window.document[thePlayer.id];
	player = document.getElementById('player2');
    player.addModelListener("TIME","timeTracker");
}

function playlistTracker(obj)
{
    ii.log('playlist:%o', obj);
}

function loadedTracker(obj)
{
    ii.log('playlist:%o', obj);
}
function seekTracker(obj)
{
    //ii_active_vid_state = 0;
    //timeTracker(obj);
    return;
    ii_active_vid_view.item.displayLat = ii_active_vid_view.item.lat;
    ii_active_vid_view.item.displayLon = ii_active_vid_view.item.lon;
    ii_active_vid_view.updatePos();
}

function streamTimer(resp) {
    if (!resp)
    {
        ii.get('q-items-user', streamTimer, {id: ii_active_vid_user});
        return;
    }
    var lat = resp.items[0].lat;
    var lon = resp.items[0].lon;
    ii_active_vid_view.item.lat = parseFloat(lat);
    ii_active_vid_view.item.lon = parseFloat(lon);


    if ((!ii_active_vid_view.animationTimer) &&
        (ii_active_vid_view.item.displayLat !== ii_active_vid_view.item.lat ||
        ii_active_vid_view.item.displayLon !== ii_active_vid_view.item.lon))
    {
        ii.log('Setting anim timer from stream!');
        ii_active_vid_view.animationTimer = window.setInterval(function() 
		{ ii_active_vid_view.updatePos(); }, ii.set_user_animate_step*2);
    }

}
ii.set_interval_trip_feed = 3000;
ii.set_interval_trip_pois = 15000;

/* local settings */

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.trip = {};


/* user constructor, initializes animation time  and creates position */
ii.items.Trip = function(itm) {

    this.init(itm);

    this.lat = parseFloat(this.lat);
    this.lon = parseFloat(this.lon);

    // if no previous pos is known, use current
    this.displayLat = this.lat;
    this.displayLon = this.lon;

    // variables needed to render the line and animate playback

    /* whether or not htis trip is playing */
    this.playing = false;

    /* all the trip points for this trip */
    //this.trippoints = [];

    /* roughly the number of playback_seconds where there is ratio of realtime
     * playback to realtime recording, eg: 60 seconds per minute. this is not
     * exact, but a rough estimate, due to other parameters such as playback
     * interval and speed factor.  Also note the data from the server is in
     * seconds.
     */
    //var playback_ratio = 60;

    /* unscientific factor to help smooth animation */
    //var max_playback_factor = 60;

    /* animation interval of playback in milliseconds */
    //this.playback_interval = 150;

    // determine the playback_factor for this trip.
    /*
	   this.trip_playback_factor = this.timespan / playback_ratio;
    if(this.trip_playback_factor > max_playback_factor){
        this.trip_playback_factor = max_playback_factor;
    }
	*/

    /**
     * the currently visited point, ie: where to move the marker;
     */
    //this.vp = 0;

    /**
     * the last visited point (lvp) while playing the trip,  always start the trip
     * at -1
     */
    this.lvp = 0;

    /** the progress to the next point (tnp) along the trip. */
    //this.progress_tnp = 1.0;

}

ii.items.Trip.prototype = new ii.items.Item;

ii.items.Trip.prototype.moveMarker = function(){
    for(var n=0, length = this.itemviews.length; n < length; n++){
        if(this.itemviews[n].moveMarker){
            this.itemviews[n].moveMarker();
        }
    }
}

/* sets the marker-icon url, based on heading, zoomLevel and status */
ii.items.Trip.prototype.getIconUrl = function(zoom) {

    var icon = 0,
        w    = 32,
        z    = zoom,
        url  = 'icon_user/trip/';

	if (this.trippoints && this.trippoints.length>1)
	{
		var l = Math.min(this.lvp, this.trippoints.length - 2);
		var lat_from = parseFloat(this.trippoints[l].lat);
		var lon_from = parseFloat(this.trippoints[l].lon);
		var lat_to = parseFloat(this.trippoints[l+1].lat);
		var lon_to = parseFloat(this.trippoints[l+1].lon);
    }
	else
	{
		var lat_from = parseFloat(this.lat);
		var lon_from = parseFloat(this.lon);
		var lat_to = parseFloat(this.endlat);
		var lon_to = parseFloat(this.endlon);
	}

    // calculate the icon size based on zoom level.
    if (z <= .3)
        w = 16;
    else if (z <= .6)
        w = 24;

	//get heading based on previous screen position
	var dx = Math.abs(lon_to - lon_from);
	var dy = -Math.abs(lat_to - lat_from);
	if (dy==0)
	{
		var c = (lon_to>lon_from)? 90:270; //going straight east or west
	}
	else
	{
		var c = Math.atan(dx/-dy) * (360/(2*Math.PI)); //in degrees
	}

	//transform to 0-360 degrees, with N=0, E=90, S=180, W=270
	if (lon_to>lon_from && lat_to<lat_from) c = 180 - c;
	if (lon_to<lon_from && lat_to<lat_from) c = 180 + c;
	if (lon_to<lon_from && lat_to>lat_from) c = 360 - c;

	//there are 12 icons = steps of 30 degree on circle
	var icon = Math.round(c/30) * 30;
	if (icon==360) icon=0;

    return {url:'media/'+url+w+'/'+icon+'.png', size:w};
}

ii.views.trip.ListItem = function(item)
{
    this.item = item;
    this.initDiv('ListItem');
    this.update();
    this.div.onclick = function() {
        ii.app.state.setState({item:'t.'+item.id})
    };
}


ii.views.trip.ListItem.prototype = new ii.views.ListItem;

ii.views.trip.ItemBrowser = function(item, args)
{
    this.item = item;
    this.map = args.map;
    this.queries = [];

    this.initDiv('ItemList');

    this.addHeader( {
        type: 'photo',
        label: 'Photos',
        dataField: 'photos',
        filter: {trip: this.item.id},
        expand: true
    });

	this.item.photoQuery = this.queries[0];

    this.update();

}

ii.views.trip.ItemBrowser.prototype = new ii.views.ItemList;

/* creates an icon for this item, store it in itemview */
ii.views.trip.Icon = function(item,args)
{
    // need the item for later use when moving the marker.
    this.item = item;

    this.map = args.map;
    var iconurl = item.getIconUrl(this.map.getZoom());

    this.icon_img = ii.elm('img', {src: iconurl.url});

    this.div = ii.elm(
        'div',
        {className:'marker'},
        this.icon_img
    );

    that = this;

    this.div.onmouseover = function(){
        that.div.style.cursor = 'pointer';
        item.onmouseover()
    };
    this.div.onmouseout = function(){
        that.div.style.cursor = 'default';
        item.onmouseout()
    };
    this.div.onclick = function(){
        item.popupAlwaysVisible=true;
        item.onmouseover();
    }

	this.addToMap('tripIcons', 
			-(iconurl.size/2),
			-(iconurl.size/2));
    //this.marker = args.map.addMarker(this.div, 'tripIcons',
    //        item.lat, item.lon,
    //        -(iconurl.size/2),
    //        -(iconurl.size/2));

    this.map.addZoomListener(this, this.moveMarker);
}

ii.views.trip.Icon.prototype = new ii.views.Mappable;

/**
 * move icon marker to a specific point, where the point is the element in the
 * trippoints array.  otherwise the point defaults to this.item.lvp
 *
 * @param {Object} point
 */
ii.views.trip.Icon.prototype.moveMarker = function()
{
	var iconurl = this.item.getIconUrl(this.map.getZoom());

    // if icon changes, marker offset also changes
    if (this.div.firstChild.src.indexOf(iconurl.url) == -1)
    {
		ii.log('updated marker from '+this.div.firstChild.src+' to '+iconurl.url);
		ii.log(this.div.firstChild.src.indexOf(iconurl.url));
        this.div.firstChild.src = iconurl.url;
        this.marker.offset.x =
            this.marker.offset.y = -iconurl.size/2;
		ii.log('updated marker offset X to '+this.marker.offset.x);

		if (this.item.centered)
		{
			var cont = this.tempContainer;
			cont.style.left = (this.marker.offset.x) + 'px';
			cont.style.top = (this.marker.offset.y + this.centerOffsetY) + 'px';
		}

    }

    this.icon_img.src = iconurl.url;

	this.move();
}


ii.views.trip.IconPopup = function(item, args) {
    this.item = item;
    this.map  = args.map;

    if(item.popupAlwaysVisible == undefined){
        item.popupAlwaysVisible = args.alwaysVisible
    }

    var divbg = ii.pngImage('user_info_bg.png', 184, 110);
    divbg.className = 'bg';

    var that = this;

    this.speed = ii.elm('span', 'stopped');

    this.div = ii.elm('div',
        {className: 'iconpopup marker'},
        divbg,
        ii.elm('img',
            {
                className: 'avatar',
                src: '/srv/d-media.php?width=64&height=48&entitytype=user&entityid='+item.userid
            }
        ),
        ii.elm('div',
            {
                className: 'content'
            },
            ii.elm('div', ii.userLink(item.userid, item.author)),
            ii.elm('div', item.name),
            this.speed
        ),
        ii.elm('img',
            {
                className: 'button',
                style: {
                    left: '160px',
                    top: '52px'
                },
                src: 'media/poi_zoom_smll.png',
                onmouseover: ii.onmouseoverbtn,
                onmouseout: ii.onmouseoutbtn,
                onclick: function(){
                    args.map.zoomTo(item.displayLat|| item.lat,
                        item.displayLon || item.lon, 50, 0);
                }
            }
        ),
        ii.elm('img',
            {
                className: 'button',
                style: {
                    left:'160px',
                    top:'5px'
                },
                src:'media/button_userpop_close.png',
                onmouseover: ii.onmouseoverbtn,
                onmouseout: ii.onmouseoutbtn,
                onclick: function(){
                    item.popupAlwaysVisible = false;
                    that.div.style.visibility='hidden';
                }
            }
        )
    );

	this.addToMap('tripIcons', -58, -124);
	this.addShadowToMap('user_info_shadow.png', 208, 60, -35, -67);

}

ii.views.trip.IconPopup.prototype = new ii.views.Mappable;

ii.views.trip.IconPopup.prototype.moveMarker = function(){
    this.map.moveMarker(this.marker, this.item.displayLat, this.item.displayLon);
    this.map.moveMarker(this.shadowMarker, this.item.displayLat, this.item.displayLon);

    if(this.item.playing){
        this.speed.innerHTML = ' traveling at ' + ii.formatSpeed(this.item.current_trip_speed);
    }
    else{
        this.speed.innerHTML = ' stopped';
    }
}

ii.views.trip.IconPopup.prototype.onmouseout = function()
{
    this.div.style.visibility =
        this.shadowDiv.style.visibility = (this.item.popupAlwaysVisible ? '' : 'hidden');
}

ii.views.trip.IconPopup.prototype.onmouseover = function()
{
    this.div.style.visibility = this.shadowDiv.style.visibility = '';
}

ii.views.trip.IconPopup.prototype.remove = function()
{
    this.map.removeMarker(this.marker,'tripIcons');
    this.shadowDiv.parentNode.removeChild(this.shadowDiv);
    this.map.removeMarker(this.shadowMarker,'shadows');
}


ii.items.Trip.prototype.tripTimer = function() {

	this.currenttime += 
		(this.trip_playback_factor * this.playback_interval / 1000);

	while (this.currenttime >= this.trippoints[this.lvp+1].loctime)
	{
		// move to next point
		this.lvp++;
		if (this.lvp +1 ==  this.trippoints.length)
		{
			this.gotoEnd();
			return;
		}
		if (this.photoQuery)
		{
			var photos = this.photoQuery.items;
			for(var i in photos){
				if( photos[i].created >= this.trippoints[this.lvp].loctime &&
					photos[i].created <= this.trippoints[this.lvp+1].loctime ){
					photos[i].hideFromMap(false);
				}
			}
		}
		this.current_trip_speed = this.trippoints[this.lvp].s_tnp;
	}

	ii.assert(this.trippoints[this.lvp+1].loctime > this.trippoints[this.lvp].loctime)
	var timespan = this.trippoints[this.lvp+1].loctime - this.trippoints[this.lvp].loctime;
	var progress = (this.currenttime - this.trippoints[this.lvp].loctime)
		  / timespan;


	this.displayLat = parseFloat(this.trippoints[this.lvp  ].lat)  * (1-progress)
					+ parseFloat(this.trippoints[this.lvp+1].lat)  * (progress);
	this.displayLon = parseFloat(this.trippoints[this.lvp  ].lon)  * (1-progress)
					+ parseFloat(this.trippoints[this.lvp+1].lon)  * (progress);

	/*ii.log(	'lvp='+this.lvp
			+',timespan='+timespan
			+',currenttime='+this.currenttime
			+',progress='+progress
			+',dlat='+this.displayLat
			+',dlon='+this.displayLon);
	*/
	this.moveMarker();
	
}

ii.items.Trip.prototype.resetTrip = function() {

    // reset to start position
    this.displayLat = this.lat;
    this.displayLon = this.lon;

    // variables needed to render the line and animate playback

    /* whether or not htis trip is playing */
    this.playing = false;
    this.playback_interval = 150;
	this.trip_playback_factor = Math.max(10, Math.min(60, 
		parseFloat(this.timespan) / 300));
	ii.log('playback_factor = '+this.trip_playback_factor);



	this.starttime = parseInt(this.trippoints[0].loctime);
	this.currenttime = this.starttime;
	this.lvp = 0;
	this.current_trip_speed = this.trippoints[this.lvp].s_tnp;

	this.moveMarker();

}

ii.items.Trip.prototype.startTrip = function() {

	if (!this.playing)
	{
		if (this.lvp == this.trippoints.length-1)
			this.resetTrip();

        // hide the photos when the trip begins to play
        if (this.photoQuery && this.lvp == 0)
        {
            var photos = this.photoQuery.items;
            for(var n in photos) {
                photos[n].hideFromMap(true);
            }
        }

		var that = this;
		this.trip_player = window.setInterval(
			function(){
				that.tripTimer();
			},
			this.playback_interval
		);

        this.playing = true;

		for (var n in this.itemviews)
			if (this.itemviews[n].fields && this.itemviews[n].fields.play)
				this.itemviews[n].fields.play.src = 'media/trip_controls_pauze.png';


	}
	else
	{
        if(this.trip_player){
            // stop the executing trip.
            window.clearInterval(this.trip_player);
        }

        this.playing = false;
        for (var n in this.itemviews)
            if (this.itemviews[n].fields && this.itemviews[n].fields.play)
                this.itemviews[n].fields.play.src = 'media/trip_controls_play.png';

		this.moveMarker();
	}

}

ii.views.trip.LargeListItem = function(item) {
    this.item = item;

    this.initDiv('LargeListItem');

    this.update();

    this.fields.endlocation.innerHTML = item.endlocname;


    this.fields.gotostart.onclick = function() { item.gotoStart(); }
    this.fields.play.onclick = function() { item.startTrip(); }
    this.fields.gotoend.onclick = function() { item.gotoEnd();}

	this.item.resetTrip();

    // setup action links
    var links = item.createView('ActionLinks');
    this.div.appendChild(links.div);
}



ii.views.trip.LargeListItem.prototype = new ii.views.ListItem;

ii.views.trip.LargeListItem.prototype.fillField_postedin = function(elm)
{
    var newPostedInLinks =  ii.views.postedInLinks(this.item.postedin);
    elm.innerHTML = '';
    elm.appendChild(newPostedInLinks);
}

ii.views.trip.ActionLinks = function(item) {
    this.item = item;
    this.initDiv();

    this.div = ii.elm('div',
        ii.elm('div', {className: 'listitem_links'},
            this.postInLink(),
            ' ',
            this.postCommentLink()
        ),
        this.postCommentDiv(),
        this.postInDiv(),
        this.statusDiv()
    );

    this.update();
}

ii.views.trip.ActionLinks.prototype = new ii.views.ActionLinks;

ii.items.Trip.prototype.gotoStart = function() 
{
    // if in motion, stop animating
    if(this.playing === true){
        this.startTrip();
    }
	// show all photos
	if (this.photoQuery)
	{
		var photos = this.photoQuery.items;
		for(var n in photos) {
			photos[n].hideFromMap(false);
		}
	}

	this.resetTrip();
}

ii.items.Trip.prototype.gotoEnd = function() {
    // if in motion, stop animating
    if(this.playing === true){
        this.startTrip();
    }

    // get the last position
	this.lvp = this.trippoints.length -1;

	this.currenttime = this.trippoints[this.lvp].loctime;
    this.displayLat = this.trippoints[this.lvp].lat;
    this.displayLon = this.trippoints[this.lvp].lon;

	this.moveMarker();

	// show all photos
	if (this.photoQuery)
	{
		var photos = this.photoQuery.items;
		for(var n in photos) {
			photos[n].hideFromMap(false);
		}
	}

}

ii.views.trip.LineString = function(item,args)
{
    this.map = args.map;
    this.autoplay = args.autoplay;
    this.item = item;

    var that = this;
    var pointsRecieved = function(resp)
    {
        item.trippoints = resp.trippoints;
        that.feature = that.map.addLineString(resp.trippoints, 'tripLines');

        var ll = {}, ur = {};    // lower-left and upper-right trip coordinates
        ll.lon = ur.lon = item.trippoints[0].lon,
        ll.lat = ur.lat = item.trippoints[0].lat;
        for(var i = 1, len = item.trippoints.length; i < len; i++){
            // loop through and determine the extent of the bounding box

            var pt = {};
            pt.lon = item.trippoints[i].lon,
            pt.lat = item.trippoints[i].lat;

            if( pt.lon < ll.lon ){ ll.lon = pt.lon; }
            if( pt.lat < ll.lat ){ ll.lat = pt.lat; }
            if( pt.lon > ur.lon ){ ur.lon = pt.lon; }
            if( pt.lat > ur.lat ){ ur.lat = pt.lat; }
        }

        that.map.zoomToExtent(ll, ur);
		window.setTimeout(function() {
				ii.app.centerActiveItem();
			},0);

        if (args.autoplay)
            item.startTrip();

    }
    ii.get('q-trippoints', pointsRecieved, {tripid: item.id});
}

ii.views.trip.LineString.prototype.remove = function()
{
    if (this.feature)
        this.map.removeLineString(this.feature, 'tripLines');

    if (this.autoplay)
        this.item.startTrip();
}

ii.views.trip.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.trip.TabFeed.prototype = new ii.views.TabFeed();

ii.views.trip.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.trip.TabDetails.prototype = new ii.views.TabDetails;

ii.views.trip.TabDetails.prototype.onload = function() 
{
	this.addComments();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-trip',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}


	this.initFields();

	this.initForm('info', onsubmit);

	this.update();

}

ii.set_interval_group_albums = 25000;
ii.set_interval_group_trips = 15000;
ii.set_interval_group_photos = 15000;
ii.set_interval_group_users = 25000;
ii.set_interval_group_map_photos = 5000;
ii.set_interval_group_feed = 3000;

ii.set_groupid_world = 1;

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.group = {};

ii.items.Group = function(itm) {
	this.init(itm);

}

ii.items.Group.prototype = new ii.items.Item;


ii.views.group.ListItem = function(item)
{
	this.item = item;
	this.initDiv('ListItem');
	this.update();
	this.div.onclick = function() {
		ii.app.state.setState({item:'g.'+item.id})
	};
}
ii.views.group.ListItem.prototype = new ii.views.ListItem;


ii.views.group.LargeListItem = function(item)
{
	if (item.id == ii.set_groupid_world) // world group has no largelistitem
	{
		this.div=ii.elm('div');
		return;
	}

	this.item = item;
	this.initDiv('LargeListItem');

	// setup action links
	var links = item.createView('ActionLinks');
	this.div.appendChild(links.div);

	this.update();
}
ii.views.group.LargeListItem.prototype = new ii.views.View;

ii.views.group.ActionLinks = function(item)
{
	this.item = item;
	this.initDiv();

	this.div = ii.elm('div',
		ii.elm('div', {className: 'listitem_links'},
			this.joinLink(),
			' ',
			this.postCommentLink()
		),
		this.postCommentDiv(),
		this.statusDiv()
	);

	this.update();
}

ii.views.group.ActionLinks.prototype = new ii.views.ActionLinks;


ii.views.group.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

    var n=1;
    function ondone() { 
        ii.log('ondone');
        if (--n == 0)
            ii.app.map.viewAll();
    }

	this.addHeader( {
		type: 'photo',
		label: 'Photos',
		dataField: 'photos',
		filter: {group: this.item.id},
        ondone: ondone,
		expand: true
	});

	this.addHeader( {
		type: 'video',
		label: 'Videos',
		dataField: 'videos',
		filter: {group: this.item.id},
		expand: true
	});

	this.addHeader( {
		type: 'trip',
		label: 'Trips',
		dataField: 'trips',
		filter: {group: this.item.id}
	});

	this.addHeader( {
		type: 'user',
		label: 'Members',
		dataField: 'members',
		filter: {group: this.item.id}
	});

	this.update();


}

ii.views.group.ItemBrowser.prototype = new ii.views.ItemList;


ii.views.group.WorldItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

	if (!item.total && item.query) {
		if (item.name)
		{
			this.div.appendChild(
				ii.elm('p', {className:'results'},
					ii.elm('p', 'Searched for "'+item.query+'" within '+item.name),
					ii.elm('p', 'No results found'),
					ii.elm('p', 
						ii.elm('a', {href:'#query='+item.query},
						'Search within World'))));
		}
		else
		{
			this.div.appendChild(
				ii.elm('p', {className:'results'},
					ii.elm('p', 'Searched for "'+item.query+'" within World'),
					ii.elm('p', 'No results found')))
		}

	}


	/*
	if (args.query)
		this.div.appendChild(ii.elm('p', 'Search result'));
	*/
	this.addSearchHeader(args.query);

	this.addHeader( {
		type: 'user',
		label: 'People',
		dataField: 'users',
		filter: args.params,
		expand: true
	});

	this.addHeader( {
		type: 'photo',
		label: 'Photos',
		dataField: 'photos',
		filter: args.params,
		expand: true
	});

	this.addHeader( {
		type: 'video',
		label: 'Videos',
		dataField: 'videos',
		filter: args.params,
		expand: true
	});


	this.addHeader( {
		type: 'trip',
		label: 'Trips',
		dataField: 'trips',
		filter: args.params
	});

	this.addHeader( {
		type: 'spot',
		label: 'Spots',
		dataField: 'spots',
		filter: args.params
	});

	this.addHeader( {
		type: 'group',
		label: 'Groups',
		dataField: 'groups',
		filter: args.params
	});


	this.update();

}

ii.views.group.WorldItemBrowser.prototype = new ii.views.ItemList;

ii.views.group.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.group.TabFeed.prototype = new ii.views.TabFeed();


ii.views.group.TabDetails = function(item, args)
{
	this.item = item;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.group.TabDetails.prototype = new ii.views.TabDetails;

ii.views.group.TabDetails.prototype.onload = function() 
{
	this.addComments();
	this.addPhotos();
	this.addVideos();
	this.addUsers();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-set',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}

	this.initFields();

	this.initForm('info', onsubmit);

	this.update();

}

ii.set_interval_spot_albums = 15000;
ii.set_interval_spot_photos = 15000;
ii.set_interval_spot_trips = 15000;
ii.set_interval_spot_users = 15000;
ii.set_interval_spot_feed = 3000;


ii.assert(ii.items);
ii.assert(ii.views);

ii.views.spot = {};

ii.items.Spot = function(itm) {
	this.init(itm);

}


ii.items.Spot.prototype = new ii.items.Item;


ii.views.spot.ListItem = function(item, args)
{
	this.item = item;
	this.initDiv('ListItem');
	this.update();

    var that = this;
    if (args && args.onclick)
        this.div.onclick = function() {
            ii.log('calling custom onclick message');
            args.onclick(that);
        }
    else
        this.div.onclick = function() {
            ii.app.state.setState({item:'s.'+item.id})
        };
}


ii.views.spot.ListItem.prototype = new ii.views.ListItem;


ii.views.spot.LargeListItem = function(item)
{
	if (item.id==1) // world spot has no largelistitem
	{
		this.div=ii.elm('div');
		return;
	}

	this.item = item;
	this.initDiv('LargeListItem');

	// setup action links
	var links = item.createView('ActionLinks');
	this.div.appendChild(links.div);

	this.update();
}
ii.views.spot.LargeListItem.prototype = new ii.views.View;

ii.views.spot.ActionLinks = function(item)
{
	this.item = item;
	this.initDiv();

	this.div = ii.elm('div',
		ii.elm('div', {className: 'listitem_links'},
			this.joinLink(),
            ' ',
            this.visitLink(),
			' ',
			this.postCommentLink()
		),
		this.postCommentDiv(),
		this.statusDiv()
	);

	this.update();
}

ii.views.spot.ActionLinks.prototype = new ii.views.ActionLinks;

ii.views.spot.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

	this.addHeader( {
		type: 'photo',
		label: 'Photos',
		dataField: 'photos',
		filter: {spot: this.item.id},
		expand: true
	});

	this.addHeader( {
		type: 'video',
		label: 'Videos',
		dataField: 'videos',
		filter: {spot: this.item.id}
	});

	this.addHeader( {
		type: 'trip',
		label: 'Trips',
		dataField: 'trips',
		filter: {spot: this.item.id}
	});

	this.addHeader( {
		type: 'user',
		label: 'Members',
		dataField: 'members',
		filter: {spot: this.item.id}
	});

	this.update();

}

ii.views.spot.ItemBrowser.prototype = new ii.views.ItemList;

/* creates an icon for this item */
ii.views.spot.Icon = function(item, args)
{
	if (!args || !args.map)
		ii.error('Icon should have map');

	this.item = item;
	this.map = args.map;
	var iconurl = {url:'media/spot_map_large.png'};

	this.div = ii.elm(
		'div',
		{className:'marker'},
		ii.elm('img', {src: iconurl.url})
	);

	this.div.onclick = function() { item.popupAlwaysVisible = true; item.onmouseover(); }


	this.addToMap('spotIcons', -23, -58);
	this.addShadowToMap('spot_shadow_large.png', 59, 22, -7, -22);

}
ii.views.spot.Icon.prototype = new ii.views.Mappable;


ii.views.spot.IconPopup = function(item, args)
{
	this.item = item;
	this.map = args.map;
	if (item.popupAlwaysVisible == undefined)
		item.popupAlwaysVisible = args.alwaysVisible;

	this.visitors = ii.elm('span', ''+item.visitors);

	var divbg = ii.pngImage('spot_balloon.png', 208, 111);
	divbg.className = 'bg';
	var that = this;
	this.div = ii.elm('div',
		{className: 'spot iconpopup marker'},
		divbg,
		ii.elm('div',
			{className: 'content'},
			ii.elm('div',
				ii.elm('label', 'name: '),
				ii.spotLink(item.id, item.name)),
			ii.elm('div',
				ii.elm('label', 'owner: '),
				ii.userLink(item.userid, item.author)),
			ii.elm('div',
				ii.elm('label', 'visitors: '),
				this.visitors)
		),
		ii.elm('img',
			{className: 'button',
			style: {left: '185px', top: '77px' },
			src:'media/poi_zoom_smll.png',
			onmouseover: ii.onmouseoverbtn,
			onmouseout: ii.onmouseoutbtn,
			onclick: function(){ args.map.zoomTo(item.lat, item.lon, 50, 0); }
			}
		),
		ii.elm('img',
			{className: 'button',
			style: {left:'185px',top:'5px'},
			src:'media/button_userpop_close.png',
			onmouseover: ii.onmouseoverbtn,
			onmouseout: ii.onmouseoutbtn,
			onclick: function(){ item.popupAlwaysVisible = false; that.div.style.visibility='hidden';}
			}
		)

	);

	this.shadowDiv = ii.pngImage('spot_balloon_shadow.png', 273, 67);
	this.shadowDiv.className = 'marker shadow';

	this.shadowMarker = args.map.addMarker(this.shadowDiv, 'shadows',
			item.lat, item.lon,
			6,
			-125);

	this.div.onmouseover = function() { item.onmouseover(); }
	this.div.onmouseout = function(){ item.onmouseout(); };

	// start hidden
	this.onmouseout();

	this.marker = args.map.addMarker(this.div, 'spotPopups',
			item.lat, item.lon,
			3,
			-172);

}

ii.views.spot.IconPopup.prototype.update = function()
{
	this.visitors.textContent = ''+this.item.visitors;
}

ii.views.spot.IconPopup.prototype.onmouseout = function()
{
	this.div.style.visibility =
		this.shadowDiv.style.visibility = (this.item.popupAlwaysVisible ? '' : 'hidden');

}

ii.views.spot.IconPopup.prototype.onmouseover = function()
{
	this.div.style.visibility =
		this.shadowDiv.style.visibility = '';
}

ii.views.spot.IconPopup.prototype.remove = function()
{
	this.map.removeMarker(this.marker,'userPopups');
	this.shadowDiv.parentNode.removeChild(this.shadowDiv);
	this.map.removeMarker(this.shadowMarker,'shadows');
}

ii.views.spot.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.spot.TabDetails.prototype = new ii.views.TabDetails;

ii.views.spot.TabDetails.prototype.onload = function()
{
	this.addComments();
	this.addPhotos();
	this.addUsers();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-set',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}

	this.initFields();
	this.initForm('info', onsubmit);
	this.update();
}

ii.views.spot.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.spot.TabFeed.prototype = new ii.views.TabFeed();


ii.set_interval_album_photos = 20000;
ii.set_interval_album_trips = 20000;
ii.set_interval_album_feed = 3000;

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.album = {};

ii.items.Album = function(itm) {
	this.init(itm);
}

ii.items.Album.prototype = new ii.items.Item;

ii.views.album.ListItem = function(item, args)
{
	this.item = item;
	this.initDiv('ListItem');
	this.update();

	this.div.onclick = function() {
		ii.app.state.setState({item:'a.'+item.id})
	};
}

ii.views.album.ListItem.prototype = new ii.views.ListItem;


ii.views.album.LargeListItem = function(item)
{
	this.item = item;
	this.initDiv('LargeListItem');
	this.update();
}
ii.views.album.LargeListItem.prototype = new ii.views.View;


ii.views.album.ItemBrowser = function(item, args)
{
	this.item = item;
	this.map = args.map;
	this.queries = [];

	this.initDiv('ItemList');

	this.addHeader( {
		type: 'photo',
		label: 'Photos',
		dataField: 'photos',
		filter: {album: this.item.id},
		expand: true
	});

	this.addHeader( {
		type: 'video',
		label: 'Videos',
		dataField: 'videos',
		filter: {album: this.item.id}
	});

	this.addHeader( {
		type: 'trip',
		label: 'Trips',
		dataField: 'trips',
		filter: {album: this.item.id}
	});

	this.update();

}

ii.views.album.ItemBrowser.prototype = new ii.views.ItemList;


ii.views.album.TabDetails = function(item, args)
{
	this.item = item;
	var that = this;
	this.queries = [];
	this.initDiv('TabDetails');
}

ii.views.album.TabDetails.prototype = new ii.views.TabDetails;

ii.views.album.TabDetails.prototype.onload = function() {
	this.addComments();
	this.addPhotos();
	this.addVideos();

    var that = this;
	function onsubmit()
	{
		var form = this;

        ii.startWaitButton(that.fields.info_submitbtn);

		var params = {
			id: that.item.id,
			name: this.name.value,
			description: this.description.value
		}
		ii.get('p-upd-set',
			function(resp) {
                ii.endWaitButton(that.fields.info_submitbtn);
				that.setEditMode(form, false);
				that.item.name = params.name;
				that.item.description = params.description;
				that.item.update();
			},
			params
		);

		return false;
	}


	this.initFields();

	this.initForm('info', onsubmit);

	this.update();
}


ii.views.album.TabFeed = function(item)
{
    this.item = item;
	this.queries = [];
    this.initDiv('TabFeed');
    this.initFeed();

}

ii.views.album.TabFeed.prototype = new ii.views.TabFeed();


ii.assert(ii.items);
ii.assert(ii.views);

ii.views.thread = {};

ii.items.Thread = function(itm) {
	this.init(itm)
}

ii.items.Thread.prototype = new ii.items.Item;

ii.views.thread.TabView = function(item, args) {

	this.item = item;
	this.initDiv('TabView');
    this.div.style.display = 'none'; // we'll unhide if there's actual content
	var div = this.div;

	div.style.display = '';
	//options
	args = args || {};
    this.options = args;
    this.options.deleteMethod = this.options.deleteMethod || 'delete';

	if (this.options.startCollapsed)
		div.className = div.className.replace('expanded', 'collapsed');


	ii.setText(this.fields.headertext, args.title || 'Conversation with ' + this.item.name);
	//if (!args.title)
	this.fields.headertext.className = 'inbox_hdr ' + item.entitytype;

	if (div.className.indexOf('expanded')>=0)
	{
		this.loaded = true;
		this.loadComments();
	}

	if (!ii.login)
        this.div.className += ' nologin';

	if (this.options.addLink) {
		this.fields['comment-link'].href = '#rel&item='
			+ii.typeletter[this.item.entitytype]
			+'.'+this.item.entityid;
		this.fields['comment-thumb'].src = '/srv/d-media.php'
							+ '?entitytype=' + this.item.entitytype
							+ '&entityid=' + this.item.entityid
							+ '&width=64&height=48'
							+ '&style=center';
	}

    ii.setDefaultText(ii.getElmByName(this.fields.addmessage, 'cont'),
        this.item.entitytype=='user' ? 'Enter a message' : 'Enter a comment');

	this.fields.addmessage.submit.value = (this.item.entitytype == 'user' 
			? 'Send message' : 'Post comment');

    var that = this;
	this.fields.addmessage.onsubmit = function()
    {
        if (ii.getTextBoxValue(ii.getElmByName(this,'cont'))=='')
            return false; // need to inform user?
        ii.startWaitButton(ii.getElmByName(this,'submit'));

        var form = this;

		var entitytype = item.entitytype.replace(
			/photo|youtube/, 'poi');

        ii.get('p-new-comment',
            function(resp)
            {
                ii.endWaitButton(ii.getElmByName(form, 'submit'));
                ii.setDefaultText(ii.getElmByName(form, 'cont'),
                    ii.getElmByName(form, 'cont').defaultText);
                that.queries[0].start();
            },
            {
                entitytype: entitytype,
                entityid: item.entityid,
                content: ii.getElmByName(form, 'cont').value
            }
        );

		return false;
	}

	for (var n=1;n<=2; n++)
	{
		if (!ii.login)
			this.fields['actions'+n].style.display='none';
		else
		{
			var actions = this.fields['actions'+n].getElementsByTagName('a');
			actions[0].onclick = function() { that.selectAll() };
			actions[1].onclick = function() { that.deselectAll() };
			actions[2].onclick = function() { that.markAsRead() };
			actions[3].onclick = function() { that.deleteSelected() };
		}
	}

	// collapse/expand handler
	this.fields.header.onclick = function() {
		div.className = div.className.replace('expanded','swapcollapse')
			.replace('collapsed','expanded')
			.replace('swapcollapse', 'collapsed');
		if (div.className.match(/expanded/)) 
		{
			ii.inboxExpand[item.entitytype+'.'+item.entityid] = true;
		}
		else
			ii.inboxExpand[item.entitytype+'.'+item.entityid] = false;
		if (!that.loaded)
		{
			that.loadComments();
			that.loaded = true;
		}
	};
	ii.inboxExpand = ii.inboxExpand || {};
	if (ii.inboxExpand[item.entitytype+'.'+item.entityid])
		this.fields.header.onclick();

	this.update();
}


ii.views.thread.TabView.prototype = new ii.views.View;

ii.views.thread.TabView.prototype.fillField_count = function(elm)
{
	ii.setText(elm, ' ('+this.item.count + ')');
}

ii.views.thread.TabView.prototype.fillField_unread = function(elm)
{
	ii.setText(elm, this.item.unread);
	elm.style.display = (this.item.unread>0 ? '' : 'none');
	ii.log('updating isread...');
}

ii.views.thread.TabView.prototype.getIdList = function()
{
	var ids;
	var cps = this.fields.commentlist.getElementsByTagName('input');
	for(var n=0; n < cps.length; n++)
	{
		if (cps[n].type=='checkbox' && cps[n].checked)
		{
			ids = (ids ? ids + ','+cps[n].value : cps[n].value);
		}
	}
	return ids;
}

ii.views.thread.TabView.prototype.selectAll = function(elm)
{
	var cps = this.fields.commentlist.getElementsByTagName('input');
	for(var n=0; n <cps.length; n++)
	{
		if (cps[n].type=='checkbox')
		{
			cps[n].checked='checked';
			cps[n].onclick();
		}
	}
}

ii.views.thread.TabView.prototype.deselectAll = function(elm)
{
	var cps = this.fields.commentlist.getElementsByTagName('input');
	for(var n=0; n <cps.length; n++)
	{
		if (cps[n].type=='checkbox')
		{
			cps[n].checked='';
			cps[n].onclick();
		}
	}
}

ii.views.thread.TabView.prototype.markAsRead = function(elm)
{
	var ids = this.getIdList();
    var that = this;
	if (!ids)
	{
		alert('Please check the Messages you wish to mark as read');
		return;
	}

	ii.get('p-upd-markasread',
		function(resp){
			//options.onUpdate();
			that.deselectAll();
            that.queries[0].doUpdate();
			that.item.modified = 0;
			if (that.options.parentQuery) that.options.parentQuery.doUpdate();
			ii.login.query.doUpdate();
		},
		{
			id:ids
		}
	);

}

ii.views.thread.TabView.prototype.deleteSelected = function()
{
	var ids = this.getIdList();
    var that = this;
	if (!ids)
	{
		alert('Please check the Messages you wish to delete');
		return;
	}
	ii.get('p-del-comment',
		function(resp){
			var cnt = ids.split(',').length;
			var del = resp.deleted.length;
			if (del < cnt)
			{
				alert(''+(cnt-del)+' comment' + (cnt-del>1?'s':'')
					+' could not be deleted'
					+' because of insufficient permissions');
			}
//			options.onUpdate();
            that.queries[0].doUpdate();
			that.item.modified = 0;
			if (that.options.parentQuery) that.options.parentQuery.doUpdate();
			ii.login.query.doUpdate();
		},
		{
			id: ids
            , method: this.options.deleteMethod
		}
	);
}

ii.views.thread.TabView.prototype.loadComments = function()
{
	var opts = {count:100};
	var entitytype = this.item.entitytype.replace(
			/photo|youtube/, 'poi');

	opts[entitytype] = this.item.entityid;
	var query = new ii.Query('comment', {interval:10000}, opts);
    var that = this;

	var div = this.fields.commentlist;
	query.addListener({ addItem: function(item) {
		var view = item.createView('ListItem', {userid:(ii.login?ii.login.id:0)});
		div.insertBefore(view.div, div.firstChild);
	}, countItems: function(n,m,count) {
        if (count || ii.login)
            that.div.style.display = '';
		that.fields.loading.style.display = 'none';
		if (count)
		{
			that.fields.actions1.style.display = '';
			that.fields.actions2.style.display = '';
		}
    }}
    );

	query.start();
    this.queries = [query];
}


/* local settings */


ii.assert(ii.items);
ii.assert(ii.views);


ii.views.comment = {};


ii.items.Comment = function(itm) {

	this.init(itm);
};

ii.items.Comment.prototype = new ii.items.Item;

// fills an element with the content of a comment, while respecting links
ii.items.Comment.prototype.fillCommentContent = function(elm)
{
    ii.text2href(this.content, elm);
};


ii.views.comment.TabView = function(item)
{
	var content = ii.elm('p', {className: 'content'});
	item.fillCommentContent(content);
	this.div = ii.elm(
		'div',
		{className:'comment tabview'},
		content,
		ii.elm('img', {style:{cssFloat:'left'}, alt:'photo', src:'/srv/d-media.php?width=32&height=24&entitytype=user&entityid=' + item.userid}),

		ii.elm('p', {className: 'details'},
			ii.elm('p',
				ii.elm('span', {className: 'field'}, 'posted by: '),
				ii.userLink(item.userid, item.author)
			),
			ii.elm('p', {className: 'field'}, ii.formatDate(item.created,'relative'))
		),

		ii.elm('hr')
	);


	this.div.onmouseover = function(){item.onmouseover(); };
	this.div.onmouseout = function(){item.onmouseout(); };


};

ii.views.comment.ListItem = function(item, args)
{
	this.item = item;

	this.initDiv('ListItem');



	var userid = args.userid; // the user owning the entity

	var direction = ((ii.login && ii.login.id == item.userid) ? 'fromme' : 'tome');

	var checkvisible = (ii.login && (ii.login.id == userid
						|| ii.login.id == item.userid));

	var contentClassName = 'msgcontent ' + (item.status == '' ? 'unreadmsg' : 'readmsg');

	function checkChanged()
	{
		// check if Select All or Deselect All must be displayed
		// we must find the parent...
		var cont = this.parentNode.parentNode; // the container

		var cps = cont.getElementsByTagName('input');
		var allChecked = true;
		for(var n=0; n <cps.length; n++)
		{
			if (cps[n].type=='checkbox')
			{
				if (!cps[n].checked)
					allChecked = false;
			}
		}
		var anchors = cont.getElementsByTagName('a');
		for(var n=0; n < anchors.length; n++)
		{
			if (anchors[n].className == 'selectall')
				anchors[n].style.display = (allChecked ? 'none' : '');
			else if (anchors[n].className == 'deselectall')
				anchors[n].style.display = (allChecked ? '' : 'none');
		}
	}

    this.fields.check.onclick = checkChanged;
    this.fields.check.value = this.item.id;

	this.update();
	return;
};

ii.views.comment.ListItem.prototype = new ii.views.View;

ii.views.comment.ListItem.prototype.fillField_check = function(elm) 
{

	this.isunread = (this.item.status == ''); //remember read-state for update check
	ii.log('set unread: '+this.isunread);
    if (this.isunread)
        this.fields.content.className = 
            this.fields.content.className.replace('readmsg','unreadmsg');
    else
        this.fields.content.className = 'msgcontent readmsg';
};

/*
ii.views.comment.ListItem.prototype.update = function()
{
	// check if this is now read
	if (this.item.status != '' && this.isunread)
	{
		this.isunread = false;
		this.content.className = 'readmsg';

		// notify overridable method for counter decrease
		if (this.markAsRead)
			this.markAsRead();
	}
}*/

ii.assert(ii.items);
ii.assert(ii.views);

ii.views.feed = {};


/* feed constructor */
ii.items.Feed = function(itm) {

	this.init(itm);

}

ii.items.Feed.prototype = new ii.items.Item;


ii.views.feed.SmallView = function(item)
{
	var item_text;
	switch(item.feedtype+'.'+item.entitytype1+'.'+item.entitytype2)
	{
        case 'islive..':

            item_text = ii.elm('span',
					' is ',
					ii.elm('span', {className:'live'}, 'Live!')
			);
            break;

		case 'atspot.spot.':
			item_text = ii.elm('span', ' visits Spot: ',
					ii.spotLink(item.entityid1, item.content));
			break;

		case 'updatepic..':
            item_text = ii.elm('span', ' updates profile picture');
			break;

        case 'add..':
            item_text = ' signed up';
            break;

        case 'add.comment.':
            item_text = ' updates Status message: ' + item.content;
            break;

		case 'add.user.':
			item_text = ii.elm('span',
					' adds ',
					ii.userLink(item.entityid1, item.content),
					' as Friend');
			break;

		case 'remove.user.':
			item_text = ii.elm('span',
					' drops ',
					ii.userLink(item.entityid1, item.content),
					' as Friend');
			break;

        case 'add.photo.':
        case 'add.poi.':
            item_text = ii.elm('span',
					' posts Photo: ',
					ii.poiLink(item.entityid1, item.content));
            break;

        case 'add.video.':
            item_text = ii.elm('span',
					' posts Video: ',
					ii.videoLink(item.entityid1, item.content));
            break;

        case 'add.trip.':
            item_text = ii.elm('span',
					' posts Trip: ',
					ii.tripLink(item.entityid1, item.content));
            break;

        case 'add.spot.':
            item_text = ii.elm('span',
					' posts Spot: ',
					ii.spotLink(item.entityid1, item.content));
			break;

        case 'add.album.':
            item_text = ii.elm('span',
					' posts Album: ', 
					ii.albumLink(item.entityid1, item.content));
			break;

        case 'add.group.':
            item_text = ii.elm('span',
					' posts Group: ',
					ii.groupLink(item.entityid1, item.content));

			break;

		case 'add.poi.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.poiLink(item.entityid1, 'Photo'),
					' Comment: ',
					cnt);
            break;

		case 'add.video.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.videoLink(item.entityid1, 'Video'),
					' Comment: ',
					cnt);
            break;
		case 'add.trip.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.tripLink(item.entityid1, 'Trip'),
					' Comment: ',
					cnt);
            break;

		case 'add.spot.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.spotLink(item.entityid1, 'Spot'),
					' Comment: ',
					cnt);
            break;

		case 'add.album.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.albumLink(item.entityid1, 'album'),
					' Comment: ',
					cnt);
            break;

		case 'add.group.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.groupLink(item.entityid1, 'Group'),
					' Comment: ',
					cnt);
            break;

		case 'add.poi.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.video.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Video: ',
					ii.videoLink(item.entityid1, item.content));

			break;


		case 'add.poi.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;

		case 'add.video.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Video: ',
					ii.videoLink(item.entityid1, item.content));

			break;
		case 'add.poi.trip':
			item_text = ii.elm('span',
					' posts ',
					ii.tripLink(item.entityid2, 'Trip'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.poi.album':
			item_text = ii.elm('span',
					' posts ',
					ii.albumLink(item.entityid2, 'Album'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.trip.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.trip.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.trip.album':
			item_text = ii.elm('span',
					' posts ',
					ii.albumLink(item.entityid2, 'Album'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.user.group':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' joins Group: ',
					ii.elm('a', {href:img_href}, item.content));
			break;

		case 'remove.user.group':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' leaves Group: ',
					ii.elm('a', {href:img_href}, item.content));

			break;

		case 'add.user.spot':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' joins Spot: ',
					ii.elm('a', {href:img_href}, item.content));

			break;

		case 'remove.user.spot':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' leaves Spot: ',
					ii.elm('a', {href:img_href}, item.content));

			break;

		default:
			item_text = ii.elm('div', ' err. unknown item in feed: ' + item.feedtype+'.'+item.entitytype1+'.'+item.entitytype2);
			break;
	}

	this.div = ii.elm('div',
			ii.userLink(item.userid, item.username),
			item_text);

    //this.div.onmouseover = function(){item.onmouseover()};
	//this.div.onmouseout = function(){item.onmouseout()};
}

ii.views.feed.ListItem = function(item, options)
{
    var options = options || {};

    // default text to display with the item
    var item_text = item_location = '';

    // show the item message box
    var show_message_box = false;

    // an object that will be used to hold parameters passed to the image
    // rendering scripts
	var img_qs_obj = {
		height:112,
		width: 150,
		style: 'center'

	}

    // default location of the image rendering script
    var img_src = '/srv/d-media.php?';
	var img_href;

	switch(item.feedtype+'.'+item.entitytype1+'.'+item.entitytype2)
	{
        case 'islive..':

            item_text = ii.elm('span',
					' is ',
					ii.elm('span', {className:'live'}, 'Live!'),
					' near: ',
					item.locname);

            //show_message_box = true;

            img_src = '/srv/d-staticmap.php?';

            img_qs_obj.userlat  = item.lat;
            img_qs_obj.userlon  = item.lon;
            img_qs_obj.type = 'live-map';

			img_href = '#rel&item=u.'+item.userid;

            break;

		case 'atspot.spot.':
			item_text = ii.elm('span', ' visits Spot: ',
					ii.spotLink(item.entityid1, item.content));
			break;

		case 'updatepic..':
            item_text = ii.elm('span', ' updates profile picture');

            //show_message_box = true;

            img_src = '/srv/d-staticmap.php?';

            img_qs_obj.userlat  = item.lat;
            img_qs_obj.userlon  = item.lon;
            img_qs_obj.type = 'live-map';

			img_href = '#rel&item=u.'+item.userid;
			break;
        case 'add..':

            item_text = ii.elm('span',
					' signed up near: ',
					item.locname);

            show_message_box = true;

            img_src = '/srv/d-staticmap.php?';

            img_qs_obj.userlat  = item.lat;
            img_qs_obj.userlon  = item.lon;
            img_qs_obj.type = 'live-map';
			img_href = '#rel&item=u.'+item.userid;

            break;
        case 'add.comment.':

            item_text = ' updates Status message:';

            show_message_box = true;

            img_src = '/srv/d-staticmap.php?';

            img_qs_obj.userlat  = item.lat;
            img_qs_obj.userlon  = item.lon;
            img_qs_obj.type = 'live-map';
			img_href = '#rel&item=u.'+item.userid;

            break;

		case 'add.user.':
			item_text = ii.elm('span',
					' adds ',
					ii.userLink(item.entityid1, item.content),
					' as Friend');
			break;

		case 'remove.user.':
			item_text = ii.elm('span',
					' drops ',
					ii.userLink(item.entityid1, item.content),
					' as Friend');
			break;

        case 'add.photo.':
        case 'add.poi.':
            item_text = ii.elm('span',
					' posts Photo: ',
					ii.poiLink(item.entityid1, item.content),
					' near ',
					item.locname);
            break;
        case 'add.video.':
            item_text = ii.elm('span',
					' posts Video: ',
					ii.videoLink(item.entityid1, item.content),
					' near ',
					item.locname);
            break;
        case 'add.trip.':

            item_text = ii.elm('span',
					' posts Trip: ',
					ii.tripLink(item.entityid1, item.content),
					' near ',
					item.locname);

            break;

        case 'add.spot.':
            item_text = ii.elm('span',
					' posts Spot: ',
					ii.spotLink(item.entityid1, item.content),
					' near ',
					item.locname);

			break;

        case 'add.album.':
            item_text = ii.elm('span',
					' posts Album: ',
					ii.albumLink(item.entityid1, item.content));

			break;

        case 'add.group.':
            item_text = ii.elm('span',
					' posts Group: ',
					ii.groupLink(item.entityid1, item.content));

			break;

		case 'add.poi.comment':
		case 'add.photo.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.poiLink(item.entityid1, 'Photo'),
					' Comment: ',
					cnt);

            img_qs_obj.marker     = 'commentcount';
			img_href = '#rel&item=p.'+item.entityid1;
            break;

		case 'add.video.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.videoLink(item.entityid1, 'Video'),
					' Comment: ',
					cnt);

            img_qs_obj.marker     = 'commentcount';
			img_href = '#rel&item=v.'+item.entityid1;
            break;

		case 'add.trip.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.tripLink(item.entityid1, 'Trip'),
					' Comment: ',
					cnt);

            break;
		case 'add.spot.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.spotLink(item.entityid1, 'Spot'),
					' Comment: ',
					cnt);

            break;
		case 'add.group.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.groupLink(item.entityid1, 'Group'),
					' Comment: ',
					cnt);

            break;

		case 'add.album.comment':
			var cnt = ii.elm('span', {style:{fontStyle:'italic'}});
			ii.text2href(item.content,cnt);
            item_text = ii.elm(
					'span',
					' posts ',
					ii.albumLink(item.entityid1, 'Album'),
					' Comment: ',
					cnt);

            break;

		case 'add.photo.group':
		case 'add.poi.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;

		case 'add.video.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Video: ',
					ii.videoLink(item.entityid1, item.content));

			break;

		case 'add.photo.spot':
		case 'add.poi.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.video.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Video: ',
					ii.videoLink(item.entityid1, item.content));

			break;
		case 'add.poi.trip':
			item_text = ii.elm('span',
					' posts ',
					ii.tripLink(item.entityid2, 'Trip'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.poi.album':
			item_text = ii.elm('span',
					' posts ',
					ii.albumLink(item.entityid2, 'Album'),
					' Photo: ',
					ii.poiLink(item.entityid1, item.content));

			break;
		case 'add.trip.spot':
			item_text = ii.elm('span',
					' posts ',
					ii.spotLink(item.entityid2, 'Spot'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.trip.group':
			item_text = ii.elm('span',
					' posts ',
					ii.groupLink(item.entityid2, 'Group'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.trip.album':
			item_text = ii.elm('span',
					' posts ',
					ii.albumLink(item.entityid2, 'Album'),
					' Trip: ',
					ii.tripLink(item.entityid1, item.content));

			break;
		case 'add.user.group':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' joins Group: ',
					ii.elm('a', {href:img_href}, item.content));

			img_qs_obj.entitytype = item.entitytype2;
			img_qs_obj.entityid = item.entityid2;
			break;

		case 'remove.user.group':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' leaves Group: ',
					ii.elm('a', {href:img_href}, item.content));

			img_qs_obj.entitytype = item.entitytype2;
			img_qs_obj.entityid = item.entityid2;
			break;

		case 'add.user.spot':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' joins Spot: ',
					ii.elm('a', {href:img_href}, item.content));

			img_qs_obj.entitytype = item.entitytype2;
			img_qs_obj.entityid = item.entityid2;
			break;

		case 'remove.user.spot':
			// in this case we need second entitytype as img
			var img_href = '#rel&item='
				+ii.typeletter[item.entitytype2]
				+'.'
				+item.entityid2;

			item_text = ii.elm('span',
					' leaves Spot: ',
					ii.elm('a', {href:img_href}, item.content));

			img_qs_obj.entitytype = item.entitytype2;
			img_qs_obj.entityid = item.entityid2;
			break;
		default:

            item_location = item.locname;

            item_text = item.feedtype+'.'+item.entitytype1+'.'+item.entitytype2+':';

			img_qs_obj.entitytype = 'poi';
    		img_qs_obj.entityid   = item.entityid2;
            img_qs_obj.marker     = 'commentcount';

			break;
	}


	// the avatar
    var avatar_qs  = ii.encode_query_string({entityid:item.userid, entitytype:'user', height:'45', width:'60'});
	var avatar_img = ii.elm('img', {alt:'avatar', src:'/srv/d-media.php?'+avatar_qs, style:{height:'45px', width:'60px'}});
    var avatar_img_link = ii.elm('a', {href: '#rel&item=u.'+item.userid}, avatar_img);

    if(options.onAvatarClick){
        avatar_img_link.onclick = function(){
            options.onAvatarClick();
        }
    }

	var avatar_container = ii.elm('div', {style:{cssFloat:'left', margin:'0px 5px 5px 0px', width:'60px'}}, avatar_img_link);


	// default link for big img is entity1
	if (!img_href)
	{
		var img_href = '#rel&item='
				+ii.typeletter[item.entitytype1]
				+'.'
				+item.entityid1;
	}

	// default bigimg = entitytype1
	if (!img_qs_obj.entitytype)
	{
		img_qs_obj.entitytype = item.entitytype1;
		img_qs_obj.entityid = item.entityid1;
	}


	var qs       = ii.encode_query_string(img_qs_obj);

    // the default big img
    var img      = ii.elm('img', {src:img_src+qs, align:'right'});
	var img_link = ii.elm('a', {href:img_href}, img);


    if(options.onItemClick){
        img_link.onclick = function(){
            options.onItemClick();
        }
    }

    var img_div = ii.elm('div', {style:{cssFloat:'right', padding: '0px 0px 5px 5px', width:img_qs_obj.width+'px'}},img_link);

    // the text content
	var metadata_date_text = ii.elm('p', {className:'feed_metadata_date', style:{margin:'0px',padding:'0px'}}, ii.formatDate(item.created, 'relative'));
	var username_link = ii.elm('a', {href:'#rel&item=u.'+item.userid}, item.username);

    if(options.onUserNameClick){
        username_link.onclick = function(){
            options.onUserNameClick();
        }
    }

    var content_div_width = (390 - img_qs_obj.width - 5) + 'px'; // parentnode width - image width - image padding + 'px'
    var content_div = ii.elm('div', {className:'feed_content', style:{margin: '0px',padding: '0px', width:content_div_width}}, metadata_date_text, username_link, item_text || '');

    // bring the img and text content together into a div.
    var content_and_img_div = ii.elm('div', {
            style:{
                clear: 'right',
                width: '390px',
                left: '0px',
                marginLeft: '65px',
                position: 'absolute',
                top: '15px'
            }
        },
        img_div,
        content_div
    );

    // the beautiful status message
    var message_box = '';
    if(show_message_box && item.content){
        message_box = ii.getMessageBox({
                message: item.content,
                disabled: true
        });

        //message_box.style.position = 'absolute';
        //message_box.style.bottom   = '17px';
        //message_box.style.left     = '0px';
    }

    // the div that holds the entire item
	this.div = ii.elm('div', {
            style:{
                borderBottom:'solid 1px #b7b7b7', minHeight:'112px', padding:'15px 0px', position:'relative', width:'100%'
            }
        },
        avatar_container,
        content_and_img_div,
        message_box
    );

    this.div.onmouseover = function() { item.onmouseover(); };
    this.div.onmouseout  = function() { item.onmouseout(); };

}


ii.views.feed.ListItem.prototype.onmouseover = function(){
    this.div.style.backgroundColor = '#d2e2f6';//'rgba(128, 176, 225, 0.35)';
}

ii.views.feed.ListItem.prototype.onmouseout = function(){
    this.div.style.backgroundColor = '';
}



ii.views.feed.query = function(){




}

