//=================================================================================================
	var
		isNS         = ( document.layers ? true : false ), 
		isIE         = ( document.all    ? true : false ), 
		isIE6        = ( isIE && window.clientInformation.appVersion.indexOf("MSIE 6") > -1 ), 
		
		server       = document.location.protocol + "//" + document.location.host + "/", 
		
		TDataTypes   = ["dtBoolean", "dtDateTime", "dtDouble", "dtInteger", "dtString", "dtMoney", "dtPercentage", "dtLong", "dtGuid"], 
		dtBoolean    = 0, 
		dtDateTime   = 1, 
		dtDouble     = 2, 
		dtInteger    = 3, 
		dtString     = 4, 
		dtMoney      = 5, 
		dtPercentage = 6, 
		dtLong       = 7, 
		dtGuid       = 8, 
		
		bodyLoaded   = false, 
		image        = document.createElement("IMG"), 
		kaTimer      = setTimeout("keepAlive();", 120000 ), 
		pageSize     = null, 
		winSize      = null, 
		
		lightBoxes   = new TLightBoxes(), 
		messageBox   = new TLightBox("divMessage", 2000, 200, imgBack );
	
	if ( ! window.XMLHttpRequest && window.ActiveXObject ) 
	{
		window.XMLHttpRequest = function() 
		{
			var 
				objects = ["Microsoft.XMLHTTP", "MSXML2.XMLHTTP"], 
				i       = objects.length; 
			
			while ( i-- )
			{
				try 
				{
					return new ActiveXObject( objects[i] );
				}
				catch ( error )
				{
				}
			}
			
			throw new Error("No XML support in this browser.");
		};
	}
	
	if ( !document.getElementByName )
	{
		document.getElementByName = function( name )
		{
			var
				elements = document.getElementsByName( name );
			
			if ( elements.length > 0 )
				return elements[0];
			else
				throw new Error("Element with name \"" + name + "\" not found.");
		}
	}
	
	window.onresize = function anonymous()
		{
			bodyResize( document.body );
		};
//=================================================================================================
var browsers = 
{
	unknown  : 0, 
	IE       : 1, 
	firefox  : 2, 
	netscape : 3, 
	mozilla  : 4, 
	opera    : 5, 
	safari   : 6, 
	chrome   : 7
}
//=================================================================================================
function bodyLoad( sender, printing )
{
	bodyResize( sender );
	
	try
	{
		if ( typeof( document.documentElement ) != "undefined")
			document.documentElement.onscroll = function anonymous()
				{
					bodyScroll( document.documentElement );
				};
	}
	catch ( error )
	{
	}
	
	if ( printing )
	{
		window.print();
		window.close();
	}
	else
	{
		lightBoxes.init();
		
		if ( messageBox.initialized() )
		{
			var
				timeout        = 10000, 
				divMessageText = document.getElementById("divMessageText"), 
				btnClose       = document.getElementById("btnCloseMessage");
			
			messageBox.show();
			
			if ( divMessageText )
			{
				var
					length = String( divMessageText.innerText ).length;
				
				timeout = Math.max( Math.floor( length / 80 * 7000 ), 5000 )
			}
			
			setTimeout("messageBox.hide();", timeout );
			
			if ( btnClose )
			{
				try
				{
					btnClose.focus();
				}
				catch ( e )
				{
				}
			}
		}
		
		if ( typeof( menu ) != "undefined" && menu.Class && menu.Class == "TMenu")
			menu.initialize();
		
		if ( isIE6 )
			checkAnchors();
	}
	
	if ( typeof( doWizards ) != "undefined")
		doWizards();
	
	if ( typeof( customBodyLoad ) != "undefined")
		customBodyLoad( sender );
	
	bodyLoaded = true;
}
//=================================================================================================
function bodyResize( sender )
{
	var
		__asptrace = document.getElementById("__asptrace");
	
	if ( __asptrace )
	{
		__asptrace.style.width    = "12px";
		__asptrace.style.overflow = "hidden";
	}
	
	pageSize = null;
	winSize  = null;
	
	var
		size = getSize( szPage );
	
	lightBoxes.position( size );
	
	if ( __asptrace )
		__asptrace.style.width = size.width + "px";
	
	if ( typeof( customBodyResize ) != "undefined")
		customBodyResize( sender, size );
}
//=================================================================================================
function bodyScroll( sender )
{
	var
		size = getSize( szPage );
	
	lightBoxes.position( size );
	
	if ( typeof( customBodyScroll ) != "undefined")
		customBodyScroll( sender );
}
//=================================================================================================
function clearElement( sender, event )
{
	if ( sender.value == sender.defaultValue )
		sender.value = "";
}
//=================================================================================================
function positionElement( element, offsetTop )
{
	var 
		sender = document.documentElement, 
		top    = (sender.scrollTop + offsetTop), 
		size   = getSize( szWindow );
	
	if ( offsetTop + element.offsetHeight + 20 > size.height )
	{
		top = sender.scrollTop + size.height - element.offsetHeight - 20;
		
		if ( top < sender.scrollTop )
			top = sender.scrollTop;
	}
	
	element.style.top = top + "px";
}
//=================================================================================================
function closeMessage( sender )
{
	var
		form = findForm();
	
	if ( messageBox.initialized() )
		messageBox.hide();
	
	if ( form && frmFormReady )
		frmFormReady( form.ID );
}
//=================================================================================================
function findForm()
{
	if ( document.forms )
	{
		for ( var i = 0; i < document.forms.length; i++ )
		{
			var
				form = document.forms[i], 
				name = String( form.name );
			
			if ( name.startsWith("frmForm_") )
			{
				var
					ID = parseInt( name.split("_")[1] );
				
				form.ID = ID;
				return form;
			}
		}
	}
}
//=================================================================================================
function intInputKeyPress( sender, event )
{
	var
		keys = [8, 9, 13, 45, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
	
	if ( ! keys.contains( event.keyCode ) )
	{
		event.returnValue = false;
		return false;
	}
	else
	{
		event.returnValue = true;
		return true;
	}
}
//=================================================================================================
function floatInputKeyPress( sender, event )
{
	var
		keys = [8, 9, 13, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
	
	if ( ! keys.contains( event.keyCode ) )
	{
		event.returnValue = false;
		return false;
	}
	else if ( event.keyCode == 44 || event.keyCode == 46 )
	{
		if ( sender.value.length == 0 || sender.value.indexOf(".") > -1 || sender.value.indexOf(",") > -1 )
		{
			event.returnValue = false;
			return false;
		}
	}
	else
	{
		event.returnValue = true;
		return true;
	}
}
//=================================================================================================
function datetimeInputKeyPress( sender, event )
{
	var
		format = Date.formatInfo, 
		keys   = [8, 9, 13, 32, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58];
	
	for ( var i = 0; i < format.dateSeparator.length; i++ )
		keys.add( format.dateSeparator.charCodeAt( i ) );
	
	for ( var i = 0; i < format.timeSeparator.length; i++ )
		keys.add( format.timeSeparator.charCodeAt( i ) );
	
	if ( ! keys.contains( event.keyCode ) )
	{
		event.cancelBubble = true;
		event.returnValue  = false;
		return false;
	}
	else
		return true;
}
//=================================================================================================
function dateInputKeyPress( sender, event )
{
	var
		format = Date.formatInfo, 
		keys   = [8, 9, 13, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
	
	for ( var i = 0; i < format.dateSeparator.length; i++ )
		keys.add( format.dateSeparator.charCodeAt( i ) );
	
	if ( ! keys.contains( event.keyCode ) )
	{
		event.cancelBubble = true;
		event.returnValue  = false;
		return false;
	}
	else
		return true;
}
//=================================================================================================
function timeInputKeyPress( sender, event )
{
	var
		format = Date.formatInfo, 
		keys   = [8, 9, 13, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58];
	
	for ( var i = 0; i < format.timeSeparator.length; i++ )
		keys.add( format.timeSeparator.charCodeAt( i ) );
	
	if ( ! keys.contains( event.keyCode ) )
	{
		event.cancelBubble = true;
		event.returnValue  = false;
		return false;
	}
	else
		return true;
}
//=================================================================================================
function checkAnchors()
{
	var
		anchors = document.getElementsByTagName("a");
	
	for ( var i = 0; i < anchors.length; i++ )
	{
		var 
			a = anchors[i];
		
		if ( !a.href )
			a.className = "anchor";
	}
}
//=================================================================================================
function rndString( length ) 
{
	if ( typeof( length ) == "undefined")
		length = 16;
	
	var 
		chars  = "1234567890abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 
		string = "";
	
	for ( var i = 0; i < length; i++ ) 
		string += chars.substr( Math.floor( Math.random() * chars.length ), 1 );
	
	return string;
}
//=================================================================================================
function setStats() 
{
	var
		siteAndCat = "steID=" + steID;
	
	if ( typeof( itmID ) != "undefined")
		siteAndCat += "&itmID=" + itmID;
	else if ( typeof( catID ) != "undefined")
		siteAndCat += "&catID=" + catID;
	
	if ( screen )
		document.writeln("<div id=\"divStats\"><img src=\"misc/setStats.aspx?ColorDepth=" + screen.colorDepth + "&ScreenWidth=" + screen.width + "&ScreenHeight=" + screen.height + "&" + siteAndCat + "\" width=\"1\" height=\"1\" alt=\"stats\" align=\"right\"/></div>");
	else
		document.writeln("<div id=\"divStats\"><img src=\"misc/setStats.aspx?" + siteAndCat + "\" width=\"1\" height=\"1\" alt=\"stats\" align=\"right\"/></div>");
}
//=================================================================================================
function keepAlive() 
{
	if ( kaTimer ) 
		clearTimeout( kaTimer );
	
	document.body.appendChild( image );
	
	image.src = "misc/keepAlive.aspx?str=" + rndString();
	kaTimer   = setTimeout("keepAlive();", 120000 );
}
//=================================================================================================
function resizeFont( sender, event, newSize )
{
	var
		fontSize = getCookie("FontSize");
	
	if ( fontSize )
		fontSize = parseInt( fontSize );
	else
		fontSize = 1;
	
	if ( typeof( newSize ) != "undefined")
		fontSize = newSize;
	else if ( fontSize == 1 )
		fontSize = 3;
	else
		fontSize = 1;
	
	document.body.style.fontSize = 60 + ( fontSize * 10 ) + "%";
	
	setCookie("FontSize", fontSize );
	
	if ( typeof( onFontResize ) != "undefined")
		onFontResize( sender, event, newSize );
	
	return 60 + ( fontSize * 10 );
}
//=================================================================================================
function printItem( itmID ) 
{
	var
		url = new Url().remove("msg"),
		win;
	
	if ( typeof( itmID ) != "undefined")
		url = url.remove("catID").add("itmID", itmID );
	
	win = window.open( url.replacePage("printItem.aspx"), "printItem", "menubar=0,location=0,toolbar=0,scrollbars=0,resizable=0,status=0,width=560,height=470");
	
	if ( win )
		win.focus();
}
//=================================================================================================
function printPage() 
{
	printItem();
}
//=================================================================================================
function sendItem( itmID ) 
{
	var
		url = new Url().remove("msg"),
		win;
	
	win = window.open( url.replacePage("sendItem.aspx"), "sendItem", "menubar=0,location=0,toolbar=0,scrollbars=0,resizable=0,status=0,width=400,height=290");
	
	if ( win )
		win.focus();
}
//=================================================================================================
function editItem( itmID ) 
{
	var 
		url = new Url().remove("msg");
	
	url = url.add("itmID", itmID );
	url = url.add("action", 1 );
	
	document.location.href = url;
}
//=================================================================================================
function displayImage( filename )
{
	var
		file = new Url( filename );
	
	if ( filename.indexOf(".aspx") == -1 )
		file = new Url( "misc/showFile.aspx?File=" + filename );
	
	var 
		url  = new Url().replacePage("misc/showImage.aspx", true ).add("Filename", file.get("Filename") ).add("File", file.get("File") ), 
		win  = window.open( url, "showFile", "menubar=0,location=0,toolbar=0,scrollbars=1,resizable=1,status=1,width=50,height=50,top=25,left=25");
	
	if ( win )
		win.focus();
}
//-------------------------------------------------------------------------------------------------
function resizeWin()
{
	var
		img    = document.getElementById("imgMain"),
		width  = img.offsetWidth, 
		height = img.offsetHeight;
	
	if ( isIE6 )
		window.resizeTo( width + 45, height + 70 );
	else
		window.resizeTo( width + 45, height + 95 );
}
//=================================================================================================
function alertWin( text, name, params )
{
	var
		win = null;
	
	if ( typeof( name ) != "undefined" && typeof( params ) != "undefined")
		win = window.open("", name, params );
	else if ( typeof( name ) != "undefined")
		win = window.open("", name );
	else if ( typeof( params ) != "undefined")
		win = window.open("", "", params );
	else
		win = window.open();
	
	if ( win )
	{
		win.document.open();
		win.document.write( text );
		win.document.close();
	}
}
//=================================================================================================
function frmSendLinkSubmit( sender, event )
{
	var
		edtName  = sender.elements["edtName"],
		edtEmail = sender.elements["edtEmail"];
	
	if ( String( edtName.value ) == "")
	{
		alert( nameEmpty[Languages.current] );
		edtName.focus();
		
		event.returnValue = false;
		return false;
	}
	
	if ( String( edtEmail.value ) == "")
	{
		alert( eMailEmpty[Languages.current] );
		edtEmail.focus();
		
		event.returnValue = false;
		return false;
	}
	
	if ( ! isEmail( edtEmail.value ) )
	{
		alert( eMailInvalid[Languages.current] );
		edtEmail.focus();
		
		event.returnValue = false;
		return false;
	}
	
	return true;
}
//=================================================================================================
function cookieName( name ) 
{
	name = escape( name );
	name = name.replace(/@/gi,  "%40");
	name = name.replace(/\*/gi, "%2A");
	name = name.replace(/-/gi,  "%2D");
	name = name.replace(/_/gi,  "%5F");
	name = name.replace(/\+/gi, "%2B");
	name = name.replace(/\./gi, "%2E");
	name = name.replace(/\//gi, "%2F");
	
	return name;
}
//=================================================================================================
function getCookie( name )
{
	name = cookieName( name );
	
	var 
		value = document.cookie, 
		begin = value.indexOf(" " + name + "=");
	
	if ( begin == -1 )
		begin = value.indexOf( name + "=");
	
	if ( begin == -1 )
		return null;
	
	begin = value.indexOf("=", begin ) + 1;
	
	var 
		end = value.indexOf(";", begin );
	
	if ( end == -1 )
		end = value.length;
	
	return unescape( value.substring( begin, end ) );
}
//=================================================================================================
function removeCookie( name ) 
{
	setCookie( name );
}
//=================================================================================================
function setCookie( name, value, date ) 
{
	name = cookieName( name );
	
	if ( value != null && typeof( value ) != "undefined" && String( value ) != "")
	{
		var 
			expiry = new Date().nextYear();
		
		if ( arguments.length > 2 )
			expiry = date;
		
		if ( expiry == null )
			document.cookie = name + "=" + escape( value ) + "; path=/";
		else
			document.cookie = name + "=" + escape( value ) + "; path=/;expires=" + expiry.toGMTString();
	}
	else
		document.cookie = name + "=; path=/;expires=" + new Date().priorDay().toGMTString();
}
//=================================================================================================
function toggleDisplay( element )
{
	if ( typeof( element ) == "string")
		element = document.getElementById( element );
	
	if ( typeof( element ) == "object")
	{
		if ( element.style.display == "none")
			element.style.display = "";
		else
			element.style.display = "none";
	}
}
//=================================================================================================
var
	checking = false;
//-------------------------------------------------------------------------------------------------
function checkBoxListClick( sender, event, name )
{
	if ( checking )
		return;
	
	checking = true;
	
	var
		checkboxes = document.getElementsByName( name );
	
	if ( sender.id.endsWith("All") )
	{
		for ( var i = 0; i < checkboxes.length; i++ )
			checkboxes[i].checked = sender.checked;
	}
	else
	{
		var
			cbAll = document.getElementById( name + "All");
			
		if ( cbAll )
		{
			var
				allChecked = true;
			
			for ( var i = 0; i < checkboxes.length; i++ )
				if ( ! checkboxes[i].checked )
					allChecked = false;
			
			cbAll.checked = allChecked;
		}
	}
	
	checking = false;
}
//=================================================================================================
function isChildOf( parent, child )
{
	if ( typeof( parent.contains ) != "undefined")
		return parent.contains( child );
	else if ( child == null )
		return false;
	else if ( parent == child )
		return true;
	else
		return isChildOf( parent, child.parentNode );
}
//-------------------------------------------------------------------------------------------------
function isParentOf( child, parent )
{
	return isChildOf( parent, child );
}
//=================================================================================================
TEvent = function( object, event, func )
{
	this.object = object;
	this.event  = event;
	this.func   = func;
}
//-------------------------------------------------------------------------------------------------
TEvent.first  = null;
TEvent.events = [];
//-------------------------------------------------------------------------------------------------
TEvent.unload = function( event )
{
	if ( TEvent.events != null )
	{
		removeEvent( window, "unload", TEvent.first );
		
		for ( var i = 0; i < TEvent.events.length; i++ )
		{
			with ( TEvent.events[i] )
			{
				if ( event != "unload")
					removeEvent( object, event, func );
				
				TEvent.events[i] == null;
			}
		}
		
		TEvent.first  = null;
		TEvent.events = null;
	}
}
//=================================================================================================
function addEvent( object, event, func )
{
	if ( typeof( object ) == "string")
		object = $( object );
	
	if ( typeof( func ) == "string")
		func = new Function("event", func );
	
	if ( object.attachEvent )
	{
		object.attachEvent("on" + event, func );
		
		if ( !TEvent.first )
		{
			TEvent.first = new Function("event", "TEvent.unload( event );");
			window.attachEvent("onunload", TEvent.first );
		}
	}
	else
	{
		object.addEventListener( event, func, false );
		
		if ( !TEvent.first )
		{
			TEvent.first = new Function("event", "TEvent.unload( event );");
			window.addEventListener("unload", TEvent.first, false );
		}
	}
	
	TEvent.events.add( new TEvent( object, event, func ) );
	
	return func;
}
//=================================================================================================
function cancelEvent( event )
{
	event.cancelBubble = true;
	
	if ( typeof( event.preventDefault ) == "function")
		event.preventDefault();
	else if ("returnValue" in event )
		event.returnValue = false;
	
	return false;
}
//=================================================================================================
function createEvent( event )
{
	var
		type = "click";
	
	if ( typeof( event ) == "string")
	{
		type  = event;
		event = null;
	}
	else if ( typeof( event ) != "undefined" && typeof( event.type ) != "undefined")
		type = event.type;
	
	var
		keyCode = event ? event.charCode   || event.keyCode : null, 
		target  = event ? event.srcElement || event.target  : null, 
		retVal  = 
			{
				altKey:        event ? event.altKey        : false,  
				button:        event ? event.button        : null, 
				bookmarks:     event ? event.bookmarks     : [], 
				boundElements: event ? event.boundElements : [], 
				cancelBubble:  event ? event.cancelBubble  : false, 
				clientX:       event ? event.clientX       : 0, 
				clientY:       event ? event.clientY       : 0, 
				ctrlKey:       event ? event.ctrlKey       : false, 
				fromElement:   event ? event.fromElement   : null, 
				keyCode:       event ? keyCode             : 0, 
				offsetX:       event ? event.offsetX       : 0, 
				offsetY:       event ? event.offsetY       : 0, 
				reason:        event ? event.reason        : null, 
				returnValue:   event ? event.returnValue   : true, 
				screenX:       event ? event.screenX       : 0, 
				screenY:       event ? event.screenY       : 0, 
				shiftKey:      event ? event.shiftKey      : false, 
				srcElement:    event ? target              : null, 
				srcFilter:     event ? event.srcFilter     : null, 
				target:        event ? target              : null, 
				toElement:     event ? event.toElement     : null, 
				type:          event ? event.type          : type, 
				x:             event ? event.x             : 0, 
				y:             event ? event.y             : 0
			};
	
	return retVal;
}
//=================================================================================================
function filterEvent( event )
{
	return String( event ).replace( /^function \w+\((event)?\)\s*{\s*((.|\n)*)\s*}/, "$2");
}
//=================================================================================================
function removeEvent( object, event, func )
{
	if ( typeof( object ) == "string")
		object = $( object );
	
	if ( object.detachEvent )
		object.detachEvent("on" + event, func );
	else
		object.removeEventListener( event, func, false );
}
//=================================================================================================
function valueString( value )
{
	var
		retVal = "";
	
	if ( typeof( value ) == "boolean")
	{
		if ( value ) 
			return "true";
		else
			return "false";
	}
	else if ( typeof( value ) == "number")
		return value;
	else if ( typeof( value ) == "string")
		return "\"" + value + "\"";
	else if ( typeof( value ) == "undefined")
		return "undefined";
	else if ( typeof( value ) == "function")
	{
		value = String( value );
		return value.substr( 0, value.indexOf(")") + 1 );
	}
	else if ( typeof( value ) == "object")
	{	
		if ( value == null )
			return "null";
		
		if ( typeof( value.add     ) != "undefined" && 
			  typeof( value.indexOf ) != "undefined" && 
			  typeof( value.clear   ) != "undefined" && 
			  typeof( value.length  ) != "undefined")
		{
			for ( var i = 0; i < value.length; i++ )
				retVal += ", " + valueString( value[i] );
			
			if ( retVal.length )
				return "[" + retVal.substr( 2 ) + "]";
			else
				return "[]";
		}
		
		if ( typeof( value.getFullYear ) != "undefined")
			return "#" + value.formatString("s").replace("T", " ") + "#";
		
		if ( typeof( value.test ) != "undefined")
			return value.toString();
			
		if ( typeof( value.nodeName ) != "undefined")
		{
			var
				name = value.nodeName;
			
			if ( name == "#text" || name == "#cdata")
				return value.nodeName + "[\"" + value.nodeValue + "\"]";
			else if ( typeof( value.attributes ) != "undefined")
			{
				if ( value.attributes )
				{
					for ( var i = 0; i < value.attributes.length; i++ )
					{
						var
							attrib = value.attributes[i];
						
						if ( attrib.nodeValue != "" && attrib.nodeValue != "inherit" && 
							  attrib.nodeValue != null && 
							  !String( attrib.nodeValue ).startsWith("function") )
							retVal += " " + attrib.nodeName + "=\"" + attrib.nodeValue + "\"";
					}
				}
				
				if ( typeof( value.nodeType ) != "undefined" && value.nodeType == 2 )
					return "@" + name + "= \"" + value.nodeValue + "\"";
				else
					return "<" + name + retVal + "/>";
			}
			else if ( typeof ( value.location ) != "undefined")
				return "window" + ( window.name ? "[\"" + value.name + "\"]" : "");
			else
				return "<" + name.toLowerCase() + 
						( value.id ? " id=\"" + value.id + "\"" : "") + 
						( value.className ? " class=\"" + value.className + "\"" : "") + "/>";
		}
		
		if ( typeof( value.Class ) != "undefined")
		{
			var
				className = value.Class;
			
			if ( className == "Point")
				return "Point(" + value.left + ", " + value.top + ")";
			else if ( className == "Size")
				return "Size(" + value.width + ", " + value.height + ")";
			else if ( className == "Url")
				return "Url(\"" + value.toString() + "\")";
			else if ( className == "Rgb")
				return "Rgb(" + value.red + ", " + value.green + ", " + value.blue + ") {\"" + value.toHex() + "\"}";
			else if ( className == "TWizard" || className == "TTable" || className == "TColumn")
			{
				if ( typeof( value.owner ) == "undefined")
					return className + "(\"" + value.name + "\")";
				else
					return valueString( value.owner ) + "." + className + "(\"" + value.name + "\")";
			}
			else if ( className == "TField")
				return valueString( value.owner.owner ) + ".TRow[" + value.owner.index + "]"  + "." + className + "(\"" + value.name + "\")";
			else if ( className == "TMenuItem")
				return className + "[" + value.id + "]";
			else if ( typeof( value.ID ) != "undefined")
				return className + "[" + valueString( value.ID ) + "]";
			else
				return className;
		}
		
		if ( typeof( value.toString ) != "undefined")
			return value.toString().replace( /^\[object( [^\]]+)\]$/gi, "$1");
		
		if ( typeof( value.srcElement ) != "undefined" || typeof( value.target ) != "undefined")
		{
			if ( typeof( value.type ) != "undefined")
				return "event[type = " + value.type + "]";
			else
				return "event";
		}
		
		try
		{
			return String( value );
		}
		catch ( error )
		{
			return "unhandled type: \"" + typeof( value ) + "\". String( value ): " + error;
		}
	}
	else
		return "unhandled type: \"" + typeof( value ) + "\"";
}
//=================================================================================================
function parseBool( value )
{
	var
		toInt = parseInt( value );
	
	if ( String( value ).substr( 0, 4 ).toLowerCase() == "true" || (!isNaN( toInt ) && toInt != 0) )
		return true;
	else if ( String( value ).substr( 0, 5 ).toUpperCase() == "false" || (!isNaN( toInt ) && toInt == 0) )
		return false;
	else 
		return null;
}
//=================================================================================================
function isSame( value1, value2, type )
{
	if ( typeof( type ) == "undefined")
	{
		var
			type1 = typeof( value1 ), 
			type2 = typeof( value2 );
		
		if ( type1 == type2 )
		{
			if ( value1 == null && value2 == null )
				return true;
			else if ( value1 == null || value2 == null )
				return false;
			
			if ( typeof( value1.Class ) != "undefined" && typeof( value2.Class ) != "undefined")
				if ( value1.Class == value2.Class )
					return value1 == value2;
			
			return value1.toString() == value2.toString();
		}
		else
			return false;
	}
	else
	{
		try
		{
			var
				value1 = convert( value1, type ), 
				value2 = convert( value2, type );
			
			return this.isSame( value1, value2 );
		}
		catch ( error )
		{
		}
	}
	
	return false;
}
//-------------------------------------------------------------------------------------------------
function convert( value, type )
{
	if ( value == null || String( value ) == "")
		return null;
	
	switch ( type )
	{
		case dtBoolean:
			if ( String( value ).toLowerCase() == "false" || String( value ) == "0") 
				return false;
			else
				return true;
		case dtDateTime:
			var
				datetime = isDateTime( value );
			
			if ( datetime != false )
				return datetime;
			else
			{
				datetime = parseXmlDate( value );
				
				if ( !isNaN( datetime ) )
					return datetime;
				else
					throw new Error( getIllegalDateMessage() );
			}
		case dtPercentage:
			if ( String( value ).endsWith("%") )
				value = String( value ).substr( 0, String( value ).length - 1 );
		case dtDouble:
		case dtMoney:
			if ( typeof( value ) != "number")
			{
				var
					format = Number.formatInfo;
				
				value = String( value ).replace( new RegExp("\\" + format.groupingSeparator, "gi"), "");
				value = value.replace( format.currencySymbol, "");
				value = value.trim();
				value = value.replace( new RegExp("\\" + format.decimalSeparator, "gi"), ".");
			}
			
			if ( ! isNumeric( value ) )
			{
				var
					message = getMessage( 17 );
				
				if ( message )
					throw new Error( message.text );
				else
					throw new Error("De ingevoerde waarde is niet correct. Er wordt een getal verwacht.");
			}
			
			return parseFloat( value );
		case dtInteger:
		case dtLong:
			if ( ! String( value ).match( /\d{1,10}/gi ) )
			{
				var
					message = getMessage( 16 );
				
				if ( message )
					throw new Error( message.text );
				else
					throw new Error("De ingevoerde waarde is niet correct. Er wordt een geheel getal verwacht.");
			}
			
			return parseInt( value );
		case dtString:
		case dtGuid:
			return String( value );
		default:
			throw new Error("Illegal assignment to parameter \"type\" (" + type + ").");
	}
}
//=================================================================================================
function getBackColor( element )
{
	if ( typeof( element ) == "string")
		element = $(element);
	
	var
		color = Element.getStyle( element, "background-color");
	
	if ( element.parentNode != null )
		if ( color == "transparent" || color.startsWith("rgba(0, 0, 0, 0)") )
			color = getBackColor( element.parentNode );
	
	return color;
}
//=================================================================================================
function getColor( element )
{
	if ( typeof( element ) == "string")
		element = $(element);
	
	var
		color = Element.getStyle( element, "color");
	
	if ( color == "transparent" || color.startsWith("rgba(0, 0, 0, 0)") )
	{
		if ( element.parentNode != null )
			return getColor( element.parentNode );
		else
			return color;
	}
	else
		return color;
}
//=================================================================================================
function rgbToHex( color )
{
	if ( isIE )
		return color.replace("#", "");
	else
	{
		if ( color.startsWith("rgb(") )
		{
			color = color.substr( 4 );
			color = color.substr( 0, color.length - 1 );
			color = color.split(", ");
		}
		
		return toHex( color[0] ) + toHex( color[1] ) + toHex( color[2] );
	}
}
//=================================================================================================
function twoDigit( value )
{
	if ( value.length == 1 )
		return "0" + value;
	else
		return value;
}
//=================================================================================================
Rgb = function( red, green, blue )
{
	this.Class = "Rgb";
	
	if ( red == "transparent")
	{
		this.red         = 128;
		this.green       = 128;
		this.blue        = 128;
		this.transparent = true;
	}
	else
	{
		if ( typeof( red   ) == "undefined" || red   == null )
			red   = 255;
		
		if ( typeof( green ) == "undefined" || green == null )
			green = 255;
		
		if ( typeof( blue  ) == "undefined" || blue  == null )
			blue  = 255;
		
		this.red         = red;
		this.green       = green;
		this.blue        = blue;
		this.transparent = false;
	}
}
//-------------------------------------------------------------------------------------------------
Rgb.prototype.lighter = function( percentage )
{
	if ( this.transparent )
		return this;
	
	if ( typeof( percentage ) == "undefined")
		percentage = 5.0;
	
	var
		red   = Math.round( this.red   * (100.0 + percentage) / 100.0 ), 
		green = Math.round( this.green * (100.0 + percentage) / 100.0 ), 
		blue  = Math.round( this.blue  * (100.0 + percentage) / 100.0 );
	
	return new Rgb( Math.min(red, 255), Math.min(green, 255), Math.min(blue, 255) );
}
//-------------------------------------------------------------------------------------------------
Rgb.prototype.darker = function( percentage )
{
	if ( this.transparent )
		return this;
	
	if ( typeof( percentage ) == "undefined")
		percentage = 5.0;
	
	var
		red   = Math.round( this.red   * (100.0 - percentage) / 100.0 ), 
		green = Math.round( this.green * (100.0 - percentage) / 100.0 ), 
		blue  = Math.round( this.blue  * (100.0 - percentage) / 100.0 );
	
	return new Rgb( red, green, blue );
}
//-------------------------------------------------------------------------------------------------
Rgb.prototype.toHex = function()
{
	if ( this.transparent )
		return "";
	else
		return twoDigit( toHex( this.red ) ) + twoDigit( toHex( this.green ) ) + twoDigit( toHex( this.blue ) );
}
//-------------------------------------------------------------------------------------------------
Rgb.prototype.toString = function()
{
	if ( this.transparent )
		return "transparent";
	else
		return "#" + this.toHex();
}
//=================================================================================================
function hexToRgb( color )
{
	if ( color == "transparent" || color == null )
		return new Rgb("transparent");
	
	if ( color.startsWith("0x") )
		color = color.substr( 2 );
	
	if ( color.startsWith("#") )
		color = color.substr( 1 );
	
	color = color.toUpperCase();
	
	var
		red, green, blue;
	
	if ( color.length == 6 )
	{
		red   = hexToNum( color.substr( 0, 2 ) ); 
		green = hexToNum( color.substr( 2, 2 ) ); 
		blue  = hexToNum( color.substr( 4, 2 ) );
	}
	else if ( color.length == 3 )
	{
		red   = hexToNum( color.substr( 0, 1 ) + color.substr( 0, 1 ) ); 
		green = hexToNum( color.substr( 1, 1 ) + color.substr( 1, 1 ) ); 
		blue  = hexToNum( color.substr( 2, 1 ) + color.substr( 2, 1 ) );
	}
	else
		throw new Error(
				"Illegal call to hexToRgb( color ) (\"" + color + "\"). Parameter 'color' is " + 
				"expected to be \'transparent\' or a hexadecimal value in the formats '0xE0FFA8', " + 
				"'0xFFF', '#EF9090', '#888', 'A8CEF3' or 'FFF'.");
	
	return new Rgb( red, green, blue );
}
//=================================================================================================
function hexToNum( hex, weight )
{
	if ( typeof( weight ) == "undefined")
		weight = 1;
	
	var
		digit = hex.substr( hex.length - 1 ).toUpperCase();
	
	if ( hex.length > 1 )
		return hexToNum( hex.substr( 0, hex.length - 1 ), weight * 16 ) + hexToNum( digit, weight );
	
	switch ( digit )
	{
		case "A":
			return 10 * weight;
		case "B":
			return 11 * weight;
		case "C":
			return 12 * weight;
		case "D":
			return 13 * weight;
		case "E":
			return 14 * weight;
		case "F":
			return 15 * weight;
		default:
			return parseInt( digit ) * weight;
	}
}
//=================================================================================================
function toHex( number )
{
	if ( typeof( number ) != "number")
		throw new Error(
				"Illegal call to toHex( number ) (\"" + number + "\"). Parameter 'number' is not " + 
				"a number.");
	
	if ( number < 10 )
		return String( number );
	
	switch ( number )
	{
		case 10:
			return "A";
		case 11:
			return "B";
		case 12:
			return "C";
		case 13:
			return "D";
		case 14:
			return "E";
		case 15:
			return "F";
	}
	
	return toHex( Math.floor( number / 16 ) ) + toHex( number % 16 );
}
//=================================================================================================
function fillOut( value )
{
	if ( Number( value ) < 10 )
		return "0" + String( value );
	else
		return String( value );
}
//=================================================================================================
function isEmail( address ) 
{
	var
		expr = new RegExp("^([\\w-\\.]+)@([\\w-]+(\\.[\\w-]+)*)\\.((com)|(edu)|(gov)|(info)|(lan)|(mil)|(net)|(org)|(\\w{2,2}))$", "gi");
	
	return expr.test( address );
}
//=================================================================================================
function isURL( address ) 
{
	return Url.isUrl( address );
}
//=================================================================================================
function flashString( value )
{
	value = value.replace( /\%/g,     "%25");
	value = value.replace( /\&amp;/g, "%26");
	value = value.replace( /\&/g,     "%26");
	value = value.replace( /\+/g,     "%2B");
	
	return value;
}
//=================================================================================================
function withZeros( floatStr, floatNum )
{
	var
		pre  = "",
		post = "",
		expr = new RegExp("^-?\\d+(\\.\\d+)?$", "gi");
	
	if ( !expr.test( floatStr ) )
		return false;
	
	if ( floatStr.startsWith("-") )
	{
		floatStr = floatStr.substr( 1 );
		pre      = "-";
	}
	
	if ( floatStr.indexOf(".") > -1 )
	{
		while ( floatStr.endsWith("0") )
			floatStr = floatStr.substr( 0, floatStr.length - 1 );
		
		if ( floatStr.endsWith(".") )
			floatStr = floatStr.substr( 0, floatStr.length - 1 );
	}
	
	if ( floatStr.startsWith("0") )
	{
		while ( floatStr.startsWith("0") )
			floatStr = floatStr.substr( 1 );
		
		if ( floatStr.startsWith(".") )
			floatStr = "0" + floatStr;
		
		if ( floatStr.length == 0 )
			floatStr = "0";
	}
	
	return parseFloat( pre + floatStr ) == floatNum;
}
//-------------------------------------------------------------------------------------------------
function isNumeric( value )
{
	value = new String( value );
	
	if ( value.indexOf(",") > -1 && value.indexOf(".") > -1 )
	{
		if ( value.indexOf(",") > value.indexOf(".") )
			value = value.replace(/\./gi, "");
		else if ( value.indexOf(",") < value.indexOf(".") )
			value = value.replace(/\,/gi, "");
	}
	
	value = value.replace(/\,/gi, ".");
	
	return withZeros( value, parseFloat( value ) );
}
//=================================================================================================
function toNumber( value )
{
	if ( value.indexOf(",") > -1 && value.indexOf(".") > -1 )
	{
		if ( value.indexOf(",") > value.indexOf(".") )
			value = value.replace(/\./gi, "");
		else if ( value.indexOf(",") < value.indexOf(".") )
			value = value.replace(/\,/gi, "");
	}
	
	value = value.replace(/\,/gi, ".");
	
	return parseFloat( value );
}
//=================================================================================================
function filterHeaders( html )
{
	html = html.replace( /\t*<\![^>]+>(\r\n)?/gi, "");
	html = html.replace( /\t*<\/?html[^>]*>(\r\n)?/gi, "");
	
	if ( html.indexOf("<img id=\"imgBack") > -1 )
	{
		html = html.split("\r\n");
		
		for ( var i = 0; i < html.length; i++ )
		{
			if ( !html[i].trim().startsWith("<img id=\"imgBack\"") )
				html[i] = "";
			else
			{
				html[i] = "";
				i = html.length;
			}
		}

		html = html.join("\r\n").trimEnd().trimStart("\r\n");
	}
	
	html = html.replace( /\t*<\/body>(\r\n)?/gi, "");
	
	return html;
}
//-------------------------------------------------------------------------------------------------
function getHtml( element, url )
{
	if ( element && typeof( element.innerHTML ) != "undefined")
	{
		if ( typeof( url.request ) == "undefined")
			url = new Url( url );
		
		url = url.add("rnd", rndString() );
		
		var
			retVal = url.request();
		
		if ( (String( retVal ).trim() != "" && retVal == false) || String( retVal ).toLowerCase() == "false")
			return false;
		
		element.innerHTML = filterHeaders( retVal );
		return true;
	}
	else
		throw new Error("Illegal call to getHtml( element, url ). Parameter \"element\" is not a valid Html object.");
}
//=================================================================================================
function htmlSize( element )
{
	if ( typeof( element ) == "string")
		element = $( element );
	
	if ( typeof( element ) == "undefined" || element == null )
		throw new Error(
				"Illegal argument. First argument is undefined or element not found (" + 
				valueString( element ) + ").");
	
	element.size = new Size
			( 
				element.offsetWidth - 
				measure( element, "margin-left") - 
				measure( element, "border-left-width") - 
				measure( element, "padding-left") - 
				measure( element, "padding-right") - 
				measure( element, "border-right-width") - 
				measure( element, "margin-right"), 
				element.offsetHeight - 
				measure( element, "margin-top") - 
				measure( element, "border-top-width") - 
				measure( element, "padding-top") - 
				measure( element, "padding-bottom") - 
				measure( element, "border-bottom-width") - 
				measure( element, "margin-bottom")
			);
	
	return element.size;
}
//=================================================================================================
function isScrolling( element )
{
	if ( typeof( element ) == "undefined" || element == null )
		return false;
	else
	{
		var
			overflow = Element.getStyle( element, "overflow");
		
		if ( isIE && Element.getStyle( element, "overflowY") != "hidden")
			overflow = "auto";
		
		if ( element.offsetHeight < element.scrollHeight && overflow != "hidden")
			return true;
		else 
			return false;
	}
}
//=================================================================================================
function xFind( element, xPath )
{
	var
		path = String( xPath ).toLowerCase().split("/");
	
	for ( var i = 0; i < path.length && element != null; i++ )
	{
		var
			found = null, 
			name  = (path[i].contains("[") ? path[i].split("[")[0]     : path[i]),
			pos   = (path[i].contains("[") ? path[i].split(/[\[\]]/)[1]: 1);
		
		for ( var k = 0; k < element.childNodes.length && pos && found == null; k++ )
		{
			var
				child = element.childNodes[k];
			
			if ( child.nodeType == 1 && (name == "*" || child.tagName.toLowerCase() == name) )
			{
				pos--;
				
				if ( pos == 0 )
					found = child;
			}
		}
		
		element = found;
	}
	
	return element;
}
//=================================================================================================
function getParent( element, count )
{
	if ( typeof( element ) == "string")
		element = $( element );
	
	if ( typeof( count ) == "undefined")
		count = 1;
	
	while ( element && count-- )
		element = element.parentNode;
	
	return element;	
}
//=================================================================================================
var
	szPage   = 1, 
	szWindow = 2;
//-------------------------------------------------------------------------------------------------
function getSize( which )
{
	if ( document.body )
	{
		if ( pageSize == null || winSize == null )
		{
			var
				windowWidth, 
				windowHeight, 
				xScroll, 
				yScroll;
			
			if ( window.innerHeight && window.scrollMaxY )
			{
				xScroll = document.body.scrollWidth;
				yScroll = window.innerHeight + window.scrollMaxY;
			}
			else if ( document.body.scrollHeight > document.body.offsetHeight )
			{
				xScroll = document.body.scrollWidth;
				yScroll = document.body.scrollHeight;
			}
			else
			{
				xScroll = document.body.offsetWidth;
				yScroll = document.body.offsetHeight;
			}
			
			if ( self.innerHeight )
			{
				windowWidth  = self.innerWidth;
				windowHeight = self.innerHeight;
			}
			else if ( document.documentElement && document.documentElement.clientHeight )
			{
				windowWidth  = document.documentElement.clientWidth;
				windowHeight = document.documentElement.clientHeight;
			}
			else if ( document.body )
			{
				windowWidth  = document.body.clientWidth;
				windowHeight = document.body.clientHeight;
			}
			
			if ( yScroll < windowHeight )
				pageHeight = windowHeight;
			else
				pageHeight = yScroll;
			
			if ( xScroll < windowWidth )
			{
				pageWidth = windowWidth;
				
				if ( yScroll > windowHeight )
					pageWidth -= 18;
			}
			else
				pageWidth = xScroll;
			
			pageSize = new Size( pageWidth, pageHeight );
			winSize  = new Size( windowWidth, windowHeight );
		}
	}
	else
		return null;
	
	switch ( which )
	{
		case szPage:
			return pageSize;
			break;
		case szWindow:
			return winSize;
			break;
		default:
			return [pageSize, winSize];
			break;
	}
}
//=================================================================================================
function measure( element, style )
{
	if ( style == null || style == "")
		return 0;
	
	style = String( style );
	
	var
		distance = Element.getStyle( element, style ), 
		value    = parseFloat( distance ), 
		pixels   = 0;
	
	if ( isNaN( value ) )
		value = 0;
	
	if ( String( distance ).endsWith("%") )
		pixels = Math.round( element.offsetWidth * value / 100, 0 );
	else if ( String( distance ).endsWith("px") )
		pixels = value;
	
	return pixels;
}
//=================================================================================================
function getLeft( sender )
{
	if ( sender && sender != document.body )
	{
		var
			pos = Element.getStyle( sender, "position");
		
		if ( pos == "absolute" || pos == "relative")
			return sender.offsetLeft;
		else 
			return sender.offsetLeft + getLeft( sender.offsetParent ) - sender.scrollLeft;
	}
	else if ( sender && browser == browsers.IE && sender == document.body )
		return measure( document.body, "margin-left");
	else
		return 0;
}
//-------------------------------------------------------------------------------------------------
function getTop( sender )
{
	if ( sender && sender != document.body )
	{
		var
			pos = Element.getStyle( sender, "position");
		
		if ( pos == "absolute" || pos == "relative")
			return sender.offsetTop;
		else
			return sender.offsetTop + getTop( sender.offsetParent ) - sender.scrollTop;
	}
	else if ( sender && browser == browsers.IE && sender == document.body )
		return measure( document.body, "margin-top");
	else
		return 0;
}
//-------------------------------------------------------------------------------------------------
function getPos( sender )
{
	return new Point( getLeft( sender ), getTop( sender ) );
}
//=================================================================================================
//	Size & Position classes.
//=================================================================================================
Point = function( left, top )
{
	this.Class = "Point";
	
	if ( typeof( left ) != "undefined")
		this.left = left;
	else
		this.left = 0;
	
	if ( typeof( top ) != "undefined")
		this.top = top;
	else
		this.top = 0;
}
//-------------------------------------------------------------------------------------------------
Point.prototype.toString = function()
{
	return "Point(" + this.left + ", " + this.top + ")";
}
//=================================================================================================
Size = function( width, height )
{
	this.Class = "Size";
	
	if ( typeof( width ) != "undefined")
		this.width = width;
	else
		this.width = 0;
	
	if ( typeof( height ) != "undefined")
		this.height = height;
	else
		this.height = 0;
}
//-------------------------------------------------------------------------------------------------
Size.prototype.toString = function()
{
	return "Size(" + this.width + ", " + this.height + ")";
}
//=================================================================================================
//	Array extensions.
//=================================================================================================
Array.isArray = function( value )
{
	if ( value == null )
		return false;
	
	return
			typeof( value.length )   == "number"   && 
			typeof( value.remove )   == "function" && 
			typeof( value.contains ) == "function";
}
//-------------------------------------------------------------------------------------------------
Array.prototype.add = function( value )
{
	var
		index = this.length;
	
	this[this.length] = value;
	
	return index;
}
//-------------------------------------------------------------------------------------------------
Array.prototype.clear = function( value )
{
	this.length = 0;
}
//-------------------------------------------------------------------------------------------------
Array.prototype.contains = function( value )
{
	for ( var i = 0; i < this.length; i++ )
	{
		if ( value != null && typeof( value.age ) == "function")
		{
			if ( value.isSameDate( this[i] ) )
				return true;
		}
		
		if ( this[i] == value ) 
			return true;
	}
	
	return false;
}
//-------------------------------------------------------------------------------------------------
Array.prototype.insert = function( index, value )
{
	if ( index < 0 )
		throw new Error("Illegal argument. Index out of range (" + index + ").");
	
	if ( index > this.length )
		index = this.length;
	
	for ( var i = this.length; i > index; i-- )
		this[i] = this[i - 1];
	
	this[index] = value;
}
//-------------------------------------------------------------------------------------------------
Array.prototype.insertAfter = function( value, element )
{
	var
		index = this.indexOf( element );
	
	if ( index == -1 )
		throw new Error("Illegal argument. Given element is not contained by the array.");
	
	this.insert( index + 1, value );
}
//-------------------------------------------------------------------------------------------------
Array.prototype.insertBefore = function( value, element )
{
	var
		index = this.indexOf( element );
	
	if ( index == -1 )
		throw new Error("Illegal argument. Given element is not contained by the array.");
	
	this.insert( index, value );
}
//-------------------------------------------------------------------------------------------------
Array.prototype.indexOf = function( value )
{
	for ( var i = 0; i < this.length; i++ )
	{
		if ( typeof( value.age ) == "function")
		{
			if ( value.isSameDate( this[i] ) )
				return i;
		}
		
		if ( this[i] == value ) 
			return i;
	}
	
	return -1;
}
//-------------------------------------------------------------------------------------------------
Array.prototype.remove = function( index )
{
	if ( typeof( index ) == "number")
	{
		for ( var i = index; i < this.length - 1; i++ )
			this[i] = this[i + 1];
		
		this.length--;
	}
	else
	{
		index = this.indexOf( index );
		
		if ( index > -1 )
			this.remove( index );
		else
			throw new Error("Illegal argument. Given element is not contained by the array.");
	}
	
	return;
}
//=================================================================================================
//	Number extensions
//=================================================================================================
NumberFormat = function( DecimalSeparator, GroupingSeparator, CurrencySymbol )
{
	this.decimalSeparator  = DecimalSeparator;
	this.groupingSeparator = GroupingSeparator;
	this.currencySymbol    = CurrencySymbol;
}
//=================================================================================================
Number.prototype.fillOut = function( length )
{
	if ( isNaN( this ) || !isFinite( this ) )
		return String( this );
	
	if ( typeof( length ) == "undefined")
		length = 2;
	
	var
		number = String( this );
	
	while ( number.length < length )
		number = "0" + number;
	
	return number;
}
//=================================================================================================
Number.prototype.formatString = function( format )
{
	if ( format == "C" || format == "c")
		return this.formatString( Number.formatInfo.currencySymbol + " ,##0.00");
	else if ( format == "D" || format == "d")
		return this.formatString( "0");
	else if ( format == "N" || format == "n")
		return this.formatString( ",##0.00");
	else if ( format == "P" || format == "p")
		return this.formatString( ",##0.00%");
	else if ( format == null || format == "" || typeof( format ) == "undefined")
		return String( this ).replace(".", Number.formatInfo.decimalSeparator );
	else
		format = String( format );
	
	var
		number   = String( this ), 
		old      = format, 
		split    = number.split( /\./gi ),
		grouping = format.indexOf(",") > -1,
		minus    = this < 0;
	
	format = format.replace( /,/gi, "");
	format = format.split( /\./gi );
	
	if ( format[0].match( /0#/gi ) )
		throw new Error("Illegal format in call to \"formatString\". '#' encountered after '0' and before the decimal separator.");
	
	if ( format.length > 1 && format[1].match( /#0/gi ) )
		throw new Error("Illegal format in call to \"formatString\". '#' encountered before '0' and after the decimal separator.");
	
	if ( format.length > 2 )
		throw new Error("Illegal format in call to \"formatString\". Multiple use of decimal separator.");
	
	if ( ! old.endsWith(".") )
	{
		if ( format.length == 1 )
			split = String( Math.round( number ) ).split(".");
		else if ( format[1].length > 0 )
		{
			var
				len = format[1].search( /[^#0]/g );
			
			if ( len == -1 )
				len = format[1].length;
			
			split = String( Math.round( number * Math.pow( 10, len ) ) / Math.pow( 10, len ) ).split(".");
		}
	}
	
	if ( minus )
		number = split[0].substr( 1 );
	else
		number = split[0];
	
	var
		zeros = format[0].replace( /^[^0]*(0+)/gi, "$1");
	
	if ( zeros.length > number.length )
		number = zeros.substr( 0, zeros.length - number.length ) + number;
	
	if ( grouping )
	{
		var
			nr     = number, 
			number = "";
		
		for ( var i = nr.length - 1; i >= 0; i -= 3 )
		{
			if ( i - 2 >= 0 )
				number = Number.formatInfo.groupingSeparator + nr.substr( i - 2, 3 ) + number;
			else
				number = nr.substr( 0, i + 1 ) + number;
		}
		
		if ( number.startsWith(".") )
			number = number.substr( 1 );
	}
	
	var
		pos = format[0].search( /[0#,\.]/ );
	
	if ( pos > 0 )
		number = format[0].substr( 0, pos ) + number;
	
	if ( format.length > 1 )
	{
		number += Number.formatInfo.decimalSeparator;
		
		if ( split.length > 1 )
		{
			number += split[1];
			
			if ( format.length > 1 )
			{
				var
					numbers = format[1].replace( /([#0])/g, "$1");
				
				if ( numbers.length > split[1].length )
					number += numbers.substr( numbers.length - split[1].length );
				
				var
					start = Math.min( split[1].length, format[1].search( /[^#0]/g ) );
				
				if ( start > -1 )
					number += format[1].substr( start );
			}
		}
		else if ( format.length > 1 )
			number += format[1];
	}
	
	number = number.replace( /#/gi, "");
	
	if ( number.endsWith( Number.formatInfo.decimalSeparator ) )
		number = number.substr( 0, number.length - 1 );
	
	return minus ? "-" + number : number;
}
//=================================================================================================
//	RegExp extensions.
//=================================================================================================
RegExp.escape = function( value )
{
	if ( value == null || value == "" || typeof( value ) == "undefined")
		return "";
	
	value = String( value );
	
	value = value.replace( /\\/g, "\\\\");
	value = value.replace( /\./g, "\\.");
	value = value.replace( /\^/g, "\\^");
	value = value.replace( /\$/g, "\\$");
	value = value.replace( /\?/g, "\\?");
	value = value.replace( /\*/g, "\\*");
	value = value.replace( /\+/g, "\\+");
	value = value.replace( /\|/g, "\\|");
	value = value.replace( /\(/g, "\\(");
	value = value.replace( /\)/g, "\\)");
	value = value.replace( /\{/g, "\\{");
	value = value.replace( /\}/g, "\\}");
	value = value.replace( /\[/g, "\\[");
	value = value.replace( /\]/g, "\\]");
	
	return value;
}
//-------------------------------------------------------------------------------------------------
var regExp = 
{
	escape : function( value )
	{
		return RegExp.escape( value );
	}
}
//=================================================================================================
//	String extensions.
//=================================================================================================
String.prototype.coalesce = function()
{
	if ( this != "" )
		return this;
	
	for ( var i = 0; i < arguments.length; i++ )
		if ( arguments[i] )
			return arguments[i];
	
	return "";
}
//-------------------------------------------------------------------------------------------------
String.prototype.contains = function()
{
	for ( var i = 0; i < arguments.length; i++ )
		if ( this.indexOf( arguments[i] ) > -1 )
			return true;
	
	return false;
}
//-------------------------------------------------------------------------------------------------
String.prototype.endsWith = function( text )
{
	return (this.substr( this.length - text.length ) == new String( text ));
}
//-------------------------------------------------------------------------------------------------
String.prototype.htmlEncode = function()
{
	var
		text = String( this );
	
	if ( ! text )
		text = "";
	
	text = text.replace( /\&/gi, "&amp;");
	
	for ( var i = 0; i < charCodes.length; i++ )
	{
		var
			code = charCodes[i], 
			html = specialChar[code - 160];
		
		text = text.replace( new RegExp( String.fromCharCode( code ), "g"), html );
	}
	
	text = text.replace( /\"/gi, "&quot;");
	text = text.replace( /\</gi, "&lt;");
	text = text.replace( /\>/gi, "&gt;");
	
	return text;
}
//-------------------------------------------------------------------------------------------------
String.prototype.indent = function( tabs )
{
	var
		chars = "\r\n";
	
	if ( typeof( tabs ) == "undefined")
		tabs = 1;
	
	for ( var i = 0; i < tabs; i++ )
		chars += "\t";
	
	return this.replace( /\r\n(\t*<)/gi, chars + "$1");
}
//-------------------------------------------------------------------------------------------------
String.prototype.innerTrim = function()
{
	var
		value = new String( this );
	
	while ( value.contains("  ") )
		value = value.replace( / {2}/gi, " ");
	
	return value;
}
//-------------------------------------------------------------------------------------------------
String.prototype.insert = function( index, text )
{
	var
		value = new String( this );
	
	if ( index > 0 )
		value = this.substr( 0, index );
	
	value += text;
	
	if ( index < this.length )
		value += this.substr( index, this.length - index );
	
	return value;
}
//-------------------------------------------------------------------------------------------------
String.prototype.lowerFirst = function()
{
	return this.substr(0, 1).toLowerCase() + this.substr(1);
}
//-------------------------------------------------------------------------------------------------
String.prototype.shortenLeft = function( count )
{
	return this.substr( count );
}
//-------------------------------------------------------------------------------------------------
String.prototype.shortenRight = function( count )
{
	return this.substr( 0, this.length - count );
}
//-------------------------------------------------------------------------------------------------
String.prototype.startsWith = function( text )
{
	return (this.substr( 0, text.length ) == new String( text ));
}
//-------------------------------------------------------------------------------------------------
String.prototype.toJs = function()
{
	var
		value = this.replace( /\\/gi, "\\\\");
	
	value = value.replace( /\"/gi, "\\\"");
	value = value.replace( /\r/gi, "\\r");
	value = value.replace( /\n/gi, "\\n");
	value = value.replace( /\t/gi, "\\t");
	
	return "\"" + value + "\"";
}
//-------------------------------------------------------------------------------------------------
String.prototype.trim = function( chars ) 
{
	var
		value = new String( this );

	if ( arguments.length == 0 )
	{
		value = value.replace( /^\s*/gi, "");
		value = value.replace( /\s*$/gi, "");
	}
	else
	{
		var
			start = new RegExp("^[" + RegExp.escape( chars ) + "]*", "gi"), 
			end   = new RegExp("[" + RegExp.escape( chars ) + "]*$", "gi");
		
		value = value.replace( start, "");
		value = value.replace( end,   "");
	}
	
	return value;
}
//-------------------------------------------------------------------------------------------------
String.prototype.trimEnd = function( chars )
{
	var
		value = new String( this );
	
	if ( typeof( chars ) == "undefined")
		value = value.replace( /\s*$/gi, "");
	else
		value = value.replace( new RegExp("[" + RegExp.escape( chars ) + "]*$", "gi"), "");
	
	return value;
}
//-------------------------------------------------------------------------------------------------
String.prototype.trimStart = function( chars )
{
	var
		value = new String( this );
	
	if ( typeof( chars ) == "undefined")
		value = value.replace( /^\s*/gi, "");
	else
		value = value.replace( new RegExp("^[" + RegExp.escape( chars ) + "]*", "gi"), "");
	
	return value;
}
//-------------------------------------------------------------------------------------------------
String.prototype.unindent = function( tabs )
{
	var
		chars = "\r\n";
	
	if ( typeof( tabs ) == "undefined")
		tabs = 1;
	
	for ( var i = 0; i < tabs; i++ )
		chars += "\t";
	
	return this.replace( new RegExp( chars ), "\r\n");
}
//-------------------------------------------------------------------------------------------------
String.prototype.upperFirst = function()
{
	return this.substr(0, 1).toUpperCase() + this.substr(1);
}
//=================================================================================================
TUser = function( ID, fullname, username, eMail )
{
	this.Class    = "TUser";
	this.ID       = ID;
	this.fullname = fullname;
	this.username = username;
	this.eMail    = eMail;
}
//-------------------------------------------------------------------------------------------------
TUser.prototype.toJS = function()
{
	var
		retVal = "new TUser( " + 
			valueString( this.ID ) + ", " + valueString( this.fullname ) + ", " + 
			valueString( this.username ) + ", " + valueString( this.eMail ) + ")";
	
	return retVal;
}
//-------------------------------------------------------------------------------------------------
TUser.prototype.toXML = function( root )
{
	if ( typeof( root ) == "undefined")
		root = "user";
	
	var
		retVal = "\r\n<" + root;
	
	if ( String( this.ID ) != "null")
		retVal += " ID=\"" + this.ID + "\"";
	
	retVal += ">";
	
	if ( this.fullname )
		retVal += "\r\n\t<fullname>" + this.fullname + "</fullname>";
	
	if ( this.username )
		retVal += "\r\n\t<username>" + this.username + "</username>";
	
	if ( this.eMail )
		retVal += "\r\n\t<eMail>" + this.eMail + "</eMail>";
	
	retVal += "\r\n</" + root + ">";
	
	return retVal;
}
//=================================================================================================
//	Url class
//=================================================================================================
Url = function( url )
{
	var
		FUrl = null;
	
	this.Class              = "Url";
	this.disposed           = false;
	this.HTTP               = null;
	this.onreadystagechange = null;
	this.index              = Url.all.add( this );
	
	if ( typeof( url ) == "undefined")
		FUrl = String( document.location );
	else
		FUrl = url.replace( /\&amp;/gi, "&");
	
	if ( Url.unload == null )
		Url.unload = addEvent( window, "unload", "Url.dispose();");
	
	//----------------------------------------------------------------
	this.url = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FUrl;
		else
			FUrl = value;
	}
	//----------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------
Url.prototype.add = function( key, value )
{
	var
		url = this.url();
	
	if ( value == null || typeof( value ) == "undefined")
		return this.remove( key );
	else
	{
		if ( typeof( value.age ) != "undefined")
			value = value.formatString("g?");
		
		value = encodeURI( value ).replace( /[&]/gi, "%26");

		if ( url.search( new RegExp("([\?&])(" + key + "=[^&]*)", "gi") ) > -1 )
			url = url.replace( new RegExp("([\?&])(" + key + "=[^&]*)", "gi"), "$1" + key + "=" + value );
		else if ( url.indexOf("?") > -1 )
			url = url + "&" + key + "=" + value;
		else
			url = url + "?" + key + "=" + value;
	}
	
	return new Url( url );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.async = function( method, xml )
{
	if ( this.onreadystatechange != null && typeof( this.onreadystatechange ) != "function")
		throw new Error("Illegal assignment to Url.onreadystatechange. Property is not a function.");
	
	if ( typeof( method ) == "undefined")
		method = "GET";
	
	if ( typeof( xml ) == "undefined")
		xml = null;
	
	this.HTTP = new XMLHttpRequest();
	
	if ( this.onreadystatechange != null )
		this.HTTP.onreadystatechange = new Function("Url.all[" + this.index + "].loaded();");
	
	this.HTTP.open( method.toUpperCase(), this.add("rnd", rndString() ) );
	this.HTTP.setRequestHeader("snakeware-ajax", "true");
	
	if ( method.toUpperCase() == "POST")
		this.HTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		
	this.HTTP.send( xml );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.current = function()
{
	return new Url( String( document.location ) );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.dispose = function()
{
	if ( !this.disposed )
	{
		this.HTTP               = null;
		this.onreadystagechange = null;
		this.disposed           = true;
	}
}
//-------------------------------------------------------------------------------------------------
Url.prototype.get = function( key )
{
	var
		url   = this.url(),
		value = url.replace( new RegExp(".*[\?&]" + key + "=([^&]*).*", "gi"), "$1");
	
	if ( value == url )
		value = null;
	else
		value = decodeURI( value ).replace( /%26/gi, "&");
	
	return value;
}
//-------------------------------------------------------------------------------------------------
Url.prototype.filter = function()
{
	var
		url = new Url( this.url() );
	
	for ( var i = 0; i < arguments.length; i++ )
		url = url.remove( arguments[i] );
	
	return url;
}
//-------------------------------------------------------------------------------------------------
Url.prototype.loaded = function()
{
	if ( this.HTTP.readyState == 4 )
		this.onreadystatechange( this.HTTP );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.page = function()
{
	var
		page = this.url().replace( new RegExp( Url.regex ), "$4");
	
	if ( page == "")
		page = null;
	
	return page;
}
//-------------------------------------------------------------------------------------------------
Url.prototype.remove = function( key )
{
	var
		url = this.url();
	
	url = url.replace( new RegExp("([\?&])" + key + "=[^&]*", "gi"), "$1");
	
	url = url.replace( /\?&/gi, "?");
	url = url.replace( /&&/gi, "&");
	url = url.replace( /&$/gi, "");
	url = url.replace( /\?$/gi, "");
	
	return new Url( url );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.removeServer = function()
{
	var
		server = this.server();
	
	if ( server != null )
		return new Url( this.url().replace( server, "") );
	else
		return new Url( this.url() );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.replacePage = function( value, noRewrite )
{
	var
		rewrite = rewriting, 
		url     = this.url(),
		page    = this.page();
	
	if ( typeof( noRewrite ) == "undefined")
		noRewrite = false;
	
	if ( noRewrite )
		rewrite = false;
	
	if ( (page != null && page.endsWith(".aspx")) || !rewrite )
	{
		if ( page == null )
		{
			url  = url.replace( new RegExp( Url.regex ), "$1/" + value + "$9");
			url  = url.replace( "//" + value, "/" + value );
			
			if ( url.startsWith("/" + value ) )
				url = url.substr( 1 );
			
			return new Url( url );
		}
		
		return new Url( url.replace( page, value ) );
	}
	else
		return this.add("use", value.replace(".aspx", "") );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.request = function( method, xml, getXml, showError )
{
	if ( typeof( method ) == "undefined")
		method = "GET";
	
	if ( typeof( xml ) == "undefined")
		xml = null;
	
	if ( typeof( getXml ) == "undefined")
		getXml = false;
	
	var
		HTTP = new XMLHttpRequest();
	
	HTTP.open( method.toUpperCase(), this.add("rnd", rndString() ), false );
	HTTP.setRequestHeader("snakeware-ajax", "true");
	
	if ( method.toUpperCase() == "POST")
		HTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		
	HTTP.send( xml );
	
	if ( HTTP.status == 200 )
	{
		if ( getXml )
			return HTTP.responseXML;
		else
			return HTTP.responseText;
	}
	else
	{
		if ( showError || typeof( showError ) == "undefined")
			this.showError( HTTP );
		
		return false;
	}
}
//-------------------------------------------------------------------------------------------------
Url.prototype.server = function()
{
	var
		server = this.url().replace( new RegExp( Url.regex ), "$1");
	
	if ( server == "")
		server = null;
	
	return server;
}
//-------------------------------------------------------------------------------------------------
Url.prototype.showError = function( HTTP )
{
	if ( this.HTTP != null && typeof( HTTP ) == "undefined")
		HTTP = this.HTTP;
	
	alertWin( HTTP.responseText );
}
//-------------------------------------------------------------------------------------------------
Url.prototype.toString = function()
{
	return this.url();
}
//-------------------------------------------------------------------------------------------------
Url.all      = [];
Url.current  = new Url();
Url.disposed = false;
Url.regex    = /^(https?:\/\/(localhost(\:\d+)?\/)?[^\/\?]+[\/]?)?(([^\/\.]+\/)*([^\.\?]+(\.(as[ph]x?|html?|php?))?)?)?(\?.*)?$/gi;
Url.unload   = null;
Url.valid    = new RegExp("^(?:http://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)(?:/(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;:@&=])*)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;:@&=])*))*)(?:\\?(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;:@&=])*))?)?)|(?:ftp://(?:(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?&=])*)(?::(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?&=])*))?@)?(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?))(?:/(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*))*)(?:;type=[AIDaid])?)?)|(?:news:(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;/?:&=])+@(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3})))|(?:[a-zA-Z](?:[a-zA-Z\\d]|[_.+-])*)|\\*))|(?:nntp://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)/(?:[a-zA-Z](?:[a-zA-Z\\d]|[_.+-])*)(?:/(?:\\d+))?)|(?:telnet://(?:(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?&=])*)(?::(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?&=])*))?@)?(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?))/?)|(?:gopher://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)(?:/(?:[a-zA-Z\\d$\\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\\d]{2}))(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\\d]{2}))*)(?:%09(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;:@&=])*)(?:%09(?:(?:[a-zA-Z\\d$\\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\\d]{2}))*))?)?)?)?)|(?:wais://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)/(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*)(?:(?:/(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*)/(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*))|\\?(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;:@&=])*))?)|(?:mailto:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\\d]{2}))+))|(?:file://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))|localhost)?/(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*))*))|(?:prospero://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)/(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&=])*))*)(?:(?:;(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&])*)=(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[?:@&])*)))*)|(?:ldap://(?:(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?))?/(?:(?:(?:(?:(?:(?:(?:[a-zA-Z\\d]|%(?:3\\d|[46][a-fA-F\\d]|[57][Aa\\d]))|(?:%20))+|(?:OID|oid)\\.(?:(?:\\d+)(?:\\.(?:\\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*))(?:(?:(?:%0[Aa])?(?:%20)*)\\+(?:(?:%0[Aa])?(?:%20)*)(?:(?:(?:(?:(?:[a-zA-Z\\d]|%(?:3\\d|[46][a-fA-F\\d]|[57][Aa\\d]))|(?:%20))+|(?:OID|oid)\\.(?:(?:\\d+)(?:\\.(?:\\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*)))*)(?:(?:(?:(?:%0[Aa])?(?:%20)*)(?:[;,])(?:(?:%0[Aa])?(?:%20)*))(?:(?:(?:(?:(?:(?:[a-zA-Z\\d]|%(?:3\\d|[46][a-fA-F\\d]|[57][Aa\\d]))|(?:%20))+|(?:OID|oid)\\.(?:(?:\\d+)(?:\\.(?:\\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*))(?:(?:(?:%0[Aa])?(?:%20)*)\\+(?:(?:%0[Aa])?(?:%20)*)(?:(?:(?:(?:(?:[a-zA-Z\\d]|%(?:3\\d|[46][a-fA-F\\d]|[57][Aa\\d]))|(?:%20))+|(?:OID|oid)\\.(?:(?:\\d+)(?:\\.(?:\\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))*)))*))*(?:(?:(?:%0[Aa])?(?:%20)*)(?:[;,])(?:(?:%0[Aa])?(?:%20)*))?)(?:\\?(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+)(?:,(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+))*)?)(?:\\?(?:base|one|sub)(?:\\?(?:((?:[a-zA-Z\\d$\\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\\d]{2}))+)))?)?)?)|(?:(?:z39\\.50[rs])://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+)(?:\\+(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+))*(?:\\?(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+))?)?(?:;esn=(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+))?(?:;rs=(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+)(?:\\+(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))+))*)?))|(?:cid:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?:@&=])*))|(?:mid:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[;?:@&=])*))?)|(?:vemmi://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)(?:/(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[/?:@&=])*)(?:(?:;(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[/?:@&])*)=(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[/?:@&])*))*))?)|(?:imap://(?:(?:(?:(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~])+)(?:(?:;[Aa][Uu][Tt][Hh]=(?:\\*|(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~])+))))?)|(?:(?:;[Aa][Uu][Tt][Hh]=(?:\\*|(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~])+)))(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~])+))?))@)?(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?))/(?:(?:(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~:@/])+)?;[Tt][Yy][Pp][Ee]=(?:[Ll](?:[Ii][Ss][Tt]|[Ss][Uu][Bb])))|(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~:@/])+)(?:\\?(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~:@/])+))?(?:(?:;[Uu][Ii][Dd][Vv][Aa][Ll][Ii][Dd][Ii][Tt][Yy]=(?:[1-9]\\d*)))?)|(?:(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~:@/])+)(?:(?:;[Uu][Ii][Dd][Vv][Aa][Ll][Ii][Dd][Ii][Tt][Yy]=(?:[1-9]\\d*)))?(?:/;[Uu][Ii][Dd]=(?:[1-9]\\d*))(?:(?:/;[Ss][Ee][Cc][Tt][Ii][Oo][Nn]=(?:(?:(?:[a-zA-Z\\d$\\-_.+!*'(),]|(?:%[a-fA-F\\d]{2}))|[&=~:@/])+)))?)))?)|(?:nfs:(?:(?://(?:(?:(?:(?:(?:[a-zA-Z\\d](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\\d]|-)*[a-zA-Z\\d])?))|(?:(?:\\d+)(?:\\.(?:\\d+)){3}))(?::(?:\\d+))?)(?:(?:/(?:(?:(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*))*)?)))?)|(?:/(?:(?:(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*))*)?))|(?:(?:(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\\d\\$\\-_.!~*'(),])|(?:%[a-fA-F\\d]{2})|[:@&=+])*))*)?)))$", "gi");
//-------------------------------------------------------------------------------------------------
Url.dispose  = function()
{
	if ( !Url.disposed )
	{
		for ( var i = 0; i < Url.all.length; i++ )
		{
			Url.all[i].dispose();
			Url.all[i] = null;
		}
		
		Url.all      = [];
		Url.disposed = true;
		Url.regex    = null;
	}
}
//-------------------------------------------------------------------------------------------------
Url.isUrl = function( obj )
{
	var
		url = 
			(
				obj != null && 
				typeof( obj ) == "object" && 
				typeof( obj.Class ) != "undefined" && 
				obj.Class == "Url"
			);
	return url;
}
//-------------------------------------------------------------------------------------------------
Url.isValid = function( url )
{
	if ( url == null )
		return false;
	
	if ( Url.isUrl( url ) )
		url = url.toString();
	
	return Url.valid.test( url );
}
//=================================================================================================