/*
						VS CLASS																	        
														
*/

const DET_X 	= 10;
const DET_Y 	= 10;
const DET_ID	= false;
const ANI   	 = 500;
const RES    	= 3*16;


/* set variables and objects,  start init of VS */	
function VS()
{	
	this.base				= window.location.href.split("explore")[0];
	this.params			  = [];
	this.paramsString = "";
	this.paramsStringUrl = "";

	this.Query 			= new Query();
	this.Collection	= new Collection();
	this.DateVis 		= new DateVis();
	this.MapVis 		= new MapVis();
	this.TagVis 		= new TagVis();
	this.ResultVis 	= new ResultVis();
	
	this.counts =  [];
	this.dates =   [];
	this.results = [];

	this.x = 0;
	this.y = 0;

	this.checkParams = ""; /*  interval for address change check  */	
	
	/*  log times  */
	this.times = [-1,-1];
	this.delays = [-1,-1];
}

/* start initial methods for params and visgets */
VS.prototype.init = function()
{
	var hash = window.location.hash;
	var bool = true; if (hash==="") bool = false;
	
	this.params = this.parseParams(hash.split("#")[1]);
	this.setParamsString(bool);

	this.loading(true);	
	this.load();
	
	/*  show about screen  */
	if (this.params.a==1) this.about(true, true);
	else $("#about_link").click(function(){VS.about(true, false	);});	
	
	/*  init visgets  */
	this.Query.init();
	this.Collection.init();
	this.DateVis.init();
	this.MapVis.init();
	this.ResultVis.init();
	/*  for TagVis not necessary  */
	
	this.writeTitleString();
	
	/* save mouse position for details */
	$(document).bind("mousemove", function(e)
	{
		VS.x=e.pageX; VS.y=e.pageY;
		if (VS.ResultVis.detail>=0) VS.ResultVis.moveDetail();
	});
	
	this.checkParams = window.setInterval(VS.checkParamsHash, 500);
}

VS.prototype.load = function()
{
	this.loading(true);
	
	$.getJSON(
		VS.base+"feeds/getAll/"+VS.paramsString+VS.ResultVis.getIdsString()+"/log:"+VS.delays[0]+","+VS.delays[1],
		function(response, textStatus)
		{
			if (textStatus=="success")
			{
				var now = new Date();
				VS.times[1] = Date.parse(now)/1000+now.getMilliseconds()/1000;
				
				if (response!==null)
				{
					VS.dates = response.dates;
					VS.counts = response.counts;	
					VS.results = response.results;
					VS.total = response.total;

					VS.ResultVis.load();
					VS.TagVis.load();

					VS.DateVis.load();
					VS.MapVis.load();
				}

				VS.loading(false);
			}
			else
			{
				VS.loading(false);
				alert("There was an error when receiving data from server");
			}
		});
}

/* parse and verify params from paramsstring */
VS.prototype.parseParams = function(paramsString)
{
	var params = [];
	
	if (typeof(paramsString)!=="undefined")
	{
		var paramsArray = paramsString.split("/");

		/* parse params */
		for (var i=0; i < paramsArray.length; i++)
		{
			var parArray = paramsArray[i].split(":");
			
			if (typeof(parArray[1])!=="undefined")
			{
				var subParsArray = parArray[1].split(";");

				if (subParsArray.length==1) params[parArray[0]] = subParsArray[0];
				else 
				{
					params[parArray[0]] = [];

					for (var j=0; j < subParsArray.length; j++)
					{
						var subSubParsArray = subParsArray[j].split(",");

						if (subSubParsArray.length==1) params[parArray[0]][j] = subSubParsArray[0];
						else
						{
							params[parArray[0]][j] = subSubParsArray;
						} 
					}
				}
			}
		}
	}

	/* verify params */
	params["c"] = this.Collection.verifyParams(params);
	params["d"] = this.DateVis.verifyParams(params);
	params["l"] = this.MapVis.verifyParams(params);
	params["t"] = this.TagVis.verifyParams(params);
	params["q"] = this.Query.verifyParams(params);
	params["o"] = this.verifyOrder(params);
	params["a"] = this.verifyAbout(params);
	
	return params;
}

VS.prototype.verifyAbout = function(params)
{
	
	if (typeof(params.a)!=="undefined")
	{
		var a = params.a;
		return a;
	}
	else return 0;
	
}

/*  sorting, limit, page  */
VS.prototype.verifyOrder = function(params)
{
	if (typeof(params.o)!=="undefined") return params.o;
	else return [0, 1, RES, 0];
}

/* update paramsString */
VS.prototype.setParamsString = function(hash)
{
	var paramsString = "";
	var d = this.params["d"];
	var l = this.params["l"];
	var t = this.params["t"];
	var q = this.params["q"];
	var o = this.params["o"];
	var c = this.params["c"];
	
	/*  about  */
	var a = this.params["a"];
	if (a===1) paramsString+= "a:"+1+"/";
	
	/*  query  */
	if (this.isArray(q))
	{
		paramsString+= "q:";
		for (var i=0; i < q.length; i++)
		{
			paramsString+= q[i];
			if (i < q.length-1) paramsString+=";";
		}
		paramsString+= "/";
	}

	/*  collection  */
	if (typeof(c)!=="undefined")
	{
		paramsString+= "c:"+c+"/";
	}

	/*  date  */
	paramsString+= "d:";

	if (typeof(d[0])!=="undefined")
	{
		if (this.isArray(d[0]))
		{
			if (typeof(d[0][0])!=="undefined") paramsString+= d[0][0]+",";
			if (typeof(d[0][1])!=="undefined") paramsString+= d[0][1]+",";
			if (typeof(d[0][2])!=="undefined") paramsString+= d[0][2];
		}
		else paramsString+= d[0];
		paramsString+= ";";
	}
	if (typeof(d[1])!=="undefined")
	{
		if (this.isArray(d[1]))
		{
			if (typeof(d[1][0])!=="undefined") paramsString+= d[1][0]+",";
			if (typeof(d[1][1])!=="undefined") paramsString+= d[1][1]+",";
			if (typeof(d[1][2])!=="undefined") paramsString+= d[1][2];
		}
		else paramsString+= d[1];
		
	}
	paramsString+= "/";
	
	
	/*  location  */
	paramsString+= "l:"+l[0][0]+","+l[0][1]+";"+l[1][0]+","+l[1][1]+"/";

	/*  tags  */
	if (this.isArray(t))
	{
		paramsString+= "t:";
		for (var j=0; j < t.length; j++)
		{
			paramsString+= t[j];
			if (j < t.length-1) paramsString+=";";
		}
		paramsString+= "/";
	}
	
	/*  sorting  */
	if (typeof(o)!=="undefined")
	{
		paramsString+= "o:";
		if (typeof(o[0])!=="undefined") paramsString+=o[0]+";";
		if (typeof(o[1])!=="undefined") paramsString+=o[1]+";";
		if (typeof(o[2])!=="undefined") paramsString+=o[2]+";";
		if (typeof(o[3])!=="undefined") paramsString+=o[3];
		paramsString+= "/";
	}
	
	this.paramsString = paramsString;
	this.paramsStringUrl = ""; if (hash) this.paramsStringUrl = paramsString;
}

/* write current paramsString to address */
VS.prototype.writeParamsHash = function(paramsString)
{
	window.location.href = "#"+this.paramsString;
}

VS.prototype.writeTitleString = function()
{
	var d = this.DateVis.getTitleString();
	var l = this.MapVis.getTitleString();
	var t = this.TagVis.getTitleString();
	var q = this.Query.getTitleString();
	
	var titleString = "";
	var otherPar = false;

	if (q!=="") titleString+=q+" | ";
	if (d!=="") titleString+=d+" | ";
	if (l!=="") titleString+=l+" | ";
	if (t!=="") titleString+=t+" | ";
	
	document.title = "VisGets | "+titleString;
}

/* check if hash has changed */
VS.prototype.checkParamsHash = function()
{	
	if (typeof(VS)!=="undefined")
	{
		if (typeof(VS.paramsStringUrl)!=="undefined")
		{
			var hash = window.location.hash;
			if (hash==="") hash="#";

			if (hash != "#"+VS.paramsStringUrl)
			{ 
				hash = hash.substring(1, hash.length);
				var bool = true; if (hash==="") bool = false;
				VS.update("all", VS.parseParams(hash), bool);
			} 
		}
	}
}

/* update all visgets */
VS.prototype.update = function(vis, params, hash)
{
	/*  stop pulsing feedback form  */
	$("#progress .feedback").stop().css({opacity: 1}).removeClass("active");

	if (vis=="all")
	{
		this.params = params;
		this.MapVis.updateMap();
	}
	else this.params[vis] = params;

	if (vis!=="o")  this.params.o[3]=0;
	
	if (vis=="d") this.DateVis.load();
	
	this.setParamsString(hash);
	
	/*  loading  */
	this.load();

	/*  update browser  */
	if (hash) this.writeParamsHash();
	this.writeTitleString();
}

/* check if obj is array */	
VS.prototype.isArray = function (obj)
{
	if (typeof(obj)!=="undefined")
	{
		if ((typeof(obj.length)!=="undefined")&&(typeof(obj)!=="string")) return true;
	}
	return false;
}

/* global hover */
VS.prototype.hoverStart = function(brush, count)
{
	if (typeof(brush)!=="undefined" && typeof(count)!=="undefined")
	{
		if (typeof(brush.d)!=="undefined") this.DateVis.hoverStart(brush.d, count);
		if (typeof(brush.l)!=="undefined") this.MapVis.hoverStart(brush.l, count);
		if (typeof(brush.t)!=="undefined") this.TagVis.hoverStart(brush.t, count);
		if (typeof(brush.r)!=="undefined") this.ResultVis.hoverStart(brush.r);
	}
}

VS.prototype.hoverEnd = function()
{
  $(".vs_active").removeClass("vs_active");
  VS.DateVis.hoverEnd();
  VS.MapVis.hoverEnd();
  VS.TagVis.hoverEnd();
}

/*  count items in associative array  */
VS.prototype.count = function(obj)
{
	var count = 0;
	for (var i in obj) count++;
	return count;
}

VS.prototype.max = function(obj)
{
	var max = 0;
	for (var i in obj)
	{
		var n = Number(obj[i]);
		if (n>max) max = n;
	}
	return max;
}

VS.prototype.loading = function(loading)
{

	if (typeof(loading)=="undefined" || loading===0) loading = false;
	
	$("#block").stop(); $("#block_loader").stop();
	
	var now = new Date();
	if (loading==true)
	{
		this.times[0] = Date.parse(now)/1000+now.getMilliseconds()/1000;
		
		/*  div blocking interaction  */
		$("#visgets").append('<div id="block" class="block"></div>');
		$("#block").css({left: 0, top: 0, width: $(document).width(), height: $(document).height()});
		$("#block_loader").animate({opacity: 1}, ANI);
		$("#block").animate({opacity: 0.5}, ANI);
		this.hoverEnd();		
	}
	else
	{
		$("#block_loader").animate({opacity: 0}, ANI/3);
		$(".block").animate({opacity: 0}, ANI/3, function(){ $(".block").remove(); });		
		this.delays[0] = this.times[1] - this.times[0];
		this.delays[1] = Date.parse(now)/1000+now.getMilliseconds()/1000 - this.times[1];
	}	
}

VS.prototype.about = function(about, first)
{
	$("#about_link").unbind();
	$("#about_continue").unbind();
	
	$("#about, #visgets, #r, #q, #c").stop();
	
	if (about)
	{
		$("#block").stop().remove();
		
		this.checkParams = "";
		this.params["a"] = 1;
		this.setParamsString(true);
		this.writeParamsHash(this.paramsString);
		this.checkParams = window.setInterval(VS.checkParamsHash, 500);
		
		
		if (!$("#about_link").hasClass("active")) /*  if already shown  */
		{
			/*  add about layer and box  */
			$("#sheet").append('<div id="about"><div id="about_box"></div></div>');
			
			/*  hide visgets+co  */
			
			if (first)
			{
				$("#about").css({opacity: 1});
				$("#visgets, #r, #q, #c").css({opacity: 0.2});
			}
			else
			{
				$("#about").animate({opacity: 1}, ANI/2);
				$("#visgets, #r, #q, #c").animate({opacity: 0.2}, ANI/2);
				
				$("#about_know").animate({opacity: 0}, ANI, null, function(){$(this).remove();});
			}
			
			$("#about_box").append($("#about_txt").html());
		}


		$("#about").css({left: 0, top: 0, width: $(document).width()-25, height: 500});
		
		
		$("#about_link").addClass("active").click(function(){VS.about(false, false);});
		
		$("#about .about_continue").click(function(){VS.about(false, false);});
		
		$(".about_goback").click(function(){VS.about(false, false);});
		
		$(".about_feedback").click(function(){window.onbeforeunload=null;});
		
	}
	else 
	{
		this.checkParams = "";
		this.params["a"] = "";
		this.setParamsString(true);
		this.writeParamsHash(this.paramsString);
		this.checkParams = window.setInterval(VS.checkParamsHash, 500);
		
		$("#visgets, #r, #q, #c").animate({opacity: 1}, ANI/2);
		
		$("#about").animate({opacity: 0}, ANI/2, function(){$(this).remove();});

		$("#about_link").removeClass("active").click(function(){VS.about(true, false);});
	}
	

	
	
}











/*
						QUERY CLASS																        

*/
	
function Query()
{
	var query = "";
}

Query.prototype.init =function()
{
	/*  events  */
	$("#q_querybox").keyup( function()
	{
		var value = "";
		if (typeof($("#q_querybox").attr("value"))!=="undefined") value = $("#q_querybox").attr("value");
		
		if (value==VS.Query.query) $("#q_submit").removeClass("active");
		else $("#q_submit").addClass("active");

	});
	
	$("#q_querybox").blur( function()
	{
		if ($(this).attr("value")==VS.Query.query) $("#q_submit").removeClass("active");
	});

	$("#q_cancel").addClass("active");
	
	$("#q_cancel").click(function(){
		$("#q_querybox").attr("value", "");
		VS.Query.change();
	});

	$("form.q_form").submit(VS.Query.change);

	this.show();
}

Query.prototype.show = function()
{
	this.query = "";
	
	/*  put query terms into box  */
	this.query = VS.params["q"].join(" ");
	
	var box = $("#q_querybox");
	box.attr({value: this.query});
	
	if (this.query!=="" && this.query!==" ")
	{
		$("#q_form").addClass("vs_filter");
		$("#q_cancel").addClass("active");
	}
	else
	{
		$("#q_form").removeClass("vs_filter");
		$("#q_cancel").removeClass("active");
	}
	
	$("#q_submit").removeClass("active");
}

Query.prototype.change = function()
{
	var box = $("#q_querybox");
	var value = "";
	if (typeof(box.attr("value"))!=="undefined") value = box.attr("value");
	
	if ( value !== VS.Query.query )
	{
		var change = false;
		var q_old = [];
		var q_new = [];

		if (value==="") 
		{
			change = true;
		}
		else
		{
			var query = value.split(" ");
			for (i in VS.params["q"]) q_old[VS.params["q"][i]] = true;
			for (i in query)
			{
				/*  cleaning  */
				if (query[i]!=="" && query[i]!==" ") q_new[query[i].toLowerCase()] = true;
			}

			for (i in q_old) if (typeof(q_new[i])=="undefined") change = true;
			for (i in q_new) if (typeof(q_old[i])=="undefined") change = true;
		}
		
		if (change)
		{
			var q = [];
			var i = 0;
			for (var term in q_new)
			{
				q[i] = term;
				i++;
			}
			
			VS.Query.query = value;
			VS.update("q", q, true);
		}
	}
	
	/*  take away focus  */
	$("form.q_form").append('<input type="text" name="q_querybox2" id="q_querybox2" />');
	document.q_form.q_querybox2.focus();
	$("#q_querybox2").remove();
	
	VS.Query.show();
	
	return false;
}

Query.prototype.verifyParams = function(params)
{
	var q = [];

	if (typeof(params.q)!=="undefined")
	{
		if (VS.isArray(params.q)) q = params.q;
		else q[0]=params.q;
	}

	return q;
}

/* generate date part of titleString */
Query.prototype.getTitleString = function()
{
	return VS.Query.query;
}



/*
						COLLECTION CLASS																        

*/

function Collection()
{
	var query = "";
	
	$("#c select").change(function ()
	{
		var str = "";
		$("select option:selected").each(function () { str += $(this).attr("value");});
		VS.Collection.change(str);
	});
}

Collection.prototype.init = function()
{
	// set to current collection
	
	$("#c select").attr("value", VS.params.c);
	
	
	
	
}

Collection.prototype.verifyParams = function(params)
{
	var c = [];
	if (typeof(params.c)!=="undefined") c[0]=params.c;
	else c = 0;
	return c;
}

Collection.prototype.change = function(id)
{
	var c=id;
	VS.update("c", c, [], [], []);
}




/*
						DATE CLASS																        

*/
	
/* initialize variables */
function DateVis()
{
	this.counts = [];
	this.matrix = new Object(); /*  brushing counts  */
	this.lookup = new Object();
	
	this.firstYear = 2000;
	this.lastYear	= new Date().getFullYear();
	
	/*  constraints  */
	this.yLeft 		= 0;
	this.yRight 	= 0;
	this.mLeft 		= 1;
	this.mRight 	= 12;
	this.dLeft	 	= 1;
	this.dRight 	= 31;

	/*  first values  */
	this.first = new Object();
	this.first.d = 1;
	this.first.m = 1;
	this.first.y = this.firstYear;

	/*  previous collection  */
	this.oldC = -1;

	/*  strings  */
	this.monthWord = ["","January", "February", "March", "April", "May", "June", "July", "August",
		"September", "October", "November", "December"];
	this.shortMonthWord = ["","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
		"Nov", "Dec"];

	/*  bar features  */
	this.barHeight	 = 2.5;
	this.offset		 = 0; //2.2;
	
	this.barWidth   = new Object();
	this.barWidth.y = 1.2; 
	this.barWidth.m = 1.2; 
	this.barWidth.d = 0.6; 
	
	/*  store old arrow locations  */
	this.pos1 = new Object();
	this.pos2 = new Object();
	this.pos1a = new Object();
	this.pos2a = new Object();
	this.moveType = "";
	
	/*  min/max  */
	this.min = new Object();
	this.max = new Object();
	this.min.y 	= Number.POSITIVE_INFINITY;
	this.max.y 	= 0;
	this.min.m 	= Number.POSITIVE_INFINITY;
	this.max.m 	= 0;
	this.min.d 	= Number.POSITIVE_INFINITY;
	this.max.d 	= 0;
	
	/*  not used yet  */
	this.fontSize 	= $("#body").css("font-size").split("px")[0];
}

/* verify params concerning DateVis */
DateVis.prototype.verifyParams = function(params)
{
	var d = [];
	
	var now = new Date();
	var nowY = now.getFullYear();
	var nowM = now.getMonth()+1;
	var nowD = now.getDate();
	
	if ((typeof(params)=="undefined") || (typeof(params.d)=="undefined")) 
	{
		d[0] = [nowY, nowM, 1];
		d[1] = [nowY, nowM, nowD];
	}
	else
	{
		for (var i=0; i < 2; i++)
		{
			d[i] = [];
			
			if (typeof(params.d[i])!=="undefined")
			{
				d[0] = params.d[0];
				d[1] = params.d[1];
			}
		}
	}
	
	//this.setFirstAndLast();
	
	this.d = d;
	
	return d;
}

/* generate date part of titleString */
DateVis.prototype.getTitleString = function()
{
	var d = VS.params.d;

	/*  same year  */
	if (d[0][0]==d[1][0])
	{
		/*  same month  */
		if (d[0][1]==d[1][1]) 
		{
			/*  same day  */
			if (d[0][2]==d[1][2]) return this.shortMonthWord[d[0][1]]+" "+d[0][2]+", "+d[0][0];
			else return this.shortMonthWord[d[0][1]]+" "+d[0][2]+"-"+d[1][2]+", "+d[0][0];
		}
		else return this.shortMonthWord[d[0][1]]+"-"+this.shortMonthWord[d[1][1]]+" "+d[0][0];
	}
	else return d[0][0]+"-"+d[1][0];
}

DateVis.prototype.setFirstAndLast = function()
{
	switch (Number(VS.params.c[0]))
	{
		case 0: this.firstYear = 2007; this.lastYear = new Date().getFullYear(); this.barWidth.y = 1.8; break; /*  Global Voices  */
		case 1: this.firstYear = 1900; this.lastYear = 2000; this.barWidth.y = 0.2; break; /*  DBpedia  */
		case 2: this.firstYear = 2008; this.lastYear = new Date().getFullYear(); this.barWidth.y = 1.8; break; /*  Flickr  */
		case 3: this.firstYear = 2001; this.lastYear = 2008; this.barWidth.y = 1.8; break; /*  ACM  */
		default: break;
	}
}

/* init visget */
DateVis.prototype.init = function()
{
	this.setFirstAndLast();	
	$("#d div.bar").remove();
	
	/*  add blank bars  */
	for (var y=this.firstYear; y <= this.lastYear; y++)
		$("#y_box").append('<div class="bar" title="'+y+
			'" id="dy_'+y+'"><span class="overlay"></span></div>');
	
	for (var i=1; i <= 12; i++)
		$("#m_box").append('<div class="bar" title="'+this.monthWord[i]+
			'" id="dm_'+i+'"><span class="overlay"></span></div>');

	for (var j=1; j <= 31; j++)
		$("#d_box").append('<div class="bar" title="'+j+'" id="dd_'+j+'"><span class="overlay"></span></div>');

	var bars = $(".bar");
	bars.find(".overlay").css({height: this.barHeight+"em"});
}

/* set constraints */
DateVis.prototype.load = function()
{
	/*  set constraints  */
	if (typeof(VS.params.d[0][0])!=="undefined") this.yLeft  = VS.params.d[0][0];
	else this.yLeft=this.firstYear;
	if (typeof(VS.params.d[1][0])!=="undefined") this.yRight	= VS.params.d[1][0];
	else this.yRight=this.lastYear;

	if (typeof(VS.params.d[0][1])!=="undefined") this.mLeft  = VS.params.d[0][1];
	else this.mLeft=1;
	if (typeof(VS.params.d[1][1])!=="undefined") this.mRight	= VS.params.d[1][1];
	else this.mRight=12;
	
	if (typeof(VS.params.d[0][2])!=="undefined") this.dLeft  = VS.params.d[0][2];
	else this.dLeft=1;
	if (typeof(VS.params.d[1][2])!=="undefined") this.dRight	= VS.params.d[1][2];
	else this.dRight=this.getAmountOfDays(VS.params.d[1][0], VS.params.d[1][1]);

	/*  set counts  */
	this.counts = VS.dates;


	/*  BRUSHING MATRIX  */
	this.matrix = new Object();
	/*  get/set brushing counts  */
	for (date_id in VS.counts.d)
	{
		this.lookup[VS.counts.d[date_id][1]] = date_id;
		this.matrix[date_id] = new Object();
		this.matrix[date_id]["l"] = new Object();
		this.matrix[date_id]["t"] = new Object();
		this.matrix[date_id]["r"] = new Object();
	}

	/*  locations  */
	for (var loc_id in VS.counts.l) /*  go through all locations  */
		for (date_id in VS.counts.l[loc_id][3]) /*  go through each location's dates  */
			this.matrix[date_id]["l"][loc_id] = VS.counts.l[loc_id][3][date_id]; /*  common counts  */
	
	/*  tags  */
	for (var tag_id in VS.counts.t) /*  go through all tags  */
		for (date_id in VS.counts.t[tag_id][3]) /*  go through each tag's dates  */
			this.matrix[date_id]["t"][tag_id] = VS.counts.t[tag_id][3][date_id]; /*  common counts  */
	
	/*  results  */
	for (var i in VS.results) /*  go through all results  */
	{
		var res_id = VS.results[i][1];
		var date_id = VS.results[i][2]["d"];
		this.matrix[date_id]["r"][res_id] = 1;
	}
	
	/*  set max/min  */
	this.max.y = VS.max(VS.dates.y);
	this.max.m = VS.max(VS.dates.m);
	this.max.d = VS.max(VS.dates.d);
	
	this.show();
}

DateVis.prototype.showBars = function(type, first, last, left, right)
{
	for (var i=first; i <= last; i++)
	{
		var bar = $("#d"+type+"_"+i);
		
		var title_amount = "";
		
		if (typeof(this.counts[type][i])!=="undefined") 
		{
			if (this.counts[type][i]==1) title_amount = "1 result for ";
			else if (this.counts[type][i]>1) title_amount = this.counts[type][i]+" results for ";
		}
		
		if (type=="y") bar.attr("title", title_amount+i);
		else if (type=="m") bar.attr("title", title_amount + this.monthWord[i]+" "+this.yLeft);
		else if (type=="d") bar.attr("title", title_amount+i+" "+this.monthWord[this.mLeft]+" "+this.yLeft);
		
		/*  widths  */
		bar.css("width", this.barWidth[type]+"em");
		bar.find(".overlay").css("width", this.barWidth[type]+"em");
		
		if (typeof(this.counts[type][i])!=="undefined" && this.max[type]>0)
		{
			var height; 
			height = (this.counts[type][i] / this.max[type]) * this.barHeight;
			height = this.barHeight - (Math.round(10*height) / 10);
			
			/*  events  */
			bar.click(function() {	VS.DateVis.click($(this).attr("id")); });  /* click bar */
			bar.mouseover(function(){	VS.DateVis.hoverPrepare($(this).attr("id")); });  /* bar mouseover */
			bar.mouseout(function() {	VS.hoverEnd(); });  /* bar mouseout */	
		}
		else height=this.barHeight;
		
		bar.find(".overlay").animate({height: height+"em"}, ANI*2);
		
		if ((i>=left)&&(i<=right)) bar.addClass("selected_bar");
		else {
			bar.unbind("mouseover");
			bar.removeClass("selected_bar");
		}
	}
}

/* display date bars, mouseover/mouseout events */
DateVis.prototype.show = function()
{	
	$("#d .selected_bar").unbind("mouseout");
	$("#d .selected_bar").unbind("mouseover");
	$("#d .bar").removeClass("selected_bar");
	
	var oldFirstYear = this.firstYear, oldLastYear = this.lastYear;
	var newCollection = Number(VS.params.c);
	
	this.setFirstAndLast();
	
	if (this.oldC!==-1 && this.oldC!==newCollection) this.init();
	this.oldC = newCollection;
	if (this.yLeft<this.firstYear) this.yLeft = this.firstYear;
	if (this.yRight>this.lastYear) this.yRight = this.lastYear;
	this.first.y = this.firstYear;
	
	/*  reset control  */
	if (this.yLeft==this.firstYear && this.yRight==this.lastYear) $("#d_cancel").removeClass("active");
	else 
	{
		$("#d_cancel").addClass("active");
		$("#d_cancel").click(VS.DateVis.reset);
	}
	
	/*  years  */
	this.showBars("y", this.firstYear, this.lastYear, this.yLeft, this.yRight);

	/*  months  */
	if (this.yLeft==this.yRight)
	{
		this.showBars("m", 1, 12, this.mLeft, this.mRight);
		$("#m_box").animate({opacity: 1}, ANI);
	}
	else
	{
		$("#m_box").animate({opacity: 0}, ANI);
		$("#m_box .bar").find(".overlay").animate({height: this.barHeight+"em"}, ANI);
		$("#m_box .bar").unbind("click").removeClass("selected_bar").attr("title", "");
	}
	
	/*  days  */
	if (this.mLeft==this.mRight && this.yLeft==this.yRight)
	{
		this.showBars("d", 1, 31, this.dLeft, this.dRight);
		$("#d_box").animate({opacity: 1}, ANI);
	}
	else
	{
	 	$("#d_box").animate({opacity: 0}, ANI);
		$("#d_box .bar").find(".overlay").animate({height: this.barHeight+"em"}, ANI);
		$("#d_box .bar").unbind("click").removeClass("selected_bar").attr("title", "");
	}
	
	this.showSlider("y", this.yLeft, this.yRight, this.firstYear, this.barWidth.y);
	this.showSlider("m", this.mLeft, this.mRight, 1, this.barWidth.m);
	this.showSlider("d", this.dLeft, this.dRight, 1, this.barWidth.d);
	
	this.showAllLabels();
	$(window).resize( function(){
		VS.DateVis.showAllLabels();
		if ($("#about_link").hasClass("active")) VS.about(true);
	});
}

DateVis.prototype.showAllLabels = function()
{
	$("#d .dateLabel").remove();
	
	this.showLabels("y", this.yLeft, this.yRight, this.firstYear, this.barWidth.y);
	
	/*  months  */
	if (this.yLeft==this.yRight)
		this.showLabels("m", this.mLeft, this.mRight, 1, this.barWidth.m);
	
	/*  days  */
	if (this.mLeft==this.mRight && this.yLeft==this.yRight)
		this.showLabels("d", this.dLeft, this.dRight, 1, this.barWidth.d);
	
}

DateVis.prototype.showLabels = function(type, left, right, min, barWidth)
{
	/*  sliders  */
	var box = $("#"+type+"_box");
	
	var pos1 = left-min; 	
	var pos2 = right-min;	
	
	box.append('<div class="clear"></div><div class="dateLabel left"></div><div class="dateLabel right"></div>');
	var label1 = box.find(".dateLabel.left"); var label2 = box.find(".dateLabel.right");

	if ((pos2-pos1)>=1)
	{
		label1.css({left: ($("#"+type+"_arrow1").position().left)});
		label2.css({left: ($("#"+type+"_arrow2").position().left)});
		label2.append(right);
	}
	else label1.css({left: ($("#"+type+"_arrow1").position().left+12)});
	
	label1.append(left);
}

DateVis.prototype.showSlider = function(type, left, right, min, barWidth)
{
	/*  remove everything  */
	var box = $("#"+type+"_box");
	box.find(".arrow").remove();
	box.find(".dateLabel").remove();
	$("#"+type+"_slider").remove();
	
	box.append('</div><div id="'+type+'_slider"><div class="hr"></div><div id="'+type+'_arrow1" class="arrow"></div><div id="'+type+'_arrow2" class="arrow"></div></div>');
	
	if (type=="y")
	{
		var sliderwidth = (this.lastYear-this.firstYear+1)*this.barWidth.y;
		$("#y_slider" ).css("width", sliderwidth+2+"em");
		$("#y_box .hr").css("width", sliderwidth+"em");
	}
	
	var arrows = $("#"+type+"_slider .arrow");
	var arrow1 = $("#"+type+"_arrow1");
	var arrow2 = $("#"+type+"_arrow2");
	
	var pos1 = left-min; 	this.pos1[type] = pos1;
	var pos2 = right-min;	this.pos2[type] = pos2;
	
	arrow1.css({left: (barWidth * pos1)+"em"});
	arrow2.css({left: (barWidth * pos2+barWidth)+"em"});
	arrows.draggable({ axis:'x', containment: '#'+type+'_slider'});
	arrows.bind ( "mousedown" , function()
	{
		VS.DateVis.moveType=$(this).attr("id").split("_")[0];
		$(document).bind("mouseup", function(){VS.DateVis.arrowMove();});
	});
	
	/*  save slider positions: left, type, arrow  */
	this.pos1a[type] = this.posToPar(type, 1);
	this.pos2a[type] = this.posToPar(type, 2);
}




/* handle arrow movement and start global update */
DateVis.prototype.arrowMove = function()
{
	var type = this.moveType;
	var fontSize = VS.DateVis.fontSize;
	var barWidth = VS.DateVis.barWidth[type];
	
	var old1a = VS.DateVis.pos1a[type];
	var old2a = VS.DateVis.pos2a[type];
	
	var pos1a = VS.DateVis.posToPar(type, 1);
	var pos2a = VS.DateVis.posToPar(type, 2);
	
	/*  console.log("old1a:"+old1a+" old2a:"+old2a+"pos1a:"+pos1a+" pos2a:"+pos2a);  */
	
	/*  arrows have not changed  */
	if (pos1a==old1a && pos2a==old2a) 
	{
		VS.DateVis.show();
	}
	/*  arrows have changed  */
	else
	{
		if (pos2a<pos1a)
		{
			var pos2soon = pos1a-1;
			pos1a = pos2a+1;
			pos2a = pos2soon;
		}
		
		if (pos1a==(pos2a+1)) pos2a++;
	
		var d = [];

	 	if (type=="d")
	 	{
	 		d[0] = VS.params.d[0];  d[0][2] = pos1a;
	 		d[1] = VS.params.d[1];  d[1][2] = pos2a;
	 	}
	 	else if (type=="m")
	 	{
	 		d[0] = VS.params.d[0];  d[0][1] = pos1a;
			d[1] = VS.params.d[1];  d[1][1] = pos2a;
			
			d[0][2] = 1;
			d[1][2] = this.getAmountOfDays(d[0][0], d[0][1]);
	 	}
	 	else if (type=="y")
	 	{
	 		d[0] = [pos1a, 1];
	 		d[1] = [pos2a, 12];
	 	}
	 	VS.update("d", d, true);
	}

	$(document).unbind("mouseup");
}

DateVis.prototype.click = function(id_string)
{
	VS.hoverEnd();
	
	var bar = $("#"+id_string);
	bar.unbind("click");
	var d = VS.params.d;
	var id = id_string.split("_")[1];
	var type = "";
	
	/*  determine type: year, month, day,   */
	if (id_string.substr(0, 2)=="dd") type = "d";
	else if (id_string.substr(0, 2)=="dy") type = "y";
	else type = "m";
	
	if (type=="d")
	{
		d[0][2] = id;
		d[1][2] = id;
	}
	else if (type=="m")
	{
		d[0] = [this.yLeft, id, 1];
		d[1] = [this.yLeft, id, this.getAmountOfDays(this.yLeft, id)];
	}
	else if (type=="y")
	{
		d[0] = [id, 1];
		d[1] = [id, 12];
	}
	
	VS.update("d", d, true);

	bar.click(VS.DateVis.click);
}

DateVis.prototype.reset = function()
{
	var d = [];
	
	d[0] = [VS.DateVis.firstYear,1];
	d[1] = [VS.DateVis.lastYear,12];

	VS.update("d", d, true);
	
	$(this).unbind();
}

/*  new function mapping pixel position to new parameter  */
DateVis.prototype.posToPar = function(type, arrow)
{
	var left = $("#"+type+"_arrow"+arrow).position().left-$("#"+type+"_slider").position().left;
	var diff = 1;
	if (arrow==2) diff = 0;
	
	if (type=="m" && arrow==1) diff=2;
	
	if (type=="y" && this.barWidth.y==0.2) diff=10;
	if (type=="y" && this.barWidth.y==0.2 && arrow==2) diff=4;
	
	if (type=="d" && arrow==1) diff=3;
	if (type=="d" && arrow==2) diff=1;
	
	return this.first[type]+Math.round((left-this.fontSize)/this.fontSize/this.barWidth[type])+diff;
}

DateVis.prototype.getAmountOfDays = function(y, m)
{
	var feb = 28;
	if ((y % 4 === 0 && y % 100 !== 0)  || y % 400 === 0) feb = 29;
	
	switch (Number(m)) {
		case 1: return 31; break;
		case 2: return feb; break;
		case 3: return 31; break;
		case 4: return 30; break;
		case 5: return 31; break;
		case 6: return 30; break;
		case 7: return 31; break;
		case 8: return 31; break;
		case 9: return 30; break;
		case 10: return 31; break;
		case 11: return 30; break;
		case 12: return 31; break;
		default: return 31; break;		
	}
	return 31;
}

DateVis.prototype.hoverPrepare = function(id_string)
{
	var id = id_string.split("_")[1];
	var type = "";
	
	/*  determine type: year, month, day,   */
	if (id_string.substr(0, 2)=="dd") type = "d";
	else if (id_string.substr(0, 2)=="dy") type = "y";
	else type = "m";
	
	var date = VS.DateVis.getFullDate(id, type);
	
	if (typeof(VS.DateVis.lookup[date])!=="undefined")
		VS.hoverStart(VS.DateVis.matrix[VS.DateVis.lookup[date]], VS.counts.d[VS.DateVis.lookup[date]][0]);
}

DateVis.prototype.hoverStart = function(brushed, count)
{
	var opacs = [];
	var max_opac = 0;
	var prefix = "#dm_";
	var left = 0;
	var right = 0;
	var type = "";
	
	/*  determine whether day, month, and year  */
	if (this.yLeft !== this.yRight)
	{
		prefix = "#dy_";
		type = "y";
		left = this.yLeft;
		right = this.yRight;
	}
	else if (this.mLeft !== this.mRight)
	{
		prefix = "#dm_";
		type = "m";
		left = this.mLeft;
		right = this.mRight;		
	}
	else
	{
		prefix = "#dd_";
		type = "d";
		left = this.dLeft;
		right = this.dRight;
	}


	for (var i = left; i <= right; i++)
	{
		/*  get full date, to get date_id  */
		var date_id  = this.lookup[this.getFullDate(i, type)];
		
		var this_count = this.counts[type][i];
		
		if (typeof(brushed[date_id])!=="undefined")
			opacs[i] = 0.5*brushed[date_id]/this_count + 0.5*brushed[date_id]/count;
			
		if (opacs[i]>max_opac) max_opac = opacs[i];
	}
	
	for (i=left; i <= right; i++)
	{
		var interpolated_opac = 0.3 + 0.7*opacs[i]/max_opac;
		var bar = $(prefix+i);
		
		bar.css({opacity: interpolated_opac});
		if (opacs[i]>0) bar.addClass("vs_active");
		else bar.css({opacity: 0.3});
	}
}

DateVis.prototype.hoverEnd = function()
{
	$("#d").find(".bar").css({opacity: 1});
}

DateVis.prototype.getFullDate = function(i, type)
{
	var month = this.mLeft;
	if (month<10) month = "0"+month;
	if (i<10) i = "0"+i;
	var date="";
	if (type=="d") date = this.yLeft+"-"+month+"-"+i;
	else if (type=="y") date = i;
	else if (type=="m") date = this.yLeft+"-"+i;
	
	return date;
}










/*
						MAP CLASS																        
														
*/

function MapVis()
{
	this.counts = []; /*  new counts  */
	this.matrix = new Object();
	
	this.map = [];
	this.dragEvent = new Object();
	this.zoomEvent = new Object();

	this.bounds = [];
	this.cluster_max = 0;
	
	/*  config  */
	this.iconPath = "img/mapvis/circle/ICON_COLOR.png";
	this.offset_factor = 12;
	
	this.cluster_size_min = 10;
	this.cluster_size_max = 25;
	
	this.maxZoom = 12;
	this.minZoom = 0;
	
	this.maxZoomSteps = 8;
}

/*  init google map and get initial set of location from server  */
MapVis.prototype.init = function()
{
	this.map = new GMap2(document.getElementById("map"));
	this.bounds = new GLatLngBounds(
		new GLatLng(VS.params.l[0][0],VS.params.l[0][1]),
		new GLatLng(VS.params.l[1][0],VS.params.l[1][1]));
	this.map.setCenter(this.bounds.getCenter(), this.map.getBoundsZoomLevel(this.bounds));
	this.map.enableDoubleClickZoom();
	this.map.enableScrollWheelZoom();

	/*  maptypes  */
	this.maptypes("phy");
	
	var mapTypes = this.map.getMapTypes(); /*  get array of map types  */

	for (var i=0; i<mapTypes.length; i++)
	{ 
		mapTypes[i].getMinimumResolution = function() {return VS.MapVis.minZoom;} 
		mapTypes[i].getMaximumResolution = function() {return VS.MapVis.maxZoom;} 
	}

	/* bind map events */
	this.dragEvent = GEvent.bind(this.map, "dragend", this, this.mapChange);
	this.zoomEvent = GEvent.bind(this.map, "zoomend", this, this.mapChange);
}

/*  sanitize location params  */
MapVis.prototype.verifyParams = function(params)
{
	var l = [];
	
	if ((typeof(params)=="undefined") || (typeof(params.l)=="undefined") ||  (params.l[0][0] > 90) || (params.l[0][0] < -90) || (params.l[1][0] > 90) || (params.l[1][0] < -90) || 		(params.l[0][1] > 180) || (params.l[0][1] < -180) || (params.l[1][1] > 180) || (params.l[1][1] < -180))
	{
		l[0] = [-90, -180]; /* SW */
		l[1] = [ 90,  180]; /* NE */
	}
	else l = params.l;

	return l;
}

/*  generate location part of title string  */
MapVis.prototype.getTitleString = function()
{
	var center = [this.map.getCenter().lat(), this.map.getCenter().lng()];

	var sw = this.bounds.getSouthWest();
	var ne = this.bounds.getNorthEast();
	
	var titleString = center[0].toFixed(2)+";"+center[1].toFixed(2);
	
	if (this.map.getZoom()===0) titleString="";
	
	return titleString;
}

/*  load new locations into locations[]  */
MapVis.prototype.load = function()
{
	VS.MapVis.counts = VS.counts.l;
	
	/*  BRUSHING MATRIX  */
	this.matrix = [];
	
	/*  get/set brushing counts  */
	for (var loc_id in VS.counts.l)
	{
		this.matrix[loc_id] = new Object();
		this.matrix[loc_id]["d"] = VS.counts.l[loc_id][3];
		this.matrix[loc_id]["t"] = new Object();
		this.matrix[loc_id]["r"] = new Object();
	}
	
	/*  tags  */
	for (var tag_id in VS.counts.t) /*  go through all tags  */
		for (loc_id in VS.counts.t[tag_id][2]) /*  go through each tag's locations  */
			this.matrix[loc_id]["t"][tag_id] = VS.counts.t[tag_id][2][loc_id]; /*  common counts  */
	
	/*  results  */
	for (var i in VS.results) /*  go through all results  */
	{
		var res_id = VS.results[i][1];
		var loc = VS.results[i][2]["l"];
		this.matrix[loc]["r"][res_id] = 1;
	}
	
	VS.MapVis.show();
}

MapVis.prototype.updateMap = function()
{
	GEvent.removeListener(this.dragEvent);
	GEvent.removeListener(this.zoomEvent);

	this.bounds = new GLatLngBounds(
		new GLatLng(VS.params.l[0][0],VS.params.l[0][1]),
		new GLatLng(VS.params.l[1][0],VS.params.l[1][1]));
	this.map.setCenter(this.bounds.getCenter(), this.map.getBoundsZoomLevel(this.bounds));
	
	this.dragEvent = GEvent.bind(this.map, "dragend", this, this.mapChange);
	this.zoomEvent = GEvent.bind(this.map, "zoomend", this, this.mapChange);
}

MapVis.prototype.zoom = function()
{
	var button = $(this);
	button.unbind("click");

	if (button.attr("id")=="map_zoom_out") 	VS.MapVis.map.zoomOut();
	else if (button.attr("id")=="map_zoom_in") 	VS.MapVis.map.zoomIn();
	else if (button.attr("id")=="map_zoom_world") VS.MapVis.map.setCenter(new GLatLng(0, 0), 0);
	
	button.click(VS.MapVis.zoom);
}

/*  update maptype buttons  */
MapVis.prototype.maptypes = function(type)
{
	//this.map.setMapType(G_PHYSICAL_MAP);
	
	var map = $("#map_type");
	map.unbind("click");

	switch (type)
	{
		case "map": this.map.setMapType(G_NORMAL_MAP);		map.click(function(){VS.MapVis.maptypes("hyb");}); break;
		case "hyb": this.map.setMapType(G_HYBRID_MAP);		map.click(function(){VS.MapVis.maptypes("sat");});  break;
		case "sat": this.map.setMapType(G_SATELLITE_MAP); 	map.click(function(){VS.MapVis.maptypes("phy");});  break;
		case "phy": this.map.setMapType(G_PHYSICAL_MAP); 	map.click(function(){VS.MapVis.maptypes("map");});  break;
		default: break;
	}
}

/*  display naively clustered locations  */
MapVis.prototype.show = function()
{
	/*  set events for zoom buttons  */
	var zoom = this.map.getZoom();
	
	if (zoom>this.minZoom)
	{
		$("#map_zoom_out").click(VS.MapVis.zoom);
		$("#map_zoom_out").addClass("active");
	}
	else
	{
		$("#map_zoom_out").unbind("click");
		$("#map_zoom_out").removeClass("active");
	}
	
	if (zoom>this.minZoom || VS.MapVis.map.getCenter().lat()<-10 || VS.MapVis.map.getCenter().lat()>10)
	{
		$("#map_zoom_world").click(VS.MapVis.zoom);
		$("#map_zoom_world").addClass("active");
	}
	else
	{
		$("#map_zoom_world").unbind("click");
		$("#map_zoom_world").removeClass("active");
	}

	if (zoom<this.maxZoom)
	{
		$("#map_zoom_in").addClass("active");
		$("#map_zoom_in").click(VS.MapVis.zoom);
	}
	else
	{
		$("#map_zoom_in").removeClass("active");
		$("#map_zoom_in").unbind("click");
	}
	
	/*  determine offset based on zoom level / bounds  */
	this.cluster_max = 0;
	var latitude = Math.abs(VS.params.l[0][0]-VS.params.l[1][0]);
	var longitude = Math.abs(VS.params.l[0][1]-VS.params.l[1][1]);
	var lat_offset = longitude/this.offset_factor;
	var lng_offset = latitude/this.offset_factor;
	
	/*  delete existing markers and clusters  */
	this.map.clearOverlays();
	
	/*  determine cluster_max  */
	for (j in this.counts)
	{
		var count = this.counts[j][0];
		if (count > this.cluster_max) this.cluster_max = count;
	}
	
	/*  display markers  */
	for (var k in this.counts)
	{
		var title = "";
		if (this.counts[k][0]==1) title = "1 result for this place";
		else title = this.counts[k][0]+" results for this region";
		
		this.counts[k]['marker'] = new GMarker(new GLatLng(this.counts[k][1], this.counts[k][2]), {icon: this.getIcon(this.counts[k][0]), title: title} );
		this.counts[k]['marker']['vs_loc_id'] = k;
		
		/*  events  */
		GEvent.addListener(this.counts[k]['marker'], "mouseover", function() {VS.MapVis.hoverPrepare(this['vs_loc_id']);});
		GEvent.addListener(this.counts[k]['marker'], "mouseout", function() {VS.hoverEnd();});
		GEvent.addListener(this.counts[k]['marker'], "click", function() {VS.MapVis.click(this);});

		this.map.addOverlay(this.counts[k]['marker']);
	}
	
}

/*  click on marker  */
MapVis.prototype.click = function(marker)
{
	var latlng = marker.getLatLng();
	var oldzoom = this.map.getZoom();
	var newzoom = oldzoom + 2;
	
	this.map.setCenter(latlng, newzoom);
	
	VS.hoverEnd();
}

/* get new locaton params and start global update */
MapVis.prototype.mapChange = function()
{
	var l = [];
	var newbounds = this.map.getBounds();
	
	/* set new location params */
	l[0] = [newbounds.getSouthWest().lat(), newbounds.getSouthWest().lng()];
	l[1] = [newbounds.getNorthEast().lat(), newbounds.getNorthEast().lng()];

	/* set new bounds */
	this.bounds = newbounds;

	/* initiate global update */
	VS.update("l", l, true);
}

MapVis.prototype.hoverPrepare = function(loc_id)
{
	VS.hoverStart(this.matrix[loc_id], this.counts[loc_id][0]);
	
	this.counts[loc_id]["marker"].setImage(this.getIconPath(true, this.counts[loc_id][0], 5));
}

MapVis.prototype.hoverStart = function(brushed, count)
{
	var opacs = [];
	var max_opac = 0;
	
	for (var loc_id in this.counts)
	{
		if (typeof(brushed[loc_id])!=="undefined")
			opacs[loc_id] = 0.5*brushed[loc_id]/this.counts[loc_id][0] + 0.5*brushed[loc_id]/count;
		if (opacs[loc_id]>max_opac) max_opac = opacs[loc_id];
	}
	
	for (var i in this.counts)
	{
		var marker = this.counts[i]['marker'];
		
		var n = Math.ceil(5*(opacs[i]/max_opac));

		if (opacs[i]>0) marker.setImage(this.getIconPath(true, this.counts[i][0], n));
		else marker.setImage(this.getIconPath(false, this.counts[i][0], 1));
	}
}

MapVis.prototype.hoverEnd = function()
{
	for (var i in this.counts)
	{	
		var cluster = this.counts[i];
		var marker = cluster['marker'];
		
		marker.setImage(this.getIconPath(false, this.counts[i][0], 5));
	}
}

MapVis.prototype.getIcon = function(count)
{
	var icon = new GIcon();
	icon.shadow = VS.base+"img/trans.png";
	icon.shadowSize = new GSize(1, 1);
	
	icon.image = this.getIconPath(false, count, 5);

	var slope = (this.cluster_size_max-this.cluster_size_min)/(this.cluster_max+1);
	var size = slope*(count+1)+this.cluster_size_min;

	if (count==1)
	{
		if (this.cluster_max > 30) size = 8;
		else if (this.cluster_max > 20) size = 9;
		else if (this.cluster_max > 10) size = 10;
		else size = 11;
	}

	icon.iconSize = new GSize(size, size);
	icon.iconAnchor = new GPoint(Math.round(size/2), Math.round(size/2));
	
	/*  not changd for now  */
	icon.infoShadowAnchor = new GPoint(10, 10);
	icon.infoWindowAnchor = new GPoint(9, 2);
	
	return icon;
}

MapVis.prototype.getIconPath = function(active, count, opac)
{
	var color = (active) ? "red" : "blue";
	var path = "";
	if (count==1) path = "img/mapvis/square/"+color+opac+".png";
	else path = "img/mapvis/circle/"+color+opac+".png";

	return VS.base+path;
}











/*
						TAG CLASS																        
														
*/

function TagVis()
{
	this.tags = new Object();
	this.matrix = new Object();
	this.lookup = new Object();
	this.count_min = Number.POSITIVE_INFINITY;
	this.count_max = 0;
	
	this.filtertags = new Object();
	this.hide_level = 0;   /*  min amount of items per tag before tag is hidden   */
	this.show_all = false;
	
	/*  config  */
	this.tag_amount_level = 50;   /*  max of tags shown until some are hidden  */
	this.cloud_max_height = 250;
	this.size_min = 1;
	this.size_max = 3.15;
}

TagVis.prototype.verifyParams = function(params)
{
	var t = [];
	
	if (typeof(params.t)!=="undefined")
	{
		if (VS.isArray(params.t)) t = params.t;
		else t[0]=params.t;
	}
	
	return t;
}

/*  load tags  */
TagVis.prototype.load = function()
{
	VS.TagVis.lookup = new Object();
	
	VS.TagVis.tags = new Object();
	
	/*  add new tags, reset old tags  */
	for (var i in VS.counts.t)
	{
			VS.TagVis.tags[VS.counts.t[i][1]] = VS.counts.t[i][0];
			VS.TagVis.lookup[VS.counts.t[i][1]] = i;
	}
	
	/*  BRUSHING MATRIX  */
	this.matrix = new Object();
	
	/*  get/set brushing counts  */
	for (var tag_id in VS.counts.t)
	{
		this.matrix[tag_id] = new Object();
		this.matrix[tag_id]["d"] = VS.counts.t[tag_id][3];
		this.matrix[tag_id]["l"] = VS.counts.t[tag_id][2];
		this.matrix[tag_id]["t"] = VS.counts.t[tag_id][4];
		this.matrix[tag_id]["r"] = new Object();
	}
	
	/*  results  */
	for (i in VS.results) /*  go through all results  */
	{
		var res_id = VS.results[i][1];
		var tag_ids = VS.results[i][2]["t"];
		for (var j in tag_ids) this.matrix[tag_ids[j]]["r"][res_id] = 1;
	}
		
	VS.TagVis.show();
}

/*  display current tags[] as .tags  */
TagVis.prototype.show = function()
{
	/*  set filter tags  */
	this.filtertags = new Object();

	for (var i in VS.params.t)
		if (VS.params.t[i]!=="") this.filtertags[VS.params.t[i]] = true;
		
	if (VS.count(this.filtertags)>0)
	{
		$("#t_cancel").addClass("active");
		$("#t_cancel").click(VS.TagVis.reset);
	}
	else $("#t_cancel").removeClass("active");
	
	/*  determine optimal hide_level  */
	var shown_tags = Number.POSITIVE_INFINITY;
	var optimal_hide_level = -1;
	while (shown_tags > this.tag_amount_level)
	{
		shown_tags=0;
		optimal_hide_level++;
		
		for (t in this.tags)
			if (this.tags[t]>optimal_hide_level) shown_tags++;
	}
	
	/*  determine if hide_level should be set if #hide_toggle should be shown  */
	var hide_toggle = $("#tags_hide_toggle");
	hide_toggle.click(VS.TagVis.hideToggle);
	if (this.show_all==true)
	{
		this.hide_level = 0;
		if (optimal_hide_level>0)
		{
			hide_toggle.addClass("active");
			hide_toggle.attr("title", "Hide small tags");
		}
	}
	else 
	{
		this.hide_level = optimal_hide_level;
		if (optimal_hide_level>0)
		{
			hide_toggle.removeClass("active");
			hide_toggle.attr("title", "Show all tags");
		}
	}
	if (optimal_hide_level>0) hide_toggle.animate({opacity:1}, ANI*2);
	else hide_toggle.animate({opacity:0}, ANI*2, function(){$(this).html("");});
		
	/*  determine min/max font sizes, delete tags  */
	this.count_min = Number.POSITIVE_INFINITY;
	this.count_max = 0;
	var ordered = [];
	
	for (var t in this.tags)
	{
		var id_count = this.tags[t];
		
		/*  determine count_min/_max   */
		if (typeof(this.filtertags[t])=="undefined")
		{
			if (id_count>this.count_max) this.count_max = id_count;
			if (id_count<this.count_min) this.count_min = id_count;
		}

		/*  delete tags that have no ids or do not comply to tag filter  */
		if (id_count>this.hide_level) ordered.push(t);
		else if (typeof(this.filtertags[t])=="undefined")
		{
			$("#t_"+t).animate({fontSize: 0}, ANI*2, function(){$(this).remove();});
			$("#t2_"+t).remove();
		}
	}
	/*  sort tags  */
	ordered.sort();
	
	
	/*  display tags  */
	var cloud = $("#cloud");
	var cloud2 = $("#cloud2");
	var lasttag = false;
	var fontsize = 0;
	for (i in ordered)
	{
		t = ordered[i];
		
		var count = this.tags[t];

		/*  determine fontsize   */
		if (typeof(this.filtertags[t])!=="undefined") count=this.count_max;

		var diff = this.count_max-this.count_min;		
		if (diff===0)
		{
			diff=1;
			count=1;
			this.count_min=0;
		}
		var slope = (this.size_max-this.size_min)/diff;
		fontsize = slope * count + this.size_min - slope * this.count_min;

		var tag = new Object();
		var tag2 = new Object();
		/*  tag already exists  */
 		if ($("#t_"+t).length>0)
		{
			tag = $("#t_"+t);
			tag2 = $("#t2_"+t);

			tag.animate({fontSize: fontsize+"em"}, ANI*2);
			tag2.css({fontSize: fontsize+"em"});
		}
		/*  tag is new  */
		else
		{
			/*  where to add  */
			if (lasttag==false)
			{
				cloud.prepend(' <span id="t_'+t+'">'+t.replace("/\_/g", " ")+"</span> ");
				cloud2.prepend(' <span id="t2_'+t+'">'+t.replace("/\_/g", " ")+"</span> ");
			}
			else
			{
				$("#t_"+lasttag).after(' <span id="t_'+t+'">'+t.replace("/\_/g", " ")+"</span> ");
				$("#t2_"+lasttag).after(' <span id="t2_'+t+'">'+t.replace("/\_/g", " ")+"</span> ");
			}

			tag = $("#t_"+t);
			tag2 = $("#t2_"+t);
			
			tag.animate({fontSize: fontsize+"em"}, ANI*2);
			tag2.css({fontSize: fontsize+"em"});
		}
		lasttag = t;
		
		/*  title amount  */
		
		var title_amount = "";
		if (this.tags[t]==1) title_amount="1 result tagged with "+t;
		else if (this.tags[t]>1) title_amount=this.tags[t]+" results tagged with "+t;
		tag.attr("title", title_amount);
		
		
		
		/*  events  */
		tag.unbind();
		tag.click(VS.TagVis.click);
		if (typeof(this.filtertags[t])=="undefined")
		{
			/*  brushing  */
			tag.mouseover(function(){$(this).addClass("vs_active"); VS.TagVis.hoverPrepare($(this).attr("id").substr(2));});
			tag.mouseout(VS.hoverEnd);
		}
		
		/*  set font style  */
		tag.removeClass("vs_filter_grey");
		if (typeof(this.filtertags[t])=="undefined") tag.removeClass("vs_filter");
		else tag.addClass("vs_filter");
	}
		
	/*  display filtertags if filtered too much  */
	if (ordered.length === 0)
	{
		for (t in this.filtertags)
		{
			fontsize=2;
			/*  add if new  */
			if ($("#t_"+t).length===0)
			{
				if (lasttag==false)
				{
					cloud.prepend(' <span id="t_'+t+'">'+t+"</span> ");
					cloud2.prepend(' <span id="t2_'+t+'">'+t+"</span> ");
				}
				else
				{
					$("#t_"+lasttag).after(' <span id="t_'+t+'">'+t+"</span> ");
					$("#t2_"+lasttag).after(' <span id="t2_'+t+'">'+t+"</span> ");
				}
			}

			tag = $("#t_"+t);
			tag2 = $("#t2_"+t);

			/*  update classes (item ids)  */
			tag.attr("class", "");
			tag.addClass("vs_filter_grey");
			tag.animate({fontSize: fontsize+"em"}, ANI*2);
			tag2.css({fontSize: fontsize+"em"});
			tag.click(VS.TagVis.click);
		}
	}
	
	
	/*  delete #tags if not in tags[]  */
	$("#cloud span").each(function (i)
	{
		var t = $(this).attr("id").substr(2);
		if (typeof(VS.TagVis.tags[t])=="undefined" && typeof(VS.TagVis.filtertags[t])=="undefined")
		{
			$("#t_"+t).animate({fontSize: 0}, ANI, function(){$(this).remove();});
			$("#t2_"+t).remove();
		}
	});


	/*  scale tagcloud using fontsize to avoid overflow  */
	fontsize = 10;
	cloud2.css({fontSize: fontsize+"px", width: cloud.width()});


	while (cloud2.height()>this.cloud_max_height)
	{
		fontsize-=0.25;
		cloud2.css({fontSize: fontsize+"px"});
	}
	while (cloud2.height()<this.cloud_max_height-20 && fontsize<20)
	{
		fontsize+=0.25;
		cloud2.css({fontSize: fontsize+"px"});
	}
	if (fontsize>14) {fontsize=14; cloud2.css({fontSize: fontsize+"px"});}
	
	var marginTop = (this.cloud_max_height-cloud2.height())/2;
	cloud.animate({paddingTop: marginTop, fontSize: fontsize+"px"}, ANI*2);
}

TagVis.prototype.reset = function()
{
	$(this).unbind("click");
	
	var t_params = [];
	
	for (var tid in VS.TagVis.filtertags)
	{
		$("#t_"+tid).css({backgroundColor2: "#fff"});
		$("#t_"+tid).removeClass("vs_filter");
	}
	
	/* initiate global update */
	VS.update("t", t_params, true);
}

TagVis.prototype.click = function()
{
	VS.hoverEnd();
	
	$(this).unbind("click");
	
	var tag = $(this);
	var tid = tag.attr("id").substr(2);
	
	if (typeof(tid)=="undefined") return;
	
	var filtertags = VS.TagVis.filtertags;
	
	var t_params = [];

	/*  tag is NEW filter  */
	if (typeof(filtertags[tid])=="undefined")
	{
		filtertags[tid] = true;
		tag.addClass("vs_filter");
	}
	/*  tag is OLD filter  */
	else
	{
		delete filtertags[tid];
		tag.removeClass("vs_filter");
		$("#t_"+tid).css({backgroundColor: "#fff"});
		
		/*  delete #tag if no ids attached  */
		if (VS.TagVis.tags[tid]===0)
		{
			$("#t_"+tid).animate({fontSize: 0}, ANI/2, function(){$(this).remove();});
			$("#t2_"+tid).remove();
		}
	}
	
	for (p in t_params) delete t_params[p]; 	
	for (s in filtertags) t_params.push(s);
	VS.TagVis.filtertags = filtertags;
	
	/* initiate global update */
	VS.update("t", t_params, true);
	
	tag.click(VS.TagVis.click);
}

TagVis.prototype.hideToggle = function()
{
	$(this).unbind("click");
	
	if (VS.TagVis.show_all==true) VS.TagVis.show_all=false; else VS.TagVis.show_all=true;
	
	VS.TagVis.show();
}

/*  generate tag part of title string  */
TagVis.prototype.getTitleString = function()
{
	/*  set filter tags  */
	this.filtertags = [];
	for (var i in VS.params.t)
		if (VS.params.t[i]!=="") this.filtertags[VS.params.t[i]] = true;
	
	var title = "";
	
	for (var tag in this.filtertags)
	{
		title+=tag+" ";
	}
	
	return title;
}

TagVis.prototype.hoverPrepare = function(tag)
{
	VS.hoverStart(this.matrix[this.lookup[tag]], this.tags[tag]);
}

TagVis.prototype.hoverStart = function(brushed, count)
{
	var max_opac = 0;
	var opacs = new Object();
	
	var tag_id = -1;
	
	for (var tag in this.tags)
	{
		tag_id = this.lookup[tag];
		
		if (typeof(brushed[tag_id])!=="undefined")
			opacs[tag_id] = 0.5*brushed[tag_id]/this.tags[tag] + 0.5*brushed[tag_id]/count;
		
		if (opacs[tag_id]>max_opac) max_opac = opacs[tag_id];
		if (opacs[tag_id]>0) $("#t_"+tag).addClass("vs_active");
	}
	
	for (tag in this.tags)
	{
		tag_id = this.lookup[tag];
		if (!$("#t_"+tag).hasClass("vs_filter")) $("#t_"+tag).css("opacity", 0.2 + 0.8*opacs[tag_id]/max_opac );
	}
}

TagVis.prototype.hoverEnd = function()
{
	for (var tag in this.tags) $("#t_"+tag).css({opacity: 1});
}








/*														
						RESULTS CLASS																        

*/

/* initialize variables */
function ResultVis()
{
	this.results  = new Object();	/*  results  */
	this.matrix = new Object();
	this.detail   = -1;
	this.page = 0;
	this.perpage = 70;
}

/* get initial result data from server */
ResultVis.prototype.init = function()
{
	$(".item").remove();
}

/* add new json to results[] */
ResultVis.prototype.load = function()
{
	var newresults = [];
	
	for (var i in VS.results)
	{
		var newitem = true;
		
		for (var j in VS.ResultVis.results)
		{
			/*  check if item exists already, if so, set new=0  */
			if (VS.ResultVis.results[j]["id"] == VS.results[i][1])
			{
				newitem = false;
				VS.ResultVis.results[j]["order"] = VS.results[i][0];
				VS.ResultVis.results[j]["newitem"] = 0;
			}
		}
		
		/*  if item is not there yet, add it to newresults  */
		if (newitem==true)
		{
			var item = new Object();
			
			item["newitem"] = 	1;
			item["order"] = 		VS.results[i][0];
			item["id"] = 			VS.results[i][1];
			
			item["link"] = 		VS.results[i][3];
			item["title"] = 		VS.results[i][4]; 
			item["description"]= VS.results[i][5];
			item["author"] = 		VS.results[i][6];
			item["timestamp"] = 	VS.results[i][7];
			item["date"] = 		VS.results[i][8];
			item["image"] = 		VS.results[i][9];
			item["thumb"] = 		VS.results[i][10];

			newresults.push(item);
		}
	}

	/*  set items to be removed, reset old items  */
	for (i in VS.ResultVis.results)
	{
		if (VS.ResultVis.results[i].newitem===null) VS.ResultVis.results[i].newitem=-1;
		else if (VS.ResultVis.results[i].newitem===0) VS.ResultVis.results[i].newitem=null;
	}
	
	
	/*  add new results  */
	for (i in newresults) VS.ResultVis.results[newresults[i].id] = newresults[i];
	
	/*  BRUSHING MATRIX  */
	this.matrix = new Object();
	/*  get/set brushing counts  */
	for (i in VS.results)
	{
		var res_id = VS.results[i][1];
		
		this.matrix[res_id] = new Object();
		this.matrix[res_id]["d"] = new Object();
		this.matrix[res_id]["d"][VS.results[i][2]["d"]] = 1;
		this.matrix[res_id]["l"] = new Object();
		this.matrix[res_id]["l"][VS.results[i][2]["l"]] = 1;
		this.matrix[res_id]["t"] = new Object();
		
		for (j in VS.results[i][2]["t"]) this.matrix[res_id]["t"][VS.results[i][2]["t"][j]] = 1;
	}
	
	this.show();
}

/* syncs #results with results[], bind mouseover/mouseout events */
ResultVis.prototype.show = function()
{
	$("#r_sorting").html("");
	
	var result = new Object();
	
	/*  remove old results  */
	for (var i in this.results )
	{
		if (this.results[i].newitem==-1)
		{
			result = $("#i_"+i);
			var result_inner = result.find(".inner");
			var result_bg = result.find(".bg");

			delete this.results[i];

			result.animate ({width: "0em", paddingLeft: 0, paddingRight: 0, marginLeft: 0, marginRight: 0}, ANI,
				function(){$(this).remove();});
		}
	}
	
	/*  sorting  */
	var results = [];
	for (var j in this.results) results.push(this.results[j]);
	results.sort(this.compare);

	var lastitem = -1; /*  used for ordering  */
	for (i in results )
	{
		var item = results[i];
		
		if (results[i].newitem==1)
		{
			this.results[item.id].newitem = null;
			
			var div = '<div class="item" id="i_'+item.id+'"><div class="bg"></div>';
			
			/*  image/thumb  */
			var bg_img ="";

			if (item.thumb!==null && item.thumb!=="")
			bg_img = 'style=\'background: transparent url("'+item["thumb"]+'") center;\'';
			else if (item["image"]!==null && item["image"]!=="") 
				bg_img = 'style=\'background: transparent url("'+item["image"]+'") center;\'';
			div+='<div class="inner" '+bg_img+'>';
			//div+='<div class="inner">';

			if (DET_ID) div+=item.id+'<br />';
			if (item.title===null) item.title="untitled";
			div+='<a target="_blank" href="'+item.link+'"><span class="title">'+item.title+'</span></a></div></div>';
			
			/* order */
			if (lastitem==-1) $("#result_list").prepend(div); /* add to beginning of #results */
			else $("#i_"+results[lastitem]['id']).after(div); /* add after precursor */
			lastitem = i;
			
			/*  events  */
			result = $("#i_"+item.id);
			
			result.find(".inner").hover(function()
			{
				/*  brushing  */
				var res_id = $(this).parent().attr("id").split("_")[1];
				VS.hoverStart(VS.ResultVis.matrix[res_id], 1);
				
				VS.ResultVis.detail=res_id;
				VS.ResultVis.showDetail();
			},
			function()
			{
				VS.hoverEnd();
				VS.ResultVis.hideDetail();
				VS.ResultVis.detail=-1;
			});

			/* display image */
			$("#i_"+item.id+" .bg").css("opacity", 1);

			result.animate({width: "7em"}, ANI);
		}
		/* untouched items */
		else
		{
			result = $("#i_"+item.id);
			
			if (lastitem==-1) result.appendTo("#result_list");
			else result.insertAfter("#i_"+results[lastitem]['id']);
			
			lastitem = i;
		}
	}

	/*  pagination  */
	
	var perpage = VS.params.o[2];
	var total = VS.total;
	var current_page = VS.params.o[3];
	var actual = results.length;
	
	if (total<=perpage) $("#r_pagination").animate({opacity:0}, ANI);
	else if (total>perpage && actual>0)
	{
		var pages = Math.ceil(total/perpage);
		
		$("#r_pagination").html('<span title="Go to previous page" class="arrow1">&nbsp;</span> <span id="r_pages"></span> <span title="Go to next page" class="arrow2">&nbsp;</span>');
	
		
		/*  arrows  */
		var arrow1 = $("#r_pagination span.arrow1");
		var arrow2 = $("#r_pagination span.arrow2");
		
		if (current_page>0)
		{
			arrow1.addClass("active");
			arrow1.click(function(){ VS.params.o[3]--; VS.update("o", VS.params.o, true); });
		}
		else arrow1.removeClass("active");

		if (current_page<pages-1)
		{
			arrow2.addClass("active");
			arrow2.click(function(){ VS.params.o[3]++; VS.update("o", VS.params.o, true); });
		}
		else arrow2.removeClass("active");
		
		/*  page links  */		
		for (i=0; i < pages; i++)
		{
			$("#r_pages").append("<span id='page_"+i+"'>"+(i+1)+"</span> ");

			if (i==current_page) /*  current page  */
			{
				$("#page_"+i).css({fontWeight: "bold"});
				
			}
			else /*  other pages  */
			{
				$("#page_"+i).css({fontWeight: "normal", textDecoration: "underline", cursor: "pointer"});
				
				$("#page_"+i).click(function(){
					VS.params.o[3] = $(this).attr("id").split("_")[1];
					VS.update("o", VS.params.o, true);
				});
			}
			
			if (i>28) { $("#r_pages").append(" ... "); i=pages+1;}
		}
	
		$("#r_pagination").animate({opacity:1}, ANI);
	}
	

	$("#r_amount").html(total);
	
	/*  sorting  */
	if (actual>0) 
	{
		var criterium = VS.params.o[0];
		var desc = VS.params.o[1];

		$("#r_sorting").html('<span class="time">time</span> <span class="arrow0">&nbsp;</span> <span class="title">title</span> <span class="arrow1">&nbsp;</span>');
		
		var time = $("#r_sorting .time");
		var title = $("#r_sorting .title");
		
		if (criterium===0 || criterium==="0") /*  time sorting  */
		{
			time.addClass("active");
			if ((desc===0) || (desc==="0")) $("#r_sorting .arrow0").addClass("desc0");
			else $("#r_sorting .arrow0").addClass("desc1");
			
			/*  click event for desc  */
			$("#r_sorting .arrow0").attr("title", "Change sorting order");
			$("#r_sorting .arrow0").click(function(){
				if ($(this).hasClass("desc0")) VS.params.o[1] = 1;
				else VS.params.o[1] = 0;
				VS.update("o", VS.params.o, true);
			});

			title.attr("title", "Sort by title");
			
			/*  click event for title  */
			title.click(function()
			{
				VS.params.o[0] = 1;
				VS.update("o", VS.params.o, true);
			});
			
		}
		else /*  title sorting  */
		{
			title.addClass("active");
			if ((desc===0) || (desc==="0")) $("#r_sorting .arrow1").addClass("desc0");
			else $("#r_sorting .arrow1").addClass("desc1");
			
			/*  click event for desc  */
			$("#r_sorting .arrow1").attr("title", "Change sorting order");			
			$("#r_sorting .arrow1").click(function(){
				if ($(this).hasClass("desc0")) VS.params.o[1] = 1;
				else VS.params.o[1] = 0;
				VS.update("o", VS.params.o, true);
			});

			time.attr("title", "Sort by time");
			
			/*  click event for title  */
			time.click(function(){
				VS.params.o[0] = 0;
				VS.update("o", VS.params.o, true);
			});
		}
	}
	
	/*  not items  */
	if (actual===0) $("#r_amount").html('There are no items complying to your query. Relax some of the parameters using the reset buttons: <img src="'+VS.base+'img/controls/cancel.png">');
}

/* compare two results[] entries according to order */
ResultVis.prototype.compare = function(a, b)
{
	return a.order-b.order;
}

ResultVis.prototype.showDetail = function()
{
	var item = this.results[this.detail];

	var result = $("#i_"+item["id"]);
	var result_inner = $("#i_"+id).find(".inner");
	var det = $("#det");
	var id = this.detail;
		
	det.stop(); /* stop animations */
	det.empty(); /* remove previous detail */

	/* add details to #det */
	if (item['image']!==null && item['image']!=="")	det.append('<img src="'+item['image']+'">');
	det.append('<h3>'+item["title"]+"</h3>");
	det.append('<p>'+item["description"]+"</p>");
	
	var date_string = "";
	
	var date_a = item['date'].split(" ")[0].split("-");
	if (Number(date_a[2])!==0) date_string = VS.DateVis.monthWord[Number(date_a[1])] + " "+Number(date_a[2])+", "+date_a[0];
	else date_string = VS.DateVis.monthWord[Number(date_a[1])] + " "+date_a[0];
	
	var author = "";
	if (typeof(item['author'])!=="undefined" && item['author']!=="" && item['author']!==null)
		author = " by " + item['author'];

	det.append('<small>' + date_string + author );
	
	det.css({display: "block", opacity: 1});
	
	this.moveDetail();
}

ResultVis.prototype.moveDetail = function()
{
	if (this.detail>0)
	{
		var det = $("#det");
		var det_width  = det.outerWidth(); 
		var det_height = det.outerHeight();

		var window_height = 	$(window).height();
		var window_width = 	$(window).width();
		
		/*  decisions if detail should be put on left/upper side  */
		var det_left_flip = 0;
		var det_top_flip  = 0;

		if ( (VS.x+det_width+DET_X) > ( window_width ) ) det_left_flip = -det_width -  2*DET_X+5;
		
		if ( (VS.y+det_height+2*DET_Y) > ( window_height )) 
		{
			if (VS.y-det_height > 375) det_top_flip  = -det_height - 2*DET_Y;
			else det_top_flip  = -VS.y -det_height -DET_Y +window_height -DET_Y;
		}
		
		var det_left = {left: VS.x+DET_X+det_left_flip};
		var det_top = {top: VS.y+DET_Y+det_top_flip};

		det.css(det_top); 
		det.css(det_left); 
	}
}

ResultVis.prototype.hideDetail = function()
{
	
	
	$("#det").css({opacity: 0, display: "none"});
}

ResultVis.prototype.hoverStart = function(brushed, count)
{
	for (var id in brushed) $("#i_"+id).addClass("vs_active");
}

ResultVis.prototype.getIdsString = function()
{
	var id_str = "";
	for (var id in this.results) id_str+=id+",";
	
	if (id_str.length>0) 
	{
		id_str="r:"+id_str;
		id_str=id_str.substring(0, id_str.length-1);
	}

	return id_str;
}
