
/*************** EVENT CLASS ***************
* Browser Compliant Class to Add/Remove Events
*******************************************/
var Event = new function(){
	// add events once DOM has loaded and before onload, perfect for Flash Sites
	this.DOMReady = function(eFunction){
		if(document.addEventListener){
			document.addEventListener("DOMContentLoaded", eFunction, false);
		}
		else{
			this.ieEvent = new ieDomReady(eFunction);
			//IE.DOMReady(eFunction);
		}
	}
	// add event handlers during runtime
	this.addEvent = function(eNode, eType, eFunction){
		if(eNode.addEventListener){
			eNode.addEventListener(eType, eFunction, false);
			return true;
		}
		else if(eNode.attachEvent){
			var result = eNode.attachEvent("on" + eType, eFunction);
			return result;
		}
		else{
			eNode["on" + eType] = eFunction;
		}
	}
	// remove events handlers during runtime
	this.removeEvent = function(eNode, eType, eFunction){
		if(eNode.removeEventListener){
			eNode.removeEventListener(eType, eFunction, false);
			return true;
		}
		else if(eNode.detachEvent){
			var result = eNode.detachEvent("on" + eType, eFunction);
			return result;
		}
		else{
			eNode["on" + eType] = null;
		}
	}
	// returns the html element where the event occurred
	this.getTarget = function(evt){
		if(window.event != null){
			return window.event.srcElement;
		}
		else{
			return evt.target;
		}
	}
	// prevents the default behaviour of the target elements
	this.preventDefault = function(evt){
		if(window.event != null){
			return event.returnValue = false;
		}
		else{
			return evt.preventDefault();
		}
	}
}
/*************** IE CLASS ***************
* IE version of the DomContentLoaded: needs to be oop for multi use
*******************************************/
function ieDomReady(eFunction){
	this.callback = eFunction;
	this.doc = window.document;
	this.finished = false;
	var self = this;
	// polling for no errors
	(function(){
		try{
			self.doc.documentElement.doScroll('left');
		}
		catch(e){
			setTimeout(arguments.callee, 0);
			return;
		}
		self.init();
	})();
	this.doc.onreadystatechange = function(){
		if(self.doc.readyState == 'complete'){
			self.doc.onreadystatechange = null;
			self.init();
		}
	};
}
ieDomReady.prototype.init = function(){
	if(! this.finished) {
			this.finished = true;
			this.callback();
		}
}
/*var ieDOMLoaded = 0;
var IE = new function(){
	this.DOMReady = function(eFunction){
		if(ieDOMLoaded == 0){
			this.IEContentLoaded(eFunction);
			ieDOMLoaded  ++;
		}
		else if(ieDOMLoaded == 1){
			this.IEContentLoaded2(eFunction);
			ieDOMLoaded  ++;
		}
		else if(ieDOMLoaded == 2){
			this.IEContentLoaded3(eFunction);
			ieDOMLoaded  ++;
		}
		else{
			alert("Internet Explorer can only accept 3 DOM Loaded Events");
		}
	}
	// IE version of DOMReady
	this.IEContentLoaded = function(eFunction){
		var doc = window.document;
		var finished = false;
		DOMInit = function(){
			if(!finished) {
				finished = true;
				eFunction();
			}
		};
		// polling for no errors
		(function(){
			try{
				doc.documentElement.doScroll('left');
			}
			catch(e){
				setTimeout(arguments.callee, 0);
				return;
			}
			DOMInit();
		})();
		doc.onreadystatechange = function(){
			if(doc.readyState == 'complete'){
				doc.onreadystatechange = null;
				DOMInit();
			}
		};
	}
	// IE version of DOMReady
	this.IEContentLoaded2 = function(eFunction){
		var doc = window.document;
		var finished = false;
		DOMInit2 = function(){
			if(!finished) {
				finished = true;
				eFunction();
			}
		};
		// polling for no errors
		(function(){
			try{
				doc.documentElement.doScroll('left');
			}
			catch(e){
				setTimeout(arguments.callee, 0);
				return;
			}
			DOMInit2();
		})();
		doc.onreadystatechange = function(){
			if(doc.readyState == 'complete'){
				doc.onreadystatechange = null;
				DOMInit2();
			}
		};
	}
	// IE version of DOMReady
	this.IEContentLoaded3 = function(eFunction){
		var doc = window.document;
		var finished = false;
		DOMInit3 = function(){
			if(!finished) {
				finished = true;
				eFunction();
			}
		};
		// polling for no errors
		(function(){
			try{
				doc.documentElement.doScroll('left');
			}
			catch(e){
				setTimeout(arguments.callee, 0);
				return;
			}
			DOMInit3();
		})();
		doc.onreadystatechange = function(){
			if(doc.readyState == 'complete'){
				doc.onreadystatechange = null;
				DOMInit3();
			}
		};
	}
}*/
/*************** DOCUMENT CLASS ***************
* Core functionality not found in JavaScript
*******************************************/
var Document = new function(){
	// returns an array of all elements with a class name
	this.getElementsByClassName = function(classProperty, container){
		var classArray = new Array();
		var parentElement = (container != undefined) ? container : document;
		var elements = parentElement.getElementsByTagName("*");
		for(var i = 0; i < elements.length; i ++){
			if(elements[i].className.indexOf(" ") >= 0){
				var classes = elements[i].className.split(" ");
				for(var j = 0; j < classes.length; j ++){
					if(classes[j] == classProperty){
						classArray.push(elements[i]);
					}
				}
			}
			else if(elements[i].className == classProperty){
				classArray.push(elements[i]);
			}
		}
		return classArray;
	}// returns an array of all elements where a string exists in a class
	this.getElementsByClassMatch = function(classProperty, container){
		var classArray = new Array();
		var parentElement = (container != undefined) ? container : document;
		var elements = parentElement.getElementsByTagName("*");
		for(var i = 0; i < elements.length; i ++){
			if(elements[i].className.indexOf(classProperty) > -1){
				classArray.push(elements[i]);
			}
		}
		return classArray;
	}
	// returns an array of all elements with a group of tag names, separated with commas
	this.getElementsByTagNames = function(elements, container){
		var elementArray = new Array();
		var parentElement = (container != undefined) ? container : document;
		var tagElements = elements.split(',');
		for(var i = 0; i < tagElements.length; i ++){
			var currentTag = parentElement.getElementsByTagName(tagElements[i].trim());
			for(var j = 0; j < currentTag.length; j ++){
				elementArray.push(currentTag[j]);
			}
		}
		return elementArray;
	}
	// returns an array of all form inputs with the request type attribute
	this.getInputsByType = function(elements, container){
		var elementArray = new Array();
		var parentElement = (container != undefined) ? container : document;
		var typeElements = elements.split(',');
		var inputElements = parentElement.getElementsByTagName("input");
		for(var i = 0; i < inputElements.length; i ++){
			for(var j = 0; j < typeElements.length; j ++){
				if(inputElements[i].type == typeElements[j].trim()){
					elementArray.push(inputElements[i]);
				}
			}
		}
		return elementArray;
	}
	this.addClass = function(element, value){
		element.className += " "+value;	
	}
	this.removeClass = function(element, value){
		element.className = element.className.replace(value,"");
	}
	// returns the current css value
	this.getStyle = function(element,cssProperty){
		if(element.currentStyle){
			var dashIndex = cssProperty.indexOf("-");
			if(dashIndex > -1){
				var convertedStyle = "";
				for(var i = 0; i < cssProperty.length; i ++){
					if(i == (dashIndex + 1)){
						convertedStyle += cssProperty.charAt(dashIndex + 1).toUpperCase();
						continue;
					}
					convertedStyle += cssProperty.charAt(i);
				}
				cssProperty = convertedStyle.replace("-","");
			}
			var returnStyle = element.currentStyle[cssProperty];
		}
		else if(window.getComputedStyle){
			var returnStyle = document.defaultView.getComputedStyle(element,null).getPropertyValue(cssProperty);
		}
		return returnStyle;
	}
	// converts rgb values to hex value
	this.rgb2HEX = function(rgb){
		if(window.getComputedStyle && !document.body.currentStyle){
			rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
			function hex(x) {
				hexDigits = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
				return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
			}
			return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
		}
		else{
			return rgb;
		}
	}
	// inserts an element after the reference element, opposite to insertBefore
	this.insertAfter = function(newNode, referenceNode){
		referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
	}
	// returns the height of the body
	this.getBodyHeight = function(){
		if(window.scrollMaxY){ //Firefox
			var bodyHeight = window.innerHeight + window.scrollMaxY;
		}
		else if(document.documentElement){ //all modern browsers
			var bodyHeight =  document.documentElement.scrollHeight;
		}
		else{
			var bodyHeight =  document.body.scrollHeight;
		}
		var windowHeight = Document.getWindowHeight();
		bodyHeight = (windowHeight > bodyHeight) ? windowHeight : bodyHeight;
		return bodyHeight;
	}
	// returns the width of the body
	this.getBodyWidth = function(){
		if(window.scrollMaxX){ //Firefox
			return window.innerWidth + window.scrollMaxX;
		}
		else if(document.documentElement){ //all modern browsers
			return document.documentElement.scrollWidth;
		}
		else{
			return document.body.scrollWidth;
		}
	}
	// returns the height of the clients window
	this.getWindowHeight = function(){
		if(document.documentElement){ // IE
			return document.documentElement.clientHeight;
		}
		else{
			return window.innerHeight;
		}
	}
	// returns the width of the clients window
	this.getWindowWidth = function(){
		if(document.documentElement){
			return document.documentElement.clientWidth;
		}
		else{
			return  window.innerWidth;
		}
	}
	// returns the srollbar location via the y axis
	this.getScrollY = function(){
		if(document.documentElement.scrollTop){
			return document.documentElement.scrollTop;
		}
		else{
			return document.body.scrollTop;
		}
	}
	// returns the srollbar location via the x axis
	this.getScrollX = function(){
		if(document.documentElement.scrollLeft){
			return document.documentElement.scrollLeft;
		}
		else{
			return document.body.scrollLeft;
		}
	}
	// returns the left(x) location of an element
	this.getX = function(element){
		var x = element.offsetLeft;
		var parentElement = element.offsetParent;
		while(parentElement != null){
			x += parentElement.offsetLeft;
			parentElement = parentElement.offsetParent;
		}
		return x;
	}
	// returns the top(y) location of an element
	this.getY = function(element){
		var y = element.offsetTop;
		var parentElement = element.offsetParent;
		while(parentElement != null){
			y += parentElement.offsetTop;
			parentElement = parentElement.offsetParent;
		}
		return y;
	}
	// returns the x location of the mouse, NEEDS TO BE CALLED WITH AN EVENT TO WORK
	this.getMouseX = function(evt){
		var x;
		if(window.event != null){ //IE
			x = event.clientX + document.documentElement.scrollLeft;
		}
		else{
			x = evt.pageX;
		}
		x = (x < 0) ? 0 : x;
		return x;
	}
	// returns the y location of the mouse, NEEDS TO BE CALLED WITH AN EVENT TO WORK
	this.getMouseY = function(evt){
		var y;
		if(window.event != null){ //IE
			y = event.clientY + document.documentElement.scrollTop;
		}
		else{
			y = evt.pageY;
		}
		y = (y < 0) ? 0 : y;
		return y;
	}
	this.getParentForm = function(element){
		var currentNode = element.parentNode;
		while(currentNode){
			var currentTag = currentNode.tagName.toLowerCase();
			if(currentTag == "form"){
				break;
			}
			currentNode = currentNode.parentNode;
		}
		return currentNode;
	}
	this.submitParentForm = function(element){
		var currentNode = element.parentNode;
		while(currentNode){
			var currentTag = currentNode.tagName.toLowerCase();
			if(currentTag == "form"){
				currentNode.submit();
				break;
			}
			currentNode = currentNode.parentNode;
		}
	}
	this.hideAllSelects = function(){
		var browser = Browser.getBrowser();
		var version = Browser.getVersion();
		if(browser == "internet explorer" && version < 7){
			var selects = document.getElementsByTagName("select");
			for(var i = 0; i < selects.length; i ++){
				selects[i].style.visibility = "hidden";
			}
		}
	}
	this.showAllSelects = function(){
		var browser = Browser.getBrowser();
		var version = Browser.getVersion();
		if(browser == "internet explorer" && version < 7){
			var selects = document.getElementsByTagName("select");
			for(var i = 0; i < selects.length; i ++){
				selects[i].style.visibility = "visible";
			}
		}
	}
	this.getArguments = function(element,classString){
		var elementClass = element.className;
		var parameters = new Array();
		var currentParameter = "";
		var start = elementClass.indexOf(classString + "(") + classString.length + 1;
		if(start > -1){
			for(var i = start; i < elementClass.length; i ++){
				var currentCharacter = elementClass.charAt(i);
				if(currentCharacter == " "){
					continue;	
				}
				else if((currentCharacter == ",") || (currentCharacter == ")")){
					if(currentParameter.charAt(0) == "'"){
						currentParameter = currentParameter.replace(/'/g, "");
						parameters.push(String(currentParameter));
					}
					else{
						if(currentParameter == "true"){
							parameters.push(Boolean(true));	
						}
						else if(currentParameter == "false"){
							parameters.push(Boolean(false));	
						}
						else{
							parameters.push(Number(currentParameter));
						}
					}
					if(currentCharacter == ")"){
						break;
					}
					else{
						currentParameter = "";
						continue;
					}
				}
				currentParameter += currentCharacter;
			}
			return parameters;
		}
	}
}

/*************** Browser CLASS ***************
* Information regarding the users browser, with cookie functionality
*******************************************/
var Browser = new function(){
	// class attributes
	this.operatingSystem = navigator.platform;
	this.browser = navigator.userAgent;
	this.cookiesEnabled = navigator.cookieEnabled;
	// returns the computer platform of the user
	this.getOS = function(){
		if(this.operatingSystem.match("Win")){
			return "windows";
		}
		else if(this.operatingSystem.match("Mac")){
			return "macintosh";
		}
		else{
			return "unknown";
		}
	}
	// returns the name of the current browser
	this.getBrowser = function(){
		var browserSearch = this.browser.toLowerCase();
		//return browserSearch;
		if(browserSearch.match("msie")){
			return "internet explorer";
		}
		else if(browserSearch.match("firefox")){
			return "firefox";
		}
		else if(browserSearch.match("chrome")){
			return "chrome";
		}
		else if(browserSearch.match("safari")){
			return "safari";
		}
		else if(browserSearch.match("opera")){
			return "opera";
		}
		else{
			return "unknown";
		}
	}
	// returns the version of the users browser
	this.getVersion = function(){
		var currentBrowser = this.getBrowser();
		var browserSearch = this.browser.toLowerCase();
		var searchLength = browserSearch.length;
		if(currentBrowser == "internet explorer"){
			var start = browserSearch.indexOf("msie ") + "msie ".length;
			var versionString = "";
			for(var i = start; i < searchLength; i ++){
				var currentChar = browserSearch.charAt(i);
				if(currentChar == ";"){
					break;
				}
				versionString += currentChar;
			}
			return parseInt(versionString);
		}
		else if(currentBrowser == "firefox"){
			var start = browserSearch.indexOf("firefox/") + "firefox/".length;
			var versionString = "";
			for(var i = start; i < searchLength; i ++){
				var currentChar = browserSearch.charAt(i);
				versionString += currentChar;
			}
			return parseInt(versionString);
		}
		else if(currentBrowser == "chrome"){
			var start = browserSearch.indexOf("chrome/") + "chrome/".length;
			var end = browserSearch.indexOf("safari");
			var versionString = "";
			for(var i = start; i < end; i ++){
				var currentChar = browserSearch.charAt(i);
				versionString += currentChar;
			}
			return parseInt(versionString);
		}
		else if(currentBrowser == "safari"){
			var start = browserSearch.indexOf("version/") + "version/".length;
			var end = browserSearch.indexOf("safari");
			var versionString = "";
			for(var i = start; i < end; i ++){
				var currentChar = browserSearch.charAt(i);
				versionString += currentChar;
			}
			return parseInt(versionString);
		}
		else if(currentBrowser == "opera"){
			var start = browserSearch.indexOf("opera/") + "opera/".length;
			var end = browserSearch.indexOf(" (");
			var versionString = "";
			for(var i = start; i < end; i ++){
				var currentChar = browserSearch.charAt(i);
				versionString += currentChar;
			}
			return parseInt(versionString);
		}
		else{
			return 0;
		}
	}
	this.isFlashInstalled = function(){
		var isInstalled = false;
		if(window.ActiveXObject){ //ie
			var control = null;
			try{
				control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
			}
			catch(e){
				return;
			}
			if(control){
				isInstalled = true;
			}
		}
		else{ //all browsers part ie
			if(navigator.plugins["Shockwave Flash"]){
				isInstalled = true;
			}
		}
		return isInstalled;
	}
	this.getFlashVersion = function(){
		var version = 0;
		if(window.ActiveXObject){ //ie
			var control = null;
			try{
				control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
			}
			catch(e){
				return;
			}
			if(control){
				version = control.GetVariable('$version').substring(4);
				version = version.split(',');
				version = parseFloat(version[0] + '.' + version[1]);
			}
		}
		else{ //all browsers part ie
			if(navigator.plugins["Shockwave Flash"]){
				var flashDescription = navigator.plugins["Shockwave Flash"].description;
				version = flashDescription.substring(16); 
				version = version.split(' ');
				version = parseFloat(version[0]);
			}
		}
		return version;
	}
	// sets a cookie variable; name, value and expires are only required
	this.setCookie = function(name, value, expires, path, domain, secure){
		if(this.cookiesEnabled){
			var today = new Date();
			today.setTime(today.getTime());
			if(expires){
				expires = expires * 1000 * 60 * 60 * 24;
			}
			var expiresDate = new Date(today.getTime() + (expires));
			var cookieString = name + "=" + escape(value);
			if(expires){ cookieString += ";expires=" + expiresDate.toGMTString();}
			if(path){ cookieString += ";path=" + path;}
			if(domain){ cookieString += ";domain=" + domain;}
			if(secure){ cookieString += ";secure=" + secure;}
			document.cookie = cookieString;
		}
	}
	// returns a cookie variable
	this.getCookie = function(name){
		if(this.cookiesEnabled){
			var start = document.cookie.indexOf(name + "=");
			var length = start + name.length + 1;
			if((! start) && (name != document.cookie.substring(0, name.length))){
				return null;
			}
			if(start == -1){
				return null;
			}
			var end = document.cookie.indexOf(";", length);
			if(end == -1){
				end = document.cookie.length;
			}
			return unescape(document.cookie.substring(length, end));
		}
	}
	// deletes a cookie variable from the clients browser
	this.deleteCookie = function(name, path, domain){
		if(this.cookiesEnabled){
			if(this.getCookie(name)){
				var cookieString = name + "=";
				if(path){ cookieString += ";path=" + path;}
				if(domain){ cookieString += ";domain=" + domain;}
				cookieString += ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
				document.cookie = cookieString;
			}
		}
	}
}

/*************** AJAX CLASS ***************
* Call HTTP methods easily and retrieve xml values 
*******************************************/
function Ajax(file, method, returnXML, callback, queryString){
	var xmlhttp;
	var returnXML = (returnXML == undefined) ? true : returnXML;
	var queryString = (queryString == undefined) ? null : queryString;
	if(window.XMLHttpRequest){
		// code for IE7+, Firefox, Chrome, Opera, Safari
		xmlhttp = new XMLHttpRequest();
	}
	else if(window.ActiveXObject){
		// code for IE6, IE5
		xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else{
		return false;
	}
	if(xmlhttp.overrideMimeType){
 		xmlhttp.overrideMimeType('text/xml');
	}
	xmlhttp.onreadystatechange = function(){
		if(xmlhttp.readyState == 4){
			if(xmlhttp.status == 200){
				if(callback != undefined){
					if(returnXML){
						callback(xmlhttp.responseXML);
					}
					else{
						callback(xmlhttp.responseText);
					}
				}
			}
			else if(xmlhttp.status == 404){
				alert("Unfortunately the page could not be found on our server.");	
			}
			else{
				alert("There was a problem with the HTTP Request, we strongly suggest you upgrade your browser");	
			}
		}
	}
	xmlhttp.open(method,file,true);
	if(method == "POST"){
		xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
		xmlhttp.setRequestHeader("Content-length", queryString.length);
		xmlhttp.setRequestHeader("Connection", "close");
	}
	xmlhttp.send(queryString);
}
Ajax.getNodeValue = function(parent,child){
	return parent.getElementsByTagName(child)[0].firstChild.nodeValue;
}
Ajax.getAtrributeValue = function(parent,child,attributeValue){
	return parent.getElementsByTagName(child)[0].attributes.getNamedItem(attributeValue).value;
}
Ajax.getNodeCollection = function(parent,child){
	return parent.getElementsByTagName(child);
}
Ajax.getNodeValues = function(parent,child){
	var nodes = new Array();
	var collection = parent[0].getElementsByTagName(child);
	for(var i = 0; i < collection.length; i ++){
		nodes.push(collection[i].firstChild.nodeValue);
	}
	return nodes;
}

/*************** STRING CLASS ***************
* Adding Methods to Built-In String Class
*******************************************/
// trims white space at boths ends
String.prototype.trim = function(){
	return this.replace(/^\s+|\s+$/, "");
}
// removes white space at the start
String.prototype.leftTrim = function(){
	return this.replace(/^\s+/, "");
}
// removes white space at the end
String.prototype.rightTrim = function(){
	return this.replace(/\s+$/, "");
}

/*************** ARRAY CLASS ***************
* Adding Methods to Built-In Array Class
*******************************************/
// reverses the order of an array
Array.prototype.reverseSort = function(){
	this.sort();
	this.reverse();
}
// removes all objects from an array
Array.prototype.clear = function(){
	this.length = 0;
}
// returns a boolean to check if the array contains a value/object
Array.prototype.contains = function(element){
	for(var i = 0; i < this.length; i ++){
		if(this[i] == element){
			return true;
		}
	}
	return false;
}
// returns the number of instances of a value/object
Array.prototype.count = function(element){
	var instances = 0;
	for(var i = 0; i < this.length; i ++){
		if(this[i] == element){
			instances ++;
		}
	}
	return instances;
}
// performs a function on each element of an array
Array.prototype.each = function(action){
	for(var i = 0; i < this.length; i ++){
		action(this[i]);
	}
}
// strips all duplicated values from the array
Array.prototype.unique = function(){
	var result = new Array();
	var temp = new Array();
	for(var i = 0; i < this.length; i ++){
		if(result.instanceOf(this[i]) == 0){
			result.push(this[i]);
		}
	}
	this.clear();
	for(var i = 0; i < result.length; i ++){
		this[i] = result[i];
	}
}

/*************** DATE CLASS ***************
* Adding Methods to Built-In Date Class
*******************************************/
// duplicates the date - NEED FOR METHODS BELOW
Date.prototype.copy = function(){
	return new Date(this.getTime());
}
// CONSTANTS
Date.prototype.DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
Date.prototype.MONTHNAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
Date.prototype.msPERDAY = 1000 * 60 * 60 * 24;
// returns the full day as text
Date.prototype.getFullDay = function(){
	return this.DAYNAMES[this.getDay()];
}
// returns the day as abbreviated text
Date.prototype.getDayAbbr = function(){
	return this.getFullDay().slice(0, 3);
}
// returns the full month as text
Date.prototype.getFullMonth = function(){
	return this.MONTHNAMES[this.getMonth()];
}
// returns the month as abbreviated text
Date.prototype.getMonthAbbr = function(){
	return this.getFullMonth().slice(0, 3);
}
// returns the the time as 24 hour text
Date.prototype.to24HourTime = function(displaySeconds){
	var hours = "0" + this.getHours();
	var minutes = "0" + this.getMinutes();
	var seconds = "0" + this.getSeconds();
	if(displaySeconds != undefined){
		return hours.slice(-2) + ":" + minutes.slice(-2) + ":" + seconds.slice(-2);
	}
	else{
		return hours.slice(-2) + ":" + minutes.slice(-2);
	}
}
// returns the last day of the month
Date.prototype.lastDay = function(){
  var d = new Date(this.getFullYear(), this.getMonth() + 1, 0);
  return d.getDate();
}
// returns the days between two dates
Date.prototype.getDaysBetween = function(date){
	date = date.copy();
	date.setHours(this.getHours(), this.getMinutes(), this.getSeconds(), this.getMilliseconds());
	var difference = date.getTime() - this.getTime();
	return (difference) / this.msPERDAY;
}
// returns the day of the year
Date.prototype.getDayOfYear = function(){
	var yearStart = new Date(this.getFullYear(), 0, 0);
	return this.getDaysBetween(yearStart) * -1;
}
// returns the date after adding days
Date.prototype.addDays = function(days){
	this.setDate(this.getDate() + days);
}
// returns the date after adding weeks
Date.prototype.addWeeks = function(weeks){
	this.addDays(weeks * 7);
}
// returns the date after adding months
Date.prototype.addMonths = function(months){
	var date = this.getDate();
	this.setMonth(this.getMonth() + months);
	if(this.getDate() < date){
		this.setDate(0);
	}
}
// returns the date after adding years
Date.prototype.addYears = function(years) {
	var month = this.getMonth();
	this.setFullYear(this.getFullYear() + years);
	if(month < this.getMonth()){
		this.setDate(0);
	}
}

/*************** Tween CLASS ***************
* Allows simple and quick access to animate an object like actionscript
*******************************************/
function Tween(element, property, easingClass, start, end, seconds){
	this.msPERFRAME = (Browser.getBrowser == "firefox") ? 100 : 34; // 30 frames per second
	this.element = element;
	this.property = property;
	this.easingClass = easingClass;
	this.start = start;
	this.end = end;
	this.milliseconds = seconds * 1000;
	this.onMotionFinished;
	switch(property){
		case "width": 
			this.animateProperty("width");
			break;
		case "height":
			this.animateProperty("height");
			break;
		case "left":
			this.animateProperty("left");
			break;
		case "x":
			this.animateProperty("left");
			break;
		case "top":
			this.animateProperty("top");
			break;
		case "y":
			this.animateProperty("top");
			break;
		case "alpha":
			this.animateAlpha();
			break;
		case "scaleX":
			this.animateScaleX();
			break;
		case "scaleY":
			this.animateScaleY();
			break;
		default:
			return false;
			break;
	}
}
// calls a function once the current animation has finished
Tween.prototype.callback = function(){
	try{
		return this.onMotionFinished();
	}
	catch(e){
		return;
	}
}
// animates the main properties of an element such as width, height, x and y
Tween.prototype.animateProperty = function(property){
	var self = this;
	var frameCount = 0;
	var totalFrames = this.milliseconds / this.msPERFRAME;
	var totalChange = self.end - self.start;
	var property = property;
	var animation = setInterval(function(){
		var currentValue = self.easingClass(frameCount, self.start, totalChange, totalFrames);
		try{
			if(currentValue < 0){
				currentValue = 0;
			}
			self.element.style[property] = currentValue + "px";
		}
		catch(e){}
		if(frameCount >= totalFrames){
			self.element.style[property] = self.end + "px";
			self.callback();
			clearInterval(animation);
		}
		frameCount ++;
	}, this.msPERFRAME);
}
// animates the transparent or opacity of an element
Tween.prototype.animateAlpha = function(){
	var self = this;
	var frameCount = 0;
	var totalFrames = this.milliseconds / this.msPERFRAME;
	var totalChange = self.end - self.start;
	var property = property;
	var animation = setInterval(function(){
		var currentValue = self.easingClass(frameCount, self.start, totalChange, totalFrames);
		try{
			if(currentValue < 0){
				currentValue = 0;
			}
			self.element.style.opacity = currentValue / 100;
			self.element.style.filter = "alpha(opacity="+currentValue+")"; 
		}
		catch(e){}
		if(frameCount >= totalFrames){
			self.element.style.opacity = self.end / 100;
			self.element.style.filter = "alpha(opacity="+self.end+")"; 
			self.callback();
			clearInterval(animation);
		}
		frameCount ++;
	}, this.msPERFRAME);
}
// animates the x and width simultaneously from center
Tween.prototype.animateScaleX = function(){
	var self = this;
	var frameCount = 0;
	var totalFrames = this.milliseconds / this.msPERFRAME;
	var totalChange = self.end - self.start;
	var property = property;
	var leftPadding = Number(Document.getStyle(this.element,"padding-left").replace("px",""));
	var rightPadding = Number(Document.getStyle(this.element,"padding-right").replace("px",""));
	var totalPadding = leftPadding + rightPadding;
	var animation = setInterval(function(){
		var currentValue = self.easingClass(frameCount, self.start, totalChange, totalFrames);
		var currentX = Document.getX(self.element);
		var difference = (currentX - (currentValue - self.element.offsetWidth) / 2) - (totalPadding / 2);
		//currentX -= 1;
		//self.element.innerHTML += "offset: " + Math.round(self.element.offsetWidth)+", ";
		//self.element.innerHTML += "current: " + Math.round(currentValue)+", ";
		try{
			if(currentValue < 0){
				currentValue = 0;
			}
			self.element.style.width = Math.round(currentValue) + "px";
			self.element.style.left = Math.round(difference) + "px";
		}
		catch(e){}
		if(frameCount >= totalFrames){
			self.element.style.width = self.end + "px";
			self.callback();
			clearInterval(animation);
		}
		frameCount ++;
	}, this.msPERFRAME);
}
// animates the y and height simultaneously from center
Tween.prototype.animateScaleY = function(){
	var self = this;
	var frameCount = 0;
	var totalFrames = this.milliseconds / this.msPERFRAME;
	var totalChange = self.end - self.start;
	var property = property;
	var topPadding = Number(Document.getStyle(this.element,"padding-top").replace("px",""));
	var bottomPadding = Number(Document.getStyle(this.element,"padding-bottom").replace("px",""));
	var totalPadding = topPadding + bottomPadding;
	var animation = setInterval(function(){
		var currentValue = self.easingClass(frameCount, self.start, totalChange, totalFrames);
		var currentY = Document.getY(self.element);
		var difference = (currentY - (currentValue - self.element.offsetHeight) / 2) - (totalPadding / 2);
		try{
			if(currentValue < 0){
				currentValue = 0;
			}
			self.element.style.height = Math.round(currentValue) + "px";
			self.element.style.top = Math.round(difference) + "px";
		}
		catch(e){}
		if(frameCount >= totalFrames){
			self.element.style.height = self.end + "px";
			self.callback();
			clearInterval(animation);
		}
		frameCount ++;
	}, this.msPERFRAME);
}

/*************** Easing PACKAGE ***************
* Various Easing classes for the Tween Class
*******************************************/
// To gain a gentle subtle sense of easing 
var Regular = new function(){
	this.easeIn = function(time, start, change, duration){
		return change * (time /= duration) * time + start;
	}
	this.easeOut = function(time, start, change, duration){
		return -change * (time /= duration) * (time - 2) + start;
	}
	this.easeInOut = function(time, start, change, duration){
		if((time /= duration / 2) < 1){
			return change / 2 * time * time + start;
		}
		return -change / 2 * ((--time) * (time - 2) - 1) + start;
	}
}
// To gain an obvious easing
var Strong = new function(){
	this.easeIn = function(time, start, change, duration){
		return change * (time /= duration) * time * time * time * time + start;
	}
	this.easeOut = function(time, start, change, duration){
		return change * ((time = time / duration - 1) * time * time * time * time + 1) + start;
	}
	this.easeInOut = function(time, start, change, duration){
		if((time /= duration / 2) < 1){
			return change / 2 * time * time * time * time * time + start;
		}
		return change / 2 * ((time -= 2) * time * time * time * time + 2) + start;
	}
}
// To add an overshoot to your animation
var Back = new function(){
	this.easeIn = function(time, start, change, duration, overShoot){
		if(!overShoot){
			overShoot = 1.70158;
		}
		return change * (time /= duration) * time * ((overShoot + 1) * time - overShoot) + start;
	}
	this.easeOut = function(time, start, change, duration, overShoot){
		if(!overShoot){
			overShoot = 1.70158;
		}
		return change * ((time = time / duration - 1) * time * ((overShoot + 1) * time + overShoot) + 1) + start;
	}
	this.easeInOut = function(time, start, change, duration, overShoot){
		if(!overShoot){
			overShoot = 1.70158; 
		}
		if((time /= duration / 2) < 1){
			return change / 2 * (time * time * (((overShoot *= (1.525)) + 1) * time - overShoot)) + start;
		}
		return change / 2 * ((time -= 2) * time * (((overShoot *= (1.525)) + 1) * time + overShoot) + 2) + start;
	}
}
// To add a bouncing effect to your animation
var Bounce = new function(){
	this.easeIn = function(time, start, change, duration){
		return change - Bounce.easeOut(duration - time, 0, change, duration) + start;
	}
	this.easeOut = function(time, start, change, duration){
		if((time /= duration) < (1 / 2.75)){
			return change * (7.5625 * time * time) + start;
		}
		else if(time < (2 / 2.75)){
			return change * (7.5625 * (time -= (1.5 / 2.75)) * time + 0.75) + start;
		}
		else if(time < (2.5 / 2.75)){
			return change * (7.5625 * (time -= (2.25 / 2.75)) * time + 0.9375) + start;
		}
		else{
			return change * (7.5625 * (time -= (2.625 / 2.75)) * time + 0.984375) + start;
		}
	}
	this.easeInOut = function(time, start, change, duration){
		if(time < (duration / 2)){
			return Bounce.easeIn(time * 2, 0, change, duration) * 0.5 + start;
		}
		else{
			return Bounce.easeOut(time * 2 - duration, 0, change, duration) * 0.5 + change * 0.5 + start;
		}
	}
}
// To add an elastic band effect to your animation
var Elastic = new function(){
	this.easeIn = function(time, start, change, duration, amplitude, period){
		if(time == 0){
			return start;
		}
		if((time /= duration) == 1){
			return start + change;
		}
		if(!period){
			period = duration * 0.3;
		}
		var sine;
		if(!amplitude || amplitude < Math.abs(change)){
			amplitude = change;
			sine = period / 4;
		}
		else{
			sine = period / (2 * Math.PI) * Math.asin(change / amplitude);
		}
		return -(amplitude * Math.pow(2, 10 * (time -= 1)) * Math.sin((time * duration - sine) * (2 * Math.PI) / period)) + start;
	}
	this.easeOut = function(time, start, change, duration, amplitude, period){
		if(time == 0){
			return start;
		}
		if((time /= duration) == 1){
			return start + change;
		}
		if(!period){
			period = duration * 0.3;
		}
		var sine;
		if(!amplitude || amplitude < Math.abs(change)){
			amplitude = change;
			sine = period / 4;
		}
		else{
			sine = period / (2 * Math.PI) * Math.asin(change / amplitude);
		}
		return amplitude * Math.pow(2, -10 * time) * Math.sin((time * duration - sine) * (2 * Math.PI) / period) + change + start;
	}
	this.easeInOut = function(time, start, change, duration, amplitude, period){
		if(time == 0){
			return start;
		}
		if((time /= duration / 2) == 2){
			return start + change;
		}
		if(!period){
			period = duration * (0.3 * 1.5);
		}
		var sine;
		if(!amplitude || amplitude < Math.abs(change)){
			amplitude = change;
			sine = period / 4;
		}
		else{
			sine = period / (2 * Math.PI) * Math.asin(change / amplitude);
		}
		if(time < 1){
			return -0.5 * (amplitude * Math.pow(2, 10 * (time -= 1)) * Math.sin((time * duration - sine) * (2 * Math.PI) / period)) + start;
		}
		return amplitude * Math.pow(2, -10 * (time -= 1)) * Math.sin((time * duration - sine) * (2 * Math.PI) / period) * 0.5 + change + start;
	}
}
// To apply no easing of any kind
var None = new function(){
	this.easeNone = function(time, start, change, duration){
		return change * time / duration + start;
	}
	this.easeIn = function(time, start, change, duration){
		return None.easeNone(time, start, change, duration);
	}
	this.easeOut = function(time, start, change, duration){
		return None.easeNone(time, start, change, duration);
	}
	this.easeInOut = function(time, start, change, duration){
		return None.easeNone(time, start, change, duration);
	}
}

var Standard = new function(){
	this.alert = function(message){
		//create overlay
		var overlay = document.createElement("div");
		overlay.setAttribute("id","js_alert_overlay");
		document.getElementsByTagName("body")[0].appendChild(overlay);
		var bodyHeight = Document.getBodyHeight();
		var windowHeight = Document.getBodyHeight();
		if(windowHeight > bodyHeight){
			overlay.style.height = windowHeight + "px";
		}
		else{
			overlay.style.height = bodyHeight + "px";
		}
		Document.hideAllSelects();
		//create alert
		var alertDiv = document.createElement("div");
		alertDiv.setAttribute("id","js_alert");
		alertDiv.style.visibility = "hidden";
		document.getElementsByTagName("body")[0].appendChild(alertDiv);
		//create content
		var alertP = document.createElement("p");
		alertP.innerHTML = message;
		alertDiv.appendChild(alertP);
		var alertP2 = document.createElement("p");
		alertDiv.appendChild(alertP2);
		var alertClose = document.createElement("a");
		alertClose.setAttribute("href","#");
		alertClose.setAttribute("title","OK");
		alertClose.innerHTML = "OK";
		alertP2.appendChild(alertClose);
		Event.addEvent(alertClose,"click",this.closeAlert);
		Event.addEvent(overlay,"click",this.closeAlert);
		//set position
		var xpos = (Document.getWindowWidth() / 2) - (alertDiv.offsetWidth / 2);
		var ypos = Document.getScrollY() + (Document.getWindowHeight() / 2) - (alertDiv.offsetHeight / 2);
		alertDiv.style.left = xpos + "px";
		alertDiv.style.top = ypos + "px";
		alertDiv.style.visibility = "visible";
	}
	this.closeAlert = function(evt){
		Event.preventDefault(evt);
		var overlay = document.getElementById("js_alert_overlay");	
		var alertDiv = document.getElementById("js_alert");
		alertDiv.parentNode.removeChild(alertDiv);
		var fadeOut = new Tween(overlay,"alpha",Regular.easeOut,80,0,0.1);
		fadeOut.onMotionFinished = function(){
			overlay.parentNode.removeChild(overlay);
			Document.showAllSelects();
		}
	}
}
