function ViewControl( cont, first ){
	if( typeof( cont ) == "string" ) cont = document.getElementById( cont );
	var VC = {};
	VC.curr = null;
	VC.busy = false;
	VC.show = function( e ){
		if( typeof( e ) == "string" ) e = document.getElementById( e );
		if( !e ) throw "Element not found '" + e + "'";
		else if( e != VC.curr && !VC.busy ){
			VC.busy = true;
			if( e.onshow ) e.onshow( e );
			DOM.ToggleSmooth( VC.curr, e, function(){ VC.busy=false; } );
			if( VC.curr && VC.curr.onhide ) VC.curr.onhide( VC.curr );
			VC.curr = e;
		}
	};
	return VC;
};
function SlideShow( container, slideTime ){
	var c = container.childNodes;
	for( var i = 0; i < c.length; i++ ) DOM.toggleElement( c[i], (i == 0) );
	var curr = container.firstChild;
	setInterval( function(){
		var next = ( curr.nextSibling ) ? curr.nextSibling: container.firstChild;
		DOM.ToggleSmooth( curr, next );
		curr = next;
	}, slideTime );
};

function DataObject( name, arr, cbInsert ){
	this.name = name;
	this.data = [];
	
	var tmpFunc = [ "({ieFix:function(o){", "}})" ];
	for( var x = 0; x < arr.fields.length; x++ ) tmpFunc.splice( x + 1, 0, "this." + arr.fields[ x ] + "=o[" + x + "]||null;" );
	tmpFunc = eval( tmpFunc.join("") );
	var dataProto = tmpFunc.ieFix;// NOW THATS SICK SHIT DUDE!
	
	for( var i = 0; i < arr.data.length; i++ ){
		var o = new dataProto( arr.data[ i ] );
		this.data.push( o );
		if( cbInsert ) cbInsert( o );
	}
};
DataObject.prototype.getById = function( id ){
	return this.getByIndex( this.findIndexById( id ) );
};
DataObject.prototype.findIndexById = function( id ){
	if( this.data.length > 0 ){
		for( var i = 0; i < this.data.length; i++ ) if( this.data[i].ID == id ) return i;
		throw "ID not found ("+id+")";
	}else throw "Data not initialized (" + this.name + ")";
	return -1;
};
DataObject.prototype.getByIndex = function( i ){
	if( i < 0 && i >= this.data.length ) return null;
	else return this.data[ i ];
};

DataObject.prototype.add = function( data, cbSuccess, cbFailure ){ this.commit( "INSERT", data, cbSuccess, cbFailure ); };
DataObject.prototype.remove = function( data, cbSuccess, cbFailure ){ this.commit( "REMOVE", data, cbSuccess, cbFailure ); };
DataObject.prototype.update = function( data, cbSuccess, cbFailure ){ this.commit( "UPDATE", data, cbSuccess, cbFailure ); };
DataObject.prototype.commit = function( action, data, cbSuccess, cbFailure ){
	var me = this;
	XHR.request({ url: "data.php", method: "POST", data: "update=" + encodeURIComponent( Util.toJSON( [ [ this.name, action, data ] ] ) ), process: function( r ){
		if( r.status == 200 ){
			me.updateData( action, data );
			if( cbSuccess ) cbSuccess( action, data );
		}else if( cbFailure ) cbFailure( action, data, r );
	}});
};
DataObject.prototype.updateData = function( action, d ){
	switch( action ){
		case "INSERT":
			this.data.push( d );
			break;
		case "UPDATE":// HANDLE PARTIAL OBJECT
			if( ( index = this.findIndexById( d.ID ) ) > -1 ) for( var fieldName in d ) this.data[ index ][ fieldName ] = d[ fieldName ];
			break;
		case "REMOVE":
		case "DELETE":// HANDLE ID-ARRAY
			for( var i = 0; i < d.length; i++ ) if( ( index = this.findIndexById( d[ i ] ) ) > -1 ) this.data.splice( index, 1 );
			break;
	}
};

// HTTP REQUEST---------------------------------------------------------------------
if( typeof XMLHttpRequest == "undefined" ) XMLHttpRequest = function() {
	try { return new ActiveXObject( "Msxml2.XMLHTTP.6.0" ); } catch(e) {}
	try { return new ActiveXObject( "Msxml2.XMLHTTP.3.0" ); } catch(e) {}
	try { return new ActiveXObject( "Msxml2.XMLHTTP" ); } catch(e) {}
	try { return new ActiveXObject( "Microsoft.XMLHTTP" ); } catch(e) {}
	alert( "This browser does not support XMLHttpRequest." );
};
function XHR( s ){
	this.timeoutID = null;
	this.respond = s.process;
	this.aborted = false;
	this.xhro = ( XHR.pool.length > 0 ) ? XHR.pool.shift() : new XMLHttpRequest();
	
	var me = this;
	var xxhro = this.xhro;
	s.method = ( s.method ) ? s.method.toUpperCase() : "GET";
	var url = s.url;
	if( s.method == "GET" && s.data ) url += "?" + s.data;
	if( s.bustCache ){
		url += ( url.indexOf( "?" ) == -1 ) ? "?" : "&";
		url += Util.randomStr() + "=" + Math.random();
	}
	if( s.timeout ) this.timeoutID = setTimeout( function(){ me.timeMeOut() }, s.timeout || 5000 );
	this.xhro.open( s.method.toUpperCase() , url, true );
	this.xhro.onreadystatechange = function(){ if( me.aborted || xxhro.readyState < 4 ) return; me.respond( xxhro ); me.release(); };
	var data = null;
	if( s.method == "POST" ){
		data = s.data;
		this.xhro.setRequestHeader( "Content-type", "application/x-www-form-urlencoded; charset=utf-8" );
		this.xhro.setRequestHeader( "Content-length", s.data.length );
		this.xhro.setRequestHeader( "Connection", "close" );
	}
	this.xhro.send( data );
};
XHR.prototype.release = function(){
	delete this.respond;
	this.aborted = false;
	XHR.pool.push( this.xhro ); this.xhro = null;
	if( this.timeoutID ){ clearTimeout( this.timeoutID ); delete this.timeoutID; }
};
XHR.prototype.cancel = function(){
	if( this.xhro.readyState < 4 ) this._abort( { status: -2, statusText: "Request was canceled" } );
};
XHR.prototype.timeMeOut = function(){
	if( this.xhro.readyState > 0 && this.xhro.readyState < 4 ) this._abort( { status: -1, statusText: "Request timed out" } );
};
XHR.prototype._abort = function( reason ){
	this.aborted = true;
	this.xhro.abort();
	this.respond( reason );
	this.release();
};
XHR.pool = [];
XHR.request = function( s ){ new XHR( s ); };

function CustomWindow( t ){
	this.elem = {
		overlay:	DOM.createElem( "div",{ className: "cw_overlay" } ),
		frame:	DOM.createElem( "div",{ className: "cw_frame" } ),
		title:		DOM.createElem( "div",{ className: "cw_title", childs: t } ),
		body:	DOM.createElem( "div", { className: "cw_body" } ),
		buttonbar:DOM.createElem( "div", { className: "cw_buttonbar" } )
	};
	DOM.toggleElement( this.elem.overlay, false );
	DOM.appendChild( this.elem.frame, [ this.elem.title, this.elem.body, this.elem.buttonbar ] );
	this.elem.overlay.appendChild( this.elem.frame );
	document.body.appendChild( this.elem.overlay );
}
CustomWindow.prototype.show = function( visible ){ DOM.toggleElement( this.elem.overlay, visible ); };
CustomWindow.prototype.destroy = function(){
	DOM.removeElement( this.elem.overlay );
	for( var e in this.elem ) this.elem[ e ] = null;
};
CustomWindow.prototype.setTitle = function( str ){ this.elem.title.innerHTML = str; };
CustomWindow.prototype.setContent = function( c, append ){
	if( !append ) DOM.removeChilds( c );
	DOM.appendChild( this.elem.body, c );
};
CustomWindow.prototype.setButtons = function( b ){
	DOM.removeChilds( this.elem.buttonbar );
	if( b ) DOM.appendChild( this.elem.buttonbar, b );
};
CustomWindow.prototype.kill = function(){
	this.show( false );
	var me = this;
	setTimeout( function(){ me.destroy(); }, 1000 );
};

// UTILITY FUNCTIONS----------------------------------------------------------------
var Util = {};
Util.createTime = function( d, t ){
	var dt = d.split( "." );
	d.reverse();
	dt = dt.join( "-" ) + " " + t;
	return strtotime( dt );
};
Util.fetch = function( p ){
	if( p.container && typeof( p.container ) == "string" ) p.container = document.getElementById( p.container );
	XHR.request({
		url: p.url,
		bustCache: p.bustCache||false,
		method: "GET",
		process: function( rs ){
			if( rs.status == 200 ){
				var data = rs.responseText;
				if( ( ct = rs.getResponseHeader( "Content-Type" ) ) != null && ct.match( /json/ ) != null ){
					try{
						var obj = eval( "(" + data + ")" );
						if( p.callback ) p.callback( obj );
						else if( p.container && obj.render ) obj.render( p.container );
					}catch(exxx){ throw exxx; }
				}else{
					if( p.callback ) p.callback( data );
					else if( p.container ) p.container.innerHTML = data;
				}
			}else throw "Couldnt fetch '" + p.url + "'";
		}
	});
};
Util.formStr = function( str, delim, values ){
	for( var i = 0; i < values.length; i++ ) str = str.replace( delim, values[i] );
	return str;
};
Util.strTrunk = function( str, len, fix ){
	if( str.length > len ) str = substr( str, 0, len - fix.length ) + fix;
	return str;
};
Util.getEventSrc = function( e ){
	var src;
	if( !e ) var e = window.event;
	if( e.target ) src = e.target;
	else if( e.srcElement ) src = e.srcElement;
	if( src.nodeType == 3 ) src = src.parentNode;// defeat Safari bug
	return src;
};
Util.setCookie = function( c_name, value, expiredays ) {
	var exdate = new Date();
	exdate.setDate( exdate.getDate() + expiredays );
	document.cookie = c_name + "="  + escape( value ) + ( ( expiredays == null ) ? "" : ";expires=" + exdate.toGMTString() );
};
Util.getCookie = function( c_name ){
	if( document.cookie.length > 0 ){
		c_start = document.cookie.indexOf( c_name + "=" );
		if( c_start != -1 ){
			c_start = c_start + c_name.length + 1;
			c_end = document.cookie.indexOf( ";", c_start );
			if( c_end == -1 ) c_end = document.cookie.length;
			return unescape( document.cookie.substring( c_start, c_end ) );
		}
	}
	return null;
};
Util.date2hr = function( s ){
	if( s == null ) return "";
	s = s.toString();
	return s.substr( 6, 2 ) + "." + s.substr( 4, 2 ) + "." + s.substr( 0, 4 );
};
Util.time2hr = function( s ){
	if( s == null ) return "";
	s = s.toString();
	return s.substr( 0, s.length - 2 ) + ":" + s.substr( s.length - 2, 2 );
};
Util.toJSON = function( obj ){
	var retval="";
	if(obj==null) retval="null";
	else if(typeof(obj)=="string")retval="\""+addslashes(obj)+"\"";
	else if(obj instanceof Array){
		var retval="[";
		for(var i=0;i<obj.length;i++)retval+=Util.toJSON(obj[i])+",";
		retval=retval.replace(/,$/,']');
	}else if(typeof obj=="object"){
		var retval="{";
		for(var x in obj)retval+="\""+x+"\":"+Util.toJSON(obj[x])+",";
		retval=retval.replace(/,$/,'}');
	}else retval=obj;
	return retval;
};
Util.secure = function( s ){ return ( s != null ) ? htmlentities( trim( s ), "ENT_QUOTES" ) : ""; };
Util.randomStr = function( len ){
	len = len || 8;
	var c = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz", cCount = c.length, retval = "";
	for( var i = 0;i < len; i++ ) retval += c.charAt( Math.floor( Math.random() * cCount ) );
	return retval;
};

// DOM-HELPER FUNCTIONS-------------------------------------------------------------
var DOM = {};
DOM.parseCSS = function( cssStr ){
	var arr = cssStr.replace( /\:/g, ";" ).split( ";" ), retval = {};
	for( var i = 0; i < arr.length; i+=2 ) retval[ arr[ i ] ] = arr[ i + 1 ];
	return retval;
};
DOM.createElem = function( tagname, edata ){
	tagname = tagname.toUpperCase();
	// CREATE ELEMENT
	var elem;
	switch( tagname ){
		case "IMG":
			elem = new Image();
			break;
		case "BUTTON":
		case "CHECKBOX":
		case "FILE":
		case "HIDDEN":
		case "IMAGE":
		case "PASSWORD":
		case "RADIO":
		case "RESET":
		case "SUBMIT":
		case "TEXT":
			elem = document.createElement( "input" );
			elem.type = tagname;
			break;
		default:
			elem = document.createElement( tagname );
			break;
	}

	if( edata ){
		// SET STYLES
		if( edata.style ){
			if( typeof( edata.style ) == "string" ) edata.style = DOM.parseCSS( edata.style );
			for( var x in edata.style ) elem.style[ x ] = edata.style[ x ];
			delete edata.style;
		}
		
		// SET CHILDREN
		if( edata.childs ){
			DOM.appendChild( elem, edata.childs );
			delete edata.childs;
		}
		
		// SET ATTRIBUTES
		for( var x in edata ) elem[ x ] = edata[ x ];
	}
	return elem;
};
DOM.duplicateAttrib = function( src, dst ){
	var a = src.attributes;
	for( var i = 0; i < a.length; i++ ) dst.setAttribute( a[i].name, a[i].value );
};
DOM.appendChild = function( parent, childs ){
	if( typeof( childs ) == "string" ){
		DOM.appendChild( parent, document.createTextNode( childs ) );
	}else if( childs instanceof Array ){
		for( var i = 0; i < childs.length; i++ ) DOM.appendChild( parent, childs[ i ] );
	}else parent.appendChild( childs );
};
DOM.prependChild = function( parent, childs ){
	if( typeof( childs ) == "string" ){
		var tmp = document.createDocumentFragment();
		tmp.innerHTML = childs;
		DOM.prependChild( parent, tmp );
	}else if( childs instanceof Array ){
		var child = null;
		for( var i = childs.length - 1; i >= 0 ; i-- ) DOM.prependChild( parent, childs[ i ] );
	}else{
		if( !parent.hasChildNodes() ) DOM.appendChild( parent, childs );
		else parent.insertBefore( childs, parent.firstChild );
	}
};
DOM.getElementPos = function( e, w ){
	var p = 0;
	while( e != null ){
		p += e[ "offset" + w ];
		e = e.offsetParent;
	}
	return p;
};
DOM.removeChilds = function( e ){
	if( e.hasChildNodes ){
		var child = null;
		while( e.hasChildNodes() ){
			child = e.firstChild;
			DOM.removeEventHandlers( child );
			DOM.removeChilds( child );
			e.removeChild( child );
		}
	}
};
DOM.seekByTagName = function( elem, tagName ){
	while( elem && elem.tagName && elem.tagName != tagName ) elem = ( elem.parentNode ) ? elem.parentNode : null;
	return elem;
};
DOM.removeElement = function( elem ){
	DOM.removeChilds( elem );
	elem.parentNode.removeChild( elem );
};
DOM.removeEventHandlers = function( elem ){
	var e = [ "onabort", "onblur", "onchange", "onclick", "ondblclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onreset", "onresize", "onselect", "onsubmit", "onunload" ];
	for( var i = e.length - 1; i >= 0; i-- ) if( elem[ e[ i ] ] ) elem[ e[ i ] ] = null;
};

DOM.toggleElement = function( elem, show ){
	if( !elem ) return;
	if( !elem.style ) elem.style = {};
	elem.style.display = (show)?"block":"none";
	elem.style.visibility = (show)?"":"hidden";
};
DOM.ToggleSmooth = function( prev, next, cb ){
	var showNext = function(){
		if( prev ) DOM.toggleElement( prev, false );
		$fx( next ).fxAdd( { type:"opacity", from: 0, to: 100, step: 15, delay: 30 } ).fxRun( cb );
		DOM.toggleElement( next, true );
	};
	if( prev ) $fx( prev ).fxAdd( { type:"opacity", from: 100, to: 0, step: -15, delay: 30 } ).fxRun( showNext );
	else showNext();
};

// PAGE HELPER FUNCTIONS------------------------------------------------------------
var Page = {};
Page.qs = null;
Page.getQS = function(){
	if( Page.qs == null ){
		var arr = window.location.search.substr( 1 ).replace( /\=/g, "&" ).split( "&" ), key, value, qs = {};
		for( var i = 0; i < arr.length; i+=2 ){
			key = arr[ i ]; value = arr[ i + 1 ];
			if( qs[ key ] ){
				if( !( qs[ key ] instanceof Array ) ) qs[ key ] = [ qs[ key ] ];
				qs[ key ].push( value );
			}else qs[ key ] = value;
		}
		Page.qs = qs;
	}
	return Page.qs;
};
Page.reload = function(){ window.location.reload(); };
Page.back =	function(){ history.go( -1 ); };
Page.go = function( url ){ window.location.href = url; };
Page.getWindowHeight = function(){
	var windowHeight = 0;
	if( typeof( window.innerHeight ) == 'number' ) windowHeight = window.innerHeight;
	else{
		if( document.documentElement && document.documentElement.clientHeight ) windowHeight = document.documentElement.clientHeight;
		else if( document.body && document.body.clientHeight ) windowHeight = document.body.clientHeight;
	}
	return windowHeight;
};
Page.getWindowWidth = function(){
	var windowWidth = 0;
	if( typeof( window.innerWidth ) == 'number' ) windowWidth = window.innerWidth;
	else{
		if( document.documentElement && document.documentElement.clientWidth ) windowWidth = document.documentElement.clientWidth;
		else if( document.body && document.body.clientWidth ) windowWidth = document.body.clientWidth;
	}
	return windowWidth;
};
Page.getScrollY = function(){
	return Math.max( window.pageYOffset ? window.pageYOffset : 0, document.documentElement ? document.documentElement.scrollTop : 0, document.body ? document.body.scrollTop : 0 );
};
Page.getScrollX = function(){
	return Math.max( window.pageXOffset ? window.pageXOffset : 0, document.documentElement ? document.documentElement.scrollLeft : 0, document.body ? document.body.scrollLeft : 0 );
};
Page.getSize = function(){
	if( window.innerHeight && window.scrollMaxY ){// Firefox
		return [ window.innerWidth + window.scrollMaxX, window.innerHeight + window.scrollMaxY ];
	}else if( document.body.scrollHeight > document.body.offsetHeight ){ // all but Explorer Mac
		return [ document.body.scrollWidth, document.body.scrollHeight ];
	}else{ // works in Explorer 6 Strict, Mozilla (not FF) and Safari
		return [ document.body.offsetWidth, document.body.offsetHeight ];
  	}
};
Page.onload_functions = [];
Page.add_onload = function( f ){
	if( Page.onload_functions ) Page.onload_functions.push( f );
	else throw "Error: Onload functions already processed!";
};
Page.onload = function(){
	for( var i = 0; i < Page.onload_functions.length; i++ ){ Page.onload_functions[ i ](); Page.onload_functions[ i ] = null; }
	Page.onload_functions = null;
};

Page.onunload_functions = [];
Page.add_onunload = function( f ){ if( Page.onunload_functions ) Page.onunload_functions.push( f );};
Page.onunload = function(){
	for( var i = 0; i < Page.onunload_functions.length; i++ ){ Page.onunload_functions[ i ](); Page.onunload_functions[ i ] = null; }
	Page.onunload_functions = null;
};