// XMLHTTP hjælpe klasse til brug ved Ajax
//
// Copyright 2007-2008 René Lønstrup @ RLdesign.dk
// 
// May not be used commercially without permission from the author.
//
// version 1.0.3.1
// 
// 
// CHANGELOG:
//
// 22/03/2008
//     1.0.3.0 -> 1.0.3.1
//           Fixed bugs in OpenConnection causing Firefox to throw errors in the console
//           Added function AbortConnection
// 28/02/2008
//     1.0.2.0 -> 1.0.3.0
//           Removed dependancy on RLdesign.js file.



/// <summary>
/// Instantiates the namespace
/// </summary>


if (!RLdesign) {
   var RLdesign = function() { };
}


RLdesign.Xml = function() { };

RLdesign.Xml.GenericRemoteProvider = function(sProviderURL) {
	this.ready = false;
	this.isbusy = false;
	this.http = null;
	this.output = null;
	// mozilla, opera and IE7+
	if (typeof(XMLHttpRequest) != "undefined" || typeof(window.XMLHttpRequest) != "undefined") {
		try {
			this.ready = true;
			this.http = new XMLHttpRequest();
		}
		catch (e) {
			this.ready = false;
			this.http = null;
		}
	}
	// Internet Explorer up to v. 6
	if (this.http == null && typeof(ActiveXObject) != "undefined") {
		try {
			this.ready = true;
			this.http = new ActiveXObject("MSXML2.XMLHTTP.3.0");
		}
		catch (e) {
			try {
				this.ready = true;
				this.http = new ActiveXObject("MSXML2.XMLHTTP");
			}
			catch (E) {
				try {
					this.http = new ActiveXObject("Microsoft.XMLHTTP");
				}
				catch (eE) {
					this.ready = false;
					this.http = null;
				}
			}
		}
	}
	// IceBrowser
	if (this.http == null && typeof(window.createRequest) != "undefined") {
		try {
			this.ready = true;
			this.http = window.createRequest();
		}
		catch (e) {
			this.ready = false;
			this.http = null;
		}
	}
	if (this.http == null) {
		alert("No XMLHttpRequest object found.\nPlease use another browser, or activate ActiveX if you're using Internet Explorer");
	}
	if (!this.ready) return;
	if (sProviderURL != null && sProviderURL != "") {
		this.ready = true;
		this.providerurl = sProviderURL;
	}
	else {
		alert("No Provider-URL was provided.\nPlease contact a webmaster or administrator and make sure that an URL gets provided.");
	}
	this.AbortConnection = function() {
		if (this.ready) {
			var oHttp = this.http;
			oHttp.onreadystatechange = null;
			oHttp.abort();
			this.isbusy = false;
		}
	}
	this.OpenConnection = function(fnReceivingFunction, oInput, bPassAlong) {
		if (this.ready) {
			var oThis = this;
			var oHttp = this.http;
			if (oHttp.readyState != 0 && oHttp.readyState != 4) {
				if (oThis.isbusy) oThis.isbusy = false;
				oHttp.onreadystatechange = function () {};
				oHttp.abort();
			}
			var sURL = this.providerurl;
			if (typeof(oInput) != "undefined" && typeof(oInput) == "object" && oInput != null) {
				var iCount = 0;
				for (var i in oInput) {
					if (typeof(oInput[i]) != "function") {
						sURL += (iCount == 0) ? "?" : "&";
						sURL += encodeURIComponent(i) + "=" + encodeURIComponent(oInput[i]);
						iCount++;
					}
				}
			}
			else if (typeof(oInput) == "string") {
				sURL += "?userInput=" + encodeURIComponent(oInput);
			}
			oHttp.open("get", sURL, true);
			oThis.isbusy = true;
			oHttp.onreadystatechange = function() {
				if (oHttp && (oHttp.readyState == 4 || oHttp.readyState == "complete")) {
					// status=200: file found and loaded;
					// status=304: file found, but determined unchanged and loaded from cache
					if (oHttp && (oHttp.status == 200 || oHttp.status == 304)) {
						var aReturnValues = null;
						if (oHttp.responseText && oHttp.responseText != "" && oHttp.responseText != " ") {
							aReturnValues = oHttp.responseText;
						}
						if (fnReceivingFunction != null) {
							fnReceivingFunction(aReturnValues, bPassAlong);
						}
						else {
							oThis.output = aReturnValues;
						}
					}
					oThis.isbusy = false;
				}
			}
			oHttp.send(null);
			if (fnReceivingFunction == null && this.output != null) {
				var out = this.output;
				this.output = null;
				return out;
			}
		}
	}
};












// events hjælpe klasse
// version 1.0.1.0
//
// CHANGELOG:
//
// 21/03/2008
//     1.0.0.2 -> 1.0.1.0
//           Added functions ClearEventHandlers and ClearEventHandler which removes all events of a given type from the object
//           Changed behavior of RemoveEventHandler to set handler as null instead of "" [empty string] in legacy browsers
// 11/03/2008
//     1.0.0.1 -> 1.0.0.2
//           Removed dependancy on RLdesign.Utils.js
// 23/02/2008
//     1.0.0.0 -> 1.0.0.1
//           Added function RemoveEventHandler, which removes an eventhandler the same way it is set


if (!RLdesign.Utils) {
	RLdesign.Utils = function() {
		return {
			// returns a crossbrowser event object
			DefineEvent: function(e) {
				return e || window.event;
			},

			// tries to return an object from an arbitrary argument that can be a string or an object
			// if successfully finding an object, either from a search for the object-id or the object itself, 
			// returns the object. If unsuccessful, returns null
			DefineObject: function(el) {
				var elem = null;
				if (typeof(el) == "object") elem = el;
				else if (document.getElementById(el)) elem = document.getElementById(el);
				else if (typeof(el) == "string" && (el.indexOf("(") || el.indexOf("["))) eval("elem = " + el);
				else if (typeof(el) == "string") eval("elem = " + el);
				return elem;
			},
			
			// evaluates whether the given argument object is an array, returning a boolean
			IsArray: function(a) {
				return (a && a.length && typeof(a) != "string" && !a.tagName && !a.alert && typeof(a[0]) != "undefined");
			},

			// evaluates whether the given argument object is an object, returning a boolean
			IsObject: function(o) {
				return (o && o.length == undefined && typeof(o) == "object" && !o.alert);
			}
		}
	} ();
}

if (!RLdesign.Arrays) {
	RLdesign.Arrays = function() {
		return {
			IsEmpty: function(oArray) {
				if (RLdesign.Utils.IsArray(oArray)) {
					var len = oArray.length;
					if (len == 0) {
						for (var key in oArray) {
							len++;
						}
					}
					return (len > 0) ? false : true;
				}
				return null;
			}
		}
	} ();
}


RLdesign.Events = function() {
	var bPageLoaded = false;
	var aHandlers = new Array();
	var aStartASAPCollection = new Array();
	var aEventsToBeConnected = new Array();
	var aEventsConnected = new Array();
	var iTIMEOUT = 50;
	return {
		// attempts to run an userdefined function (fn) when the specified object (obj) has been loaded in memory
		StartWhenLoaded: function(obj, fn) {
			// fn should be referenced as a string representation of the functions name
			// if it is not, we will attempt to extract the function name from the function
			if (typeof(fn) != "string") {
				var sFn = fn.toString();
				var iStart = sFn.indexOf("function") + 9;
				var iEnd = sFn.indexOf("(");
				fn = sFn.substring(iStart,iEnd);
				if (fn == "") return false;
			}
			// if obj was referenced as a string, it will be checked for the correct syntax for this use
			if (typeof(obj) == "string" && obj.indexOf("'")) {
				obj = obj.replace(/'/g,"\"");
			}
			// saves info about what we are about to do
			var aStartASAP = new Array(obj,fn);
			if (!aStartASAPCollection.findArray(aStartASAP)) {
				aStartASAPCollection.push(aStartASAP);
			}
			// tries to extract an object from obj
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem) {
				// if object referenced was an array it will be iterated through 
				// to see if any of the objects is ready loaded and if so,
				// the function will be executed
				// and information on the objects and the function will be saved
				if (RLdesign.Utils.IsArray(elem)) {
					var elemA = null;
					for (var i = 0; i < elem.length; i++) {
						aEventsToBeConnected = new Array(elem[i],fn);
						elemA = RLdesign.Utils.DefineObject(obj);
						if (elemA) {
							if (!aEventsConnected.findArray(aEventsToBeConnected)) {
								aEventsConnected.push(aEventsToBeConnected);
								eval(fn + "(elem[i])");
							}
						}
					}
				}
				// if obj is a single object, the function will be executed directly
				// and information on the object and the function will be saved
				else if (RLdesign.Utils.IsObject(elem)) {
					aEventsToBeConnected = new Array(elem,fn);
					if (!aEventsConnected.findArray(aEventsToBeConnected)) {
						aEventsConnected.push(aEventsToBeConnected);
						eval(fn + "(elem)");
					}
				}
			}
			// recursive runs until page has been loaded
			if (!bPageLoaded) {
				setTimeout("RLdesign.Events.StartWhenLoaded('" + obj + "','" + fn + "')", iTIMEOUT);
			}
		},

		/// <summary>
		/// Appends an user-defined event handler of the specified type to the object
		/// </summary>
		/// <param name="obj">The object to append the eventhandler to - can be either an object or a stringID</param>
		/// <param name="sEventType">A string-representation of the eventtype - e.g. "load" for the onload-event, "click" for onclick and so on</param>
		/// <param name="funktion">The function to run - can be either a function or a string-representation of the function (beta)</param>
		/// <param name="bOptionalAvoidWrapping">Tells the script not to wrap the function - basically avoids returning anything</param>
		/// <returns>void</returns>
		SetEventHandler: function(obj, sEventType, funktion, bOptionalAvoidWrapping) {
			if (!bOptionalAvoidWrapping || bOptionalAvoidWrapping == undefined) var bOptionalAvoidWrapping = false;
			else bOptionalAvoidWrapping = true;
			// if the object is an array, we sets the eventhandler to every contained element, one at a time
			if (RLdesign.Utils.IsArray(obj)) {
				var ok = true;
				for (var i = 0; i < el.length; i++) {
					ok = (this.SetEventHandler(obj[i],sEventType,funktion) && ok);
				}
				return ok;
			}
			// if obj was referenced as a string, it will be checked for the correct syntax for this use
			// replaces ' (single pling) with " (quotation mark)
			if (typeof(obj) == "string" && obj.indexOf("'")) {
				obj = obj.replace(/'/g,"\"");
			}
			// tries to extract an object from obj
			var elem = RLdesign.Utils.DefineObject(obj);
			// if object doesn't exists yet, saves event-handler information to array
			if (elem == null) {
				var aHandler = new Array(obj, sEventType, funktion);
				aHandlers.push(aHandler);
				return false;
			}
			// wraps function in order to provide easy cross-browser event-trapping
			var fnWrapped = null;
			if (!bOptionalAvoidWrapping) {
				var fnWrapped = function(e) {
					return funktion(RLdesign.Utils.DefineEvent(e));
				};
			}
			else {
				//alert(typeof(funktion));
				fnWrapped = (typeof(funktion) == "string") ? eval(funktion) : funktion;
			}
			// adding event-handler to element
			if (elem.addEventListener) { elem.addEventListener(sEventType,fnWrapped,false); }
			else if (elem.attachEvent) { elem.attachEvent("on"+sEventType,fnWrapped); }
			else {
				var ontype = "on" + sEventType;
				var old = elem[ontype];
				if (old) {
					elem[ontype] = function(event) {
						var res = old(event);
						return fnWrapped(event) && res;
					}
				}
				else { elem[ontype] = fnWrapped; }
			}
			return true;
		},
		
		RemoveEventHandler: function(obj, sEventType, funktion, bOptionalAvoidWrapping) {
			if (!bOptionalAvoidWrapping || bOptionalAvoidWrapping == undefined) var bOptionalAvoidWrapping = false;
			else bOptionalAvoidWrapping = true;
			// if the object is an array, we remove the eventhandler from every contained element, one at a time
			if (RLdesign.Utils.IsArray(obj)) {
				var ok = true;
				for (var i = 0; i < el.length; i++) {
					ok = (this.RemoveEventHandler(obj[i],sEventType,funktion) && ok);
				}
				return ok;
			}
			// if obj was referenced as a string, it will be checked for the correct syntax for this use
			// replaces ' (single pling) with " (quotation mark)
			if (typeof(obj) == "string" && obj.indexOf("'")) {
				obj = obj.replace(/'/g,"\"");
			}
			// tries to extract an object from obj
			var elem = RLdesign.Utils.DefineObject(obj);
			// if object doesn't exists yet, returns because then it isn't possible to remove an eventhandler that doesn't exist
			if (elem == null) return false;
			// wraps function in order to provide easy cross-browser event-trapping
			var fnWrapped = null;
			if (!bOptionalAvoidWrapping) {
				var fnWrapped = function(e) {
					return funktion(RLdesign.Utils.DefineEvent(e));
				};
			}
			else {
				fnWrapped = (typeof(funktion) == "string") ? eval(funktion) : funktion;
			}
			// removing event-handler to element
			if (elem.removeEventListener) { elem.removeEventListener(sEventType,fnWrapped,false); }
			else if (elem.detachEvent) { elem.detachEvent("on"+sEventType,fnWrapped); }
			else {
				var ontype = "on" + sEventType;
				elem[ontype] = null;
			}
			return true;
		},

		ClearEventHandlers: function (obj, aEventTypes) {
			aEvents = null;
			if (aEventTypes != null && typeof(aEventTypes) == "string") aEvents = [aEventTypes];
			if (aEventTypes == null) aEvents = ['abort', 'blur', 'change', 'error', 'focus', 'load', 'reset', 'resize', 'scroll', 'select', 'submit', 'unload', 'click', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'dblclick', 'keydown', 'keypress', 'keyup'];
			for (var i = 0; i < aEvents.length; i++) {
				RLdesign.Events.ClearEventHandler(obj, aEvents[i]);
			}
		},
		ClearEventHandler: function (o, sEventType) {
			var obj = RLdesign.Utils.DefineObject(o);
			if (obj == null) return;
			var onevent = "on" + sEventType;
			obj[onevent] = null;
		},


		// tries to add event-handlers to objects as soon as they are available to the DOM
		PreloadHandler: function() {
			var aDeletableHandlers = new Array();
			for (var i = 0; i < aHandlers.length; i++) {
				var aH = aHandlers[i];
				if (aH) {
					var oEl = RLdesign.Utils.DefineObject(aH[0]);
					if (oEl) {
						this.SetEventHandler(oEl, aH[1], aH[2]);
						aDeletableHandlers.push(i);
					}
				}
			}
			for (i = aDeletableHandlers.length; i > 0; i--) {
				aHandlers.removeElement(aDeletableHandlers[i-1]);
			}
			if (!bPageLoaded) {
				setTimeout("RLdesign.Events.PreloadHandler()",iTIMEOUT);
			}
		},


		// sets a flag telling the rest of the class that the page has been loaded
		// also flushes all obsolete data from memory
		_load: function() {
			bPageLoaded = true;
			if (!RLdesign.Arrays.IsEmpty(aStartASAPCollection)) {
				for (var i = 0; i < aStartASAPCollection.length; i++) {
					RLdesign.Events.StartWhenLoaded(aStartASAPCollection[i][0],aStartASAPCollection[i][1]);
				}
			}
			if (!RLdesign.Arrays.IsEmpty(aHandlers)) {
				RLdesign.Events.PreloadHandler();
			}
		}
	};
} ();
RLdesign.Events.SetEventHandler(window, "load", RLdesign.Events._load);
RLdesign.Events.PreloadHandler();
