//EXAMPLE
//var oSlideshowItems_ctl00_SlideShow1 = new Array();
//	var oSlideshowVars_ctl00_SlideShow1 = new Object();
//		oSlideshowVars_ctl00_SlideShow1.ContainerID = "ctl00_SlideShow1";
//		oSlideshowVars_ctl00_SlideShow1.FadeTime = 1000;
//		oSlideshowVars_ctl00_SlideShow1.WaitTime = 5;
//	var ultimizeslideshow_ctl00_SlideShow1 = new RLdesign.Web.UI.Slideshow(oSlideshowVars_ctl00_SlideShow1, oSlideshowItems_ctl00_SlideShow1);




// Utilities hj?lpe klasse
// 
// Copyright 2006-2009 Ren? L?nstrup @ RLdesign.dk
// 
// May not be used commercially without permission from the author.
//
// Version: 1.1.2.15
//
//
// CHANGELOG:
//

//
// 29/09/2009
//     1.1.2.14 -> 1.1.2.15
//           Fixed bug in FixDecimalNumber resulting in it not working in Internet Explorer 7 and down
// 05/08/2009
//     1.1.2.13 -> 1.1.2.14
//           Added clear and fill functionality to Serialize function
//           Added handling of whether the function should use an objects value or a string
// 04/05/2009
//     1.1.2.12 -> 1.1.2.13
//           Added functions FilterNumberKeys and FixDecimalNumber
// 18/03/2009
//     1.1.2.11 -> 1.1.2.12
//           Fixed a small potential bug i function ReorderList
// 04/03/2009
//     1.1.2.10 -> 1.1.2.11
//           Fixed several bugs in OpenPopup function
// 09/02/2009
//     1.1.2.9 -> 1.1.2.10
//           Added find functionality to Serialize function
// 19/01/2009
//     1.1.2.8 -> 1.1.2.9
//           Added functions GetCookie, SetCookie and RemoveCookie to enable manipulation of cookies
//           Fixed bug in GetMargins and GetPaddings eliminating af NaN error in Internet Explorer
// 11/01/2009
//     1.1.2.7 -> 1.1.2.8
//           Removed unnessesary argument from function ReorderList
// 07/11/2008
//     1.1.2.6 -> 1.1.2.7
//           Extended GetMargins to work in a multiple-frame environment
//           Extended GetPaddings to work in a multiple-frame environment
// 02/10/2008
//     1.1.2.5 -> 1.1.2.6
//           Added new function GetTypedKey
// 30/09/2008
//     1.1.2.4 -> 1.1.2.5
//           Fixed a bug in CenterObject which meant that it didn't center objects according to the 
//           scrolling offset of the page
// 10/07/2008
//     1.1.2.3 -> 1.1.2.4
//           Added new function ToggleVisibility
// 10/07/2008
//     1.1.2.2 -> 1.1.2.3
//           Added possibility to pass variables or objects through ReorderList
// 30/06/2008
//     1.1.2.1 -> 1.1.2.2
//           Added new function OpenPopup
// 12/06/2008
//     1.1.2.0 -> 1.1.2.1
//           Fixed a very small potential bug in ReorderList
// 30/05/2008
//     1.1.1.7 -> 1.1.2.0
//           Reordered all functions alphabetically
//           Added better memory cleanup to function ReorderSelectOption
//           Added new function ReorderList
// 29/05/2008
//     1.1.1.6 -> 1.1.1.7
//           Added new function ClearWhiteSpace
// 25/04/2008
//     1.1.1.5 -> 1.1.1.6
//           Extended defineObject to work in a multiple-frame environment
//           Extended makeElement to work in a multiple-frame environment
// 20/04/2008
//     1.1.1.4 -> 1.1.1.5
//           Fixed bug in new function SetOffsetPosition
// 15/04/2008
//     1.1.1.3 -> 1.1.1.4
//           Added new function ToggleDisplay
// 13/04/2008
//     1.1.1.2 -> 1.1.1.3
//           Change name of function SetOffsetPosition to SetPositionToOffset
//           Added new function SetOffsetPosition
//           Tweaked function CenterObject a little bit
// 07/04/2008
//     1.1.1.1 -> 1.1.1.2
//           Added function GetCursorPosition
// 07/04/2008
//     1.1.1.0 -> 1.1.1.1
//           Added function InsertAfter
//           Added function PrependChild
// 23/03/2008
//     1.1.0.9 -> 1.1.1.0
//           Added function GetHighestZIndex
//           Added function CenterObject
//           Added function GetCssValue
//           Added function SetOffsetPosition
// 22/03/2008
//     1.1.0.8 -> 1.1.0.9
//           Fixed another bug in GetOpacity
// 21/03/2008
//     1.1.0.7 -> 1.1.0.8
//           Fixed bug in GetOpacity
//           Fixed bug in GetMargins and GetPaddings which meant that they didn't parse the values correctly, thus
//           wrongly returning NaN-values
//           Added functions GetWindowSize and GetPageSize which should be used in place of the seperate functions for
//           height and width.
//           Added function SetDisplay which set the display property of an object
//           Added function GetOpacity to join SetOpacity
// 14/03/2008
//     1.1.0.6 -> 1.1.0.7
//           Fixed a bug in GetOffsetPosition making it useless i IE6 when run on an advanced page-layout
// 11/03/2008
//     1.1.0.5 -> 1.1.0.6
//           Fixed a couple of bugs in Serialize, and added an extra arguments-switch to force it out of
//           running the supplied object through DefineObject - so the function also works with strings with commas
// 10/03/2008
//     1.1.0.4 -> 1.1.0.5
//           Added error-handling to DefineObject to avoid error when passing an ID of a non-existing object
// 09/03/2008
//     1.1.0.3 -> 1.1.0.4
//           Added function GetOffsetPosition to get top left position of element
//           Changed functions GetPaddings and GetMargins to correctly return an Object instead of an Array
// 06/03/2008
//     1.1.0.2 -> 1.1.0.3
//           Fixed bug caused by a misspelled variable i DefineEventRelatedTarget
// 02/03/2008
//     1.1.0.1 -> 1.1.0.2
//           Removed dependancy of RLdesign.js file.
// 24/02/2008
//     1.1.0.0 -> 1.1.0.1
//           Added 'get count' switch to Serialize-function, which returns the number of serialized items
// 23/02/2008
//     1.0.0.0 -> 1.1.0.0
//           Added function Serialize which serializes data to and from an input field


if (!RLdesign) {
	var RLdesign = function() { };
}
RLdesign.Utils = function() {
	return {

		// centers an object relative to the browser-window
		CenterObject: function(obj, horizontal, vertical) {
			var h = (horizontal === null) ? false : horizontal;
			var v = (vertical === null) ? false : vertical;
			var o = RLdesign.Utils.DefineObject(obj);
			if (!o) return;

			var scroll = RLdesign.Utils.GetScrollingOffset();

			var width = parseInt(o.offsetWidth);
			var height = parseInt(o.offsetHeight);
			var windowSize = RLdesign.Utils.GetWindowSize();

			var hcenter = Math.floor((windowSize["width"] - width) / 2) + scroll["horizontal"];
			var vcenter = Math.floor((windowSize["height"] - height) / 2) + scroll["vertical"];

			if (h) o.style.left = hcenter + "px";
			if (v) o.style.top = vcenter + "px";
		},

		// removes any child nodes of the given object
		ClearChildElements: function(obj) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null) return;
			if (elem.hasChildNodes()) {
				while (elem.childNodes.length >= 1) {
					elem.removeChild(elem.firstChild);
				}
			}
		},

		// clears the specified global interval variable (specified as a string), if exists
		ClearInterval: function(sInterval) {
			var bIntervalExist = !!window[sInterval];
			if (bIntervalExist) window.clearInterval(window[sInterval]);
		},

		// clears the specified global timeout variable (specified as a string), if exists
		ClearTimeout: function(sTimeout) {
			var bTimeoutExist = !!window[sTimeout];
			if (bTimeoutExist) window.clearTimeout(window[sTimeout]);
		},

		// removes whitespace children from the given object
		ClearWhiteSpace: function(obj) {
			var o = RLdesign.Utils.DefineObject(obj);
			var aTextnodes = new Array();
			for (var i = 0; i < o.childNodes.length; i++) {
				if (o.childNodes[i].tagName == undefined) {
					aTextnodes[aTextnodes.length] = o.childNodes[i];
				}
			}
			for (var t = 0; t < aTextnodes.length; t++) {
				o.removeChild(aTextnodes[t]);
			}
		},

		// returns a crossbrowser event object
		DefineEvent: function(e) {
			return e || window.event;
		},

		// returns the keycode for the key that was pressed during the event		
		DefineEventKeyCode: function(e) {
			var ev = RLdesign.Utils.DefineEvent(e);
			var keycode = 0;
			if (ev.which) keycode = ev.which; // Netscape4
			else if (ev.keyCode) keycode = ev.keyCode; // IE
			else if (ev.charCode) keycode = ev.charCode; // Gecko
			return keycode;
		},

		// returns the related target from the event
		// used in conjunction with mouseover / -out events, and returns the element from which the mouse came / goes
		// ie. in the case of a mouseover, returns the element from which the mouse came, and vice versa for mouseout
		DefineEventRelatedTarget: function(e) {
			var t = e.relatedTarget;
			if (!t && (e.type == "mouseover" || e.type == "mouseout")) {
				t = (e.type == "mouseout") ? e.toElement : e.fromElement;
			}
			return t;
		},

		// returns a boolean representation of whether the shift key was pressed during the event		
		DefineEventShiftKey: function(e) {
			var ev = RLdesign.Utils.DefineEvent(e);
			var bShift = false;
			if (e.shiftKey) { bShift = e.shiftKey } // IE etc
			else if (e.modifiers) { // Netscape 4
				if (e.modifiers & 4) { // bitwise AND to see if shift is pressed
					bShift = true;
				}
			}
			return bShift;
		},

		// returns the target for the event in question, typically a click-event
		// ie. in the case of a click-event, the target is the element being clicked on
		DefineEventTarget: function(e) {
			var ev = RLdesign.Utils.DefineEvent(e);
			var element = ev.srcElement || ev.target;
			if (element.nodeType == 3) element = element.parentNode; // defeat Safari bug
			return element;
		},

		// 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, d) {
			var doc = (d) ? d : document;
			var elem = null;
			// if el is an object
			if (typeof (el) == "object") {
				try {
					elem = el;
				}
				catch (ex) {
					elem = null;
				}
			}
			// if el is the id of an html-object
			else if (doc.getElementById(el)) {
				try {
					elem = doc.getElementById(el);
				}
				catch (ex) {
					elem = null;
				}
			}
			// if el is a string representation of an document.getElementById - or similar statement
			else if (typeof (el) == "string" && (el.indexOf("(") != -1 || el.indexOf("[") != -1)) {
				try {
					eval("elem = " + el);
				}
				catch (ex) {
					elem = null;
				}
			}
			// last resort
			else if (typeof (el) == "string") {
				try {
					eval("elem = " + el);
				}
				catch (ex) {
					elem = null;
				}
			}
			return elem;
		},

		// returns a crossbrowser return code designed to prevent further events i mozilla browser, if need be
		DefineReturnCode: function(e, r) {
			var ev = RLdesign.Utils.DefineEvent(e);
			if (r == false) {
				if (ev.stopPropagation) ev.stopPropagation();
				else if (ev.cancelBubble) ev.cancelBubble = true;
				if (ev.preventDefault) ev.preventDefault();
				else if (ev.returnValue) ev.returnValue = false;
			}
			else {
				if (typeof (ev.returnValue) == "string") ev.returnValue = r;
			}
			return r;
		},

		// Filters keys pressed, only allowing numeric numbers (and certain special keys)
		// Usage:
		// <input type="text" onkeydown="return RLdesign.Utils.FilterNumberKeys(this, event, false);" />
		FilterNumberKeys: function(oInput, e, allowdecimals) {
			var ev = RLdesign.Utils.DefineEvent(e);
			var charcode = RLdesign.Utils.DefineEventKeyCode(e);
			var whitelist = [8, 9, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 144];
			if (allowdecimals) {
				whitelist[whitelist.length] = 110;
				whitelist[whitelist.length] = 188;
				whitelist[whitelist.length] = 190;
			}
			if (ev.ctrlKey && charcode == 65) return true; // ctrl+a
			else if (ev.ctrlKey && charcode == 67) return true; // ctrl+c
			else if (ev.ctrlKey && charcode == 86) return true; // ctrl+v
			else if (ev.ctrlKey && charcode == 88) return true; // ctrl+x
			else if (ev.ctrlKey && charcode == 90) return true; // ctrl+z
			else if (RLdesign.Arrays.InArray(whitelist, charcode)) return true;
			else return false;
		},

		FixDecimalNumber: function(no) {
			if (typeof no == "string") {
				var fixed = no;
				var commas = 0;
				var dots = 0;
				var firstcomma = -1;
				var firstdot = -1;
				for (var i = 0; i < no.length; i++) {
					var c = String.fromCharCode(no.charCodeAt(i));
					if (c == ".") {
						dots++;
						if (firstdot == -1) firstdot = i;
						continue;
					}
					if (c == ",") {
						commas++;
						if (firstcomma == -1) firstcomma = i;
						continue;
					}
				}
				if (dots == 1 && commas == 0) { // uses dots as thousands delimiter
					fixed = fixed;
				}
				else if (dots == 0 && commas == 1) { // uses commas as thousands delimiter
					fixed = fixed.replace(",", ".");
				}
				else if (dots > commas || firstdot < firstcomma) { // uses dots as thousands delimiter
					fixed = fixed.replace(".", "").replace(",", ".");
				}
				else if (commas > dots || firstcomma < firstdot) { // uses commas as thousands delimiter
					fixed = fixed.replace(",", "");
				}

				return fixed;
			}
			else {
				return no;
			}
		},

		GetCssValue: function(obj, sCss) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null) return;
			var cStyle = null;
			if (elem.currentStyle) {
				cStyle = elem.currentStyle;
			}
			else if (document.defaultView && document.defaultView.getComputedStyle) {
				cStyle = document.defaultView.getComputedStyle(elem, "");
			}
			var sValue;
			if (cStyle) {
				sValue = cStyle[sCss];
			}
			else {
				sValue = elem.style[sCss];
			}
			return sValue;
		},

		GetCursorPosition: function(e) {
			var ev = RLdesign.Utils.DefineEvent(e);
			var pos = new Object();
			pos["top"] = 0;
			pos["left"] = 0;
			if (ev.pageX || ev.pageY) {
				pos["left"] = ev.pageX;
				pos["top"] = ev.pageY;
			}
			else if (ev.clientX || ev.clientY) {
				pos["left"] = ev.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
				pos["top"] = ev.clientY + document.body.scrollTop + document.documentElement.scrollTop;
			}
			return pos;
		},

		GetHighestZIndex: function(oRoot, sTag) {
			if (!document.getElementsByTagName) return 0;
			var root = (!oRoot) ? document : oRoot;
			var tag = (!sTag) ? "*" : sTag;
			var allElems = root.getElementsByTagName(tag);
			var maxZIndex = 0;
			for (var i = 0; i < allElems.length; i++) {
				var elem = allElems[i];
				var cStyle = null;
				if (elem.currentStyle) { cStyle = elem.currentStyle; }
				else if (document.defaultView && document.defaultView.getComputedStyle) {
					cStyle = document.defaultView.getComputedStyle(elem, "");
				}
				var sNum;
				if (cStyle) {
					sNum = Number(cStyle.zIndex);
				}
				else {
					sNum = Number(elem.style.zIndex);
				}
				if (!isNaN(sNum)) {
					maxZIndex = Math.max(maxZIndex, sNum);
				}
			}
			return maxZIndex;
		},

		// returns an object of the top, bottom, left and right margins of the given object
		GetMargins: function(obj, d) {
			var doc = (d) ? d : document;
			var elem = RLdesign.Utils.DefineObject(obj);
			var aReturn = new Object();
			aReturn["top"] = 0;
			aReturn["bottom"] = 0;
			aReturn["left"] = 0;
			aReturn["right"] = 0;
			if (elem == null) return aReturn; // returns default values if no correct object was specified
			var cStyle = null;
			if (elem.currentStyle) {
				cStyle = elem.currentStyle;
			}
			else if (doc.defaultView && doc.defaultView.getComputedStyle) {
				cStyle = doc.defaultView.getComputedStyle(elem, "");
			}
			if (cStyle) {
				aReturn["top"] = parseInt(cStyle.marginTop);
				aReturn["bottom"] = parseInt(cStyle.marginBottom);
				aReturn["left"] = parseInt(cStyle.marginLeft);
				aReturn["right"] = parseInt(cStyle.marginRight);
			}
			else {
				aReturn["top"] = parseInt(elem.style.marginTop);
				aReturn["bottom"] = parseInt(elem.style.marginBottom);
				aReturn["left"] = parseInt(elem.style.marginLeft);
				aReturn["right"] = parseInt(elem.style.marginRight);
			}
			if (isNaN(aReturn["top"])) aReturn["top"] = 0;
			if (isNaN(aReturn["bottom"])) aReturn["bottom"] = 0;
			if (isNaN(aReturn["left"])) aReturn["left"] = 0;
			if (isNaN(aReturn["right"])) aReturn["right"] = 0;
			return aReturn;
		},

		// gets top left position of object
		GetOffsetPosition: function(obj) {
			var oNode = RLdesign.Utils.DefineObject(obj);
			var iLeft = 0;
			var aReturn = new Object();
			aReturn["top"] = 0;
			aReturn["left"] = 0;
			if (oNode.offsetParent) {
				do {
					aReturn["left"] += parseInt(oNode.offsetLeft);
					aReturn["top"] += parseInt(oNode.offsetTop);
				} while (oNode = oNode.offsetParent);
			}
			else if (oNode.getBoundingClientRect) { // IE only method of finding elements position / dimension
				aReturn["top"] = oNode.getBoundingClientRect().top - 2; // minus two to counteract IE upper-left corner anomaly
				aReturn["left"] = oNode.getBoundingClientRect().left - 2; // minus two to counteract IE upper-left corner anomaly
			}
			else {
				while (oNode.tagName.toLowerCase() != "body") {
					aReturn["left"] += parseInt(oNode.offsetLeft);
					aReturn["top"] += parseInt(oNode.offsetTop);
					oNode = oNode.offsetParent;
				}
			}
			return aReturn;
		},

		// positions an object relative to the browser-window
		//
		// Usage:
		//     Centering the object horizontally and vertically:
		//     [Utils].SetOffsetPosition(myObject, "center", "center");
		//     Centering the object horizontally and fixing its position to 20 pixel from the top:
		//     [Utils].SetOffsetPosition(myObject, "center", 20);
		SetOffsetPosition: function(obj, horizontal, vertical) {
			var h = (horizontal === null || (isNaN(horizontal) && horizontal != "center")) ? 0 : horizontal;
			var v = (vertical === null || (isNaN(vertical) && vertical != "center")) ? 0 : vertical;
			var o = RLdesign.Utils.DefineObject(obj);
			if (!o) return;

			var position = new Object();
			position["left"] = parseInt(RLdesign.Utils.GetCssValue(o, "left"));
			position["top"] = parseInt(RLdesign.Utils.GetCssValue(o, "top"));
			var scroll = RLdesign.Utils.GetScrollingOffset();

			if (h === "center") RLdesign.Utils.CenterObject(o, true, false);
			else o.style.left = scroll["horizontal"] + h + "px";
			if (v === "center") RLdesign.Utils.CenterObject(o, false, true);
			else o.style.top = scroll["vertical"] + v + "px";
		},

		GetOpacity: function(obj) {
			var opacity = (parseInt(obj.style.width) == obj.offsetWidth) ? 100 : 0;
			if (obj.style.opacity) { opacity = Math.round(obj.style.opacity * 100); }
			else if (obj.style.MozOpacity) { opacity = Math.round(obj.style.MozOpacity * 100); }
			else if (obj.style.KHTMLOpacity) { opacity = Math.round(obj.style.KHTMLOpacity * 100); }
			else if (obj.style.filter) {
				var filter = obj.style.filter;
				//				var pattern = /opacity\b[^=]*=(.*?)\)/;
				var pattern = /\(opacity:(.*?)\)/;
				oRegex = filter.match(pattern);
				if (typeof (oRegex) == "object") {
					var match = oRegex[1];
					opacity = (match != null) ? parseInt(match) : opacity;
				}
			}
			return opacity;
		},

		// returns an object of the top, bottom, left and right paddings of the given object
		GetPaddings: function(obj, d) {
			var doc = (d) ? d : document;
			var elem = RLdesign.Utils.DefineObject(obj);
			var aReturn = new Object();
			aReturn["top"] = 0;
			aReturn["bottom"] = 0;
			aReturn["left"] = 0;
			aReturn["right"] = 0;
			if (elem == null) return aReturn;
			var cStyle = null;
			if (elem.currentStyle) {
				cStyle = elem.currentStyle;
			}
			else if (doc.defaultView && doc.defaultView.getComputedStyle) {
				cStyle = doc.defaultView.getComputedStyle(elem, "");
			}
			if (cStyle) {
				aReturn["top"] = parseInt(cStyle.paddingTop);
				aReturn["bottom"] = parseInt(cStyle.paddingBottom);
				aReturn["left"] = parseInt(cStyle.paddingLeft);
				aReturn["right"] = parseInt(cStyle.paddingRight);
			}
			else {
				aReturn["top"] = parseInt(elem.style.paddingTop);
				aReturn["bottom"] = parseInt(elem.style.paddingBottom);
				aReturn["left"] = parseInt(elem.style.paddingLeft);
				aReturn["right"] = parseInt(elem.style.paddingRight);
			}
			if (isNaN(aReturn["top"])) aReturn["top"] = 0;
			if (isNaN(aReturn["bottom"])) aReturn["bottom"] = 0;
			if (isNaN(aReturn["left"])) aReturn["left"] = 0;
			if (isNaN(aReturn["right"])) aReturn["right"] = 0;
			return aReturn;
		},

		// returns the width and height of the current page (or more precisely, the width/height of the body element of the page)
		GetPageSize: function() {
			var size = new Object();
			size["width"] = null;
			size["height"] = null;
			var scrollWidth = parseInt(document.body.scrollWidth);
			var offsetWidth = parseInt(document.body.offsetWidth);
			var scrollHeight = parseInt(document.body.scrollHeight);
			var offsetHeight = parseInt(document.body.offsetHeight);
			size["width"] = (scrollWidth > offsetWidth) ? scrollWidth : offsetWidth;
			size["height"] = (scrollHeight > offsetHeight) ? scrollHeight : offsetHeight;
			return size;
		},

		// returns the height of the current page (or more precisely, the height of the body element of the page)
		GetPageHeight: function() {
			var y = null;
			var scrollHeight = parseInt(document.body.scrollHeight);
			var offsetHeight = parseInt(document.body.offsetHeight);
			if (scrollHeight > offsetHeight) { // all but Explorer Mac
				y = scrollHeight;
			}
			else { // Explorer Mac - would also work in Explorer 6 Strict, Mozilla and Safari
				y = offsetHeight;
			}
			return y;
		},

		// returns the width of the current page (or more precisely, the width of the body element of the page)
		GetPageWidth: function() {
			var x = null;
			var scrollWidth = parseInt(document.body.scrollWidth);
			var offsetWidth = parseInt(document.body.offsetWidth);
			if (scrollWidth > offsetWidth) { // all but Explorer Mac
				x = scrollWidth;
			}
			else { // Explorer Mac - would also work in Explorer 6 Strict, Mozilla and Safari
				x = offsetWidth;
			}
			return x;
		},

		// returns the scrolling offset on both the horizontal and the vertical axis
		GetScrollingOffset: function() {
			var offset = new Object();
			offset["vertical"] = parseInt(RLdesign.Utils.GetVerticalScrollingOffset());
			offset["horizontal"] = parseInt(RLdesign.Utils.GetHorizontalScrollingOffset());
			return offset;
		},

		// returns the scrolling offset on the horizontal axis, measured from the left edge of the page
		GetHorizontalScrollingOffset: function(d) {
			var doc = (d) ? d : document;
			var x = null;
			if (self.pageXOffset) { // all except Explorer
				x = self.pageXOffset;
			}
			else if (doc.documentElement && doc.documentElement.scrollLeft) { // Explorer 6 Strict
				x = doc.documentElement.scrollLeft;
			}
			else if (doc.body) { // all other Explorers
				x = doc.body.scrollLeft;
			}
			return parseInt(x);
		},

		// returns the scrolling offset on the vertical axis, measured from the top of the page
		GetVerticalScrollingOffset: function(d) {
			var doc = (d) ? d : document;
			var y = null;
			if (self.pageYOffset) { // all except Explorer
				y = self.pageYOffset;
			}
			else if (doc.documentElement && doc.documentElement.scrollTop) { // Explorer 6 Strict
				y = doc.documentElement.scrollTop;
			}
			else if (doc.body) { // all other Explorers
				y = doc.body.scrollTop;
			}
			return parseInt(y);
		},

		// returns the key that was pressed as a string
		GetTypedKey: function(e) {
			var charcode = RLdesign.Utils.DefineEventKeyCode(e);
			return String.fromCharCode(charcode);
		},

		// returns the height and width of the current browser window
		GetWindowSize: function() {
			var size = new Object();
			size["width"] = null;
			size["height"] = null;
			var y, x = null;
			if (self.innerHeight && self.innerWidth) { // all except Explorer
				y = self.innerHeight;
				x = self.innerWidth;
			}
			else if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) { // Explorer 6 Strict Mode
				y = document.documentElement.clientHeight;
				x = document.documentElement.clientWidth;
			}
			else if (document.body) { // other Explorers
				y = document.body.clientHeight;
				x = document.body.clientWidth;
			}
			size["height"] = parseInt(y);
			size["width"] = parseInt(x);
			return size;
		},

		// returns the height of the current browser window
		GetWindowHeight: function() {
			var y = null;
			if (self.innerHeight) { // all except Explorer
				y = self.innerHeight;
			}
			else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
				y = document.documentElement.clientHeight;
			}
			else if (document.body) { // other Explorers
				y = document.body.clientHeight;
			}
			return parseInt(y);
		},

		// returns the width of the current browser window
		GetWindowWidth: function() {
			var x = null;
			if (self.innerWidth) { // all except Explorer
				x = self.innerWidth;
			}
			else if (document.documentElement && document.documentElement.clientWidth) { // Explorer 6 Strict Mode
				x = document.documentElement.clientWidth;
			}
			else if (document.body) { // other Explorers
				x = document.body.clientWidth;
			}
			return parseInt(x);
		},

		// returns the z-index value of the given object
		GetZIndex: function(obj) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null) return;
			var cStyle = null;
			if (elem.currentStyle) {
				cStyle = elem.currentStyle;
			}
			else if (document.defaultView && document.defaultView.getComputedStyle) {
				cStyle = document.defaultView.getComputedStyle(elem, "");
			}
			var sNum;
			if (cStyle) {
				sNum = Number(cStyle.zIndex);
			}
			else {
				sNum = Number(elem.style.zIndex);
			}
			return sNum;
		},

		InsertAfter: function(parent, node, referenceNode) {
			parent.insertBefore(node, referenceNode.nextSibling);
		},

		// inserts a given textstring at the cursors position in a textfield
		InsertAtCursor: function(obj, sValue, bSelectRange) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null || (elem.tagName.toLowerCase() != "textarea" && (elem.tagName.toLowerCase() != "input") || elem.type.toLowerCase() != "text")) return;
			if (document.selection) {
				elem.focus();
				sel = document.selection.createRange();
				sel.text = sValue;
				if (bSelectRange) {
					sel = document.selection.createRange();
					sel.moveStart("character", sValue.length * -1);
					sel.moveEnd("character", 0);
					sel.select();
				}
			}
			else if (elem.selectionStart || elem.selectionStart == "0") {
				var startPos = elem.selectionStart;
				var endPos = elem.selectionEnd;
				elem.value = elem.value.substring(0, startPos) + sValue + elem.value.substring(endPos, elem.value.length);
				if (bSelectRange) {
					elem.setSelectionRange(startPos, startPos + 1);
				}
				elem.focus();
			}
			else {
				elem.value += sValue;
				elem.focus();
			}
		},

		// 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);
		},

		// returns a boolean representation of whether the given argument is numeric
		IsNumeric: function(sInput) {
			var sValidChars = "0123456789,.-";
			sInput = sInput.toString();
			if (sInput.length == 0) return false;
			var bResult = true;
			for (var i = 0; i < sInput.length; i++) {
				cChar = sInput.charAt(i);
				if (sValidChars.indexOf(cChar) == -1) {
					bResult = false;
					break;
				}
			}
			return bResult;
		},

		// creates a given html element in memory and returns the element
		MakeElement: function(tag, attrs, text, d) {
			var doc = (d) ? d : document;
			var e = doc.createElement(tag);
			if (attrs) {
				for (var key in attrs) {
					if (typeof (attrs[key]) == "function") continue; // defeat bug caused by augmenting arrays with custom functions
					if (key == "class") { e.className = attrs[key]; }
					else if (key == "id") { e.id = attrs[key]; }
					else { e.setAttribute(key, attrs[key]); }
				}
			}
			if (text) e.appendChild(doc.createTextNode(text));
			return e;
		},

		OpenPopup: function(url, name, parameters, size, position) {
			var popup = null;

			var p = null;
			if (parameters != null) {
				p = "";
				if (RLdesign.Utils.IsObject(parameters)) {
					for (var key in parameters) {
						p += key + "=" + parameters[key] + ",";
					}
					if (p.lastIndexOf(",") == p.length - 1) p = p.substring(0, p.length - 1);
				}
				else {
					p = parameters;
				}
			}

			var pw = 0;
			var ph = 0;

			if (size != null && RLdesign.Utils.IsObject(size)) {
				if (p == null) { p = ""; }
				else if (p.indexOf("height") != -1 || p.indexOf("width") != -1) {
					alert("Cannot set the size of the popup window twice.");
					return null;
				}
				if (size["width"].indexOf("%") != -1) {
					size["width"] = size["width"].replace("%", "");
					var scrw = screen.width;
					size["width"] = parseInt((scrw / 100) * size["width"]);
				}
				if (size["height"].indexOf("%") != -1) {
					size["height"] = size["height"].replace("%", "");
					var scrh = screen.height;
					size["height"] = parseInt((scrh / 100) * size["height"]);
				}
				if (p != "") p += ",";
				p += "width=" + size["width"];
				p += ",height=" + size["height"];
				pw = parseInt(size["width"]);
				ph = parseInt(size["height"]);
			}

			if (arguments.length == 0) {
				popup = window.open();
			}
			else if (url != null && name != null && p != "") {
				popup = window.open(url, name, p);
			}
			else if (url != null && name != null) {
				popup = window.open(url, name);
			}
			else if (url != null) {
				popup = window.open(url);
			}

			if (position != null && RLdesign.Utils.IsObject(position)) {
				if (position["left"].indexOf("%") != -1) {
					position["left"] = position["left"].replace("%", "");
					var scrw = screen.width;
					position["left"] = parseInt(((scrw - pw) / 100) * position["left"]);
				}
				if (position["top"].indexOf("%") != -1) {
					position["top"] = position["top"].replace("%", "");
					var scrh = screen.height;
					position["top"] = parseInt(((scrh - ph) / 100) * position["top"]);
				}
				popup.focus();
				popup.moveTo(parseInt(position["left"]), parseInt(position["top"]));
			}

			return popup;
		},


		PrependChild: function(parent, node) {
			parent.insertBefore(node, parent.firstChild);
		},

		// Enables moving of list items in elements such as <ul>, <ol> and <table>
		ReorderList: function(obj, delta, ListType, postFunction, postPassAlong) {
			var o = RLdesign.Utils.DefineObject(obj);
			if (!ListType) ListType = "ul";
			else ListType = ListType.toLowerCase();
			var tagName = (ListType.toLowerCase() == "table") ? "tr" : "li";
			var iDelta = parseInt(delta);

			var row = o;
			//			do {
			//				row = row.parentNode;
			//			} while (row.tagName.toLowerCase() != tagName);
			while (row.tagName.toLowerCase() != tagName) {
				row = row.parentNode;
			}

			var list = row.parentNode;

			RLdesign.Utils.ClearWhiteSpace(list);

			var bFirst = false;
			var bLast = false;
			var bSecLast = false;

			for (var i = 0; i < list.childNodes.length; i++) {
				if (list.childNodes[i] === row && i == 0) {
					bFirst = true;
					break;
				}
				if (list.childNodes[i] === row && i == (list.childNodes.length - 1)) {
					bLast = true;
					break;
				}
				if (list.childNodes[i] === row && i == (list.childNodes.length - 2)) {
					bSecLast = true;
					break;
				}
			}

			// move down
			if (iDelta < 0) {
				if (bLast) { // insert at top
					list.removeChild(row);
					list.insertBefore(row, list.childNodes[0]);
				}
				else if (bSecLast) { // insert at end
					list.removeChild(row);
					list.appendChild(row);
				}
				else { // move one down
					try {
						var next = row.nextSibling.nextSibling;
						list.removeChild(row);
						list.insertBefore(row, next);
						var next = null;
					}
					catch (ex) {
						// if failed, probably means that the list-item is a single child, and thus shouldn't be moved
					}
				}
			}
			// move up
			else if (iDelta > 0) {
				if (bFirst) { // insert at bottom
					list.removeChild(row);
					list.appendChild(row);
				}
				else { // move one up
					var prev = row.previousSibling;
					list.removeChild(row);
					list.insertBefore(row, prev);
					prev = null;
				}
			}

			if (postFunction != null && typeof (postFunction) == "function") {
				postFunction(postPassAlong);
			}
			list = row = o = null;
		},

		// Enables moving of options in a select
		ReorderSelectOption: function(obj, delta) {
			var oSelect = RLdesign.Utils.DefineObject(obj);
			if (oSelect == null || oSelect.tagName.toLowerCase() != "select" || oSelect.options.length <= 0) return false; // end if not <select>
			var bMoveAbsolute = (arguments.length == 4) ? !!(arguments[3]) : false;
			var iOptionIndex = (arguments.length >= 3) ? parseInt(arguments[2]) : oSelect.selectedIndex;
			var iDelta = parseInt(delta);

			var iNewIndex = null;

			// determine which index position the selected option should be moved to:
			// if absolute position and not out of range
			if (bMoveAbsolute && iDelta >= 0 && iDelta < oSelect.options.length) {
				iNewIndex = iDelta;
			}
			// if relative position - outer edge values should loop around to other end of list
			// ie. move down from start, go to end and vice versa
			else if (iDelta == 1 || iDelta == -1) {
				iNewIndex = (iOptionIndex + iDelta);
				if (iNewIndex == -1) { iNewIndex = oSelect.options.length - 1; }
				else if (iNewIndex == oSelect.options.length) { iNewIndex = 0; }
			}
			// if all else fails, set new index the same as old index
			else {
				iNewIndex = iOptionIndex;
			}

			if (iNewIndex == iOptionIndex) return false; // end if old index == new index, thus no reason to go further

			var tmpOption = oSelect.options[iOptionIndex]; // build temp option in memory to store information
			oSelect.options[iOptionIndex] = new Option(oSelect.options[iNewIndex].text, oSelect.options[iNewIndex].value);
			oSelect.options[iNewIndex] = new Option(tmpOption.text, tmpOption.value);
			oSelect.selectedIndex = iNewIndex;

			tmpOption = oSelect = null;
			return true;
		},

		// replaces a given set of characters starting at the cursors position in a textfield
		ReplaceAfterCursor: function(obj, sValue, iLength, bSelectRange) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null || (elem.tagName.toLowerCase() != "textarea" && (elem.tagName.toLowerCase() != "input") || elem.type.toLowerCase() != "text")) return;
			if (iLength == null) iLength = sValue.length;
			if (document.selection) {
				elem.focus();
				var sel = document.selection.createRange();
				if (sel.text.length != iLength) {
					sel.moveStart("character", 0);
					sel.moveEnd("character", iLength);
				}
				sel.select();
				sel.text = sValue;
				if (bSelectRange) {
					sel = document.selection.createRange();
					sel.moveStart("character", 0);
					sel.moveEnd("character", sValue.length);
				}
				sel.select();
			}
			else if (elem.selectionStart || elem.selectionStart == "0") {
				var startPos = elem.selectionStart;
				var endPos = elem.selectionEnd;
				elem.value = elem.value.substring(0, startPos) + sValue + elem.value.substring(endPos, elem.value.length);
				if (bSelectRange) {
					elem.setSelectionRange(startPos, startPos + iLength);
				}
				elem.focus();
			}
		},

		// replaces a given set of characters ending at the cursors position in a textfield
		ReplaceBeforeCursor: function(obj, sValue, iLength, bSelectRange) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null || (elem.tagName.toLowerCase() != "textarea" && (elem.tagName.toLowerCase() != "input") || elem.type.toLowerCase() != "text")) return;
			if (iLength == null) iLength = sValue.length;
			if (document.selection) {
				elem.focus();
				var sel = document.selection.createRange();
				sel.moveStart("character", iLength * -1);
				sel.moveEnd("character", 0);
				sel.select();
				sel.text = sValue;
				if (bSelectRange) {
					sel = document.selection.createRange();
					sel.moveStart("character", sValue.length * -1);
					sel.moveEnd("character", 0);
				}
				sel.select();
			}
			else if (elem.selectionStart || elem.selectionStart == "0") {
				var startPos = obj.selectionStart - iLength;
				if (startPos < 0) startPos = 0;
				var endPos = elem.selectionEnd;
				elem.value = elem.value.substring(0, startPos) + sValue + elem.value.substring(endPos, elem.value.length);
				elem.focus();
			}
		},

		// rounds a number off to a default of two decimal places.
		// The amount decimals can be customized by providing a second (optional) argument in the form of an int
		RoundNumber: function(fNumber) {
			var rlength = (arguments.length == 2) ? parseInt(arguments[1]) : 2; // The number of decimal places to round to
			var returnNumber = parseFloat(fNumber);
			if (returnNumber.toFixed) { // if browser supports js 1.5 method of rounding
				returnNumber = returnNumber.toFixed(rlength);
			}
			else { // if legacy browser
				if (returnNumber > 8191 && returnNumber < 10485) { // workaround for javascript bug
					returnNumber = returnNumber - 5000;
					returnNumber = Math.round(returnNumber * Math.pow(10, rlength)) / Math.pow(10, rlength);
					returnNumber = returnNumber + 5000;
				}
				else {
					returnNumber = Math.round(returnNumber * Math.pow(10, rlength)) / Math.pow(10, rlength);
				}
			}
			return returnNumber;
		},

		// sets the cursors position relative to its current position in a textfield
		SetRelativeCursorPosition: function(obj, iLength) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null || (elem.tagName.toLowerCase() != "textarea" && (elem.tagName.toLowerCase() != "input") || elem.type.toLowerCase() != "text")) return;
			if (document.selection) {
				elem.focus();
				var sel = document.selection.createRange();
				sel.moveStart("character", iLength);
				sel.moveEnd("character", iLength);
				sel.select();
			}
			else if (elem.selectionStart || elem.selectionStart == "0") {
				var startPos = elem.selectionStart + iLength;
				elem.setSelectionRange(startPos, startPos);
				elem.focus();
			}
		},

		// selects a range of characters in a textfield
		SelectRange: function(obj, iStart, iLength) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null || (elem.tagName.toLowerCase() != "textarea" && (elem.tagName.toLowerCase() != "input") || elem.type.toLowerCase() != "text")) return;
			if (elem.createTextRange) {
				var oRange = elem.createTextRange();
				oRange.moveStart("character", iStart);
				oRange.moveEnd("character", iLength - elem.value.length);
				oRange.select();
			}
			else if (elem.selectionStart || elem.selectionStart == "0") {
				elem.setSelectionRange(iStart, iLength);
			}
			elem.focus();
		},


		SetCookie: function(cookieName, cookieValue, nDays) {
			var today = new Date();
			var expire = new Date();
			if (nDays == null || nDays == 0) nDays = 1;
			expire.setTime(today.getTime() + (nDays * 24 * 60 * 60 * 1000));
			document.cookie = cookieName + "=" + escape(cookieValue) + ";expires=" + expire.toGMTString();
		},

		GetCookie: function(cookieName) {
			var nameEQ = cookieName + "=";
			var ca = document.cookie.split(';');
			for (var i = 0; i < ca.length; i++) {
				var c = ca[i];
				while (c.charAt(0) == ' ') c = c.substring(1, c.length);
				if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
			}
			return null;
		},

		RemoveCookie: function(cookieName) {
			RLdesign.Utils.SetCookie(cookieName, "", -1);
		},

		SetDisplay: function(obj, sParam) {
			obj = RLdesign.Utils.DefineObject(obj);
			obj.style.display = (sParam) ? sParam : "";
		},

		// sets opacity in a cross-browser sort-of way (doesn't work in pre-9 operas)
		SetOpacity: function(obj, iOpacity, bRelative, iDirection) {
			iDirection = (iDirection && iDirection < 0) ? -1 : 1;
			oElem = RLdesign.Utils.DefineObject(obj);
			if (oElem == null) return;
			if (bRelative) {
				iOpacity = iOpacity * iDirection;
				/*  NOT WORKING! - Figure out opacity when first time (should possibly be 100% but seen as "" (empty string)  */
				//						if (oElem.filter) oElem.filter.item("DXImageTransform.Microsoft.Alpha").opacity += iOpacity;
				//						oElem.style.KHTMLOpacity += (iOpacity / 100); // Safari<1.2, Konqueror
				//						oElem.style.MozOpacity += (iOpacity / 100); // Older Mozilla and Firefox
				//						oElem.style.opacity += (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
				oElem.style.opacity = oElem.style.opacity * 1 + (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
			}
			else {
				iOpacity = (iOpacity == 100) ? 99.999 : iOpacity;
				oElem.style.filter = "alpha(opacity:" + iOpacity + ")"; // IE/Win
				oElem.style.KHTMLOpacity = iOpacity / 100; // Safari<1.2, Konqueror
				oElem.style.MozOpacity = iOpacity / 100; // Older Mozilla and Firefox
				oElem.style.opacity = iOpacity / 100; // Safari 1.2, newer Firefox and Mozilla, CSS3
			}
		},

		Serialize: function(o, action, seperator, value) {
			var addtoobject = !(arguments.length > 4 && arguments[4]);
			var obj = (addtoobject) ? RLdesign.Utils.DefineObject(o) : o;
			var sval = (addtoobject) ? obj.value : obj;
			switch (action.toLowerCase()) {
				case "add":
					sval = (sval == "") ? value : sval + seperator + value;
					if (addtoobject)
						obj.value = sval;
					else
						return sval;
					break;
				case "remove":
					var aValues = sval.split(seperator);
					var sValues = "";
					for (var i = 0; i < aValues.length; i++) {
						if (aValues[i] != value) {
							sValues = (sValues == "") ? aValues[i] : sValues + seperator + aValues[i];
						}
					}
					if (addtoobject)
						obj.value = sValues;
					else
						return sValues;
					break;
				case "get":
				case "fetch":
					return sval.split(seperator);
					break;
				case "length":
				case "count":
				case "getlength":
				case "getcount":
					return sval.split(seperator).length;
					break;
				case "find":
				case "search":
					var aValues = sval.split(seperator);
					var sValues = "";
					for (var i = 0; i < aValues.length; i++) {
						if (aValues[i] === value) {
							return true;
						}
					}
					return false;
					break;
				case "empty":
				case "clear":
					sval = "";
					if (addtoobject)
						obj.value = sval;
					else
						return sval;
					break;
				case "fill":
					if (RLdesign.Utils.IsArray(value)) {
						var sval = "";
						for (var i = 0; i < value.length; i++) {
							if (value[i] != "") {
								sval = (i == 0) ? value[i] : sval + seperator + value[i];
							}
						}
					}
					if (addtoobject)
						obj.value = sval;
					else
						return sval;
					break;
			}
		},

		SetPositionToOffset: function(obj, horizontal, vertical) {
			var h = (horizontal === null) ? true : horizontal;
			var v = (vertical === null) ? true : vertical;
			var o = RLdesign.Utils.DefineObject(obj);
			if (!o) return;

			var position = new Object();
			position["left"] = parseInt(RLdesign.Utils.GetCssValue(o, "left"));
			position["top"] = parseInt(RLdesign.Utils.GetCssValue(o, "top"));
			var scroll = RLdesign.Utils.GetScrollingOffset();
			if (h) o.style.left = scroll["horizontal"] + position["left"] + "px";
			if (v) o.style.top = scroll["vertical"] + position["top"] + "px";
		},

		ToggleDisplay: function(obj, sProp) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null) return;

			if (sProp != undefined && sProp != null) {
				elem.style.display = sProp;
			}
			else {
				var sProp = RLdesign.Utils.GetCssValue(obj, "display");
				if (sProp == "none") elem.style.display = "block";
				else elem.style.display = "none";
			}
		},

		ToggleVisibility: function(obj, sProp) {
			var elem = RLdesign.Utils.DefineObject(obj);
			if (elem == null) return;

			if (sProp != undefined && sProp != null) {
				elem.style.visibility = sProp;
			}
			else {
				var sProp = RLdesign.Utils.GetCssValue(obj, "visibility");
				if (sProp == "hidden") elem.style.display = "visible";
				else elem.style.display = "hidden";
			}
		},

		// converts first character of textstring to uppercase while lowercasing the rest of the string
		UcFirst: function(sText) {
			var sLower = sText.toLowerCase();
			sFirst = sLower.substring(0, 1);
			sRest = sLower.substring(1);
			return sFirst.toUpperCase() + sRest;
		}
	}
} ();

// Fader class for opacity-ramping of objects
// 
// Copyright 2007-2008 René Lønstrup @ RLdesign.dk
// 
// May not be used commercially without permission from the author.
//
// Version: 1.0.0.0
//
//
// CHANGELOG:
//
// 22/03/2008
//     1.0.0.0
//           First public release
//

if (!RLdesign) {
	var RLdesign = function() { };
}
if (!RLdesign.Web) {
	RLdesign.Web = function() { };
}
if (!RLdesign.Web.UI) {
	RLdesign.Web.UI = function() { };
}
RLdesign.Web.UI.Fader = function() {
	return {
		Fade: function(obj, iEndOpacity, iTotalDuration, iResolution, sDisplayProp, fnWhenDone) {
			if (sDisplayProp == null) sDisplayProp = "block";
			if (iResolution == null || isNaN(iResolution) || iResolution < 1) iResolution = 6;
			var bSetNoneDisplay = false;
			switch (sDisplayProp.toString().toLowerCase()) {
				case "inline":
					sDisplayProp = "inline";
					break;
				case "inline-block":
					sDisplayProp = "inline-block";
					break;
				case "none":
					bSetNoneDisplay = true;
				case "block":
				default:
					sDisplayProp = "block";
					break;
			}
			
			obj = RLdesign.Utils.DefineObject(obj);
			if (obj == null) return false;
			
			fnWhenDone = (typeof(fnWhenDone) == "function") ? fnWhenDone : null;
			
			if (obj.tRLdesignFader) {
				clearTimeout(obj.tRLdesignFader);
			}
			var iCurrentOpacity = parseInt(RLdesign.Utils.GetOpacity(obj));
			if (iCurrentOpacity != iEndOpacity) {
				RLdesign.Utils.SetOpacity(obj, iCurrentOpacity);
				RLdesign.Utils.SetDisplay(obj,sDisplayProp);
				var iTotalSteps = (iTotalDuration / iResolution) / 2;
				var iTimeout = iTotalDuration / iTotalSteps;
				var iStep = (iEndOpacity - iCurrentOpacity) / iTotalSteps;
				obj.tRLdesignFader = window.setTimeout(function() {RLdesign.Web.UI.Fader._DoFade(obj, iCurrentOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				RLdesign.Utils.SetDisplay(obj,sDisplayProp);
				if (typeof(fnWhenDone) == "function") fnWhenDone(obj);
			}
		},
		
		_DoFade: function(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone) {
			iOpacity += iStep;
			if (iOpacity < 0) iOpacity = 0;
			else if (iOpacity > 100) iOpacity = 100;
			else if (iStep > 0 && iOpacity > iEndOpacity) iOpacity = iEndOpacity;
			else if (iStep < 0 && iOpacity < iEndOpacity) iOpacity = iEndOpacity;
			RLdesign.Utils.SetOpacity(obj, iOpacity);
			if (bSetNoneDisplay && iOpacity == 0 && iOpacity == iEndOpacity) {
				RLdesign.Utils.SetDisplay(obj, "none");
			}
			if (((iStep > 0 && iOpacity < iEndOpacity) || (iStep < 0 && iOpacity > iEndOpacity)) && (iOpacity > 0 && iOpacity < 100)) {
				obj.tRLdesignFader = window.setTimeout(function() {RLdesign.Web.UI.Fader._DoFade(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				if (typeof(fnWhenDone) == "function") fnWhenDone(obj);
			}
		}
	}
} ();

// Slideshow class
// 
// Copyright 2008-2009 Ren? L?nstrup @ RLdesign.dk
// 
// May not be used commercially without permission from the author.
//
// Version: 1.1.1.1
//
//
// CHANGELOG:
//
// 30/05/2009
//     1.1.1.1
//           Tweaked parts of the code a little to ensure it does not remove any placeholder content in case the supplied images array is empty
// 28/05/2009
//     1.1.1.0
//           Made it possible to supply an array of images to use in the slideshow, which will be created instead of any content in the container div
// 28/05/2009
//     1.1.0.2
//           Fixed a bug meaning the script would fail if there were no elements in the slide container
// 16/12/2008
//     1.1.0.1
//           Fixed a small bug meaning you had to manually set position: relative on the container div
// 15/12/2008
//     1.1.0.0
//           Drastically changed the functionality of the class, making it possible to control it externally
// 14/08/2008
//     1.0.0.0
//           First public release
//

// USAGE:
//
// var oSlideshowItems = new Array();
// oSlideshowItems[0] = ["/url/to/image.jpg", "optional alt text - or blank string", (isSelectedByDefault) ? true : false];
// oSlideshowItems[1] = ["/url/to/image2.jpg", "optional alt text - or blank string", false];
// oSlideshowItems[2] = ["/url/to/image3.jpg", "optional alt text - or blank string", false];
//
// var oSlideshowVars = new Object();
// oSlideshowVars.ContainerID = "rl_slideshow";
// oSlideshowVars.FadeTime = 2000; // milliseconds
// oSlideshowVars.WaitTime = 10; // seconds
//
// var slideshow = new RLdesign.Web.UI.Slideshow(oSlideshowVars, oSlideshowItems);
// slideshow.Start();


if (!RLdesign) {
	var RLdesign = function() { };
}
if (!RLdesign.Web) {
	RLdesign.Web = function() { };
}
if (!RLdesign.Web.UI) {
	RLdesign.Web.UI = function() { };
}
RLdesign.Web.UI.Slideshow = function(varArray, itmArray) {
	this._ready = false;
	this.oVars = null;
	this.oElements = null;
	this._currentdisplay = "block";
	this._current = 0;
	this._next = 0;
	this._max = 0;
	this._waittime = 10;
	this._fadetime = 2000;
	this._waittimeout = null;

	this.Init = function(Variables, ItemsArray) {
		var oThis = this;

		if (!RLdesign.Utils.IsObject(Variables) && typeof (Variables) != "string") {
			alert("Exiting slideshow - no container ID.");
			return;
		}
		this.oVars = Variables;
		this._current = 0;


		if (ItemsArray != null) {
			this._createitems(ItemsArray);
		}


		var container = RLdesign.Utils.DefineObject(this.oVars.ContainerID);
		if (container == null) return;
		if (RLdesign.Utils.GetCssValue(container, "position") != "absolute") {
			container.style.position = "relative";
		}
		if (container.childNodes != null && container.childNodes.length != 0) {
			var els = container.childNodes;
			this.oElements = new Array();
			var q = 0;
			var satActive = false;
			for (var i = 0; i < els.length; i++) {
				if (els[i].tagName != null && els[i].tagName.toLowerCase() == "div") {
					this.oElements[q] = els[i];
					this.oElements[q].style.position = "absolute";
					this.oElements[q].style.top = "0px";
					this.oElements[q].style.left = "0px";
					this.oElements[q].style.zIndex = "1";
					this.oElements[q].style.display = "none";
					RLdesign.Utils.SetOpacity(this.oElements[q], 0);
					if (this.oElements[q].className.indexOf("active") > -1) {
						RLdesign.Utils.SetOpacity(this.oElements[q], 100);
						RLdesign.Utils.SetDisplay(this.oElements[q], this._currentdisplay);
						this.oElements[q].style.zIndex = "10";
						satActive = true;
						this._current = q;
					}
					q++;
				}
			}
			if (!satActive && this.oElements.length > 0) {
				RLdesign.Utils.SetOpacity(this.oElements[0], 100);
				this.oElements[0].style.display = this._currentdisplay;
				this.oElements[0].style.zIndex = "10";
			}
		}
		else if (this.oVars.Elements != null && this.oVars.Elements.length > 0) {
			// fetch images
			this.oElements = this.oVars.Elements;
		}
		else {
			return;
		}


		this._max = this.oElements.length;
		this._waittime = this.oVars.WaitTime;
		this._fadetime = this.oVars.FadeTime;

		if (this._current < this._max - 1) {
			this._next = this._current + 1;
		}
		else {
			this._next = 0;
		}

		//this._initopacity();
		//this._setnext();

		this.Start();
	}


	this.Stop = function() {
		this._ready = false;
		this._stoptimeouts();
	}

	this.Start = function() {
		if (!RLdesign.Utils.IsObject(this.oVars)) {
			alert("Exiting slideshow - no container ID.");
			return;
		}
		else {
			this._ready = true;
		}

		//		for (var i = 0; i < this._max; i++) {
		//			if (this.oElements[i])
		//				this.oElements[i].style.display = "none";
		//		}
		//		this.oElements[this._current].style.display = this._currentdisplay;

		this._wait();
	}



	this._wait = function() {
		var oThis = this;
		if (!oThis._ready) return;
		oThis._waittimeout = window.setTimeout(function() { oThis._nextimage(oThis); }, oThis._waittime * 1000);
	}


	this._nextimage = function(oThis) {
		if (!oThis._ready) return;
		if (oThis.oElements.length == 1) return;
		RLdesign.Utils.SetOpacity(oThis.oElements[oThis._next], 100);
		RLdesign.Utils.SetDisplay(oThis.oElements[oThis._next], oThis._currentdisplay);
		//RLdesign.Web.UI.Fader.Fade(oThis.oElements[oThis._next], 100, oThis._fadetime, 20, oThis._currentdisplay, null);
		RLdesign.Web.UI.Fader.Fade(oThis.oElements[oThis._current], 0, oThis._fadetime, 20, "none", function() { oThis._setnext(oThis); });

	}

	// moves the cursor to the next image
	this._setnext = function(oThis) {
		if (!oThis) oThis = this;
		if (!oThis._ready) return;

		oThis.oElements[oThis._current].style.zIndex = 1;
		oThis.oElements[oThis._next].style.zIndex = 10;

		oThis._current = oThis._next;
		if (oThis._next < oThis._max - 1) {
			oThis._next++;
		}
		else {
			oThis._next = 0;
		}

		for (var i = 0; i < oThis._max; i++) {
			if (oThis.oElements[i])
				oThis.oElements[i].style.display = "none";
		}
		RLdesign.Utils.SetDisplay(oThis.oElements[oThis._current], oThis._currentdisplay);

		oThis._wait();
	}

	this._stoptimeouts = function() {
		window.clearTimeout(this._waittimeout);
	}

	// sets the opacity of the images
	this._initopacity = function() {
		if (!this._ready) return;
		for (var i = 0; i < this._max; i++) {
			if (this.oElements[i])
				RLdesign.Utils.SetOpacity(this.oElements[i], 0);
		}
		RLdesign.Utils.SetOpacity(this.oElements[this._current], 100);
	}

	this._createitems = function(itemArray) {
		if (itemArray.length == 0) return;
		var container = RLdesign.Utils.DefineObject(this.oVars.ContainerID);
		RLdesign.Utils.ClearChildElements(container);
		for (var i = 0; i < itemArray.length; i++) {
			var oParams = new Object();
			var selected = (i == 0) ? true : false;
			if (itemArray[i].length > 2) {
				selected = (itemArray[i][2]);
			}
			oParams["class"] = (selected) ? "slideshow_item active" : "slideshow_item";
			var oDiv = RLdesign.Utils.MakeElement("div", oParams);

			oParams = new Object();
			oParams["alt"] = itemArray[i][1];
			oParams["src"] = itemArray[i][0];
			var oImg = RLdesign.Utils.MakeElement("img", oParams);

			oDiv.appendChild(oImg);
			container.appendChild(oDiv);

			oDiv = oImg = null;
		}
		container = null;
	}


	this.Init(varArray, itmArray);
}


if (!RLdesign) {
	var RLdesign = function() { };
}

if (!RLdesign.Utils) {
	RLdesign.Utils = function() {
		return {
			// removes any child nodes of the given object
			ClearChildElements: function(obj) {
				var elem = RLdesign.Utils.DefineObject(obj);
				if (elem == null) return;
				if (elem.hasChildNodes()) {
					while (elem.childNodes.length >= 1) {
						elem.removeChild(elem.firstChild);
					}
				}
			},

			// returns a crossbrowser event object
			DefineEvent: function(e) {
				return e || window.event;
			},

			// returns the target for the event in question, typically a click-event
			// ie. in the case of a click-event, the target is the element being clicked on
			DefineEventTarget: function(e) {
				var ev = RLdesign.Utils.DefineEvent(e);
				var element = ev.srcElement || ev.target;
				if (element.nodeType == 3) element = element.parentNode; // defeat Safari bug
				return element;
			},

			// 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, d) {
				var doc = (d) ? d : document;
				var elem = null;
				// if el is an object
				if (typeof (el) == "object") {
					try {
						elem = el;
					}
					catch (ex) {
						elem = null;
					}
				}
				// if el is the id of an html-object
				else if (doc.getElementById(el)) {
					try {
						elem = doc.getElementById(el);
					}
					catch (ex) {
						elem = null;
					}
				}
				// if el is a string representation of an document.getElementById - or similar statement
				else if (typeof (el) == "string" && (el.indexOf("(") != -1 || el.indexOf("[") != -1)) {
					try {
						eval("elem = " + el);
					}
					catch (ex) {
						elem = null;
					}
				}
				// last resort
				else if (typeof (el) == "string") {
					try {
						eval("elem = " + el);
					}
					catch (ex) {
						elem = null;
					}
				}
				return elem;
			},

			// returns a crossbrowser return code designed to prevent further events i mozilla browser, if need be
			DefineReturnCode: function(e, r) {
				var ev = RLdesign.Utils.DefineEvent(e);
				if (r == false) {
					if (ev.stopPropagation) ev.stopPropagation();
					else if (ev.cancelBubble) ev.cancelBubble = true;
					if (ev.preventDefault) ev.preventDefault();
					else if (ev.returnValue) ev.returnValue = false;
				}
				else {
					if (typeof (ev.returnValue) == "string") ev.returnValue = r;
				}
				return r;
			},

			// clears the specified global timeout variable (specified as a string), if exists
			ClearTimeout: function(sTimeout) {
				var bTimeoutExist = !!window[sTimeout];
				if (bTimeoutExist) window.clearTimeout(window[sTimeout]);
			},

			// creates a given html element in memory and returns the element
			MakeElement: function(tag, attrs, text, d) {
				var doc = (d) ? d : document;
				var e = doc.createElement(tag);
				if (attrs) {
					for (var key in attrs) {
						if (typeof (attrs[key]) == "function") continue; // defeat bug caused by augmenting arrays with custom functions
						if (key == "class") { e.className = attrs[key]; }
						else if (key == "id") { e.id = attrs[key]; }
						else { e.setAttribute(key, attrs[key]); }
					}
				}
				if (text) e.appendChild(doc.createTextNode(text));
				return e;
			},

			// 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);
			},

			SetDisplay: function(obj, sParam) {
				obj = RLdesign.Utils.DefineObject(obj);
				obj.style.display = (sParam) ? sParam : "";
			},

			GetCssValue: function(obj, sCss) {
				var elem = RLdesign.Utils.DefineObject(obj);
				if (elem == null) return;
				var cStyle = null;
				if (elem.currentStyle) {
					cStyle = elem.currentStyle;
				}
				else if (document.defaultView && document.defaultView.getComputedStyle) {
					cStyle = document.defaultView.getComputedStyle(elem, "");
				}
				var sValue;
				if (cStyle) {
					sValue = cStyle[sCss];
				}
				else {
					sValue = elem.style[sCss];
				}
				return sValue;
			},

			GetOpacity: function(obj) {
				var opacity = (parseInt(obj.style.width) == obj.offsetWidth) ? 100 : 0;
				if (obj.style.opacity) { opacity = Math.round(obj.style.opacity * 100); }
				else if (obj.style.MozOpacity) { opacity = Math.round(obj.style.MozOpacity * 100); }
				else if (obj.style.KHTMLOpacity) { opacity = Math.round(obj.style.KHTMLOpacity * 100); }
				else if (obj.style.filter) {
					var filter = obj.style.filter;
					//				var pattern = /opacity\b[^=]*=(.*?)\)/;
					var pattern = /\(opacity:(.*?)\)/;
					oRegex = filter.match(pattern);
					if (typeof (oRegex) == "object") {
						var match = oRegex[1];
						opacity = (match != null) ? parseInt(match) : opacity;
					}
				}
				return opacity;
			},

			// sets opacity in a cross-browser sort-of way (doesn't work in pre-9 operas)
			SetOpacity: function(obj, iOpacity, bRelative, iDirection) {
				iDirection = (iDirection && iDirection < 0) ? -1 : 1;
				oElem = RLdesign.Utils.DefineObject(obj);
				if (oElem == null) return;
				if (bRelative) {
					iOpacity = iOpacity * iDirection;
					/*  NOT WORKING! - Figure out opacity when first time (should possibly be 100% but seen as "" (empty string)  */
					//						if (oElem.filter) oElem.filter.item("DXImageTransform.Microsoft.Alpha").opacity += iOpacity;
					//						oElem.style.KHTMLOpacity += (iOpacity / 100); // Safari<1.2, Konqueror
					//						oElem.style.MozOpacity += (iOpacity / 100); // Older Mozilla and Firefox
					//						oElem.style.opacity += (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
					oElem.style.opacity = oElem.style.opacity * 1 + (iOpacity / 100); // Safari 1.2, newer Firefox and Mozilla, CSS3
				}
				else {
					iOpacity = (iOpacity == 100) ? 99.999 : iOpacity;
					oElem.style.filter = "alpha(opacity:" + iOpacity + ")"; // IE/Win
					oElem.style.KHTMLOpacity = iOpacity / 100; // Safari<1.2, Konqueror
					oElem.style.MozOpacity = iOpacity / 100; // Older Mozilla and Firefox
					oElem.style.opacity = iOpacity / 100; // Safari 1.2, newer Firefox and Mozilla, CSS3
				}
			}

		}
	} ();
}



RLdesign.Web.UI.Fader = function() {
	return {
		Fade: function(obj, iEndOpacity, iTotalDuration, iResolution, sDisplayProp, fnWhenDone) {
			if (sDisplayProp == null) sDisplayProp = "block";
			if (iResolution == null || isNaN(iResolution) || iResolution < 1) iResolution = 6;
			var bSetNoneDisplay = false;
			switch (sDisplayProp.toString().toLowerCase()) {
				case "inline":
					sDisplayProp = "inline";
					break;
				case "inline-block":
					sDisplayProp = "inline-block";
					break;
				case "none":
					bSetNoneDisplay = true;
				case "block":
				default:
					sDisplayProp = "block";
					break;
			}

			obj = RLdesign.Utils.DefineObject(obj);
			if (obj == null) return false;

			fnWhenDone = (typeof (fnWhenDone) == "function") ? fnWhenDone : null;

			if (obj.tRLdesignFader) {
				clearTimeout(obj.tRLdesignFader);
			}
			var iCurrentOpacity = parseInt(RLdesign.Utils.GetOpacity(obj));
			if (iCurrentOpacity != iEndOpacity) {
				RLdesign.Utils.SetOpacity(obj, iCurrentOpacity);
				RLdesign.Utils.SetDisplay(obj, sDisplayProp);
				var iTotalSteps = (iTotalDuration / iResolution) / 2;
				var iTimeout = iTotalDuration / iTotalSteps;
				var iStep = (iEndOpacity - iCurrentOpacity) / iTotalSteps;
				obj.tRLdesignFader = window.setTimeout(function() { RLdesign.Web.UI.Fader._DoFade(obj, iCurrentOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				RLdesign.Utils.SetDisplay(obj, sDisplayProp);
				if (typeof (fnWhenDone) == "function") fnWhenDone(obj);
			}
		},

		_DoFade: function(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone) {
			iOpacity += iStep;
			if (iOpacity < 0) iOpacity = 0;
			else if (iOpacity > 100) iOpacity = 100;
			else if (iStep > 0 && iOpacity > iEndOpacity) iOpacity = iEndOpacity;
			else if (iStep < 0 && iOpacity < iEndOpacity) iOpacity = iEndOpacity;
			RLdesign.Utils.SetOpacity(obj, iOpacity);
			if (bSetNoneDisplay && iOpacity == 0 && iOpacity == iEndOpacity) {
				RLdesign.Utils.SetDisplay(obj, "none");
			}
			if (((iStep > 0 && iOpacity < iEndOpacity) || (iStep < 0 && iOpacity > iEndOpacity)) && (iOpacity > 0 && iOpacity < 100)) {
				obj.tRLdesignFader = window.setTimeout(function() { RLdesign.Web.UI.Fader._DoFade(obj, iOpacity, iStep, iTimeout, iEndOpacity, bSetNoneDisplay, fnWhenDone); }, iTimeout);
			}
			else {
				if (typeof (fnWhenDone) == "function") fnWhenDone(obj);
			}
		}
	}
} ();

