__ie6 = (/MSIE ((5\.5)|6)/.test(navigator.userAgent) && navigator.platform == "Win32") ? true : false;
__ie7 = (/MSIE (7)/.test(navigator.userAgent) && navigator.platform == "Win32") ? true : false;

String.prototype.repeat = function(n) {
	return new Array(isNaN(n)? 1 : ++n).join(this);
}

Default = {
	redirectToLogin: function() {
		window.location = "/login";
	},
	
	loadURL: function(parameters) {
		var defaultParameters =  {
			data: {},
			url: ''
		};
		
		var url = parameters.url;
		
		if(!$.isEmptyObject(parameters.data)) {
			var pairs = [];
			for(key in parameters.data)
				pairs.push(key+'='+parameters.data[key]);
			url += '?' + pairs.join("&");
		}
		
		location.href = url;
		return true;
	},
	
	helpers: {
		getPagination: function(settings) {
			var html = '';
			
			settings.page = parseInt(settings.page);
			settings.totalPages = parseInt(settings.totalPages);
			
			html += __('Browse:') + ' ';
			
			//Prev
			if (settings.page > 1)
				html += '<a self:val="'+(settings.page-1)+'" href="#"><b>'+__('Prev')+'</b></a>';
			else
				html += '<span class="cDisabled"><b>'+__('Prev')+'</b></span>';
	
	
			//Pages
			var startAt = settings.page - 4; if (startAt < 1) startAt = 1;
			var finishAt = settings.page + 4; if (finishAt > settings.totalPages) finishAt = settings.totalPages;
			
			
			
			if (startAt > 1) {
				html += '<a self:val="1" href="#"><b>1</b></a>';
				if(startAt > 2) html += '<span class="space">...</span>';
			}
				
			for (var i=startAt; i<=finishAt; i++) {
				if (i == settings.page)
					html += '<span class="cActive"><b>'+ i +'</b></span>';
				else
					html += '<a self:val="'+ i +'" href="#"><b>'+ i +'</b></a>';
			}
			
			if (finishAt < settings.totalPages) {
				if(finishAt < (settings.totalPages-1)) html += '<span class="space">...</span>';
				html += '<a self:val="'+settings.totalPages+'" href="#"><b>'+settings.totalPages+'</b></a>';
			}
	
			//Next
			if (settings.totalPages > 1 && settings.page < settings.totalPages)
				html += '<a self:val="'+(settings.page+1)+'" href="#"><b>'+__('Next')+'</b></a>';
			else
				html += '<span class="cDisabled"><b>'+__('Next')+'</b></span>';
	
			return html;
		},
		
		/**
		 * s.id 
		 * s.page 
		 * s.totalPages 
		 * s.pageResults 
		 * s.totalResults 
		 * s.results = []
		 */
		getTableFooter: function(s) {
			s.page = parseInt(s.page);
			s.totalPages = parseInt(s.totalPages);
			s.pageResults = parseInt(s.pageResults);
			s.totalResults = parseInt(s.totalResults);
			
			if(s.totalResults == 0) return '';
			
			var html = '';
			
			html += '<div class="DataTableFooter group" id="'+s.id+'">';
				if(s.infoBar)
					html += '<div class="info">'+(s.infoBarContent?s.infoBarContent:'')+'</div>';
				
				html += '<div class="pagination">';
					if(s.totalPages > 1)
						html += Default.helpers.getPagination({
							page: s.page,
							totalPages: s.totalPages
						});
				html += '</div>';
				html += '<div class="results">';
					var resultOffset = (s.page-1)*s.pageResults;
					var cap = (s.page == s.totalPages) ? s.totalResults : resultOffset + s.pageResults;
					var str = __('Showing {FROMPAGE} to {TOPAGE} of {TOTALPAGES}.')
					.replace('{FROMPAGE}', resultOffset+1)
					.replace('{TOPAGE}', cap)
					.replace('{TOTALPAGES}', s.totalResults);
					html += '<span class="cLeft">'+str+'</span>';
					
					if(s.results) {
						html += '<span>'+__('Show')+'</span>';
						html += '<div class="selectBox" id="'+s.id+'_RPP"><div class="inner">';
							var buffer1 = '';
							var _label = s.pageResults;
							buffer1 += '<ul>';
								if($.isPlainObject(s.results)) {
									for(var val in s.results) {
										buffer1 += '<li svalue="'+val+'"'+(val==s.pageResults ? ' class="selected"' : '')+'>'+s.results[val]+'</li>';
										if(val==s.pageResults) _label = s.results[val];
									}
								} else
									for (var i=0; i<s.results.length; i++)
										buffer1 += '<li svalue="'+s.results[i]+'"'+(s.results[i]==s.pageResults ? ' class="selected"' : '')+'>'+s.results[i]+'</li>';
							buffer1 += '</ul>';
							
							html += '<span>'+_label+'</span>';
							html += buffer1;
						html += '</div></div>';
						if(s.totalPages > 1)
							html += '<span>'+__('per page')+'.</span>';
					}
					
				html += '</div>';
				html += '<div class="clear"></div>';
			html += '</div>';
			
			return html;
		},
			
		dateFormat: {
			
			calculateCountdown: function(datetime) {
				return calculateCountdown(datetime);
			},
			
			createCountdown: function(datetime) {	
				
				var parsedCountdown = this.calculateCountdown(datetime);
				var output = '<span tooltip="'+datetime+'" onmousemove="Default.helpers.toolTip.open(event, this);" onmouseout="Default.helpers.toolTip.close();">'+parsedCountdown+'</span>';
	
				return output;
			}
		},
		
		/**
		 * @deprecated
		 */
		confirmBox: {
			stackedIds: [],
			
			/*
			screenBox: null,
			alertBox: null,
			animation: null,
			*/
			
			//settings.action = function()
			//settings.alert = false;
			//settings.success = false;
			//settings.dialog = false;
			//settings.dialogHtml = false;
			//settings.dialogFunction = function()
			//settings.large = false
			//settings.light = false
			//settings.customId = null
			//settings.alertMessage = '';
			//settings.attr1 = ANYTHING; //to be passed to the ACTION handler
			createInstance: function(settings) {
				// create box
				var box = document.createElement('div');
				box.id = 'ScreenBox' + Default.helpers.confirmBox.stackedIds.length;
				box.className = 'ScreenBox';
				box.style.display = 'none';
	
				if (settings.customId)  box.innerHTML = '<div class="cBg"></div><div class="cInner" id="'+settings.customId+'"></div>';
				else if (settings.large) box.innerHTML = '<div class="cBg"></div><div class="cInnerLarge"></div>';
				else if (settings.light) box.innerHTML = '<div class="cBg"></div><div class="cInnerLight"></div>';
				else box.innerHTML = '<div class="cBg"></div><div class="cInner"></div>';
	
				//parse
				var bg = box.childNodes[0];
				var ib = box.childNodes[1];
	
				//parse
				box._bg = bg;
	
				//Default.SetOpacity(bg, 0.7);
				//Default.SetOpacity(ib, 0.8);
				//set opacity
				Default.setOpacity(box, 0);
				
				document.body.appendChild(box);
				
				var instance = {
					screenBox: box,
					alertBox: ib,
					id: Default.helpers.confirmBox.stackedIds.length
				};
				
				//populate
	
				if (settings.dialog && settings.dialogHtml) {
						if($.isFunction(settings.dialogHtml))
							ib.innerHTML = settings.dialogHtml();
						else ib.innerHTML = settings.dialogHtml;
						
						if (typeof settings.dialogFunction == 'function')
							settings.dialogFunction();
				} else {
					if (settings.alert && settings.alertMessage)
						ib.innerHTML = '<h3 class="cRed">Error Occurred</h3><div class="cContent">'+settings.alertMessage+'<div class="cButtons"><a class="cGreen" id="ConfirmBoxCancel_'+instance.id+'">OK</a></div></div>';
					else if (settings.success && settings.alertMessage)
						ib.innerHTML = '<h3 class="cGreen">Success</h3><div class="cContent">'+settings.alertMessage+'<div class="cButtons"><a class="cGreen" id="ConfirmBoxCancel_'+instance.id+'">OK</a></div></div>';
					else if (settings.alertMessage)
						ib.innerHTML = '<h3>Please Confirm</h3><div class="cContent">'+settings.alertMessage+'<div class="cButtons"><a class="cRed" id="ConfirmBoxCancel_'+instance.id+'">No, Cancel</a><a class="cGreen" id="ConfirmBoxAction_'+instance.id+'">Yes</a></div></div>';
					else
						ib.innerHTML = '<h3>Please Confirm</h3><div class="cContent"><div class="cButtons"><a class="cRed" id="ConfirmBoxCancel_'+instance.id+'">No, Cancel</a><a class="cGreen" id="ConfirmBoxAction_'+instance.id+'">Yes</a></div></div>';
					
					var yes = document.getElementById('ConfirmBoxAction_'+instance.id);
					if (yes) {
						if (settings.action)
							yes._action = settings.action;
						if (settings.attr1)
							yes._attr1 = settings.attr1;
						yes._close = this.close;
						yes._this = this;
						
						yes.onclick = function() {
							if (this._action)
								this._action();
							
							this._close();
						};
					}
					
					var no = document.getElementById('ConfirmBoxCancel_'+instance.id);
					if (no) {
						no._close = this.close;
						no._this = this;
						
						no.onclick = function() {
							this._close();
						}
					}
				}
				
				Default.helpers.confirmBox.stackedIds.push(instance);
				return instance;
			},
			
			open: function(settings) {
				//create a new instance
				var instance = this.createInstance(settings);
				
				var box = instance.screenBox;
				var alert = instance.alertBox;
				
				//prepare screen box
				box.style.width = box._bg.style.width = 	Default.info.getPageWidth() + 'px';
				box.style.height = box._bg.style.height = Default.info.getPageHeight() + 'px';
				
				//display screen
				box.style.display = 'block';
							
				//position child box in the center of the screen
				alert.style.top = Math.ceil((Default.info.getWindowHeight() - alert.offsetHeight) / 2 + Default.info.getScrollTop()) + "px";
				alert.style.left = Math.ceil((Default.info.getWindowWidth() - alert.offsetWidth) / 2 + Default.info.getScrollLeft()) + "px";
				
				//start animation
				$(box).fadeIn(300);
				
				/*
				instance.animation = new Animations.fade({
					duration: 300,
					targetObject: box,
					beforeStart: function() {
						var t = Default.helpers.confirmBox.stackedIds[Default.helpers.confirmBox.stackedIds.length-1];
						t.screenBox.style.zIndex += 100;
						t.alertBox.style.zIndex += 100;
					},
					afterEnd: function() {
						
						//var t = Default.helpers.confirmBox.stackedIds[Default.helpers.confirmBox.stackedIds.length-1];
						//t.screenBox.style.zIndex -= 100;
						//t.alertBox.style.zIndex -= 100;
						
						//Delete
						var abbr = Default.helpers.confirmBox.stackedIds;
						document.body.removeChild(abbr[abbr.length-1].screenBox);
						abbr.splice(abbr.length-1, 1);
						
					}
				});
				instance.animation.startAnimation();
				*/
			},
			close: function() {
				var instance = Default.helpers.confirmBox.stackedIds[Default.helpers.confirmBox.stackedIds.length-1];
				if (typeof instance == 'undefined') return;		
				instance.animation.reverseAnimation();
			}
		}
	},
	
	/*
	 * @deprecated
	 */
	setOpacity: function(o, op) {
		if (typeof o.style.opacity != 'undefined')
			o.style.opacity = (op==1)?(0.9999999):(op);
		else if (typeof o.style.KhtmlOpacity != 'undefined')
			o.style.KhtmlOpacity = op;
		else if (typeof o.filters == 'object')
			o.style.filter = 'alpha(opacity='+(op*100)+')';

		if (typeof o.style.MozOpacity != 'undefined')
			o.style.MozOpacity = (op==1)?(0.9999999):(op);
	},
	
	/*
	 * @deprecated
	 */
	getRadioValue: function(o) {
		if (!o)
			return "";
		var rl = o.length;
		if (rl==undefined) {
			if (o.checked)
				return o.value;
			return "";
		}
		for (var i=0; i<rl; i++) {
			if (o[i].checked)
				return o[i].value;
		}
		return "";
	},
	
	mergeObject: function(obj1, obj2) {
		var newObj = {};
		for (name in obj1)
			newObj[name] = obj1[name];
		for (name in obj2)
			if(obj2[name] == null)
				delete newObj[name];
			else
				newObj[name] = obj2[name];
		return newObj;
	},
	
	cloneObject: function(obj) {
		var clone = {};
        for(var i in obj) {
            if(typeof(obj[i])=="object" && !$.isArray(obj[i]))
                clone[i] = Default.cloneObject(obj[i]);
            else
                clone[i] = obj[i];
        }
        return clone;

	},
	
	countObject: function(obj) {
		var c = 0;
		for(tmp in obj)
			c++;
		return c;
	},
	
	getServerDate: function() {
		var d = new Date();
		
		//server time is New York, USA
		var offset = -5; //EST
		
		var utc = d.getTime() + (d.getTimezoneOffset() * 60 * 1000);
		var nd = new Date(utc + (60 * 60 * 1000 * offset));
		
		//DST?
		//There is no DST for the server time, at least not for all the date values in the DB, or is there?
		var dst = {
			'2011': [[3, 14], [11, 7]],
			'2012': [[3, 11], [11, 4]],
			'2013': [[3, 10], [11, 3]],
			'2014': [[3, 9], [11, 2]],
			'2015': [[3, 8], [11, 1]],
			'2016': [[3, 13], [11, 6]]
		};
		var dstVals = dst[nd.getFullYear()];
		if( (nd.getMonth()+1 < dstVals[1][0] || (nd.getMonth()+1 == dstVals[1][0] && nd.getDate() < dstVals[1][1])) && (nd.getMonth()+1 > dstVals[0][0] || (nd.getMonth()+1 == dstVals[0][0] && nd.getDate() >= dstVals[0][1])) )
			nd = new Date(utc + (60 * 60 * 1000 * (offset+1)));
		
		
		return nd;
	},
	
	info: {
		getPageWidth: function() {
			var ww = this.getWindowWidth();
			var ow = document.body.offsetWidth;
			
			//all but Explorer Mac
			if ( ww > ow )
				return ww;
			else
				return ow;	
		},
		
		getPageHeight: function() {
			var wh = this.getWindowHeight();
			var oh = document.body.offsetHeight;
			
			//all but Explorer Mac
			if ( wh > oh )
				return wh;
			else
				return oh;	
		},
		
		getWindowHeight: function() {
			var d = document;
			
			// all except Explorer
			if (self.innerHeight)
				return self.innerHeight;
			// Explorer 6 Strict Mode
			else if (d.documentElement && d.documentElement.clientHeight)
				return d.documentElement.clientHeight;
			//other Explorers
			else if (d.body) 
				return d.body.clientHeight;
		},
		
		getWindowWidth: function() {
			var d = document;
			
			// all except Explorer
			if (self.innerWidth)
				return self.innerWidth;
			// Explorer 6 Strict Mode
			else if (d.documentElement && d.documentElement.clientWidth)
				return d.documentElement.clientWidth;
			//other Explorers
			else if (d.body) 
				return d.body.clientWidth;
		},
		
		getScrollTop: function() {
			if (window.pageYOffset)
				return window.pageYOffset;
			else if (document.documentElement.scrollTop) 
				return document.documentElement.scrollTop;
			else if (document.body.scrollTop) 
				return document.body.scrollTop;
			else
				return 0;
		},
		
		getScrollLeft: function() {
			if (window.pageXOffset)
				return window.pageXOffset;
			else if (document.documentElement.scrollLeft)
				return document.documentElement.scrollLeft;
			else if (document.body.scrollLeft)
				return document.body.scrollLeft;
			else
				return 0;
		}
	},
	
	page: {
		hash: {
			//adds and, if already available, replaces an existing set with the same name
			// param name: 		The name of the set to be added/replaced
			// param values: 	The name/value pairs packed in an object, e.g. {name:"val", name2:21}
			addSet: function(name, values) {
				var anchor = this.getFull();
				
				//split into sets
				//format being: Name(p:something,l:22)/Name2(p:something,l:22)
				var sets = [];
				if (anchor)
					sets = anchor.split('/');
				
				var newSets = [];
				//add all sets except for the one that will be added afterwards (used to implicitly replace that set)
				if (sets.length) {
					for (var x=0; x<sets.length; x++) {
						//get name of set and compare
						if (sets[x].split('(')[0] != name)
							newSets.push(sets[x]);
					}
				}
				
				//now generate and add the new set
				var pairs = [];
				for (var n in values) {
					if (values[n] != null) {
						if(typeof values[n] == 'string') pairs.push(n+':'+values[n].replace(/\//g, '\\/'));
						else pairs.push(n+':'+values[n]);
					}
				}
				var allPairs = pairs.join(",");
				
				newSets.push(name + "(" + allPairs + ")");
							
				//now put everything in the URL
				var anchor = newSets.join("/");
				window.location = window.location.toString().split('#')[0] + '#' + escape(anchor);
			},
			
			// returns FALSE or an object with name/value pairs
			// param name: The name of the set to be retrieved
			getSet: function(name) {
				var anchor = this.getFull();
				
				if (!anchor)
					return false;
				
				//split into sets
				//format being: Name(p:something,l:22)/Name2(p:something,l:22)
				var safeSets = anchor.replace(/([^\\])\//g, "$1#SELF:SEPARATOR#");
				safeSets = safeSets.replace(/\\\//g, "/");
				var sets = safeSets.split('#SELF:SEPARATOR#');
	
				for (var x=0; x<sets.length; x++) {
					//get name of set
					var setName = sets[x].split('(')[0];
					//if that isn't the set we are looking for, continue looking
					if (setName != name)
						continue;
					
					//get all name/value pairs
					var allPairs = sets[x].substring(sets[x].indexOf('(')+1, sets[x].indexOf(')'));
					//split to single name/value pairs
					var pairs = allPairs.split(',');
					if (!pairs.length)
						return false;
					
					//traverse all pairs
					var returnVals = {};
					for (var y=0; y<pairs.length; y++) {
						var vals = pairs[y].split(':');
						returnVals[vals[0]] = vals[1];
					}
					return returnVals;
				}
				//No such set found
				return false;
			},
			
			getFull: function() {
				var url = window.location.toString();
				
				if (!url.match('#'))
					return "";
				
				return unescape(url.split('#')[1]);
			}
			
		},
		
		queryString: {
			// returns FALSE or an object with name/value pairs
			// param name: The name of the set to be retrieved
			getValue: function(name) {
				var query = this.getFull();
				
				var gy = query.split("&");
				for (var i=0; i<gy.length; i++) {
					var ft = gy[i].split("=");
					if (ft[0] == name)
						return ft[1];
				}
				return false;
			},
			
			addTo: function(name, value) {
				var query = this.getFull();
				
				var np = {};
				
				if(query) {
					var gy = query.split("&");
					for (var i=0; i<gy.length; i++) {
						var ft = gy[i].split("=");
						np[ft[0]] = ft[1];
					}
				}
				
				
				np[name] = escape(value);
				
				var prs = [];
				for(var n in np)
					prs.push(n + '=' + np[n]);
				
				
				if(prs.length)
					return '?' + prs.join('&');
				return '?';
			},
			
			getFull: function() {
				return window.location.search.substring(1);
			}
		}
	},
	
	
	
	/**
	 * Page Loader
	 * 	
	 * Makes use of Default.pageMessage
	 */	
	pageLoader: {
		queue: [],
		addProcess: function(name) {
			//if there have been no processes before, start loading
			if(this.queue.length == 0)
				this.startLoading();
			
			this.queue.push({name: name, status: false});
		},
		finishProcess: function(name) {
			for (var x=0; x<this.queue.length; x++)
				if (this.queue[x].name == name)
					this.queue.splice(x, 1);
			
			this.isFinished();
		},
		//This function is called by each page after all scripts have been invoked.
		//If no process have been added and, as a result, the queue is 0, then finish loading 
		isFinished: function() {
			if (this.queue.length == 0)
				this.finishLoading();			
		},
		startLoading: function() {
			Default.pageMessage.displayLoading('Loading...');
			//$('#pageLoader').fadeIn(500);
		},		
		finishLoading: function() {
			Default.pageMessage.hideIfLoading();
			//$('#pageLoader').fadeOut(500);
		}
	},
	
	pageMessage: {
		active: false,
		timer: null,
		displaySuccess: function(msg, timeout) {
			this.create();
			var timeout = timeout || 6000;
			
			$('#pageMessage').removeClass('error loading').addClass('success');
			$('#pageMessage div.i2').html(msg);
			
			this.show();
			
			if(this.timer != null) window.clearTimeout(this.timer);
			this.timer = window.setTimeout('Default.pageMessage.hide();', timeout);
		},
		displayError: function(msg, timeout) {
			this.create();
			var timeout = timeout || 6000;
			
			$('#pageMessage').removeClass('success loading').addClass('error');
			$('#pageMessage div.i2').html(msg);
			
			this.show();
			
			if(this.timer != null) window.clearTimeout(this.timer);
			this.timer = window.setTimeout('Default.pageMessage.hide();', timeout);
		},
		displayMessage: function(msg, timeout) {
			this.create();
			var timeout = timeout || 6000;
			
			$('#pageMessage').removeClass('error success loading');
			$('#pageMessage div.i2').html(msg);
			
			this.show();
			
			if(this.timer != null) window.clearTimeout(this.timer);
			this.timer = window.setTimeout('Default.pageMessage.hide();', timeout);
		},
		displayLoading: function(msg, timeout) {
			this.create();
			var timeout = timeout || 60000;
			
			$('#pageMessage').removeClass('error success').addClass('loading');
			$('#pageMessage div.i2').html('<div class="loader">' + msg + '</div>');
			
			this.show();
			
			if(this.timer != null) window.clearTimeout(this.timer);
			this.timer = window.setTimeout('Default.pageMessage.hideIfLoading();', timeout);
		},
		
		show: function() {
			if(!this.active)
				$('#pageMessage').css('visibility', 'hidden').show();
			
			var width = $('#pageMessage .i').outerWidth();
			width += 140
			$('#pageMessage').css('margin-left', -width);
			
			if(!this.active) {
				$('#pageMessage').hide().css('visibility', 'visible');
				$('#pageMessage').fadeIn(500);
			}
			
			this.active = true;
		},
		create: function() {
			if(!$('#pageMessage').length)
				$("body").append('<div id="pageMessage"><div class="i"><div class="i2"></div></div></div>');
		},
		hide: function() {
			$('#pageMessage').fadeOut(500);
			this.timer = null;
			this.active = false;
		},
		hideIfLoading: function() {
			if($('#pageMessage').hasClass('loading')) {
				$('#pageMessage').fadeOut(500);
				this.timer = null;
				this.active = false;
			}
		}
	},
	
	cookieHandler: {
		setCookie: function (name, value, seconds) {
	 
			if (typeof(seconds) != 'undefined') {
				var date = new Date();
				date.setTime(date.getTime() + (seconds*1000));
				var expires = "; expires=" + date.toGMTString();
			}
			else {
				var expires = "";
			}
	 
			document.cookie = name+"="+value+expires+"; path=/";//+path;
		},
	 
		getCookie: function (name) {
	 
			name = name + "=";
			var carray = document.cookie.split(';');
	 
			for(var i=0;i < carray.length;i++) {
				var c = carray[i];
				while (c.charAt(0)==' ') c = c.substring(1,c.length);
				if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
			}
	 
			return null;
		},
	 
		deleteCookie: function (name) {
		    if(this.getCookie(name))
			    this.setCookie(name, "", -1);
		}
	},
	
	/*
	 * The sidebar menu
	 */
	menu: {
		init: function() {
		    Default.menu.restore();
			
			$("#sidebar li.collapsible > a")
			.click(function() {
				$("ul", $(this).parent()).toggleClass('active');
				
				if ( $(this).hasClass('NC') )
					$(this).toggleClass('NCUp');
				
				Default.menu.save();
			});
			
			$("#sidebar a")
			.focus(function() {
				this.blur();
			});
			
			$("#sidebar a[href!='#']")
			.click(function() {
				Default.pageLoader.startLoading();
			});
						
		},
		
		save: function() {
			var state = '';
			$("ul.active", $("#sidebar li.collapsible"))
			.each(function(i){
				state += $(this).attr('order') + ',';
			});
			if(state!='')
				state = state.substring(0,state.length-1); 
			Default.cookieHandler.setCookie("BodisMenu", state, 604800)//expires after 1 week				
		},
		
		restore: function() {
			var state = Default.cookieHandler.getCookie("BodisMenu");
			if(state) {
			    $("ul.active", $("#sidebar li.collapsible"))
			    .removeClass("active");
				var castate = state.split(","); 
				for(var i=0; i<castate.length; i++){
					$("#sidebar li.collapsible ul[order=" + castate[i] +"]")
					.toggleClass("active");
				};
			}
		}
	},
	
	ajax: {
		checkAuthentication: function(response) {
			if ( !response.isAuthenticated )
				Default.redirectToLogin();
		},
		checkForErrors: function(response) {
			if (response.isError) {
				Default.popups.create({
					message: response.errorMessage
				});
				return true;
			}
			return false
		}
	},
	
	form: {
		handlers: {
			tmp1: null
		},
		/**
		 * Enable checkbox behavior
		 * 
		 * @param {Object} context The context from which to search for checkboxes, can be any DOM or jQuery object
		 */
		enableCheckboxes: function(context) {
			var context = context ? context : null;
			$("span.checkbox:not(.checkedForced), div.checkbox:not(.checkedForced)", context)
			.unbind()
			.bind('mouseover', function() {
				$(this).addClass('over');
			})
			.bind('mouseout', function() {
				$(this).removeClass('over');
			})
			.bind('mouseup', function() {
				if($(this).hasClass('checked')) {
					$(this).trigger('_uncheck');
				} else {
					$(this).trigger('_check');
				}
				return false;
			});
			
			$("span.checkbox.checkedForced, div.checkbox.checkedForced", context).unbind();
			
			$("span.checkbox, div.checkbox", context)
			.bind('_check', function() {
				$(this).addClass('checked')
			})
			.bind('_uncheck', function() {
				$(this).removeClass('checked');
			});
			
		},
		
		/**
		 * Enable radiobox behavior
		 * 
		 * @param {Object} context The context from which to search for radioboxes, can be any DOM or jQuery object
		 */
		enableRadioboxes: function(context) {
			var context = context ? context : null;
			$("span.radiobox, div.radiobox", context)
			.die()
			.live('mouseover', function() {
				if($(this).hasClass('radioboxChecked'))
					$(this).addClass('radioboxCheckedOver');
				else $(this).addClass('radioboxOver');
				return false;
			})
			.live('mouseout', function() {
				$(this).removeClass('radioboxOver radioboxCheckedOver');
				return false;
			})
			.live('mouseup', function() {
				if(!this._checked) {
					$(this)
					.addClass('radioboxCheckedOver')
					.trigger('_check');
				}
				return false;
			})
			.live('_check', function() {
				//Disable all in the same radio class
				var radioClass = $(this).attr('radioclass');
				$('span.radiobox[radioclass='+radioClass+'], div.radiobox[radioclass='+radioClass+']').trigger('_uncheck');
				$(this).addClass('radioboxChecked');
				this._checked = true;
			})
			.live('_uncheck', function() {
				$(this)
				.removeClass('radioboxChecked');
				this._checked = false;
			})
			.live('_isChecked', function() {
				return this._checked;
			});
		},
		
		enableSelects: function(context) {
			var context = context ? context : null;
			
			$("div.selectBox, div.dropdownBtn", context)
			.unbind()
			.bind('mouseenter', function(e) {
				$(this).addClass('over');
				if($(this).hasClass('autoOpen'))
					$(this).trigger('_open');
			})
			.bind('mouseleave', function(e) {
				$(this).removeClass('over');
			})
			.bind('click', function(e) {
				if($(this).hasClass('disabled'))
					return false;
				$("div.selectBox, div.dropdownBtn").each(function() { $(this).trigger('_close'); });
				$(this).trigger('_open');
				e.stopPropagation();
				return false;
			})
			.bind('mousemove', function(e) {
				e.stopPropagation();
				return false;
			})
			.bind('_open', function() {
				//get available height
				var st = Default.info.getScrollTop();
				var ot = $(this).offset()['top'];
				var wh = Default.info.getWindowHeight();
				
				var available = wh - (ot - st + this.offsetHeight);
				//some space
				available -= 50;
				
				if(available < 100) {
					//open up above
					$('.inner > ul', this).addClass('above');
					//redefine height
					available = ot - st - 50; 
				} else
					$('.inner > ul', this).removeClass('above');
				
				$(this).addClass('active');
				$('.inner > ul', this).css('max-height', available).addClass('open');
				if(__ie6 && $('.inner > ul', this)[0].scrollHeight >= available)
					$('.inner > ul', this).css('height', available)
				
				var t = $('.inner > ul', this)[0];
				t.scrollTop = t._scrollTop;
			})
			.bind('_close', function() {
				$(this).removeClass('active over');
				$('.inner > ul', this).removeClass('open');
			});
			
			$("div.selectBox .inner > ul li:not(.group), div.dropdownBtn .inner > ul li:not(.group)", context)
			.unbind()
			.bind('mouseover', function() {
				$(this).addClass('over');
				return false;
			})
			.bind('mouseout', function() {
				$(this).removeClass('over');
				return false;
			})
			.bind('click', function() {
				if($(this).hasClass('disabled')) return false;
				var current = $(this).parent().find('li');
				if(current == $(this))
					return false;
				current.removeClass('selected');
				$(this).addClass('selected');
				if($(this).attr('slabel'))
					var val = $(this).attr('slabel');
				else var val = $(this).html();
				$(this).closest(".inner").find('span').html(val);
				$(this).closest("div.selectBox, div.dropdownBtn").trigger('_close').removeClass('over').trigger('_change');
				if(this._change)
					this._change();
				
				$(this).closest(".inner").find('ul').css('visibility', 'hidden').css('display', 'block');
				var scrollTop = this.offsetTop - this.clientHeight;
				if(scrollTop < 0) scrollTop = 0;
				$(this).closest(".inner").find('ul')[0]._scrollTop = scrollTop;
				$(this).closest(".inner").find('ul').css('display', '').css('visibility', '');
				
				return false;
			});
			
		
			$("div.selectBox, div.dropdownBtn", context).each(function() {
				$(".inner > ul", this).css('visibility', 'hidden').css('display', 'block');
				
				//set scrolling position to wherever the active element is
				var _tmp = $(".inner > ul li.selected", this)[0];
				if(_tmp) {
					var scrollTop = _tmp.offsetTop - _tmp.clientHeight;
					if(scrollTop < 0) scrollTop = 0;
					$(".inner > ul", this)[0]._scrollTop = scrollTop;
				}
				
				//get width of the largest element
				var w = $(".inner > ul", this)[0].clientWidth - 21;
				$('span', this).css('width', w);
				
				if($(this).hasClass('selectBox'))
					var mod = 29;
				else var mod = 25;
				
				$(".inner > ul", this).css('display', '').css('visibility', '').css('min-width', w+mod);
				if(__ie6 || __ie7)
					$(".inner > ul", this).css('width', w+40);
				
				this._getVal = function() {
					return $('.inner > ul li.selected', this).attr('svalue');
				};
				this._setVal = function(val) {
					$('.inner > ul li.selected', this).removeClass('selected');
					var v = $('.inner > ul li[svalue='+val+']', this).addClass('selected').html();
					$('.inner > span', this).html(v);
				};
				this._unselect = function(v) {
					var v = v || '';
					$('.inner > ul li.selected', this).removeClass('selected');
					$('.inner > span', this).html(v);
				};
			});
			
			
			$('body').click(function() {
				$("div.selectBox, div.dropdownBtn").each(function() {
					$(this).trigger('_close');
				});
			});
			
			/*$('body')
			.unbind('mousemove', this.handlers.tmp1)
			.bind('mousemove', this.handlers.tmp1 );*/
			
			
			
		}
	},
	
	/**
	 * Popups
	 * 
	 * This class will replace the deprecated .confirmBox class
	 */
	popups: {
		//Contains the active popups
		activePopups: {},
		//Default settings
		settings: {
			type: 'alert', //alert, confirm, dialog, blank
			title: '',
			message: '', //If type=alert OR type=confirm
			content: '', //If type=dialog
			confirmAction: function() {}, //The function to call when the confirm button is clicked, for type=confirm
			continueLabel: 'Continue',
			action: function() {}, //This function will be called immediately after the content has been rendered, therefore allowing to add functionality to the popup
			width: 400,
			maxWidth: null,
			maxHeight: '95%',
			'':''
		},
		
		/**
		 * Create a new popup
		 * 
		 * @return object The popup
		 */
		create: function(settings) {
			if(settings.type != 'alert' && settings.type != 'confirm' && settings.type != 'dialog' && settings.type != 'blank')
				settings.type = this.settings.type;
			//merge settings
			if(settings.type == 'alert')
				settings.continueLabel = 'OK';
			var settings = Default.mergeObject(this.settings, settings);
			
			//Create the popup layer
			this._createLayer();
			
			//Generate a unique ID
			do {
				settings.id = Math.floor(Math.random()*1001);
			} while(this.activePopups[settings.id]);
			
			//Default cancel action
			settings.cancelAction = function() {
				$(this).parents('div.popup').trigger('close');
				return false;
			};
			
			if(settings.type == 'alert') {
				settings.confirmAction = function() {
					$(this).parents('div.popup').trigger('close');
					return false;
				};
				var obj = this._createAlert(settings);
			} else if(settings.type == 'confirm') {
				var obj = this._createConfirm(settings);
			}
			else if(settings.type == 'dialog') {
				var obj = this._createDialog(settings);
			} else {
				var obj = this._createBlank(settings);
			}
			
			$('#popups .overlay').mousemove(function(e) {
				e.stopPropagation();
				return false;
			});
			
			if($.isFunction(settings.action))
				settings.action();
			
			obj.settings = settings;
			
			Default.popups.activePopups[settings.id] = obj;
			
			//fade in
			$(obj).hide();
			Default.setOpacity($("#popups")[0], 100);
			$(obj).fadeIn(300);
			
			return obj;
		},
		
		_createLayer: function() {
			//exists already?
			if(!$("#popups").length)
				$("body").append('<div id="popups"></div>');
			//make opaque for now
			Default.setOpacity($("#popups")[0], 0);
			this._showLayer();
			return true;
		},
		_showLayer: function() {
			$("#popups").show();
		},
		_hideLayer: function() {
			$("#popups").hide();
		},
		
		_parsePopupWidth: function(settings) {
			if(!settings.width) return;
			
			//Determine width
			settings.width = String(settings.width);
			if(settings.width.indexOf("%")!=-1) {
				//Percentage width, determine by getting the total width of our available window space
				settings.width = Default.info.getPageWidth() * (parseInt(settings.width)/100);
			}
		},
		
		_parsePopupMaxWidth: function(settings) {
			if(!settings.maxWidth) return;
			
			//Determine width
			settings.maxWidth = String(settings.maxWidth);
			if(settings.maxWidth.indexOf("%")!=-1) {
				//Percentage width, determine by getting the total width of our available window space
				settings.maxWidth = Default.info.getWindowWidth() * (parseInt(settings.maxWidth)/100);
			}
		},
		
		_parsePopupMaxHeight: function(settings) {
			if(!settings.maxHeight) return;
			
			//Determine height
			settings.maxHeight = String(settings.maxHeight);
			if(settings.maxHeight.indexOf("%")!=-1) {
				//Percentage height, determine by getting the total height of our available window space
				settings.maxHeight = Default.info.getWindowHeight() * (parseInt(settings.maxHeight)/100);
			}
		},
		
		_createBlank: function(settings) {
			var html = '';
			html += '<div class="popup blankPopup" id="'+settings.id+'">';
				html += '<div class="overlay"></div>';
				this._parsePopupWidth(settings);
				this._parsePopupMaxHeight(settings);
				html += '<div class="inner'+(!settings.title?' noTitle':'')+'" style="width:'+settings.width+'px;">';
					if(settings.title)
						html += '<h1 class="title">' + settings.title + '</h1>';
					
					html += '<div class="content">';
						html += settings.content;
					html += '</div>';
					
					html += '<div class="buttons" style="text-align:right;">';
						html += '<a href="#" class="medBtn btnCancel"><b>Close</b></a>';
					html += '</div>';
				html += '</div>';
			html += '</div>';
			
			$("#popups").append(html);
			$("#"+settings.id+" a.btnCancel").click(settings.cancelAction);
			
			//Center popup vertically and horizontally
			//get width and height
			this._centerPopup($("#"+settings.id+" div.inner")[0]);
			
			$("#"+settings.id).bind('close', function() { Default.popups.close(this); });
			
			return $("#"+settings.id)[0];
		},

		_createAlert: function(settings) {
			var html = '';
			html += '<div class="popup alertPopup" id="'+settings.id+'">';
				html += '<div class="overlay"></div>';
				this._parsePopupWidth(settings);
				this._parsePopupMaxHeight(settings);
				this._parsePopupMaxWidth(settings);
				
				var styles = '';
				if(settings.maxWidth) {
					styles += 'max-width:'+settings.maxWidth+'px;';
					styles += 'width:auto;';
				} else styles += 'width:'+settings.width+'px;';
				styles += 'max-height:'+settings.maxHeight+'px;';
				
				html += '<div class="inner" style="'+styles+'">';
					html += '<h1 class="title">'+(settings.title?settings.title:"Attention")+'</h1>';
					
					if(settings.message) {
						html += '<div class="content message">';
							html += settings.message;
						html += '</div>';
					} else {
						html += '<div class="content">';
							html += settings.content;
						html += '</div>';
					}
					
					html += '<div class="buttons" style="text-align:center;">';
						html += '<a href="#" class="medBtn btnConfirm"><b>'+settings.continueLabel+'</b></a>';
					html += '</div>';
				html += '</div>';
			html += '</div>';
			
			$("#popups").append(html);
			$("#"+settings.id+" a.btnConfirm").click(settings.confirmAction);
			
			//Center popup vertically and horizontally
			//get width and height
			this._centerPopup($("#"+settings.id+" div.inner")[0]);
			
			$("#"+settings.id).bind('close', function() { Default.popups.close(this); });
			
			return $("#"+settings.id)[0];
		},

		_createConfirm: function(settings) {
			var html = '';
			html += '<div class="popup confirmPopup" id="'+settings.id+'">';
				html += '<div class="overlay"></div>';
				this._parsePopupWidth(settings);
				html += '<div class="inner" style="width:'+settings.width+'px;">';
					html += '<h1 class="title">'+(settings.title?settings.title:"Please confirm")+'</h1>';
					
					html += '<div class="content message">';
						html += settings.message;
					html += '</div>';
					
					html += '<div class="buttons" style="text-align:center;">';
						html += '<a href="#" class="medBtn btnCancel" style="float:left;"><b>Cancel</b></a>';
						html += '<a href="#" class="medBtn btnConfirm" style="float:right;"><b>'+settings.continueLabel+'</b></a>';
					html += '</div>';
				html += '</div>';
			html += '</div>';
			
			$("#popups").append(html);
			$("#"+settings.id+" a.btnCancel").click(settings.cancelAction);
			$("#"+settings.id+" a.btnConfirm").click(settings.confirmAction).click(settings.cancelAction);
			$("#"+settings.id+" a.btnConfirm")[0].settings = settings;
			
			//Center popup vertically and horizontally
			//get width and height
			this._centerPopup($("#"+settings.id+" div.inner")[0]);
			
			$("#"+settings.id).bind('close', function() { Default.popups.close(this); });
			
			return $("#"+settings.id)[0];
		},

		_createDialog: function(settings) {
			var html = '';
			html += '<div class="popup dialogPopup" id="'+settings.id+'">';
				html += '<div class="overlay"></div>';
				this._parsePopupWidth(settings);
				html += '<div class="inner" style="width:'+settings.width+'px;">';
					html += '<h1 class="title">'+(settings.title?settings.title:"Action Required")+'</h1>';
					
					html += '<div class="content">';
						html += settings.content;
					html += '</div>';
					
					html += '<div class="buttons" style="text-align:center;">';
						html += '<a href="#" class="medBtn btnCancel" style="float:left;"><b>'+ __('Cancel') + '</b></a>';
						html += '<a href="#" class="medBtn btnConfirm" style="float:right;"><b>'+settings.continueLabel+'</b></a>';
					html += '</div>';
				html += '</div>';
			html += '</div>';
			
			$("#popups").append(html);
			$("#"+settings.id+" a.btnCancel").click(settings.cancelAction);
			$("#"+settings.id+" a.btnConfirm").click(settings.confirmAction);
			
			//Center popup vertically and horizontally
			//get width and height
			this._centerPopup($("#"+settings.id+" div.inner")[0]);
			
			$("#"+settings.id).bind('close', function() { Default.popups.close(this); });
			
			return $("#"+settings.id)[0];
		},
		
		_centerPopup: function(obj) {
			//get width and height
			var width = obj.offsetWidth;
			var height = obj.offsetHeight;
			$(obj).css('margin-top', (-height/2)).css('margin-right', (-width/2));
			return true;
		},
		
		/**
		 * Refresh Position
		 * 
		 * This refreshes, and effectively re-centers the popup. Especially useful if the data in the popup changes and the popup should be centered again.
		 */
		refreshPositionLatest: function() {
			//get object
			var obj = null;
			for(popup in Default.popups.activePopups)
				obj = Default.popups.activePopups[popup];
			if(obj) Default.popups._centerPopup($("div.inner", obj)[0]);
		},
		
		/**
		 * Get Last Popup
		 */
		getLast: function() {
			var obj = null;
			for(popup in Default.popups.activePopups)
				obj = Default.popups.activePopups[popup];
			if(obj) return obj;
		},
		
		/**
		 * Close popup
		 * 
		 * @param object obj
		 */
		close: function(obj) {
			$(obj).fadeOut(300, function() {
				delete Default.popups.activePopups[this.id];
				$(this).remove();
				
				if($.isEmptyObject(Default.popups.activePopups))
					Default.popups._hideLayer();
			});
		},
		
		closeLatest: function() {
			//get object
			var obj = null;
			for(popup in Default.popups.activePopups)
				obj = Default.popups.activePopups[popup];
			if(obj) Default.popups.close(obj);
		}
	},
	
	popins: {
		ref: null,
		settings: {
			content: '',
			posX: 0,
			posY: 0,
			light: false
		},
		isOpen: false,
		
		open: function(s) {
			var s = Default.mergeObject(this.settings, s);
			
			//create if it doesnt exist yet
			if(this.ref == null)
				this.create();
			
			//fill with content if its not open
			if(!this.isOpen) {
				$('#popin .content').html(s.content);
				
				if(s.light) $('#popin .content').addClass('light');
				else $('#popin .content').removeClass('light');
				
				Default.setOpacity($("#popin")[0], 0);
				$('#popin').show();
				
				this.settings.w = $('#popin')[0].offsetWidth;
				this.settings.h = $('#popin')[0].offsetHeight;
			}
				
			//default position is above and to the right of the cursor, calculate available space
			var st = Default.info.getScrollTop();
			var sl = Default.info.getScrollLeft();
			var ot = $('#popin').offset()['top'];
			var ol = $('#popin').offset()['left'];
			var wh = Default.info.getWindowHeight();
			var ww = Default.info.getWindowWidth();
			
			var availTop = s.posY - st - 10;
			var availRight = ww - (s.posX - sl) - 10;
			
			if(availTop > this.settings.h) {
				//position above
				$('#popin').css('top', s.posY - this.settings.h - 10);
			} else {
				//position below
				$('#popin').css('top', s.posY + 20);
			}
			
			if(availRight > this.settings.w) {
				//position to the right
				$('#popin').css('left', s.posX + 10);
			} else {
				//position to the left
				$('#popin').css('left', s.posX - this.settings.w - 10);
			}
			
			if(!this.isOpen)
				Default.setOpacity($("#popin")[0], 100);
			
			this.isOpen = true;
		},
		
		close: function() {
			$('#popin').hide();
			$('#popin .content').html();
			this.isOpen = false;
		},
		
		create: function() {
			var html = '';
			html += '<div id="popin"><div class="inner"><div class="content"></div></div></div>';
			$("body").append(html);
			
			this.ref = $('#popin');
			return true;
		}
	},
	
	permissions: {
		hasPermission: function(permission) {
			if(_permissions == 'ALL') return true;
			
			if(permission.indexOf('|') != -1) {
				var p = permission.split('|');
				for(var i=0; i<p.length; i++)
					if(_permissions[p[i]] == true)
						return true;
			} else if(permission.indexOf('&') != -1) {
				var p = permission.split('&');
				for(var i=0; i<p.length; i++)
					if(_permissions[p[i]] != true)
						return false;
			}
			
			if(_permissions[permission] == true)
				return true;
			return false;	
		}
	},
	
	qHash: {
		add: function(name, val) {
			var hash = window.location.hash.substr(1);
			
			if(hash)
				var pairs = hash.split('&');
			else var pairs = [];
			var newPairs = [];
			
			for(var i=0; i<pairs.length; i++)
				if(pairs[i].split('=')[0] != name)
					newPairs.push(pairs[i]);
			
			if(typeof val == 'undefined')
				val = '';
			
			newPairs.push(escape(name) + '=' + escape(val));
			
			window.location.hash = '#' + newPairs.join('&');
		},
		get: function(name) {
			var hash = decodeURIComponent(window.location.hash.substr(1));
			
			var pairs = hash.split('&');
			if (!pairs.length)
				return false;
			
			//traverse all pairs
			for (var y=0; y<pairs.length; y++) {
				var vals = pairs[y].split('=');
				if(vals[0] == name) {
					return vals[1];
				}
					
			}
			
			return false;
		},
		newState: function(properties) {
			var hash = window.location.hash.substr(1);
			
			var pairs = [];
			
			for(var name in properties) {
				if(typeof properties[name] != 'undefined')
					pairs.push(escape(name) + '=' + escape(properties[name]));
			}
			if(pairs.length)
				window.location.hash = '#' + pairs.join('&');
		},
		remove: function() {
			window.location.hash = '';
		},
		getFull: function() {
			return window.location.hash;	
		},
		isEmpty: function() {
			if(!window.location.hash)
				return true;
			return false;
		}
	},
	
	/**
	 * Edit Popin
	 * Opens a small popin used for small in-place editing of fields.
	 */
	editPopin: {
		//Default settings
		settings: {
			target: null,
			content: '',
			description: '',
			offsetLeft: -10,
			offsetTop: -10,
			confirmAction: function() {},
			//This function will be called immediately after the content has been rendered,
			//therefore allowing to add functionality to the popin
			action: function() {},
			width: 300
		},
		_activeSettings: null,
		_activeInstance: null,
		_activeConfirmAction: null,
		_isInit: false,
		
		open: function(settings) {
			var settings = Default.mergeObject(this.settings, settings);
			this._activeSettings = settings;
			
			if(!this._isInit)
				this._init();
				
			
			this._activeConfirmAction = settings.confirmAction;
			
			//Create the popup layer
			this._create(settings);
			
			//write content
			this._writeContent(settings);
			this._writeDescription(settings);
			
			//position
			this._position(settings);
			
			//assign handlers
			$("#edit-popin a.btnCancel").click(function() {
				Default.editPopin.close();
				return false;
			});
			$("#edit-popin").click(function(e) {
				e.stopPropagation();
			});
			
			settings.action();
		},
		
		close: function(cb) {
			this._hide(cb);
			this._activeConfirmAction = function() {};
		},
		
		doSave: function() {
			Default.editPopin._activeConfirmAction();
			Default.editPopin.close();
		},
		
		_init: function() {
			$("body").click(function() {
				Default.editPopin._activeConfirmAction();
				Default.editPopin.close();
			});
			this._isInit = true;
		},
		
		_create: function(settings) {
			if(!$("#edit-popin").length)
				$("body").append('<div id="edit-popin"><div class="t"><div class="t2"><div id="edit-popin-content"></div></div></div><div class="i"><div class="i2"><div id="edit-popin-description"></div></div></div><div class="b"><div class="b2"></div></div></div>');
			//make opaque for now
			this._show();
			
			return true;
		},
		
		_position: function(settings) {
			$("#edit-popin").css('width', settings.width);
			var offset = $(settings.target).offset();
			
			//position
			var top = offset.top + settings.offsetTop;
			var left = offset.left + settings.offsetLeft;
			
			$("#edit-popin").css('top', top).css('left', left);
		},
		
		_writeContent: function(settings) {
			var html = '';
			html += settings.content;
			
			$("#edit-popin-content").html(html);
		},
		
		_writeDescription: function(settings) {
			var html = '';
			html += settings.description;
			
			$("#edit-popin-description").html(html);
		},
		
		_show: function() {
			$("#edit-popin").fadeIn(300);
		},
		
		_hide: function(cb) {
			__tmp_editPopin_cb = cb;
			$("#edit-popin").fadeOut(300, function() {
				$("#edit-popin").remove();
				if(typeof __tmp_editPopin_cb == 'function')
					__tmp_editPopin_cb();
			});
		},
	},
	
	toolTip: {
		_active: false,
		instance: null,
		create: function() {
			$("body").append('<div id="tooltip"><div class="i" id="tooltip-content"></div></div>');
		},
		setObject: function(obj) {
			this.instance = obj;
		},
		open: function(e, obj) {
			if(obj) this.setObject(obj);
			var obj = this.instance;
			
			if(!$("#tooltip").length)
				this.create();
			
			$('#tooltip-content').html($(obj).attr('stooltip'));
			
			//if (!e) var e = window.event;
			var offset = $(obj).offset();
			
			var x = offset.left + $(obj).outerWidth() - 10;
			var y = offset.top - $(obj).outerHeight() - 5;
			
			this._active = true;
			$('#tooltip').css('left', x).css('top', y)
			.stop().show().animate({opacity: 0.9 }, 300);
		},
		close: function() {
			$('#tooltip').stop().animate({opacity: 0 }, 300, '', function() {
				$(this).hide();
				Default.toolTip._active = false;
			});
		},
		
		enable: function(obj) {
			$(obj).mouseenter(function(e) {
				if($(this).attr('stooltipdisable') != '1') {
					Default.toolTip.setObject(this);
					
					//only run delay if not already active
					if(Default.toolTip._active) {
						Default.toolTip.open();
					} else {
						if(this._t)
							window.clearTimeout(this._t);
						
						this._t = window.setTimeout(function() {
							Default.toolTip.open();
						}, 300);
					}
				}
			}).mouseleave(function() {
				if(this._t)
					window.clearTimeout(this._t);
				this._t = null;
				
				Default.toolTip.close();
			});
		}
	}
	
};

DataTable = {
	getTableCols: function(cols, orderBy) {
		var html = '';
		
		for (var y=0; y<cols.length; y++) {
			var col = cols[y];
			var tmpClass = [];
			var append = col.append ? col.append : '';
			var useTag = 'td';
			var colspan = '';
			
			if (orderBy == col.name)
				tmpClass.push('sorted');
				
			if (col.HL)
				tmpClass.push('highlighted');
				
			if (col.span)
				colspan = ' colspan="'+col.span+'"';
			
			if (col.classes)
				tmpClass.push(col.classes);
			
			if(y==0)
				var useTag = 'th';
			if(y+1==cols.length)
				tmpClass.push('last');
			
			if (col.currency) {
				tmpClass.push('currency');
				//html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'><b>$<i>'+formatCurrency(col.value)+append+'</i></b></'+useTag+'>';
				if(col.precision) var number = formatCurrency(col.value, col.precision);
				else var number = formatCurrency(col.value);
				html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'><b>$'+number+append+'</b></'+useTag+'>';
			} else if (col.number) {
				tmpClass.push('number');
				html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'>'+formatNumber(col.value)+append+'</'+useTag+'>';
			} else if (col.percent) {
				tmpClass.push('number');
				html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'>'+formatPercent(col.value)+'%'+append+'</'+useTag+'>';
			} else if (col.countdown) {
				tmpClass.push('countdown');
				html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'><span tooltip="'+col.value+'" onmousemove="Default.helpers.toolTip.open(event, this);" onmouseout="Default.helpers.toolTip.close();">'+calculateCountdown(col.value)+'</span> ago'+append+'</'+useTag+'>';
			} else
				html += '<'+useTag+' class="'+tmpClass.join(" ")+'"'+colspan+'>'+col.value+append+'</'+useTag+'>';
		}
		
		return html;
	},
	
	getTableHeaderCols: function(cols, orderBy, orderType, sortableCols) {
		var html = '';
		
		for (var x=0; x<cols.length; x++) {
			var col = cols[x];
			var tmpClass = [];
			var useTag = 'td';
			
			if(x==0)
				var useTag = 'th';
			if(x+1==cols.length)
				tmpClass.push('last');
			
			if ( col.name && RegExp('\\b'+col.name+'\\b').test(sortableCols) ) {
				tmpClass.push('sortable');
				if(orderBy==col.name)
					if (orderType.toLowerCase()=='asc')
						tmpClass.push('sortedASC');
					else tmpClass.push('sortedDESC');
			}
			
			if(col.align)
				var align = ' align="'+col.align+'"';
			else var align = '';
				
			html += '<'+useTag+align+' class="'+tmpClass.join(" ")+'"'+(col.width?' style="width:'+col.width+'px;"':'')+(col.span ? ' colspan="'+col.span+'"' : '')+'><span self:name="'+col.name+'">'+col.value+'</span></'+useTag+'>';
			
		}
		
		return html;
	},
	
	getTableHeader2Cols: function(cols) {
		var html = '';
		
		for (var x=0; x<cols.length; x++) {
			var col = cols[x];
			var tmpClass = [];
			var useTag = 'td';
			
			if(x==0)
				var useTag = 'th';
			if(x+1==cols.length)
				tmpClass.push('last');
				
			if(col.align)
				var align = ' align="'+col.align+'"';
			else var align = '';
			
			html += '<'+useTag+align+' class="'+tmpClass.join(" ")+'"'+(col.span ? ' colspan="'+col.span+'"' : '')+'>'+col.value+'</'+useTag+'>';
			
		}
		
		return html;
	},
	
	/**
	 * Get Footer Page Navigation
	 * 
	 * settings:
	 * - id 
	 * - page 
	 * - totalPages 
	 * - pageResults 
	 * - totalResults 
	 * - results = []
	 */
	getFooterPageNavigation: function(s) {
		var html = '';
		
		s.page = parseInt(s.page);
		s.totalPages = parseInt(s.totalPages);
		s.pageResults = parseInt(s.pageResults);
		
		html += '<div class="pagination">';
		
			if(s.totalPages > 1) {
				
				//Prev
				if (s.page > 1)
					html += '<a self:val="'+(s.page-1)+'" href="#" class="prev"><b>'+__('Prev')+'</b></a>';
				else
					html += '<span class="cDisabled prev"><b>'+__('Prev')+'</b></span>';
		
				//Pages
				var startAt = s.page - 1; if (startAt < 1) startAt = 1;
				var finishAt = s.page + 1; if (finishAt > s.totalPages) finishAt = s.totalPages;
				
				if (startAt > 1) {
					html += '<a self:val="1" href="#"><b>1</b></a>';
					if(startAt > 2) html += '<span class="space">...</span>';
				}
					
				for (var i=startAt; i<=finishAt; i++) {
					if (i == s.page)
						html += '<span class="cActive"><b>'+ i +'</b></span>';
					else
						html += '<a self:val="'+ i +'" href="#"><b>'+ i +'</b></a>';
				}
				
				if (finishAt < s.totalPages) {
					if(finishAt < (s.totalPages-1)) html += '<span class="space">...</span>';
					html += '<a self:val="'+s.totalPages+'" href="#"><b>'+s.totalPages+'</b></a>';
				}
		
				//Next
				if (s.totalPages > 1 && s.page < s.totalPages)
					html += '<a self:val="'+(s.page+1)+'" href="#" class="next"><b>'+__('Next')+'</b></a>';
				else
					html += '<span class="cDisabled next"><b>'+__('Next')+'</b></span>';
				
			}
			
		html += '</div>';
		
		html += '<div class="results">';
			
			if(s.results) {
				html += '<span class="showRows">'+__('Show Rows')+':</span>';
				html += '<div class="selectBox compact" id="'+s.id+'_RPP"><div class="inner">';
					var buffer1 = '';
					var _label = s.pageResults;
					buffer1 += '<ul>';
						if($.isPlainObject(s.results)) {
							for(var val in s.results) {
								buffer1 += '<li svalue="'+val+'"'+(val==s.pageResults ? ' class="selected"' : '')+'>'+s.results[val]+'</li>';
								if(val==s.pageResults) _label = s.results[val];
							}
						} else
							for (var i=0; i<s.results.length; i++)
								buffer1 += '<li svalue="'+s.results[i]+'"'+(s.results[i]==s.pageResults ? ' class="selected"' : '')+'>'+s.results[i]+'</li>';
					buffer1 += '</ul>';
					
					html += '<span>'+_label+'</span>';
					html += buffer1;
				html += '</div></div>';
			}
			
			var resultOffset = (s.page-1)*s.pageResults;
			var cap = (s.page == s.totalPages) ? s.totalResults : resultOffset + s.pageResults;
			var str = __('{FROMPAGE} - {TOPAGE} of {TOTALPAGES}')
			.replace('{FROMPAGE}', resultOffset+1)
			.replace('{TOPAGE}', cap)
			.replace('{TOTALPAGES}', s.totalResults);
			html += '<span class="rowCount">'+str+'</span>';
			
		html += '</div>';
		
		return html;
	}
};

function formatCurrency(n, f) {
	if(typeof f == 'undefined') f = 2;
	
	var c = '';
	if(f > 0) {
		n = String(parseFloat(n).toFixed(f));
		var vals = n.split('.');
		c = '.' + vals[1];
		var s = vals[0];
	} else {
		n = String(parseInt(n));
		var s = n;
	}
	
	var omit = true;
	while(s.length) {
		var push = s.slice((s.length-3 > 0) ? s.length-3 : 0);
		if(omit)
			c = push + c;
		else c = push +',' + c;
		s = s.substr(0, s.length-3);
		omit = false;
	}
	return c;
}
function formatDecimal(n, f) {
	var f = f || 2;
	
	var r = parseFloat(n);
	
	if(isNaN(r))
		return new Number(0).toFixed(f);
	
	return r.toFixed(f);
}
function formatNumber(n) {
	return formatCurrency(n, 0);
	
}
function formatPercent(n) {
	return formatCurrency(n, 2);
	
}

function __(str) {
	if(typeof _translations == 'undefined') return str;
	if(_translations[str])
		return _translations[str];
	return str;
}

$.datepicker.setDefaults({
	minDate: new Date(2011, 7, 1),
	maxDate: '+0',
	hideIfNoPrevNext: true,
	numberOfMonths: 3,
	showCurrentAtPos: 1,
	showButtonPanel: true,
	showAnim: '',
	altFormat: 'mm/dd/yy'
});

$(function() {
	$('#languageSelector')
	.mouseenter(function() {
		$(this).addClass('languageSelectorOver');
	})
	.mouseleave(function() {
		$(this).removeClass('languageSelectorOver');
	})
	.click(function(e) {
		$(this).addClass('languageSelectorOpen');
		e.stopPropagation();
		return false;
	});
	
	$('#languageSelector li')
	.mouseover(function() { $(this).addClass('over'); })
	.mouseout(function() { $(this).removeClass('over'); })
	.click(function(e) {
		//submit
		$.ajax({
			type: "POST",
			url: '/_ajax/switchLanguage',
			data: {
				language: $(this).attr('lang')
			},
			dataType: 'html',
			success: function(response){
				
				$('#languageSelector').removeClass('languageSelectorOpen');
				//refresh
				window.location.reload();
				
			}

		});
		
		
		e.stopPropagation();
		return false;
	});
	
	$('body').click(function() {
		$('#languageSelector').removeClass('languageSelectorOpen');
	});
	
});

Chart = {
	colors: [
		'f2b600',
		'ff6a00',
		'3cb300',
		'cc00a0',
		'6800b3',
		'8ae599',
		'0080ff',
		'8adce5',
		'cc0000', 
		'ffff00',
		'00CCFF',
		'993333',
		'FF9966',
		'009999',
		'996600'
	],
	colorsBlue: [
		'e5f7ff',
		'99ddff',
		'4cc3ff',
		'00aaff',
		'2e7599',
		'006699',
		'173b4d', 
		'00334d',
		'aac2ce',
		'5c8599',
	],
	colorsOrange: [
		'fff4e5',
		'ffd599',
		'ffb54c',
		'ff9500',
		'996c2e',
		'995900',
		'4d3617', 
		'4d2d00',
		'cfbfa9',
		'99805c',
	],
	othersColor: 'f2f2f2'
};

_dateMonths = [
	'January', 
	'February', 
	'March', 
	'April', 
	'May', 
	'June', 
	'July', 
	'August', 
	'September', 
	'October', 
	'November', 
	'December'
];
_dateShortMonths = [
	'Jan', 
	'Feb', 
	'Mar', 
	'Apr', 
	'May', 
	'Jun', 
	'Jul', 
	'Aug', 
	'Sep', 
	'Oct', 
	'Nov', 
	'Dec'
];

/*
 * Initialization of the page
 */
$(function() {
	Default.form.enableCheckboxes();
	Default.form.enableRadioboxes();
});
