/*******************************************************************************
 * Common JavaScript functions library.
 * Author:		John
 * Created:		Mon, 3-Jun-2008
 * Modified:	Thu, 21-Aug-2008
 ******************************************************************************/
/*******************************************************************************
 * Class Timer
 * Description: Determine passed time in ms.
 ******************************************************************************/
/*global Timer*/
Timer = function () {
	//Constructor.
	this.iStart = 0;
	this.iEnd = 0;
	this.iMs = 0;
	this.running = false;
	this.dateStart = 0;
	this.dateEnd = 0;
};

Timer.prototype = {
	start: function () {
		if (!this.running) {
			this.running = true;
			this.dateStart = new Date();
			this.iStart = this.dateStart.getTime();
		}
	},
	stop: function () {
		this.dateEnd = new Date();
		this.iEnd = this.dateEnd.getTime();
		this.running = false;
		this.interval = (this.iEnd - this.iStart);
		return this.interval;
	}
};


/*******************************************************************************
 * Class Ajax
 * Description: Send an asynchronous request to the servers.
 ******************************************************************************/
/*global Ajax*/
Ajax = function (sUrl, fCallback) {
	//Private variables.
	var that = this;
	this.t1 = new Timer();
	
	//Constructor.
	this.t1.start();
	this.sUrl = sUrl;
	this.callback = fCallback || function () { };
	this.init();
	
	this.oXHR.onreadystatechange = function () {
		if (that.oXHR.readyState === 4 && (that.oXHR.status === 200 || that.oXHR.status === 304)) { // The request is complete.
			that.updating = false;
			that.callback(that.oXHR.responseText, that.oXHR.status, that.oXHR.responseXML, that.t1.stop());
			that.oXHR = null;
		}
	};
};


Ajax.prototype = {
	//Methods.
	init: function () {
		this.updating = false;
		
		try {
			this.oXHR = new XMLHttpRequest(); // Modern browsers.
		} catch (e) {
			try {
				this.oXHR = new ActiveXObject("Msxml2.XMLHTTP"); // Modern IE browsers.
			}
			catch (e2) {
				try {
					this.oXHR = new ActiveXObject("Microsoft.XMLHTTP"); // Old IE browsers.
				}
				catch (e3) {
					this.oXHR = false; // AJAX not supported.
				}
			}
		}
		
		if (!this.oXHR) {
			return false;
		} else {
			
		}
	},
	update: function (sPassData, postMethod) {
		if (this.updating) {
			return false;
		}

		var sUri;
		this.updating = new Date();
			
		if (/post/i.test(postMethod)) {
			sUri = this.sUrl + "?" + this.updating.getTime();
			this.oXHR.open("POST", sUri, true);
			this.oXHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			this.oXHR.send(sPassData);
		} else {
			sUri = this.sUrl + "?" + sPassData + "&timestamp=" + this.updating.getTime();
			this.oXHR.open("GET", sUri, true);
			this.oXHR.send(null);
		}
	
		return true;
	},
	abort: function () {
		if (this.updating) {
			this.updating = false;
			this.oXHR.abort();
			this.oXHR = null;
		}
	}
};


/*******************************************************************************
 * Event functions.
 * Description: Add eventlisteners to DOM elements to enforce unobtrusive js.
 ******************************************************************************/
function addEvent(elm, evType, fn, useCapture) {
	useCapture = useCapture || false;
	
	if (elm.addEventListener) {
		elm.addEventListener(evType, fn, useCapture);
		return true;
	} else if (elm.attachEvent) {
		var r = elm.attachEvent("on" + evType, fn);
		return r;
	} else {
		elm["on" + evType] = fn;
	}
}


function addLoadEvent(f) {
	var oldOnload = window.onload;
	
	if (typeof window.onload !== "function") {
		window.onload = f;
	}
	else {
		window.onload = function () {
			oldOnload();
			f();
		};
	}
}


/*******************************************************************************
 * Id & Class functions.
 * Description: Get DOM elements by ID and cache them.
 * 				Manipulate element classes.
 ******************************************************************************/
/*global oElemCache*/
var oElemCache = {}; // Literal object used for caching elements.

function getById(id) {
	if (!(id in oElemCache)) {
		oElemCache[id] = document.getElementById(id);
	}

	return oElemCache[id];
}

function getClassList(el) {
	return (el.className && el.className.length) ? el.className.split(/\s+/) : [];
}

function setClassList(el, aClassList) {
	el.className = aClassList.join(" ");
}

function removeClass(el, sClassName) {
	var aClassList = getClassList(el), index;
	
	if ((index = aClassList.indexOf(sClassName)) !== -1) {
		delete aClassList[index];
		setClassList(el, aClassList);
	}
}

function addClass(el, sClassName) { // Adds -or replaces in case exists- a classname to an element.
	removeClass(el, sClassName);

	var aClassList = getClassList(el);
		
	aClassList[aClassList.length] = sClassName;
	setClassList(el, aClassList);
}

