/*	usemedia.com . joes koppers . 07-09.2008
	thnx for reading this code */


/*	310K grid layout
*/

function Grid(dev)
{
	var obj = this;
	
	//defaults
	this.name = '310K';
	this.version = '1.0';
	this.language = 'en';
	this.mode = (dev)? 'test':'production';
	
	//initialize server comm
	this.server = XHR.init('','');
	
	//build GUI
	this.scale = 100; //default itemsize
	this.defaultsize = 'large';
	this.addLayout();
	
	//get items from database
	this.server.get('page=json.projects',function(rsp) { obj.serverRsp(rsp) });
}

Grid.prototype.serverRsp = function(rsp)
{
	/*	parse server response
	*/
	
	this.itemurl = rsp.itemurl;
	
	this.thumbpath = rsp.thumbpath;
	this.thumbname = rsp.thumbname;
	
	//item types
	this.types = rsp.types;
	this.layout.addTypeSelect(this.types);
	
	//add items
	this.addItems(rsp.items);
}

Grid.prototype.setState = function()
{
	/*	default state of grid
	*/
	
	this.selectSize(this.defaultsize,true);
	
	//sorting default
	this.sorting = { defaulttype:'date', A:0, B:0, C:0, r:0, g:0, b:0 };
	this.selectFilter(this.sorting.defaulttype,true);

	this.layout.searchinput.value = '';
	this.layout.select.value = 'all';
	this.selectType('all');
	
	this.layout.resetSliders();

	//this.sort(this.sorting.defaulttype);
}

Grid.prototype.addLayout = function()
{
	/*	create grid and gui
	*/
	
	function Layout(parent)
	{
		this.parent = parent;
		
		this.div = document.getElementById('centered');
		this.div.style.width = '100%';
		this.div.style.height = '100%';
		
		this.fade = document.getElementById('transition');
		this.faded = 0;

		//grid layout
		this.margin = { top:73, right:0, bottom:100, left:24 }
		this.padding = 0;
		this.min_width = 800;
		this.min_height = 500;
		
		this.grid = document.getElementById('grid-container');
		this.grid.style.margin = this.margin.top+'px '+this.margin.right+'px '+this.margin.bottom+'px '+this.margin.left+'px';

		this.div.style.minWidth= this.min_width + this.margin.left +'px';
		this.div.style.minHeight= this.min_height + this.margin.top + this.margin.bottom +'px';

		//home/close project button
		this.addBackButton();
		
		//controls pane
		this.addControls(200,100);
		
		//result display
		this.addDisplay();
		
		//item page
		this.page = document.getElementById('item-page');
		this.page.style.top = this.margin.top +1 +'px';
		this.page.style.left = this.margin.left +1 +'px';
		
		//set initial dimensions
		this.resize();
	
		//window resize event
		var obj = this;
		window.onresize = function() { obj.resize() }
	}
	
	Layout.prototype.addBackButton = function()
	{
		var img = document.createElement('img');
			img.id = 'back';
			img.src = 'media/home.png';
		
		var obj = this.parent;
		img.onmouseover = function() { this.src = this.src.replace('.png','X.png') };
		img.onmouseout = function() { this.src = this.src.replace('X.png','.png') };
		img.onclick = function() { obj.selectItem() };
		
		this.back = img;
		this.div.appendChild(img);
		
		//attach sliding anim
		var update = function(values) { img.style.left = values[0] +'px' };
		
		img.anim = this.addAnimation(update,undefined,.3);
	}
	
	Layout.prototype.addDisplay = function()
	{
		var div = document.createElement('div');
			div.id = 'result';
			
		document.getElementById('layout').appendChild(div);
		this.display = div;
	}
	
	Layout.prototype.addAnimation = function(update,callback,speed,margin)
	{
		/*	return a slide object
		*/
		
		function Slide(update,callback,speed,margin)
		{
			this.sliding = false;
			this.speed = speed || 0.35;
			this.margin = margin || 1;

			this.update = update; //called during slide with current values as array
			this.callback = callback;
		}
		
		Slide.prototype.start = function()
		{
			/*	init and start slide,
				param = (value,targetvalue) pairs */
				
			this.values = new Array();
			this.tvalues = new Array();
		
			for (var i=0; i<arguments.length; i+=2)
			{
				this.values[i] = arguments[i];
				this.tvalues[i] = arguments[i+1];
			}

			this.slide();
		}
		
		Slide.prototype.slide = function()
		{
			var update = false;

			for (var i=0; i<this.values.length; i++)
			{
				var d = this.tvalues[i]-this.values[i];
				this.values[i] += this.speed*(d);
				var upd = (d>0 && this.values[i]<this.tvalues[i]-this.margin) || (d<0 && this.values[i]>this.tvalues[i]+this.margin);
				if (upd) update = true;
			}

			if (update)
			{
				this.update(this.values);
				//loop
				var obj = this;
				this.sliding = window.setTimeout(function() { obj.slide() },40);
			}
			else
			{
				//done, set to exact end target position
				for (var i=0; i<this.values.length; i+=2) this.values[i] = this.tvalues[i];
				this.update(this.values);
				
				if (this.callback) this.callback();
				this.sliding = false;
			}
		}
		
		return new Slide(update,callback,speed,margin);
	}
	
	Layout.prototype.addControls = function(x,y)
	{
		/*	controls GUI
		*/
		var div = document.createElement('div');
			div.id = 'view-controls';
		this.grid.appendChild(div);
		this.ctrls = div;
		
		if (x)
		{
			this.ctrls.x = x;
			div.style.left = x +'px';
		}
		if (y)
		{
			this.ctrls.y = y;
			div.style.top = y +'px';
		}
		
		//size select
		var grid = this.parent;
		var small = document.createElement('img');
			small.id = 'size-select-small';
			small.className = 'size-select';
			small.src = 'media/size_select_small.png';
		small.onmouseover = function() { if (grid.scale!=50) this.src = 'media/size_select_smallX.png' }
		small.onmouseout = function() { if (grid.scale!=50) this.src = 'media/size_select_small.png' };
		small.onclick = function() { grid.selectSize('small') };

		var large = document.createElement('img');
			large.id = 'size-select-large';
			large.className = 'size-select';
			large.src = 'media/size_select_largeXX.png'; //default size
		large.onmouseover = function() { if (grid.scale!=100) this.src = 'media/size_select_largeX.png' }
		large.onmouseout = function() {  if (grid.scale!=100) this.src = 'media/size_select_large.png' }
		large.onclick = function() { grid.selectSize('large') };

		div.appendChild(small);
		div.appendChild(large);
		
		//color display
		var display = document.createElement('div');
			display.id = 'color-display';

		div.appendChild(display);
		
		//ABC and rgb sliders
		this.sliders = new Object();

		this.createSlider('A','vertical',{ left:'11px', top:'53px' },10,0,function(type,value) { grid.sliderCallback(type,value) } );
		this.createSlider('B','vertical',{ left:'38px', top:'53px' },10,0,function(type,value) { grid.sliderCallback(type,value) } );
		this.createSlider('C','vertical',{ left:'65px', top:'53px' },10,0,function(type,value) { grid.sliderCallback(type,value) } );

		this.createSlider('r','vertical',{ left:'104px', top:'53px' },25,0,function(type,value) { grid.sliderCallback(type,value) } );
		this.createSlider('g','vertical',{ left:'131px', top:'53px' },25,0,function(type,value) { grid.sliderCallback(type,value) } );
		this.createSlider('b','vertical',{ left:'158px', top:'53px' },25,0,function(type,value) { grid.sliderCallback(type,value) } );
		
		//selected filter indication
		var img = document.createElement('img');
			img.id = 'filter-selected';
			img.src = 'media/greendot.png';
		div.appendChild(img);
		
		//search
		var search = document.createElement('input');
			search.id = 'search';
		div.appendChild(search);	
		this.searchinput = search;

		//master reset
		var img = document.createElement('img');
			img.id = 'master-reset';
			img.src = 'media/reset.png';
			img.onmousedown = function() { this.src = 'media/resetX.png' };
			img.onclick = function() { grid.setState() };
			img.onmouseup = function() { this.src = 'media/reset.png' };
		div.appendChild(img);
	}
	
	Layout.prototype.addTypeSelect = function(types)
	{
		/*	type select element
		*/
		var obj = this.parent;
		
		var select = document.createElement('select');
			select.id = 'type-select';
			select.onchange = function() { obj.selectType(this.value) };

		this.ctrls.appendChild(select);
		
		var str = '';
		types.splice(0,0,'all');
		for (var i=0; i<types.length; i++)
		{
			select.options[i] = new Option(types[i],types[i],false,false);
		}
		
		this.select = select;
	}
	
	Layout.prototype.createSlider = function(id,type,style,min,max,callback)
	{
		/*	slider control elm (note horizontal style is not implemented)
		*/
		var filter = (String('ABC').indexOf(id)!=-1) ? 'ABC':'rgb';

		var ctls = document.createElement('div');
			ctls.className = 'slider slider-'+type;
			for (p in style) ctls.style[p] = style[p];
		var bg = document.createElement('img');
			bg.style.left = '10px';
			bg.style.top = '0px';
			
		var c = (id=='r' || id=='g' || id=='b')? '_'+id:'';
			
			bg.src = 'media/slider_bg_'+type+c+'.png';
			bg.onmousedown = function() { return false }; //prevent drag select on safari/firefox
		var handle = document.createElement('img');
			handle.style.left = '0px';
			handle.style.top = '45px';
			handle.style.cursor = 'pointer';
			handle.style.width = '9px';
			handle.style.height = '11px';
// 			handle.onmouseover = function() { this.src = 'media/slider_handleX.png' }
// 			handle.onmouseout = function() { if (!DD_dragging) this.src = 'media/slider_handle.png' }
			handle.src = 'media/slider_handle.png';
			
		var obj = this;
		var drag = makeDragableItem(handle);
			drag.id = id;
			drag.setEnabled(true,false,true); //y-only
			drag.setRange('y',true,45,0);
			drag.appearance = function(d) { this.elm.src = d ? 'media/slider_handleX.png':'media/slider_handle.png'; }
			drag.ondragstart = function() { obj.parent.selectFilter(filter); document.body.style.cursor = 'pointer' }
			drag.dragging = function()
			{	
				var value = type=='horizontal' ? this.x:this.y;
				value = min + Math.round((value/45) * (max-min));
				
				if (callback) callback(this.id,value);
			}
			drag.drop = function() { document.body.style.cursor = 'auto' }
			
		ctls.appendChild(bg);
		ctls.appendChild(handle);
		
		this.ctrls.appendChild(ctls);
		this.sliders[id] = drag;
	}

	Layout.prototype.resetSliders = function()
	{
		for (id in this.sliders) this.sliders[id].rset();
		//reset color display
		document.getElementById('color-display').style.backgroundColor = 'rgb(0,0,0)';
	}

	Layout.prototype.resize = function()
	{
		/*	cross browser document body dimensions
		*/
		this.w = (window.innerWidth!=null)? window.innerWidth:(document.documentElement && document.documentElement.clientWidth)? document.documentElement.clientWidth:(document.body!=null)? document.body.clientWidth:0;
		this.h = (window.innerHeight!=null)? window.innerHeight:(document.documentElement && document.documentElement.clientHeight)? document.documentElement.clientHeight:(document.body!=null)? document.body.clientHeight:0;

		this.updateGrid();
	}
	
	Layout.prototype.transition = function(reset)
	{
		/*	fade-in background for expanded item
		*/
		
		if (reset)
		{
			this.faded = 0;
			this.fade.style.opacity = this.faded;
			this.fade.style.display = 'none';	
			this.page.style.display = 'none';
			this.back.src = 'media/home.png';
			return;
		}
		
		if (this.faded<1)
		{
			var obj = this;

			if (this.faded==0)
			{
				/*	init transition
				*/
				var item = this.parent.db_items[this.parent.item];
				var c = 'rgb('+item.r+','+item.g+','+item.b+')';
				this.setPageBg('#'+item.bg);
				this.fade.style.display = 'block';
				
				//slide in/out back button
				this.back.anim.callback = function() { 
					//slide back into view
					obj.back.src = 'media/close.png';
					delete obj.back.anim.callback;
					obj.back.anim.start(-140,22);
				}
				this.back.anim.start(22,-140);
				
			}
		
			this.faded += .13;
			if (typeof(document.body.style.filter)=='string')
			{
				this.fade.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+(this.faded*100)+')'; //IE 7
			}
			else
			{
				this.fade.style.opacity = this.faded;
			}
			var obj = this;
			window.setTimeout(function() { obj.transition() },60);
		}
		else
		{
			this.page.style.display = 'block';
		}
	}
	
	Layout.prototype.setPageBg = function(c)
	{
		this.fade.style.backgroundColor = c;
		this.page.style.backgroundColor = c;
	}
	
	Layout.prototype.updateGrid = function()
	{
		/*	calculate avail item rows and colums 
		*/
		var s = this.parent.scale;
		var availw = this.div.offsetWidth - this.margin.left;
		var availh = this.div.offsetHeight;
		var p = this.margin.top + this.margin.bottom;
		
		this.cols = Math.floor((availw)/s);
		this.rows = Math.floor((availh-p)/s);
		
		//max amount of items on grid
		var skipped = this.parent.scale==100? 6:24; //space taken by view-controls
		this.items = (this.cols*this.rows) - skipped;
		
		//adjust cols to keep controls centered (even amount for scale 50, odd for scale 100)
// 		if ((this.parent.scale==100 && !(this.cols % 2)) || (this.parent.scale==50 && (this.cols % 2)))
// 		{
// 			dbg.msg('adjusting cols..');
// 			this.cols--;
// 		}
		
		//update grid
		this.grid.style.width = (this.cols * s) +'px';
		this.grid.style.height = (this.rows * s) +'px';
	
		//update item page 
		this.page.style.width = (document.getElementById('layout').offsetWidth - this.margin.left - 1) +'px';
		this.page.style.height = (document.getElementById('layout').offsetHeight - this.margin.top - 1) +'px';
		
		//keep layout centered
// 		this.grid.style.left = (availw-(this.cols * s))/2 +'px';
// 		this.page.style.left = (availw-(this.cols * s))/2 +'px';
// 
// 		//centered controller area
// 		var x = ((this.cols * this.parent.scale)-300)/2;
// 		var y = 200;
// 		
// 		this.ctrls.style.left = x + this.padding +'px';
// 		this.ctrls.style.top = y + this.padding +'px';
// 		this.ctrls.x = x;
// 		this.ctrls.y = y;
		
		if (this.parent.sorted) this.displayItems();
	}
	
	Layout.prototype.displayItems = function()
	{
		/*	add item elements to grid container, clear first
		*/
		//clear		
		while (this.grid.childNodes.length>2) this.grid.removeChild(this.grid.lastChild);

		//add
		var i = 0;
		var p = this.padding;
		for (var r=0; r<this.rows; r++)
		{
			for (var c=0; c<this.cols; c++)
			{
				if (i==this.parent.sorted.length) break; //we're done
				
				var x = c * this.parent.scale;
				var y = r * this.parent.scale;
				
				if (y>=this.ctrls.y && y<this.ctrls.y+200 && x>=this.ctrls.x && x<this.ctrls.x+300) continue; //no items under view-controls

				var item = this.parent.items[this.parent.sorted[i].id].img;
					item.style.left = x+p +1 +'px';
					item.style.top = y+p +1 +'px';
				
				this.grid.appendChild(item);
				
				i++;
			}
		}
		
		//update count
		this.display.innerHTML = 'You are viewing '+i+' of '+this.parent.count+' projects, use the filters to see them all!';
	}
	
	/*	init
	*/
	this.layout = new Layout(this);
}


Grid.prototype.addItems = function(items)
{

	//create items
	this.db_items = new Object(); //all items from db
	this.items = new Object(); //selected items (by type / search match)
	this.sorted = new Array();
	this.count = items.length;

	var obj = this;
	var s = this.scale;//default size
	var size = this.scale==50 ? '_48':'_98';

	for (var i=0; i<items.length; i++)
	{
		var id = items[i].id;
		var img = document.createElement('img');
			img.className = 'thumb';
			img.id = 'item_'+id;
			img.style.backgroundColor = 'rgb('+items[i].r+','+items[i].g+','+items[i].b+')';
			img.title = items[i].title;
			img.onclick = function() { obj.selectItem(this.id) }

		this.db_items[id] = items[i];
		this.db_items[id].img = img;
	}

	//start state of grid
	this.setState();
	
	//add search
	this.addSearch();
}

Grid.prototype.addSearch = function()
{
	/*	keyword and text search (client-side)
	*/
	this.search = 
	{
		parent: this,
		items: this.items,
		ignoreKeys: {9:'tab',16:'shift',17:'ctrl',18:'alt',224:'apple',37:'arrow',38:'arrow',39:'arrow',40:'arrow'},

		init: function()
		{
			var obj = this;
			this.inputfield = this.parent.layout.searchinput;
			this.inputfield.onkeydown = function(e) { obj.keyDown(e) };
		},

		keyDown: function(e)
		{
			if (!e) e = event;
			if (e.keyCode==13) return this.input('last') ; //enter key
			if (this.ignoreKeys[e.keyCode]) return e.returnValue;
			else
			{
				var obj = this;
				window.setTimeout(function() { obj.find() },10);
				return e.returnValue;
			}
		},
		
		input: function(type)
		{
			/*	form submit handling, add space so last word is search with wordbounderies
			*/
			this.inputfield.value = this.inputfield.value+' ';
			return false;
		},
				
		find: function()
		{
			var searchstr = this.inputfield.value;
			var searchmode;
		
			//clear search?
			if (searchstr.length<=1)
			{
				this.rset();
				return;
			}
			else
			{
				this.active = true;
			}
			
			//quoted search?
			var quote = new RegExp('\"','g');
			var quotes = searchstr.match(quote);
			var quoted = new Array();
			if (quotes && quotes.length>1)
			{
				//find pairs
				for (var i=0; i<quotes.length-1; i+=2)
				{
					var firstquote = searchstr.indexOf('"');
					var secondquote = searchstr.indexOf('"',firstquote+1);
					//substract quoted portion
					quoted[i/2] = searchstr.substring(firstquote+1,secondquote);
					//update searchstring
					searchstr = searchstr.substr(0,firstquote) + searchstr.substr(secondquote+1);
				}
			}
				
			//perform search
			if (searchstr.length>1 || quoted.length>0)
			{
				var searchstrings = new Array();
				
				//one or multi search-terms
				if (searchstr.indexOf(' ')==-1) searchstrings[0] = (searchstr.indexOf('"')==-1)? searchstr:searchstr.substr(1); //strip first quote
				else searchstrings = searchstr.split(' ');
			
				var results = new Array();
					
				var s = 0;
				for (var id in this.items)
				{
					if (typeof(this.items[id])!='object' || id=='selection') continue;
				
					results[s] = { id:id, match:0 };
					
					//find matches
					
					searchmode = 'AND';
					quoted_matchloop:
					for (var i=0; i<quoted.length; i++)
					{
						if (quoted[i]=='') continue quoted_matchloop;
						
						// 'AND' searchmode
						if (searchmode=='AND' && i>0 && results[s].match==0) continue quoted_matchloop;
						
						var regexp = new RegExp('\\b'+quoted[i]+'\\b','gi'); //with word bounderies
						matches = this.items[id].title.match(regexp);
						if (matches) results[s].match += matches.length;
						else if (searchmode=='AND' && i>0) results[s].match = 0;
					}
		
					searchmode = 'OR';
					matchloop:
					for (var i=0; i<searchstrings.length; i++)
					{
						if (searchstrings[i].length<=1 || searchstrings[i]==' ') continue matchloop;
		
						//remove first quote if any
						if (searchstrings[i].indexOf('"')==0) searchstrings[i] = searchstrings[i].substr(1);
		
						//use wordbounderies if multiple words and not the last word
						if (searchstrings.length!=1 && i<searchstrings.length-1) var regexp = new RegExp('\\b'+searchstrings[i]+'\\b','gi');
						else var regexp = new RegExp(searchstrings[i],'gi');
						
						matches = this.items[id].title.match(regexp);
						if (matches) results[s].match += matches.length;
					}
					this.items[id].found = (results[s].match!=0)? true:false;
					
					s++;
				}
				
				//sort
				results.sort( function(a,b) { return b.match-a.match } );
	
				this.found(results);
			}
		},
		
		rset: function(norefresh)
		{
			/*	clear search, update display to previous section (selection)
			*/
			if (!this.active) return;
			
			
			this.active = false;
			if (!norefresh) this.parent.selectType(this.parent.layout.select.value);
		},
		
		found: function(results,rset)
		{
			//clear current selection
			delete this.parent.items;
			this.parent.items = new Object();
	
			for (var i=0; i<results.length; i++)
			{
				if (results[i].match==0) break; //no more matches
				
				var id = results[i].id;
				this.parent.items[id] = this.parent.db_items[id];
			}
			

			//display items
			this.parent.sort(this.parent.sorting.type || this.parent.sorting.defaulttype);
		}
	}
	
	this.search.init();
}

Grid.prototype.selectSize = function(type,force)
{
	switch (type)
	{
		case 'small':
			if (this.scale==50 && !force) return;
			this.scale = 50;
			document.getElementById('size-select-small').src = 'media/size_select_smallXX.png';
			document.getElementById('size-select-large').src = 'media/size_select_large.png';
			this.layout.grid.style.backgroundImage = 'url(media/thumb_bg_50.gif)';
			break;

		case 'large':
			if (this.scale==100 && !force) return;
			this.scale = 100;
			document.getElementById('size-select-small').src = 'media/size_select_small.png';
			document.getElementById('size-select-large').src = 'media/size_select_largeXX.png';
			this.layout.grid.style.backgroundImage = 'url(media/thumb_bg_100.gif)';
			break;
	}

	this.resizeItems(this.scale);
}

Grid.prototype.selectFilter = function(type,noupdate)
{
	if (this.sorting.type==type) return;
	
	this.sorting.type = type;
	
	var x = (type=='ABC')? 72:165;
	var dot = document.getElementById('filter-selected');
		dot.style.left = x +'px';
		dot.style.visibility = type!='date'? 'visible':'hidden';
		
	if (!noupdate) this.sort(type);
}	

Grid.prototype.selectType = function(type)
{
	/*	add all db_items matching type to this.items
	*/

	//clear
	delete this.items;
	this.items = new Object();

	//add
	for (var id in this.db_items)
	{
		if (type=='all' || this.db_items[id].type[type])
		{
			this.items[id] = this.db_items[id];
		}
	}
	
	//update search db
	if (this.search) this.search.items = this.items;
	//clear search input
	this.layout.searchinput.value = '';

	//display
	this.sort(this.sorting.type || this.sorting.defaulttype);
}

Grid.prototype.resizeItems = function(s)
{
	//this.scale = s;
	var size = this.scale=='50' ? '48':'98';
	
	for (var id in this.db_items)
	{
		//this.db_items[id].img.src = this.thumbpath + this.thumbname + id + size +'.jpg';
		this.db_items[id].img.src = this.thumbpath + this.db_items[id]['thumb_'+size];
		this.db_items[id].img.style.width = size +'px';
		this.db_items[id].img.style.height = size +'px';
	}
	
	this.layout.updateGrid();
}

Grid.prototype.sliderCallback = function(type,value)
{
	
	//return;
	var filter = (String('ABC').indexOf(type)!=-1) ? 'ABC':'rgb';
	
	//update required?
	if (this.sorting[type]==value) return;
	
	//update
	this.sorting.type = filter;
	this.sorting[type] = value;
	
	if (filter=='rgb')
	{
		//update color display
		var color = 'rgb('+this.sorting.r*10+','+this.sorting.g*10+','+this.sorting.b*10+')';
		var elm = document.getElementById('color-display');
		elm.style.backgroundColor = color;
	}
	
	//apply
	this.sort(filter);
}

Grid.prototype.sort = function(type)
{
	/*	sort items by filter or color
	*/
	
	var ranking = new Array();
			
	switch (type)
	{
		case 'ABC':
			/*	ordered sort
			*/
			var tA = this.sorting.A;
			var tB = this.sorting.B;
			var tC = this.sorting.C;

			var order = [ { id:'A', value:tA },{ id:'B', value:tB },{ id:'C', value:tC } ];
				order.sort( function(a,b) { return b.value - a.value } );
				order = order[0].id + order[1].id + order[2].id;
			var byOrder = function(a,b) { return sortByOrder(a,b,order) }

			for (var id in this.items)
			{
				var item = this.items[id];
				var A = Math.abs(tA - item.A);
				var B = Math.abs(tB - item.B);
				var C = Math.abs(tC - item.C);

				ranking.push( { id:id, A:A, B:B, C:C } );
			}

			ranking.sort(byOrder);
			break;

		case 'rgb':
			/*	average sort
			*/
			var tr = this.sorting.r;
			var tg = this.sorting.g;
			var tb = this.sorting.b;
						
			for (var id in this.items)
			{
				var item = this.items[id];
				var r = Math.abs(tr - Math.round(item.r/10));
				var g = Math.abs(tg - Math.round(item.g/10));
				var b = Math.abs(tb - Math.round(item.b/10));

				ranking.push( { id:id, ave:(r+g+b) } );
			}

			ranking.sort(sortByAverage);
			break;
			
		case 'date':
			/*	date sort
			*/
			for (var id in this.items)
			{
				var item = this.items[id];
				ranking.push( { id:id, date:Number(item.date) } );
			}

			ranking.sort(sortByDateDesc);
			break;
	}

	//display sorted items
	this.sorted = ranking;
	this.layout.displayItems();
	
	/*	local (numeric) sort functions
	*/
	function sortByDateDesc(a,b) { return (b.date - a.date) };
	function sortByAverage(a,b) { return (a.ave - b.ave) };
	function sortByOrder(a,b,order)
	{
		var o1 = order.substring(0,1);
		var o2 = order.substring(1,1);
		var o3 = order.substring(2,1);
	
		if (a[o1]!=b[o1]) return a[o1]-b[o1];
		else if (a[o2]!=b[o2]) return a[o2]-b[o2];
		else return a[o3]-b[o3];
	}
}

Grid.prototype.selectItem = function(id)
{
	/*	select / un-select an item, 
		update and show iframe contents */

	if (id==undefined)
	{
		if (!this.item)
		{
			/*	return to main 310k.nl page
			*/
			window.location = '../';
		}
		else
		{
			//un-select
			delete this.item;
			this.layout.page.src = 'empty.php';

			//reset fade, hide item page
			this.layout.transition(true);
		}
		return;
	}

	this.item = id.substr(5);

	//load item page 	
 	this.layout.page.src = this.itemurl + this.item;
 	
 	//fade to item color, show item page when done
 	this.layout.transition();
}