var ts_majorVersion = '586';
var ts_minorVersion = '89';
var buildCode = '?ts='+ts_majorVersion+'.'+ts_minorVersion;

(function ()
{
	function _$ts()
	{
		// Local vars
		this.ajaxSettings = { 'url': 'blank.htm', 'async': true, 'data': '', 'type': 'GET', 'noncacheable': true };
	}

	_$ts.prototype =
	{
		getComputedStyle: function (element, style)
		{
			/// <summary>
			/// Gets the current active value, for a specified style.
			/// </summary>
			/// <param name="element">The element.</param>
			/// <param name="style">The style to look up.</param>
			/// <returns>The active value of the style.</returns>
			var value = "";

			if (document.defaultView && document.defaultView.getComputedStyle)
			{
				value = document.defaultView.getComputedStyle(element, "").getPropertyValue(style);
			}
			else if (element.currentStyle)
			{
				style = style.replace(/\-(\w)/g, function (match, capture)
				{
					return capture.toUpperCase();
				});
				value = element.currentStyle[style];
			}

			return value;
		},
		getPosition: function (element, absolute, topRef)
		{
			/// <summary>
			/// Gets an elements correct x and y position.
			/// </summary>
			/// <param name="element">The element.</param>
			/// <param name="topRef">The window to use as reference for absolute positioning (optional, default = window.top).</param>
			/// <returns>An array [x,y].</returns>
			var curleft = 0, curtop = 0, parentFrames;

			if (!$ts.exists(topRef))
			{
				topRef = window.top;
			}

			if (element.offsetParent)
			{
				do
				{
					curleft += element.offsetLeft;
					curleft -= element.scrollLeft;
					curtop += element.offsetTop;
					curtop -= element.scrollTop;
					element = element.offsetParent;
				} while (this.exists(element));
			}

			if (absolute && window.self != topRef)
			{
				parentFrames = parent.$elms('iframe', 'frame');

				for (var i = 0; i < parentFrames.length; i++)
				{
					if (parentFrames[i].contentWindow == window)
					{
						element = parentFrames[i];

						var parentPos = parent.$ts.getPosition(element, true);

						curleft += parentPos[0];
						curtop += parentPos[1];
						break;
					}
				}
			}

			return [curleft, curtop];
		},
		hasClass: function (element, className)
		{
			/// <summary>
			/// Checks if an element impliments a specified class.
			/// </summary>
			/// <param name="element">The element.</param>
			/// <param name="className">The class to look up.</param>
			/// <returns>Boolean whether or not the class is implemented.</returns>
			if (this.exists(className) && className !== '')
			{
				return new RegExp("\\b" + className + "\\b").test(element.className);
			}
			else
			{
				throw 'className must be specified.';
			}
		},
		addClass: function (element, className)
		{
			/// <summary>
			/// Adds a specified class to the element.
			/// </summary>
			/// <param name="element">The element.</param>
			/// <param name="className">The class to add.</param>
			if (!this.hasClass(element, className))
			{
				element.className += ' ' + className;
			}
		},
		removeClass: function (element, className)
		{
			/// <summary>
			/// Removes a specified class from the element.
			/// </summary>
			/// <param name="element">The element.</param>
			/// <param name="className">The class to remove.</param>
			element.className = element.className.replace(new RegExp("\\b" + className + "\\b", 'g'), '');
			element.className = element.className.replace(/ {2,}/g, " ");
			element.className = this.trim(element.className);
		},
		createElement: function (tagName, props, styles)
		{
			/// <summary>
			/// Instanciate a dom element, with optional expandos.
			/// </summary>
			/// <param name="tagName">The element type.</param>
			/// <param name="props">A jsonized expando bag, that will be appended to the element. (optional)</param>
			/// <param name="styles">A jsonized style bag, that will be appended to the element. (optional)</param>
			/// <returns>Instanciated element.</returns>
			var element = document.createElement(tagName);

			for (var prop in props)
			{
				if (props.hasOwnProperty(prop))
				{
					element[prop] = props[prop];
				}
			}

			for (var style in styles)
			{
				if (styles.hasOwnProperty(style))
				{
					element.style[style] = styles[style];
				}
			}

			return element;
		},
		addEvent: function (el, type, fn, bubbleDown)
		{
            if (!$ts.exists(el)) return;
			if (!$ts.exists(bubbleDown))
			{
				bubbleDown = false;
			}

			if (el === window && type.toLowerCase() === 'load' && window.loaded === true)
			{
				fn();
				return;
			}

			if (window.addEventListener)
			{
				try
				{
					el.removeEventListener(type, fn, bubbleDown);
				}
				catch (ex) { }

				el.addEventListener(type, fn, bubbleDown);
			}
			else if (window.attachEvent) // IE 8-
			{
				if (type.match(/(?:on)?DOMContentLoaded/i))
				{
					// Diego Perini's hack
					var doc = window.document, done = false;
					init = function () { if (!done) { done = true; fn(); } };
					(function () { try { doc.documentElement.doScroll('left'); } catch (e) { setTimeout(arguments.callee, 50); return; } init(); })();
					doc.onreadystatechange = function () { if (doc.readyState === 'complete') { doc.onreadystatechange = null; init(); } };
				}
				else // Use pre IE 9 attachEvent
				{
					el.attachEvent('on' + type, fn);
				}
			}
		},
		removeEvent: function (el, type, fn, bubbleDown)
		{
            if (!$ts.exists(el)) return;
			if (!$ts.exists(bubbleDown))
			{
				bubbleDown = false;
			}

			if (window.removeEventListener)
			{
				el.removeEventListener(type, fn, bubbleDown);
			}
			else if (window.detachEvent)
			{
				el.detachEvent('on' + type, fn);
			}
		},
		cancelBubble: function (evt)
		{
			var e = evt || window.event;
			if (!e) return false;
			if (e.preventDefault) e.preventDefault();
			if (e.stopPropagation) e.stopPropagation();
			e.cancelBubble = true;
			e.returnValue = false;
			return false;
		},
		loadScriptAsync: function (src, callback)
		{
			/// <summary>
			/// Loads external script files.
			/// </summary>
			/// <param name="src">The path of the script file.</param>
			/// <param name="callback">A callback to fire, when the script is loaded (optional).</param>
			src = src.toLowerCase();
			var loadedScripts = document.getElementsByTagName('script'),
			notLoaded = true;

			for (var i = 0; i < loadedScripts.length; i++)
			{
				if ($ts.exists(loadedScripts[i].src) && loadedScripts[i].src.toLowerCase().indexOf(src) !== -1)
				{
					notLoaded = false;
					break;
				}
			}

			if (notLoaded)
			{
				document.getElementsByTagName('head')[0].appendChild($ts.createElement('script',
				{
					"type": 'text/javascript', "src": src, "loaded": false,
					"onload": function () { if (!this.loaded && $ts.exists(callback)) { callback(); } this.loaded = true; },
					"onreadystatechange": function () { if (this.readyState == 'complete' || this.readyState == 'loaded') { this.onload(); } }
				}));
			}
		},
		pad: function (input, endLength, char, direction)
		{
			/// <summary>
			/// Pads a string to a specified length.
			/// </summary>
			/// <param name="input">The string to pad.</param>
			/// <param name="char">The character to pad with (optional, default = '0').</param>
			/// <param name="direction">The direction to pad, specified with 'left' or 'right' (optional, default = 'left').</param>
			/// <returns>Padded string.</returns>
			var output = input, right = direction === 'right';

			if (!this.exists(char))
			{
				char = '0';
			}

			while (output.length < endLength)
			{
				if (right)
				{
					output += char;
				}
				else
				{
					output = char + output;
				}
			}

			return output;
		},
		trim: function (input, direction, char)
		{
			/// <summary>
			/// Trims any leading and/or trailing characters.
			/// </summary>
			/// <param name="input">The string to trim.</param>
			/// <param name="direction">Leading, trailing or both, specified with 'left' or 'right' (optional, default = 'both').</param>
			/// <param name="char">The character to trim (optional, default = ' ').</param>
			/// <returns>Trimmed string.</returns>
			if (this.exists(input))
			{
				var left = true,
				right = true,
				startIndex = 0,
				endIndex = input.length;

				switch (direction)
				{
					case 'left': right = false; break;
					case 'right': left = false; break;
					default:
				}

				if (!this.exists(char)) { char = ' '; }
				if (left) { while (startIndex < input.length && input.charAt(startIndex) === char) { startIndex++; } }
				if (right) { while (endIndex > startIndex && input.charAt(endIndex - 1) === char) { endIndex--; } }

				return input.substring(startIndex, endIndex);
			}
		},
		addThousandSeparator: function (value, separator)
		{
			/// <summary>
			/// Inserts a thousand/group separator
			/// </summary>
			/// <param name="value">The number</param>
			/// <param name="separator">The char to be inserted as separator</param>
			/// <returns></returns>
			var re = new RegExp('(-?[0-9]+)([0-9]{3})');

			while (re.test(value)) { value = value.replace(re, '$1' + separator + '$2'); }
			return value;
		},
		formatValue: function (value, decimalsign, numdecimals, extended, thousandSeparator)
		{
			/// <summary>
			/// Stig comments missing.
			/// </summary>
			/// <param name="value"></param>
			/// <param name="decimalsign"></param>
			/// <param name="numdecimals"></param>
			/// <param name="extended"></param>
			/// <returns></returns>
			if (isNaN(value)) { return value; }
			value = ($ts.formatNumber(value, numdecimals)).replace('.', decimalsign);
			extended = true;
			if (extended) { value = $ts.addThousandSeparator(value, $ts.exists(thousandSeparator) ? thousandSeparator : (decimalsign === '.' ? ',' : '.')); }
			return value;
		},
		formatNumber: function (value, numDecimals)
		{
			/// <summary>
			/// Formats a number to only have (numDecimals) after the decimal separator
			/// </summary>
			/// <param name="value">The value to format</param>
			/// <param name="numDecimals">The number of decimals</param>
			/// <returns></returns>
			if (isNaN(value)) { return value; }
			if (value === '') { return value; }

			var snum = value + '';
			var sec = snum.split('.');
			var whole = parseFloat(sec[0]);
			var result = '';
			var dot, dec;

			if (sec.length > 1)
			{
				dec = sec[1] + '';
				dec = String(parseFloat(sec[1]) / Math.pow(10, (dec.length - numDecimals)));
				if (whole >= 0) { dec = String(whole + Math.round(parseFloat(dec)) / Math.pow(10, numDecimals)); }
				else { dec = String(whole - Math.round(parseFloat(dec)) / Math.pow(10, numDecimals)); }
				dot = dec.indexOf('.');
				if (dot == -1 && numDecimals > 0)
				{
					dec += '.';
					dot = dec.indexOf('.');
				}
				while (dec.length <= dot + numDecimals) { dec += '0'; }
				result = dec;
			} else
			{
				dec = whole + '';
				if (numDecimals > 0)
				{
					dec += '.';
					dot = dec.indexOf('.');
					while (dec.length <= dot + numDecimals) { dec += '0'; }
				}
				result = dec;
			}
			return result;
		},
		safeInt: function (input, defaultValue)
		{
			/// <summary>
			/// Force casts an object to integer type, with an optional default value.
			/// </summary>
			/// <param name="input">The value to force cast to an integer.</param>
			/// <param name="defaultValue">The default return value, if the cast fails (optional, default = 0).</param>
			/// <returns>Integer - either af succesful cast of the input value or the default value.</returns>
			var returnValue = parseInt(input, 10);

			if (isNaN(returnValue))
			{
				returnValue = parseInt(defaultValue, 10);

				if (isNaN(returnValue))
				{
					returnValue = 0;
				}
			}

			return returnValue;
		},
		setCookie: function (name, value, days)
		{
			/// <summary>
			/// Set a specified cookie.
			/// </summary>
			/// <param name="name">The name of the cookie.</param>
			/// <param name="value">The value to store in the cookie.</param>
			/// <param name="days">The number of days to store the cookie (optional).</param>
			var expires = '';
			if (this.exists(days))
			{
				var date = new Date();
				date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
				expires = '; expires=' + date.toGMTString();
			}
			document.cookie = name + '=' + value + expires + '; path=/';
		},
		getCookie: function (name)
		{
			/// <summary>
			/// Retrieves a specified cookie.
			/// </summary>
			/// <param name="name">The name of the cookie.</param>
			/// <returns>The cookie object.</returns>
			var regex = new RegExp(name + '=([^;]*)', 'i');
			var obj = regex.exec(document.cookie);
			if (obj)
			{
				return obj[1];
			}
			else
			{
				return null;
			}
		},
		deleteCookie: function (name)
		{
			/// <summary>
			/// Deletes a specified cookie.
			/// </summary>
			/// <param name="name">The name of the cookie.</param>
			this.setCookie(name, '', -1);
		},
		getRootUrl: function (url, withTrailingSlash)
		{
			/// <summary>
			/// Returns the root part of the url.
			/// </summary>
			/// <param name="url">The url to analyze.</param>
			/// <param name="withTrailingSlash">Whether or not the returned url is going to end on / (optional, default false).</param>
			var match = url.match(/(.+?:\/\/[^\/]+).*/),
			root = '';

			if (match != null)
			{
				root = match[1];
			}

			if (withTrailingSlash === true)
			{
				root += '/';
			}

			return root;
		},
		getCurrentRootUrl: function (withTrailingSlash)
		{
			/// <summary>
			/// Returns the root part of the current window url.
			/// </summary>
			/// <param name="withTrailingSlash">Whether or not the returned url is going to end on / (optional, default false).</param>
			return this.getRootUrl(window.location.href, withTrailingSlash);
		},
		isUrlLocal: function (url)
		{
			/// <summary>
			/// Checks if the root of the url is the same as the current window location root.
			/// </summary>
			/// <param name="url">The url to analyze.</param>
			return ((url.substring(0, 1) === '/') ? true : (this.getRootUrl(url) === this.getCurrentRootUrl()));
		},
		toRelativeUrl: function (url)
		{
			/// <summary>
			/// Returns the url, without the root part.
			/// </summary>
			/// <param name="url">The url to analyze.</param>
			return url.replace(this.getRootUrl(url), '');
		},
		exists: function (object, property)
		{
			/// <summary>
			/// Checks whether an object, or an objects property, is defined and not null.
			/// </summary>
			/// <param name="object">The object in question.</param>
			/// <param name="property">The property of the object in question (optional).</param>
			/// <returns>Boolean - true if object is not undefined or null.</returns>
			if (object !== undefined && object !== null)
			{
				if (property !== undefined && property !== null)
				{
					return object[property] !== undefined && object[property] !== null;
				}

				return true;
			}

			return false;
		},
		visible: function (element)
		{			
			while (element.nodeName.toLowerCase() != 'body' && element.style.display.toLowerCase() != 'none' && element.style.visibility.toLowerCase() != 'hidden')
			{
				element = element.parentNode;
			}
			if (element.nodeName.toLowerCase() == 'body')
			{
				return true;
			}
			else
			{
				return false;
			}
		},
		getExpando: function (element, property)
		{
			/// <summary>
			/// Retrieves an expando.
			/// </summary>
			/// <param name="element">The element in question.</param>
			/// <param name="property">The name of the expando.</param>
			/// <returns>The value of the expando.</returns>
			return (this.exists(element, property) ? element[property] : element.getAttribute(property));
		},
		collectFormValues: function (fm)
		{
			var form = $elm(fm);
			if (!form) return;
			var p = "";
			var supressAmpersand = false;
			for (var i = 0; i < form.elements.length; i++)
			{
				var item = form.elements[i];
				if (i > 0 && !supressAmpersand)
				{
					p = p + '&';
				}
				if ((item.type == 'checkbox' || item.type == 'radio') && !item.checked) { }
				else
				{
					if (item.type == 'button' || item.type == 'submit')
					{
						supressAmpersand = true;
					} else
					{
						p = p + item.name + '=' + encodeURIComponent(item.value);
						supressAmpersand = false;
					}
				}
			}
			return p;
		},
		ajaxSetup: function (s)
		{
			/// <summary>
			/// Redefines the default settings for ajax requests.
			/// </summary>
			/// <param name="s">JSON object with none or more of the ajax settings (url, async, type, data, complete)</param>
			/// <returns>void.</returns>
			for (var prop in s) { if (this.ajaxSettings.hasOwnProperty(prop)) { this.ajaxSettings[prop] = s[prop]; } }
		},
		ajax: function (s)
		{
			/// <summary>
			/// Executes an ajax request based on the supplied settings.
			/// </summary>
			/// <param name="s">JSON object with none or more of the ajax settings (url, async, type, data, complete)</param>
			/// <returns>responsetext if async is false, otherwise void.</returns>
			for (var prop in this.ajaxSettings) { if (this.ajaxSettings.hasOwnProperty(prop) && !$ts.exists(s, prop)) { s[prop] = this.ajaxSettings[prop]; } }
			var createRequest = function ()
			{
				if (window.XMLHttpRequest) { return new XMLHttpRequest(); }
				else if (window.ActiveXObject)
				{
					var msXMLs = ['Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'];
					for (var i = 0; i < msXMLs.length; i++)
					{
						try
						{
							return new ActiveXObject(msXMLs[i]);
						}
						catch (e) { }
					}
				}
			};

			var request = createRequest();
			var url = s.url;
			if (s.type == 'GET' && $ts.exists(s, 'data') && s.data !== '') { url += s.data; }

           if (this.ajaxSettings['noncacheable'] == true)
			{
				var cacheKey = new Date().getTime(),
				preFix;

				if (url.indexOf('?') === -1)
				{
					preFix = '?';
				}
				else
				{
					preFix = '&';
				}

				url += preFix + 'ts' + cacheKey + '=' + cacheKey;
			}

			function callback()
			{
				if (request.readyState == 4 && s.complete) { s.complete(request, request.responseText); }
			}
			request.open(s.type, url, s.async);
			request.onreadystatechange = callback;
			if (s.type == 'POST') { request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); request.send(s.data); }
			else { request.send(); }
			if (!s.async) { return request.responseText; }
		},
		Observer: (function ()
		{
			/// <summary>
			/// Singleton implementation of the classic observer pattern.
			/// </summary>		    
			var observers = [];

			var _findObserverIndex = function (obs)
			{
				for (var i = 0; i < observers.length; i++)
				{
					var observer = observers[i];
					if (observer.who === obs.who && observer.what === obs.what && observer.where === obs.where)
					{
						return i;
					}
				}
				return -1;
			};

			var _findObservers = function (who, what)
			{
				if (typeof (who) != 'string') { who = who.id; }
				var listeners = [];
				for (var i = 0; i < observers.length; i++)
				{
					var observer = observers[i];
					if (observer.who == who && observer.what == what)
					{
						listeners.push(observer);

						if (observer.oneshot)
						{
							// Remove one shots.
							observers.splice(i, 1);
						}
					}
				}
				return listeners;
			};

			var _wrap = function (who, what, where)
			{
				return { 'who': who, 'what': what, 'where': where };
			};

			this.Register = function (who, what, where)
			{
				/// <summary>
				/// Registers an observer to a subject
				/// </summary>
				/// <param name="who">The subject you wish to listen for</param>
				/// <param name="what">The broadcast event name to listen for</param>
				/// <param name="where">The callback to invoke</param>

				observers.push(_wrap(who, what, where));
			};

			this.RegisterOneShot = function (who, what, where)
			{
				/// <summary>
				/// Registers an observer to a subject, but automaticly unregister after the first broadcast
				/// </summary>
				/// <param name="who">The subject you wish to listen for</param>
				/// <param name="what">The broadcast event name to listen for</param>
				/// <param name="where">The callback to invoke</param>
				observers.push({ "who": who, "what": what, "where": where, "oneshot": true });
			};

			this.UnRegister = function (who, what, where)
			{
				/// <summary>
				/// UnRegisters an observer from a subject
				/// </summary>
				/// <param name="who">The subject</param>
				/// <param name="what">The broadcast event name</param>
				/// <param name="where">callback</param>
				var idx = _findObserverIndex(_wrap(who, what, where));
				if (idx > -1)
				{
					observers = observers.splice(idx, 1);
					return true;
				}
				return false;
			};

			this.Broadcast = function (who, what, data)
			{
				/// <summary>
				/// Broadcasts a message to anyone who wants to listen
				/// </summary>
				/// <param name="who">The subject sending the message</param>
				/// <param name="what">The event name </param>
				/// <param name="data">An object with EventArgs</param>
				var listeners = _findObservers(who, what);

				for (var i = 0; i < listeners.length; i++)
				{
					listeners[i].where.call(who, who, what, data);
				}
			};

			return this;
		})(),
		mathExpressions: (function ()
		{
			this._decimalSign = ",";
			this._thousandSeparator = ".";
			this._expressions = [];
			this._resolvers = [];

			this.formatNumber = function (value, numDecimals)
			{
				return $ts.formatNumber(value, numDecimals);
			};

			this.addThousandSeparator = function (value)
			{
				return $ts.addThousandSeparator(value, this._thousandSeparator);
			};

			this.FormatValue = function (value, decimalsign, numdecimals, extended)
			{
				return $ts.formatValue(value, decimalsign, numdecimals, extended);
			};

			this.removeFormatting = function (value)
			{
				/// <summary>
				/// Stig comments missing.
				/// </summary>
				/// <param name="value"></param>
				/// <returns></returns>
				var isValue = typeof (value) == 'object';
				value = value + '';
				if (value.indexOf(this._decimalSign) > -1) { value = value.replace(this._decimalSign, '|'); }
				if (isValue) { value = value.replace('.', '|'); }
				var re = new RegExp('\\' + this._thousandSeparator, 'gi');
				value = value.replace(re, '');
				value = value.replace('|', '.');
				return this.toNumber(value);
			};

			this.toNumber = function (value)
			{
				/// <summary>
				/// Parses the input to float.
				/// </summary>
				/// <param name="value">Object to parse</param>
				/// <returns>Float</returns>
				return parseFloat(value, 10);
			};

			this.addResolver = function (name, callback)
			{
				/// <summary>
				/// Stig comments missing.
				/// </summary>
				/// <param name="name"></param>
				/// <param name="callback"></param>
				this._resolvers[name] = callback;
			};

			this.addExpression = function (name, expr)
			{
				/// <summary>
				/// Stig comments missing.
				/// </summary>
				/// <param name="name"></param>
				/// <param name="expr"></param>
				this._expressions[name] = expr;
			};

			this.execExpression = function (name, args)
			{
				/// <summary>
				/// Stig comments missing.
				/// </summary>
				/// <param name="name"></param>
				/// <param name="args"></param>
				/// <returns></returns>
				var expr = this._expressions[name];
				var re = new RegExp("{.*?}", "");
				var mf = null;
				var realExpr = expr;
				mf = re.exec(expr);
				while (mf)
				{
					if (args && typeof (args[mf]) != 'undefined')
					{
						realExpr = realExpr.replace(mf, args[mf]);
					}
					else
					{
						var sMf = mf[0];
						var defValue = 0;
						if (mf[0].indexOf(',') > -1)
						{
							sMf = mf[0].split(',')[0] + '}';
							defValue = Number(this.removeFormatting(mf[0].split(',')[1].replace('}', '')));
						}
						var value = 0;
						try
						{
							var resolver = this._resolvers[sMf];
							if (resolver) { value = this.removeFormatting(resolver()); }
							else { value = this.removeFormatting(this.execExpression(sMf.replace('{', '').replace('}', ''))); }
							if (isNaN(value)) { value = defValue; }
						}
						catch (e)
						{
							value = defValue;
						}
						realExpr = realExpr.replace(mf, value);
					}
					var rc = realExpr; //RegExp.rightContext;            
					mf = re.exec(rc);
				}
				return Number(eval(realExpr));
			};

			return this;
		})(),
		urlParser: (function ()
		{
			/// <summary>
			/// Singleton object, with the function Parse, and the collection Parameters.
			/// </summary>
			this.Parameters = [];
			this.IndexedParameters = [];

			this.Parse = function (url)
			{
				/// <summary>
				/// Parses a specified url.
				/// </summary>
				/// <param name="url">The url in question.</param>
				/// <returns>An array containing the url itself, and any key/value pairs.</returns>
				var fractions = url.split('?');
				var qs = fractions.length > 1 ? fractions[1] : "";
				var params = qs.split('&');
				var pset = [];
				for (var i = 0; i < params.length; i++)
				{
					var parts = params[i].split('=');
					var name = parts[0];
					var value = parts[1];
					pset[name] = value;
					pset.length++;
				}
				return pset;
			};

			/// <summary>
			/// Parses the current url.
			/// </summary>
			/// <returns>An array containing the url itself, and any key/value pairs.</returns>
			this.Parameters = this.Parse(location.href);

			for (var i in this.Parameters)
			{
				if (this.Parameters.hasOwnProperty(i))
				{
					var a = { q: i, v: this.Parameters[i] };
					this.IndexedParameters.push(a);
				}
			}

			return this;
		})()
	};

	window.$ts = new _$ts();
	window.loaded = false;
	$ts.addEvent(window, 'load', function () { window.loaded = true; });
})();

if (typeof (Tangora) == 'undefined') { var Tangora = {}; }
Tangora.BroadcastController = $ts.Observer;
Tangora.CalculationLibrary = $ts.mathExpressions;

var LazyLoad = new function ()
{
	/// LazyLoad makes it possible to call functions in external scriptfiles that has not been loaded in DOM, hence allowing load on demand.

	this.WireUp = function (ns, fns, srcs)
	{
		/// <summary>
		/// Parses a specified url.
		/// </summary>
		/// <param name="url">The url in question.</param>
		var nsI = GetNS(ns);
		fns = fns.split(',');
		for (var i = 0; i < fns.length; i++)
		{
			var fn = fns[i];
			nsI[fn] = (function (val) { return function () { return Load(srcs, ns, fns[val], arguments); }; })(i);
		}
	};

	function GetNS(ns)
	{
		if ($ts.exists(ns) && ns !== '')
		{
			var i, nsA = ns.split('.');
			ns = window;
			for (i = 0; i < nsA.length; i++)
			{
				var curNS = nsA[i] + '';
				if (!$ts.exists(ns[curNS])) { ns[curNS] = {}; }
				ns = ns[curNS];
			}
			return ns;
		}
		else { return window; }
	}

	function Load(srcs, ns, fn, args)
	{
		srcs = srcs.split(',');
		for (var i = 0; i < srcs.length; i++)
		{
			eval($ts.ajax({ "url": srcs[i] + buildCode, "async": false, "type": "get" }));
		}

		var nsI = GetNS(ns);
		if (nsI === window) { return eval(fn).apply(nsI, args); }
		else { return nsI[fn].apply(nsI, args); }
	}
};

LazyLoad.WireUp('Tangora.PublicAnimation', 'AnimationEnded,CurrentView,WireupElements,AddAnimationCapabilities,OpacityFade,Resize,ChangeColor,MoveToCenter,Move,StartTimer,Ease,SetOpacity', '/lib/tangora.public.animation.js');
LazyLoad.WireUp('LightBox', 'SetOverlay,SetContents,Show,SetCloseEvents,Close,Init,Open,OpenPageContent', '/lib/lightbox.js');
LazyLoad.WireUp('Tangora.DOM', 'GetType,EnsureElement,CheckElements,MoveElement,CloneElement,GetCollection,GetCollectionByClassName,GetFirstCollectionMember,GetFirstCollectionMemberByClassName,MoveFirstCollectionMember,MoveFirstCollectionMemberByClassName,CloneFirstCollectionMember,CloneFirstCollectionMemberByClassName', '/lib/tslib/tdom.js');
LazyLoad.WireUp('Tangora.Browser', 'GetType,Name,Version,Safari,Gecko,Firefox,Opera,IE', '/lib/tslib/tbrowser.js');
LazyLoad.WireUp('Tangora.Common', 'GetType,DoUnEscape', '/lib/tslib/tcommon.js');
LazyLoad.WireUp('Tangora.ErrorHandler', 'GetType,Silent,ThrowError', '/lib/tslib/terrorhandler.js');
LazyLoad.WireUp(null, 'CancelBubble,TSSetCapture,TSReleaseCapture,TSSetCaptureOnFocus,TSCaptureOnclickHandler,TSCaptureOncontextmenuHandler,TSCaptureKeyHandler,addSaveKeyHandler,saveKeyHandler,CalendarHide,CalendarLoaded,getWindowHeight,getWindowWidth,get_url,TSCA_LoadContentArea,TSCA_Hover,ToLegalNumberString,GetIframeDocument,setCaretToStart,setCaretToEnd,evalExpr,TSGetSelectValues,setWindowStatus,PostFormUsingHTTPReq', '/lib/tslib/ILScriptLazy.js');
LazyLoad.WireUp('Tangora.Common', 'GetType,DoUnEscape', '/lib/tslib/tcommon.js');

//Javascript Punycode converter derived from example in RFC3492.
//This implementation is created by some@domain.name and released into public domain
LazyLoad.WireUp('punycode', 'utf16,decode,encode,ToASCII,ToUnicode,ToSafeASCII', '/lib/tslib/punicode.js');
LazyLoad.WireUp('PagePreview', 'Generate', '/lib/PagePreview.js');

// Dummy scripts that prevents harmless errors, when script files hasn't been
window.showLoginStatus = function () { };

