//=================================================================================================
var
	TWeekDay     = ["wdSunday", "wdMonday", "wdTuesday", "wdWednesday", "wdThursday", "wdFriday", "wdSaturday"], 
	wdSunday     = 0, 
	wdMonday     = 1, 
	wdTuesday    = 2, 
	wdWednesday  = 3, 
	wdThursday   = 4, 
	wdFriday     = 5, 
	wdSaturday   = 6;
//=================================================================================================
DateTimeFormat = function( DateSeparator, LongDatePattern, ShortDatePattern, TimeSeparator, LongTimePattern, ShortTimePattern, FirstDay )
{
	this.dateSeparator    = DateSeparator;
	this.longDatePattern  = LongDatePattern;
	this.shortDatePattern = ShortDatePattern;
	
	this.timeSeparator    = TimeSeparator;
	this.longTimePattern  = LongTimePattern;
	this.shortTimePattern = ShortTimePattern;
	this.firstDay         = FirstDay;
}
//-------------------------------------------------------------------------------------------------
DateTimeFormat.prototype.getDateDisplayPattern = function()
{
	var
		pattern = this.shortDatePattern;
	
	pattern = pattern.split("'");
	
	for ( var i = 1; i < pattern.length; i++ )
		pattern[i] = "";
	
	pattern = pattern.join("");
	pattern = pattern.replace( new RegExp("[^dmy" + regExp.escape( this.dateSeparator ) + "]", "gi"), "").trim();
	
	return pattern;
}
//-------------------------------------------------------------------------------------------------
DateTimeFormat.prototype.getTimeDisplayPattern = function()
{
	var
		pattern = this.shortTimePattern;
	
	pattern = pattern.split("'");
	
	for ( var i = 1; i < pattern.length; i++ )
		pattern[i] = "";
	
	pattern = pattern.join("");
	pattern = pattern.replace( new RegExp("[^hnst" + regExp.escape( this.timeSeparator ) + "]", "gi"), "").trim();
	
	return pattern;
}
//=================================================================================================
//	Date extensions.
//=================================================================================================
Date.prototype.addDays = function( days )
{
	var
		date = new Date( this );
	
	date.setDate( this.getDate() + days );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.addHours = function( hours )
{
	var
		date = new Date( this );
	
	date.setHours( this.getHours() + hours );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.addMinutes = function( minutes )
{
	var
		date = new Date( this );
	
	date.setMinutes( this.getMinutes() + minutes );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.addMonths = function( months )
{
	var
		date = new Date( this );
	
	date.setMonths( this.getMonths() + months );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.addSeconds = function( seconds )
{
	var
		date = new Date( this );
	
	date.setSeconds( this.getSeconds() + seconds );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.addYears = function( years )
{
	var
		date = new Date( this );
	
	date.setFullYear( this.getFullYear() + years );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.age = function()
{
	var
		date  = new Date(),
		years = date.getFullYear() - this.getFullYear();
	
	if ( date.getMonth() < this.getMonth() || 
			( date.getMonth() == this.getMonth() && date.getDate() < this.getDate() ) )
		years--;
	
	return years;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.daysInMonth = function()
{
	switch ( this.getMonth() + 1 )
	{
		case 4:	//	april
		case 6:	//	juni
		case 9:	//	september
		case 11:	//	november
			return 30;
		case 2:
			return ( this.isLeapYear() ? 29 : 28 );
		default:
			return 31;
	}
}
//-------------------------------------------------------------------------------------------------
Date.prototype.formatString = function( format )
{
	var
		date = String( format );
	
	if ( format == null || format == "" || typeof( format ) == "undefined")
		date = Date.formatInfo.shortDatePattern + " " + Date.formatInfo.shortTimePattern;
	else if ( format == "s")	//	Xml date pattern
		date = "yyyy-mm-ddTHH:nn:ss";
	else if ( format == "d")	//	short date pattern
		date = Date.formatInfo.shortDatePattern;
	else if ( format == "D")	//	long date pattern
		date = Date.formatInfo.longDatePattern;
	else if ( format == "t")	//	short time pattern
		date = Date.formatInfo.shortTimePattern;
	else if ( format == "T")	//	long time pattern
		date = Date.formatInfo.longTimePattern;
	else if ( format == "f?")	//	full date/optional short time pattern
	{
		if ( this.getHours() == 0 && this.getMinutes() == 0 )
			date = Date.formatInfo.longDatePattern;
		else
			date = Date.formatInfo.longDatePattern + " " + Date.formatInfo.shortTimePattern;
	}
	else if ( format == "f")	//	full date/short time pattern
		date = Date.formatInfo.longDatePattern + " " + Date.formatInfo.shortTimePattern;
	else if ( format == "F?")	//	full date/optional long time pattern
	{
		if ( this.getHours() == 0 && this.getMinutes() == 0 && this.getSeconds() == 0 )
			date = Date.formatInfo.longDatePattern;
		else
			date = Date.formatInfo.longDatePattern + " " + Date.formatInfo.longTimePattern;
	}
	else if ( format == "F")	//	full date/long time pattern
		date = Date.formatInfo.longDatePattern + " " + Date.formatInfo.longTimePattern;
	else if ( format == "g?")	//	short date/optional short time pattern
	{
		if ( this.getHours() == 0 && this.getMinutes() == 0 )
			date = Date.formatInfo.shortDatePattern;
		else
			date = Date.formatInfo.shortDatePattern + " " + Date.formatInfo.shortTimePattern;
	}
	else if ( format == "g")	//	short date/short time pattern
		date = Date.formatInfo.shortDatePattern + " " + Date.formatInfo.shortTimePattern;
	else if ( format == "G?")	//	short date/optional long time pattern
	{
		if ( this.getHours() == 0 && this.getMinutes() == 0 && this.getSeconds() == 0 )
			date = Date.formatInfo.shortDatePattern;
		else
			date = Date.formatInfo.shortDatePattern + " " + Date.formatInfo.longTimePattern;
	}
	else if ( format == "G")	//	short date/long time pattern
		date = Date.formatInfo.shortDatePattern + " " + Date.formatInfo.longTimePattern;
	
	date = date.replace( /\%/g, "");
	date = date.replace( /\//g, Date.formatInfo.dateSeparator );
	date = date.replace( /-/g,  Date.formatInfo.dateSeparator );
	date = date.replace( /:/g,  Date.formatInfo.timeSeparator );
	
	//	year formats 
	date = date.replace( /yyyy/gi, this.getFullYear() );
	
	if ( date.toLowerCase().indexOf("yyy") > -1 ) 
		throw new Error("Illegal yearformat \"yyy\".");
	
	date = date.replace( /yy/gi, new String( this.getFullYear() ).substr( 2 ) );
	
	// month formats 
	date = date.replace( /^mm$/gi,                  fillOut( this.getMonth() + 1 )       );
	date = date.replace( /^mm([^m])/gi,             fillOut( this.getMonth() + 1 ) + "$1");
	date = date.replace( /([^m])mm$/gi,      "$1" + fillOut( this.getMonth() + 1 )       );
	date = date.replace( /([^m])mm([^m])/gi, "$1" + fillOut( this.getMonth() + 1 ) + "$2");
	date = date.replace( /^m$/gi,                   ( this.getMonth() + 1 )       );
	date = date.replace( /^m([^m])/gi,              ( this.getMonth() + 1 ) + "$1");
	date = date.replace( /([^m])m$/gi,       "$1" + ( this.getMonth() + 1 )       );
	date = date.replace( /([^m])m([^m])/gi,  "$1" + ( this.getMonth() + 1 ) + "$2");
	
	// day formats 
	date = date.replace( /^dd$/gi,                  fillOut( this.getDate() )       );
	date = date.replace( /^dd([^d])/gi,             fillOut( this.getDate() ) + "$1");
	date = date.replace( /([^d])dd$/gi,      "$1" + fillOut( this.getDate() )       );
	date = date.replace( /([^d])dd([^d])/gi, "$1" + fillOut( this.getDate() ) + "$2");
	date = date.replace( /^d$/gi,                   this.getDate()       );
	date = date.replace( /^d([^d])/gi,              this.getDate() + "$1");
	date = date.replace( /([^d])d$/gi,       "$1" + this.getDate()       );
	date = date.replace( /([^d])d([^d])/gi,  "$1" + this.getDate() + "$2");
	
	// hour formats 
	if ( this.getHours() > 12 )
	{
		date = date.replace( /hh/g, fillOut( this.getHours() - 12 ) );
		date = date.replace( /h/g, this.getHours() - 12 );
	}
	else if ( this.getHours() == 0 )
	{
		date = date.replace( /hh/g, "12");
		date = date.replace( /h/g, "12");
	}
	else
	{
		date = date.replace( /hh/g, fillOut( this.getHours() ) );
		date = date.replace( /h/g, this.getHours() );
	}
	
	date = date.replace( /HH/g, fillOut( this.getHours() ) );
	date = date.replace( /H/g, this.getHours() );
	
	// minute formats 
	date = date.replace( /nn/gi, fillOut( this.getMinutes() ) );
	date = date.replace( /n/gi, this.getMinutes() );
	
	// second formats 
	date = date.replace( /ss/gi, fillOut( this.getSeconds() ) );
	date = date.replace( /s/gi, this.getSeconds() );
	
	// AM/PM
	if ( this.getHours() < 12 )
	{
		date = date.replace( /tt/g, "AM");
		date = date.replace( /t/g, "A");
	}
	else
	{
		date = date.replace( /tt/g, "PM");
		date = date.replace( /t/g, "P");
	}
	
	// month formats 
	date = date.replace( /mmmm/gi, months[this.getMonth()] );
	date = date.replace( /mmm/gi, months[this.getMonth()].substr( 0, 3 ) );
	
	// day formats 
	date = date.replace( /dddd/gi, days[this.getDay()] );
	date = date.replace( /ddd/gi, days[this.getDay()].substr( 0, 2 ) );
	
	if ( format == "s")
	{
		// Xml date pattern: date separator = '-' and time separator = ':'...
		if ( this.dateSeparator != "-")
			date = date.replace( new RegExp( regExp.escape( Date.formatInfo.dateSeparator ), "gi"), "-");
		
		if ( this.timeSeparator != ":")
			date = date.replace( new RegExp( regExp.escape( Date.formatInfo.timeSeparator ), "gi"), ":");
	}
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.integrateDate = function( date )
{
	var
		time = new Date( this );
	
	time.setFullYear( date.getFullYear() );
	time.setMonth( date.getMonth() );
	time.setDate( date.getDate() );
	
	return time;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.integrateTime = function( time )
{
	var
		date = new Date( this );
	
	date.setHours( time.getHours() );
	date.setMinutes( time.getMinutes() );
	date.setSeconds( time.getSeconds() );
	date.setMilliseconds( time.getMilliseconds() );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.isLeapYear = function()
{
	var
		year = this.getFullYear();
	
	if ( year % 4 == 0 && (year % 100 || year % 1000 == 0) )
		return true;
	else
		return false;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.isSameDate = function( date )
{
	return (
			this.getDate()     == date.getDate() && 
			this.getMonth()    == date.getMonth() && 
			this.getFullYear() == date.getFullYear() );
}
//-------------------------------------------------------------------------------------------------
Date.prototype.isSameTime = function( date )
{
	return (
			this.getSeconds() == date.getSeconds() && 
			this.getMinutes() == date.getMinutes() && 
			this.getHours()   == date.getHours() );
}
//-------------------------------------------------------------------------------------------------
Date.prototype.jsDate = function()
{
	return ("new Date(" + 
				this.getFullYear() + ", " + this.getMonth() + ", " + this.getDate() + ", " + 
				this.getHours() + ", " + this.getMinutes() + ", " + this.getSeconds() + ", " + 
				this.getMilliseconds() + ")");
}
//-------------------------------------------------------------------------------------------------
Date.prototype.nextDay = function( count )
{
	if ( ! count )
		count = 1;
	
	var
		date = new Date( this );
	
	if ( date.getDate() + count <= date.daysInMonth() )
		date.setDate( date.getDate() + count );
	else if ( date.getMonth() < 11 )
	{
		date.setDate( date.getDate() + count - date.daysInMonth() );
		date.setMonth( date.getMonth() + 1 );
	}
	else
	{
		date.setDate( date.getDate() + count - date.daysInMonth() );
		date.setYear( date.getFullYear() + 1 );
		date.setMonth( 0 );
	}
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.nextMonth = function()
{
	var
		date = new Date( this );
	
	if ( date.getMonth() < 11 )
	{
		date.setMonth( date.getMonth() + 1 );
		
		while ( date.getMonth() > this.getMonth() + 1 )
			date = date.priorDay();
	}
	else
	{
		date.setMonth( 0 );
		date.setYear( date.getFullYear() + 1 );
	}
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.nextWeek = function()
{
	return this.nextDay( 7 );
}
//-------------------------------------------------------------------------------------------------
Date.prototype.nextYear = function( count )
{
	if ( ! count )
		count = 1;
	
	var
		date = new Date( this );
	
	date.setYear( date.getFullYear() + count );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.priorDay = function( count )
{
	if ( ! count )
		count = 1;
	
	var
		date = new Date( this );
	
	if ( date.getDate() - count >= 1 )
		date.setDate( date.getDate() - count );
	else if ( date.getMonth() > 0 )
	{
		date.setMonth( date.getMonth() - 1 );
		date.setDate( date.daysInMonth() - count + date.getDate() );
	}
	else
	{
		date.setYear( date.getFullYear() - 1 );
		date.setMonth( 11 );
		date.setDate( date.daysInMonth() - count + date.getDate() );
	}
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.priorWeek = function()
{
	return this.priorDay( 7 );
}
//-------------------------------------------------------------------------------------------------
Date.prototype.priorMonth = function()
{
	var
		date = new Date( this );
	
	if ( date.getMonth() > 0 )
	{
		date.setMonth( date.getMonth() - 1 );
		
		while ( date.getMonth() == this.getMonth() )
			date = date.priorDay();
	}
	else
	{
		date.setMonth( 11 );
		date.setYear( date.getFullYear() - 1 );
	}
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.priorYear = function( count )
{
	if ( ! count )
		count = 1;
	
	var
		date = new Date( this );
	
	date.setYear( date.getFullYear() - count );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.round = function()
{
	var
		date = new Date( this );
	
	date.setHours( 0 );
	date.setMinutes( 0 );
	date.setSeconds( 0 );
	date.setMilliseconds( 0 );
	
	return date;
}
//-------------------------------------------------------------------------------------------------
Date.prototype.weekNo = function()
{
	var
		year  = this.getFullYear(), 
		month = this.getMonth() + 1, 
		day   = this.getDate() + Date.formatInfo.firstDay;
	
	var
		a    = Math.floor( (14 - month) / 12 ), 
		y    = year + 4800 - a, 
		m    = month + 12 * a - 3, 
		b    = Math.floor( y / 4 ) - Math.floor( y / 100 ) + Math.floor( y / 400 ), 
		J    = day + Math.floor( (153 * m + 2) / 5 ) + 365 * y + b - 32045, 
		d4   = (J + 31741 - (J % 7)) % 146097 % 36524 % 1461, 
		L    = Math.floor( d4 / 1460 ), 
		d1   = ( (d4 - L) % 365 ) + L, 
		week = Math.floor( d1 / 7 ) + 1;
	
	return week;
}
//-------------------------------------------------------------------------------------------------
Date.isDate = function( value )
{
	return isDate( value );
}
//-------------------------------------------------------------------------------------------------
Date.isDateTime = function( value )
{
	return isDateTime( value );
}
//-------------------------------------------------------------------------------------------------
Date.isTime = function( value )
{
	return isTime( value );
}
//=================================================================================================
//	class TDateInput
//=================================================================================================
var
	dateInputs = [];
//-------------------------------------------------------------------------------------------------
TDateInput = function( name, element, button, allowTime, block, date )
{
	var
		FBlock    = block, 
		FButton   = button, 
		FDataUrl  = null, 
		FDate     = ( date ? new Date( date ) : null ), 
		FFilled   = [], 
		FElement  = element, 
		FIndex    = dateInputs.length, 
		FMaxDate  = new Date( 9999, 11, 31, 23, 59, 59 ), 
		FMinDate  = new Date( 1753,  0,  1 ), 
		FName     = name, 
		FShowDate = ( FDate ? FDate : new Date() );
	
	this.allowTime      = allowTime;
	this.blockedMessage = blockedMessage[Languages.current];
	this.Class          = "TDateInput";
	this.doHide         = true;
	this.maxDateMessage = maxDateMessage[Languages.current];
	this.minDateMessage = minDateMessage[Languages.current];
	this.onchange       = null;
	this.settingDate    = false;
	this.timer          = 0;
	
	if ( typeof( name ) == "undefined" || String( name ).length == 0 )
		throw new Error("Illegal call to constructor. \"name\" cannot be empty.");
	
	if ( typeof( allowTime ) == "undefined")
		allowTime = false;
	
	if ( typeof( element ) == "undefined")
		throw new Error("Illegal call to constructor. \"element\" cannot be empty.");
	
	if ( typeof( button ) == "undefined")
		throw new Error("Illegal call to constructor. \"button\" cannot be empty.");
	
	if ( ! FBlock )
		FBlock = [];
	else if ( ! FBlock.contains )
		throw new Error("Illegal call to constructor. \"block\" should be an array of Date.");
	
	for ( var i = 0; i < FBlock.length; i++ )
		if ( typeof( FBlock[i].age ) != "function")
			throw new Error("Illegal call to constructor. \"block\" contains elements which are not of type Date.");
		else
			FBlock[i] = FBlock[i].round();
	
	dateInputs[dateInputs.length] = this;
	
	this.div                   = document.createElement("DIV");
	this.div.id                = "div" + name.upperFirst();
	this.div.style.display     = "none";
	this.div.style.background  = "white";
	this.div.style.border      = "1px solid black";
	this.div.style.color       = "black";
	this.div.style.display     = "block";
	this.div.style.padding     = "0px";
	this.div.style.position    = "absolute";
	this.div.onmouseover       = new Function("event", "dateInputs[" + FIndex + "].stopHide( this );");
	this.div.onmouseout        = new Function("event", "dateInputs[" + FIndex + "].hide( this );");
	
	if ( isIE )
	{
		this.frame                 = document.createElement("IFRAME");
		this.frame.id              = "frm" + name.upperFirst();
		this.frame.src             = "misc/empty.htm";
		this.frame.style.visiblity = "hidden";
		this.frame.style.position  = "absolute";
		this.frame.style.border    = "0px solid";
		this.frame.onmouseover     = new Function("event", "dateInputs[" + FIndex + "].stopHide( this );");
		this.frame.onmouseout      = new Function("event", "dateInputs[" + FIndex + "].hide( this );");
	}
	
	if ( !bodyLoaded )
		addEvent( window, "load", "dateInputs[" + FIndex + "].init( event );");
	
	//----------------------------------------------------------------
	this.blocked = function( date )
	{
		for ( var i = 0; i < FBlock.length; i++ )
		{
			if ( FBlock[i].isSameDate( date ) )
				return true;
		}
		
		return false;
	}
	//----------------------------------------------------------------
	this.pButton = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FButton;
		else
			FButton = document.getElementById( value );
	}
	//----------------------------------------------------------------
	this.pClearFilled = function()
	{
		FFilled = [];
	}
	//----------------------------------------------------------------
	this.pDataUrl = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FDataUrl;
		else if ( typeof( value.Class ) != "undefined" && value.Class == "Url")
			FDataUrl = value;
		else
			FDataUrl = new Url( value );
		
		if ( typeof( FElement ) == "string")
			this.getData();
	}
	//----------------------------------------------------------------
	this.pDate = function( value, event, doHide )
	{
		if ( typeof( value ) == "undefined")
			return FDate;
		
		if ( this.settingDate )
			return;
		
		this.settingDate = true;
		
		if ( value != null )
		{
			if ( typeof( value.isLeapYear ) == "undefined")
				throw new Error("Illegal assignment to date. Value is not a date object and not null (\"" + valueString( value ) + "\").");
			
			if ( ! this.allowTime )
				value = value.round();
			
			if ( value >= FMaxDate )
				throw new Error( this.maxDateMessage.replace("[MAXDATE]", FMaxDate.formatString("d") ) );
			
			if ( value < FMinDate )
				throw new Error( this.minDateMessage.replace("[MINDATE]", FMinDate.formatString("d") ) );
			
			if ( this.blocked( value.round() ) )
				throw new Error( this.blockedMessage.replace("[DATE]", value.round().formatString("d") ) );
		}
		
		if ( !isSame( FDate, value ) )
		{
			FDate = value;
			
			if ( FDate == null )
			{
				this.pElement().value = "";
				this.write();
			}
			else
			{
				this.pShowDate( FDate );
				this.pFillElement( FDate );
			}
			
			if ( typeof( doHide ) == "boolean" && doHide )
				 this.pHide();
			
			if ( this.onchange )
			{
				if ( typeof( event ) == "undefined")
					event = createEvent("change");
				else
					event = createEvent( event );
					
				event.srcElement = FElement;
					
				this.onchange( event );
			}
		}
		
		this.settingDate = false;
		
		return;
	}
	//----------------------------------------------------------------
	this.pElement = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FElement;
		else
			FElement = document.getElementById( value );
	}
	//----------------------------------------------------------------
	this.pFilled = function()
	{
		return FFilled;
	}
	//----------------------------------------------------------------
	this.pFillElement = function( value )
	{
		if ( value == null )
			this.pElement().value = "";
		else if ( value.getHours() > 0 || value.getMinutes() > 0 || value.getSeconds() > 0 )
			this.pElement().value = value.formatString("g");
		else
			this.pElement().value = value.formatString("d");
	}
	//----------------------------------------------------------------
	this.getData = function( oldValue, newValue )
	{
		if ( newValue == null )
			newValue = FShowDate;
		
		if ( typeof( oldValue ) != "undefined" && oldValue != null )
		{
			if ( oldValue.getMonth() == newValue.getMonth() && oldValue.getFullYear() == newValue.getFullYear() )
				return;
		}
		
		if ( FDataUrl != null )
		{
			var
				url = FDataUrl.add("date", newValue.formatString("d") ), 
				xml = url.request("GET", null, true );
			
			this.pClearFilled();
			
			if ( xml != null )
			{
				if ( xml.firstChild != null && xml.firstChild.childNodes != null )
				{
					for ( var i = 0; i < xml.firstChild.childNodes.length; i++ )
					{
						var
							date      = xml.firstChild.childNodes[i], 
							disabled  = parseBool( date.getAttribute("disabled") ), 
							className = date.getAttribute("class");
						
						date = parseXmlDate( date.firstChild.nodeValue );
						
						if ( !Date.isDate( date ) )
							continue;
						
						if ( disabled )
						{
							if ( !FBlock.contains( date ) )
								FBlock.add( date );
							
							if ( isSame( FDate, date ) )
							{
								FDate = null;
								
								if ( FElement )
									FElement.value = "";
							}
							
							if ( className )
								this.addFilled( date, className );
						}
						else
							this.addFilled( date, className );
					}
				}
			}
		}
	}
	//----------------------------------------------------------------
	this.pGetRef = function()
	{
		return "dateInputs[" + FIndex + "]";
	}
	//----------------------------------------------------------------
	this.pHide = function()
	{
		this.div.style.display = "none";
		
		if ( this.frame && this.frame.parentNode == document.body )
			document.body.removeChild( this.frame );
	}
	//----------------------------------------------------------------
	this.pMaxDate = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FMaxDate;
		else if ( value > new Date( 9999, 11, 31 ) )
			throw new Error("Illegal assignment to maxDate. Max. value is 31-12-9999");
		else if ( value < new Date( 1753, 0,  1  ) )
			throw new Error("Illegal assignment to maxDate. Min. value is 1-1-1753");
		else if ( value <= FMinDate )
			throw new Error("Illegal assignment to maxDate. Date smaller than minDate");
		else
		{
			FMaxDate = value.round();
			
			if ( FDate && FDate >= FMaxDate )
				this.pDate( FMaxDate.priorDay() );
			
			if ( FShowDate && FShowDate >= FMaxDate )
				this.pShowDate( FMaxDate.priorDay() );
			else
				this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pMinDate = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FMinDate;
		else if ( value > new Date( 9999, 11, 31 ) )
			throw new Error("Illegal assignment to minDate. Max. value is 31-12-9999");
		else if ( value < new Date( 1753, 0,  1  ) )
			throw new Error("Illegal assignment to minDate. Min. value is 1-1-1753");
		else if ( value >= FMaxDate )
			throw new Error("Illegal assignment to minDate. Date greater than maxDate");
		else
		{
			FMinDate = value.round();
			
			if ( FDate && FDate < FMinDate )
				this.pDate( FMinDate );
			
			if ( FShowDate && FShowDate < FMinDate )
				this.pShowDate( FMinDate );
			else
				this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pName = function()
	{
		return FName;
	}
	//----------------------------------------------------------------
	this.pShowDate = function( value )
	{
		var
			oldValue = FShowDate;
		
		if ( typeof( value ) == "undefined")
			return FShowDate;
		else if ( value >= FMaxDate )
			FShowDate = FMaxDate.priorDay();
		else if ( value < FMinDate )
			FShowDate = FMinDate;
		else
			FShowDate = value.round();
		
		if ( !isSame( oldValue, FShowDate ) )
		{
			this.getData( oldValue, FShowDate );
			this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.td = function( date )
	{
		var
			min      = new Date( FMinDate ), 
			max      = new Date( FMaxDate ), 
			disabled = false, 
			retVal   = "";
		
		if ( date < FMinDate || date >= FMaxDate || this.blocked( date ) )
		{
			disabled  = true;
			retVal += " disabled=\"true\"";
		}
		else
			retVal += " onclick=\"" + this.pGetRef() + ".setDate(" + date.jsDate() + ", event, true );\"";
		
		if ( date.getMonth() != FShowDate.getMonth() )
			retVal += " class=\"calDayOM";
		else
			retVal += " class=\"calDay";
		
		if ( date.isSameDate( new Date() ) )
			retVal += " calToday";
		
		if ( FDate && date.isSameDate( FDate ) )
			retVal += " calSelected";
		
		if ( typeof( FFilled[date] ) == "boolean" && FFilled[date] == true )
			retVal += " calFilled";
		else if ( typeof( FFilled[date] ) == "string" && FFilled[date] != "")
			retVal += " " + FFilled[date];
		
		if ( disabled )
			retVal += " calDisabled";
		
		retVal += "\"";
		
		if ( !disabled )
		{
			retVal += " onmouseover=\"this.oldclass = this.className; this.className += ' calSelected';\"";
			retVal += " onmouseout=\"this.className = this.oldclass;\"";
		}
		else
			retVal += " style=\"cursor:default;\"";
		
		return retVal;
	}
	//----------------------------------------------------------------
	
	if ( bodyLoaded )
		this.init();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.addFilled = function( date, className )
{
	if ( !Date.isDate( date ) )
		date = new Date( date );
	
	if ( typeof( date.age ) == "function")
	{
		if ( typeof( className ) == "undefined" || className == null )
			className = true;
		else
			className = String( className );
		
		this.pFilled()[date.round()]          = className;
		this.pFilled()[this.pFilled().length] = date;
	}
	else
		throw new Error("Illegal call to TDateInput.addFilled(). Parameter \"date\" is no date.");
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.button = function()
{
	return this.pButton();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.clearFilled = function()
{
	this.pClearFilled();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.dataUrl = function( value )
{
	return this.pDataUrl( value );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.date = function( value )
{
	return this.pDate( value );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.dayNo = function( date )
{
	return ( date.getDay() < Date.formatInfo.firstDay ? (7 - Date.formatInfo.firstDay) + date.getDay() : date.getDay() - Date.formatInfo.firstDay );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.element = function()
{
	return this.pElement();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.filled = function()
{
	return this.pFilled();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.hide = function( sender, time )
{
	if ( this.doHide )
	{
		if ( typeof( time ) == "undefined")
			time = 50;
		
		this.timer = setTimeout( this.pGetRef() + ".pHide();", time );
	}
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.init = function( event )
{
	this.pElement( this.pElement() );
	
	this.pElement().DateInput = this;
	
	if ( this.pElement().value != "")
		this.setDate( this.pElement() );
	
	if ( this.pElement().onchange )
	{
		this.onchange = new Function("event", filterEvent( this.pElement().onchange ).replace("this", "this.pElement()") );
		this.pElement().onchange = null;
	}
	
	addEvent( this.pElement(), "change", this.pGetRef() + ".setDate( this, event );");
	
	if ( isIE )
		this.pElement().style.behavior = "";
	
	this.pButton( this.pButton() );
	this.pButton().DateInput = this;
	
	addEvent( this.pButton(), "mouseout",  this.pGetRef() + ".hide( this, 500 );");
	addEvent( this.pButton(), "mouseover", this.pGetRef() + ".stopHide( this );");
	addEvent( this.pButton(), "click",     this.pGetRef() + ".show( this )");
	
	if ( this.pButton().hideFocus )
		this.pButton().hideFocus = true;
	
	this.write();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.maxDate = function( value )
{
	return this.pMaxDate( value );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.minDate = function( value )
{
	return this.pMinDate( value );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.name = function()
{
	return this.pName();
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.nextMonth = function()
{
	try
	{
		this.pShowDate( this.pShowDate().nextMonth() );
		return true;
	}
	catch ( error )
	{
		this.settingDate = false;
		
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.priorMonth = function()
{
	try
	{
		this.pShowDate( this.pShowDate().priorMonth() );
		return true;
	}
	catch ( error )
	{
		this.settingDate = false;
		
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.showDate = function( value )
{
	return this.pShowDate( value );
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.setDate = function( date, event, doHide )
{
	if ( date == this.pElement() )
	{
		if ( String( this.pElement().value ).length > 0 )
			if ( this.allowTime )
				date = isDateTime( this.pElement().value );
			else
				date = isDate( this.pElement().value );
		else
			date = null;
		
		if ( date == false )
		{
			var
				message = getIllegalDateMessage();
			
			alert( message );
			
			if ( !isIE )
			{
				this.pFillElement( this.date() );
				this.pElement.focus();
			}
			else
				this.pElement().select();
			
			if ( typeof( event ) != "undefined")
				return cancelEvent( event );
			else
				return false;
		}
	}
	else if ( date != null && typeof( date.age ) != "function")
		if ( this.allowTime )
			date = isDateTime( date );
		else
			date = isDate( date );
	
	if ( this.allowTime && date != null )
		if ( date.formatString("HHnnss") == "000000" && this.pDate() != null && this.pDate().formatString("HHnnss") != "000000")
			date = date.integrateTime( this.pDate() );
	
	try
	{
		this.pDate( date, event, doHide );
		return true;
	}
	catch ( error )
	{
		this.settingDate = false;
		
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		if ( ! isIE )
		{
			if ( this.date() )
				this.pFillElement( this.date() );
			else
				this.pElement().value = "";
			
			this.pElement().focus();
		}
		else
		{
			this.pElement().select();
			
			if ( typeof( event ) != "undefined")
				event.returnValue = false;
		}
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.setMonth = function( element )
{
	try
	{
		var
			date = new Date( this.pShowDate() );
		
		date.setMonth( element.value );
		
		this.pShowDate( date );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.setYear = function( element )
{
	try
	{
		var
			date = new Date( this.pShowDate() );
		
		date.setYear( element.value );
		
		this.pShowDate( date );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.show = function( sender )
{
	if ( this.div.parentNode != document.body )
		document.body.appendChild( this.div );
	
	if ( isIE )
		document.body.appendChild( this.frame );
	
	if ( this.div.style.display == "none" && this.date() )
		this.pShowDate( this.date() );
	
	var
		btnRight = getLeft( this.pButton() ) + this.pButton().offsetWidth, 
		btnTop   = getTop( this.pButton()  ) + this.pButton().offsetHeight, 
		elmLeft  = getLeft( this.pElement() ), 
		elmTop   = getTop( this.pElement() ) + this.pElement().offsetHeight;
	
	this.x                 = elmLeft;
	this.y                 = Math.max( btnTop, elmTop );
	
	this.div.style.left    = this.x + "px";
	this.div.style.top     = this.y + "px";
	this.div.style.zIndex  = 9999;
	this.div.style.display = "";
	
	this.div.style.left    = (btnRight - this.div.offsetWidth) + "px";
	
	if ( typeof( this.frame ) != "undefined")
	{
		this.frame.style.zIndex     = 9998;
		this.frame.style.left       = this.div.offsetLeft   + "px";
		this.frame.style.top        = this.div.offsetTop    + "px";
		this.frame.style.width      = this.div.offsetWidth  + "px";
		this.frame.style.height     = this.div.offsetHeight + "px";
		this.frame.style.visibility = "visible";
	}
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.startHiding = function()
{
	this.doHide = true;
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.stopHiding = function()
{
	this.doHide = false;
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.stopHide = function( sender )
{
	clearTimeout( this.timer );
	this.timer = 0;
}
//-------------------------------------------------------------------------------------------------
TDateInput.prototype.write = function()
{
	var
		name  = this.name(), 
		date  = new Date( this.pShowDate() ), 
		min   = new Date( this.pMinDate() ), 
		max   = new Date( this.pMaxDate() ), 
		year  = date.getFullYear(), 
		month = date.getMonth(), 
		bDate = new Date( year, month, 1 ), 
		eDate = bDate.nextMonth(), 
		dayNo = this.dayNo( bDate ), 
		prior = new Date( date ), 
		next  = date.nextMonth(), 
		HTML  = "";
	
	prior.setDate( 1 );
	prior = prior.priorDay();
	
	if ( prior < min )
		prior = " disabled=\"true\"";
	else
		prior = "";
	
	next.setDate( 1 );
	
	if ( next > max )
		next = " disabled=\"true\"";
	else
		next = "";
	
	HTML = 
			"<table border=\"0\" cellspacing=\"0\" cellpadding=\"3\" style=\"float:left;\">\r\n" + 
			"	<col/><col/><col/><col/><col/><col/><col/><col/>\r\n" + 
			"	<tr style=\"font-size:90%;\">\r\n" + 
			"		<td colspan=\"5\" align=\"center\" style=\"padding:0px 0px; border-bottom:1px solid black;\">\r\n" + 
			"			<select onchange=\"" + this.pGetRef() + ".setMonth( this ); " + this.pGetRef() + ".startHiding();\" onmousedown=\"" + this.pGetRef() + ".stopHide( this ); " + this.pGetRef() + ".stopHiding();\" onmouseleave=\"" + this.pGetRef() + ".startHiding();\" style=\"width:100%\">\r\n";
	
	var
		from = 0, 
		to   = 11;
	
	if ( from < min.getMonth() && year == min.getFullYear() )
		from = min.getMonth();
	
	if ( to > max.getMonth() && year == max.getFullYear() )
		to = max.getMonth();
	
	for ( var i = from; i < to + 1; i++ )
		HTML += 
			"				<option value=\"" + i + "\"" + ( i == month ? " selected=\"selected\"" : "") + ">" + months[i] + "</option>\r\n";
	
	HTML += 
			"			</select>\r\n" + 
			"		</td>\r\n" + 
			"		<td colspan=\"3\" align=\"center\" style=\"padding:0px 0px; border-bottom:1px solid black;\">\r\n" + 
			"			<select onchange=\"" + this.pGetRef() + ".setYear( this ); " + this.pGetRef() + ".startHiding();\" onmousedown=\"" + this.pGetRef() + ".stopHide( this ); " + this.pGetRef() + ".stopHiding();\" onmouseleave=\"" + this.pGetRef() + ".startHiding();\" style=\"width:100%\">\r\n";
	
	from = date.getFullYear() - 75;
	to   = date.getFullYear() + 75;
	
	if ( from < min.getFullYear() )
		from = min.getFullYear();
	
	if ( to > max.getFullYear() )
		to = max.getFullYear();
	
	for ( var i = from; i < to + 1; i++ )
		HTML += 
			"				<option value=\"" + i + "\"" + ( i == year ? " selected=\"selected\"" : "") + ">" + i + "</option>\r\n";
	
	HTML += 
			"			</select>\r\n" + 
			"		</td>\r\n" + 
			"	</tr>\r\n" + 
			"	<tr id=\"trButtons\" style=\"font-size:90%;\">\r\n" + 
			"		<td style=\"padding:0px 0px;\"><button type=\"button\"" + prior + " onclick=\"" + this.pGetRef() + ".priorMonth();\" onmouseover=\"" + this.pGetRef() + ".stopHide( this );\" style=\"width:100%; margin:0px;\">&lt;</button></td>" + 
			"		<td colspan=\"6\" align=\"center\">" + date.formatString("MMMM yyyy") + "</td>\r\n" + 
			"		<td style=\"padding:0px 0px;\"><button type=\"button\"" + next  + " onclick=\"" + this.pGetRef() + ".nextMonth();\"  onmouseover=\"" + this.pGetRef() + ".stopHide( this );\" style=\"width:100%; margin:0px;\">&gt;</button></td>\r\n" + 
			"	</tr>\r\n" + 
			"	<tr height=\"20\" style=\"font-size:90%;\">\r\n" + 
			"		<td><img src=\"img/default/pixTrans.gif\" height=\"1\" width=\"20\" /></td>\r\n";
	
	for ( var i = Date.formatInfo.firstDay; i < 7; i++ )
		HTML += 
			"		<td class=\"calDayHeader\"><img src=\"img/default/pixTrans.gif\" height=\"1\" width=\"20\" /><br/>" + days[i].substr(0, 2) + "</td>\r\n";
	
	for ( var i = 0; i < Date.formatInfo.firstDay; i++ )
		HTML += 
			"		<td class=\"calDayHeader\"><img src=\"img/default/pixTrans.gif\" height=\"1\" width=\"20\" /><br/>" + days[i].substr(0, 2) + "</td>\r\n";
	
	HTML += 
			"	</tr>\r\n" + 
			"	<tr style=\"font-size:90%;\">\r\n" + 
			"		<td class=\"calWeekNo\" style=\"cursor:default;\">" + bDate.priorDay( dayNo ).weekNo() + "</td>\r\n";
	
	for ( var i = dayNo; i > 0; i-- )
	{
		var
			prior = bDate.priorDay( i );
		
		HTML += 
			"		<td" + this.td( prior ) + ">" + prior.formatString("%d") + "</td>\r\n";
	}
	
	while ( bDate < eDate )
	{
		HTML += 
			"		<td" + this.td( bDate ) + ">" + bDate.formatString("%d") + "</td>\r\n";
		
		bDate = bDate.nextDay();
		dayNo = this.dayNo( bDate );
		
		if ( bDate < eDate && dayNo == 0 )
			HTML += 
			"	</tr>\r\n" + 
			"	<tr style=\"font-size:90%;\">\r\n" + 
			"		<td class=\"calWeekNo\" style=\"cursor:default;\">" + bDate.weekNo() + "</td>";
	}
	
	if ( dayNo )
	{
		for ( var i = 0; i < 20 && dayNo < 7; bDate = bDate.nextDay(), i++ )
		{
			HTML += "<td" + this.td( bDate ) + ">" + bDate.formatString("%d") + "</td>";
			dayNo++;
		}
	}
	
	HTML +=
			"	</tr>\r\n" + 
			"</table>";
	
	this.div.innerHTML = HTML;
	
	if ( this.frame )
	{
		this.frame.style.left   = this.div.offsetLeft   + "px";
		this.frame.style.top    = this.div.offsetTop    + "px";
		this.frame.style.width  = this.div.offsetWidth  + "px";
		this.frame.style.height = this.div.offsetHeight + "px";
	}
}
//=================================================================================================
//	class TCalendar
//-------------------------------------------------------------------------------------------------
var
	calendars = [];
//=================================================================================================
TCalendar = function( name, parent, allowTime, block, date, showSelects )
{
	var
		FBlock       = block, 
		FDataUrl     = null, 
		FDate        = ( date ? new Date( date ) : null ), 
		FDirect      = false, 
		FFilled      = [], 
		FIndex       = calendars.length, 
		FMaxDate     = new Date( 9999, 11, 31, 23, 59, 59 ), 
		FMinDate     = new Date( 1753,  0,  1 ), 
		FName        = name, 
		FParent      = parent, 
		FShowDate    = ( FDate ? FDate : new Date() ), 
		FShowSelects = ( typeof( showSelects ) == "boolean" ? showSelects : true );
	
	this.allowTime      = allowTime;
	this.blockedMessage = blockedMessage[Languages.current];
	this.Class          = "TCalendar";
	this.maxDateMessage = maxDateMessage[Languages.current];
	this.minDateMessage = minDateMessage[Languages.current];
	this.onchange       = null;
	this.timer          = 0;
	
	if ( typeof( name ) == "undefined" || String( name ).length == 0 )
		throw new Error("Illegal call to constructor. \"name\" cannot be empty.");
	
	if ( typeof( allowTime ) == "undefined")
		allowTime = false;
	
	if ( typeof( parent ) == "undefined")
		throw new Error("Illegal call to constructor. \"parent\" cannot be empty.");
	
	if ( ! FBlock )
		FBlock = [];
	else if ( ! FBlock.contains )
		throw new Error("Illegal call to constructor. \"block\" should be an array of Date.");
	
	for ( var i = 0; i < FBlock.length; i++ )
		if ( typeof( FBlock[i].age ) != "function")
			throw new Error("Illegal call to constructor. \"block\" contains elements which are not of type Date.");
		else
			FBlock[i] = FBlock[i].round();
	
	calendars[calendars.length] = this;
	
	this.div                    = document.createElement("DIV");
	this.div.id                 = "div" + name.upperFirst();
	this.div.style.border       = "0px solid";
	this.div.style.color        = "black";
	this.div.style.display      = "block";
	this.div.style.padding      = "0px";
	
	if ( !bodyLoaded )
		addEvent( window, "load", "calendars[" + FIndex + "].init();");
	
	//----------------------------------------------------------------
	this.blocked = function( date )
	{
		for ( var i = 0; i < FBlock.length; i++ )
		{
			if ( FBlock[i].isSameDate( date ) )
				return true;
		}
		
		return false;
	}
	//----------------------------------------------------------------
	this.pClearFilled = function()
	{
		FFilled = [];
	}
	//----------------------------------------------------------------
	this.pDataUrl = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FDataUrl;
		else if ( typeof( value.Class ) != "undefined" && value.Class == "Url")
			FDataUrl = value;
		else
			FDataUrl = new Url( value );
		
		if ( typeof( FParent ) == "string")
			this.getData();
	}
	//----------------------------------------------------------------
	this.pDate = function( value, event, sender )
	{
		if ( typeof( value ) == "undefined")
			return FDate;
		else if ( value != null )
		{
			if ( typeof( value.age ) != "function")
				throw new Error("Illegal assignment to date. Value is not a date object and not null (\"" + valueString( value ) + "\").");
			
			if ( ! this.allowTime )
				value = value.round();
			
			if ( value >= FMaxDate )
				throw new Error( this.maxDateMessage.replace("[MAXDATE]", FMaxDate.formatString("d") ) );
			
			if ( value < FMinDate )
				throw new Error( this.maxDateMessage.replace("[MINDATE]", FMinDate.formatString("d") ) );
			
			if ( this.blocked( value.round() ) )
				throw new Error( this.blockedMessage.replace("[DATE]", value.round().formatString("d") ) );
		}
		
		if ( !isSame( FDate, value ) )
		{
			var
				oldValue = FDate;
			
			FDate = value;
			
			if ( FDate == null || FDirect )
				this.write();
			else
				this.pShowDate( FDate );
			
			if ( this.onchange )
			{
				if ( typeof( event ) != "undefined")
				{
					var
						newEvent = createEvent( event );
					
					if ( typeof( sender ) != "undefined")
					{
						sender.calendar     = this;
						newEvent.srcElement = sender;
					}
					else
						newEvent.srcElement = this;
					
					this.onchange( this, newEvent );
				}
				else
					this.onchange( this );
			}
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pDirect = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FDirect;
		else
			FDirect = ( value ? true : false );
	}
	//----------------------------------------------------------------
	this.pFilled = function()
	{
		return FFilled;
	}
	//----------------------------------------------------------------
	this.getData = function( oldValue, newValue )
	{
		if ( newValue == null )
			newValue = FShowDate;
		
		if ( typeof( oldValue ) != "undefined" && oldValue != null )
		{
			if ( oldValue.getMonth() == newValue.getMonth() && oldValue.getFullYear() == newValue.getFullYear() )
				return;
		}
		
		if ( FDataUrl != null )
		{
			var
				url = FDataUrl.add("date", newValue.formatString("d") ), 
				xml = url.request("GET", null, true );
			
			this.pClearFilled();
			
			if ( xml != null )
			{
				if ( xml.firstChild != null && xml.firstChild.childNodes != null )
				{
					for ( var i = 0; i < xml.firstChild.childNodes.length; i++ )
					{
						var
							date      = xml.firstChild.childNodes[i], 
							disabled  = parseBool( date.getAttribute("disabled") ), 
							className = date.getAttribute("class");
						
						date = parseXmlDate( date.firstChild.nodeValue );
						
						if ( !Date.isDate( date ) )
							continue;
						
						if ( disabled )
						{
							if ( !FBlock.contains( date ) )
								FBlock.add( date );
							
							if ( isSame( FDate, date ) )
								this.pDate( null );
							
							if ( className )
								this.addFilled( date, className );
						}
						else
							this.addFilled( date, className );
					}
				}
			}
		}
	}
	//----------------------------------------------------------------
	this.pGetRef = function()
	{
		return "calendars[" + FIndex + "]";
	}
	//----------------------------------------------------------------
	this.pMaxDate = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FMaxDate;
		else if ( value > new Date( 9999, 11, 31 ) )
			throw new Error("Illegal assignment to maxDate. Max. value is 31-12-9999");
		else if ( value < new Date( 1753, 0,  1  ) )
			throw new Error("Illegal assignment to maxDate. Min. value is 1-1-1753");
		else if ( value <= FMinDate )
			throw new Error("Illegal assignment to maxDate. Date smaller than minDate");
		else
		{
			FMaxDate = value.round();
			
			if ( FDate && FDate >= FMaxDate )
				this.pDate( FMaxDate.priorDay() );
			
			if ( FShowDate && FShowDate >= FMaxDate )
				this.pShowDate( FMaxDate.priorDay() );
			else
				this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pMinDate = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FMinDate;
		else if ( value > new Date( 9999, 11, 31 ) )
			throw new Error("Illegal assignment to minDate. Max. value is 31-12-9999");
		else if ( value < new Date( 1753, 0,  1  ) )
			throw new Error("Illegal assignment to minDate. Min. value is 1-1-1753");
		else if ( value >= FMaxDate )
			throw new Error("Illegal assignment to minDate. Date greater than maxDate");
		else
		{
			FMinDate = value.round();
			
			if ( FDate && FDate < FMinDate )
				this.pDate( FMinDate );
			
			if ( FShowDate && FShowDate < FMinDate )
				this.pShowDate( FMinDate );
			else
				this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pName = function()
	{
		return FName;
	}
	//----------------------------------------------------------------
	this.pParent = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FParent;
		else if ( typeof( value ) == "string")
			FParent = document.getElementById( value );
		else
			FParent = value;
	}
	//----------------------------------------------------------------
	this.pShowDate = function( value, event, sender )
	{
		var
			oldValue = FShowDate;
		
		if ( typeof( value ) == "undefined")
			return FShowDate;
		else if ( value >= FMaxDate )
			FShowDate = FMaxDate.priorDay();
		else if ( value < FMinDate )
			FShowDate = FMinDate;
		else
			FShowDate = value.round();
		
		if ( !isSame( oldValue, FShowDate ) )
		{
			this.getData( oldValue, FShowDate );

			if ( FDirect )
				this.pDate( FShowDate, event, sender );
			else		
				this.write();
		}
		
		return;
	}
	//----------------------------------------------------------------
	this.pShowSelects = function( value )
	{
		if ( typeof( value ) == "undefined")
			return FShowSelects;
		else
		{
			FShowSelects = value;
			
			var
				trSelects = document.getElementById("trSelects");
			
			if ( trSelects )
			{
				if ( FShowSelects )
					trSelects.style.display = "block";
				else
					trSelects.style.display = "none";
			}
		}
	}
	//----------------------------------------------------------------
	this.td = function( date )
	{
		var
			min      = new Date( FMinDate ), 
			max      = new Date( FMaxDate ), 
			disabled = false, 
			retVal   = "";
		
		if ( date < FMinDate || date >= FMaxDate || this.blocked( date ) )
		{
			disabled = true;
			retVal += " disabled=\"true\"";
		}
		else
			retVal += " onclick=\"" + this.pGetRef() + ".setDate(" + date.jsDate() + ", event );\"";
		
		if ( date.getMonth() != FShowDate.getMonth() )
			retVal += " class=\"calDayOM";
		else
			retVal += " class=\"calDay";
		
		if ( date.isSameDate( new Date() ) )
			retVal += " calToday";
		
		if ( FDate && date.isSameDate( FDate ) )
			retVal += " calSelected";
		
		if ( typeof( FFilled[date] ) == "boolean" && FFilled[date] == true )
			retVal += " calFilled";
		else if ( typeof( FFilled[date] ) == "string" && FFilled[date] != "")
			retVal += " " + FFilled[date];
		
		if ( disabled )
			retVal += " calDisabled";
		
		retVal += "\"";
		
		if ( !disabled )
		{
			retVal += " onmouseover=\"this.oldclass = this.className; this.className += ' calSelected';\"";
			retVal += " onmouseout=\"this.className = this.oldclass;\"";
		}
		else
			retVal += " style=\"cursor:default;\"";
		
		return retVal;
	}
	//----------------------------------------------------------------
	
	if ( bodyLoaded )
		this.init();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.addFilled = function( date, className )
{
	if ( typeof( date.age ) != "function")
		date = new Date( date );
	
	if ( typeof( date.age ) == "function")
	{
		if ( typeof( className ) == "undefined" || className == null )
			className = true;
		else
			className = String( className );
		
		this.pFilled()[date.round()]          = className;
		this.pFilled()[this.pFilled().length] = date;
	}
	else
		throw new Error("Illegal call to TCalendar.addFilled(). Parameter \"date\" is no date.");
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.clearFilled = function()
{
	this.pClearFilled();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.dataUrl = function( value )
{
	return this.pDataUrl( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.date = function( value )
{
	return this.pDate( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.dayNo = function( date )
{
	return ( date.getDay() < Date.formatInfo.firstDay ? (7 - Date.formatInfo.firstDay) + date.getDay() : date.getDay() - Date.formatInfo.firstDay );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.direct = function( value )
{
	return this.pDirect( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.filled = function()
{
	return this.pFilled();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.hideSelects = function()
{
	this.pShowSelects( false );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.init = function()
{
	this.pParent( this.pParent() );
	this.write();
	
	var
		parent = this.parent();
	
	parent.appendChild( this.div );
	
	this.div.style.width = this.div.firstChild.offsetWidth + "px";
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.maxDate = function( value )
{
	return this.pMaxDate( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.minDate = function( value )
{
	return this.pMinDate( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.name = function()
{
	return this.pName();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.nextMonth = function( sender, event )
{
	try
	{
		this.pShowDate( this.pShowDate().nextMonth(), event, sender );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.priorMonth = function( sender, event )
{
	try
	{
		this.pShowDate( this.pShowDate().priorMonth(), event, sender );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.parent = function()
{
	return this.pParent();
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.showDate = function( value )
{
	return this.pShowDate( value );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.showSelects = function()
{
	this.pShowSelects( true );
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.setDate = function( date, event )
{
	if ( typeof( date.isLeapYear ) == "undefined" && date != null )
		if ( this.allowTime )
			date = isDateTime( date );
		else
			date = isDate( date );
	
	if ( this.allowTime )
		if ( date.formatString("HHnnss") == "000000" && this.pDate() != null && this.pDate().formatString("HHnnss") != "000000")
			date = date.integrateTime( this.pDate() );
	
	try
	{
		this.pDate( date, event );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.setMonth = function( element )
{
	try
	{
		var
			date = new Date( this.pShowDate() );
		
		date.setMonth( element.value );
		
		this.pShowDate( date );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.setYear = function( element )
{
	try
	{
		var
			date = new Date( this.pShowDate() );
		
		date.setYear( element.value );
		
		this.pShowDate( date );
		return true;
	}
	catch ( error )
	{
		if ( error.description )
			alert( error.description );
		else if ( error.message )
			alert( error.message );
		else
			alert( error );
		
		return false;
	}//*/
}
//-------------------------------------------------------------------------------------------------
TCalendar.prototype.write = function()
{
	var
		name  = this.name(), 
		date  = new Date( this.pShowDate() ), 
		min   = new Date( this.pMinDate() ), 
		max   = new Date( this.pMaxDate() ), 
		year  = date.getFullYear(), 
		month = date.getMonth(), 
		bDate = new Date( year, month, 1 ), 
		eDate = bDate.nextMonth(), 
		dayNo = this.dayNo( bDate ), 
		prior = new Date( date ), 
		next  = date.nextMonth(), 
		HTML  = "";
	
	prior.setDate( 1 );
	prior = prior.priorDay();
	
	if ( prior < min )
		prior = " disabled=\"true\"";
	else
		prior = "";
	
	next.setDate( 1 );
	
	if ( next > max )
		next = " disabled=\"true\"";
	else
		next = "";
	
	HTML = 
			"<table border=\"0\" cellspacing=\"0\" cellpadding=\"3\" style=\"float:left;\">\r\n" + 
			"	<col/><col/><col/><col/><col/><col/><col/><col/>\r\n" + 
			"	<tr id=\"trSelects\" style=\"font-size:90%;" + ( this.pShowSelects() ? "" : " display:none;") + "\">\r\n" + 
			"		<td colspan=\"5\" align=\"center\" style=\"padding:0px 0px;\">\r\n" + 
			"			<select onchange=\"" + this.pGetRef() + ".setMonth( this );\" style=\"width:100%\">\r\n";
	
	var
		from = 0, 
		to   = 11;
	
	if ( from < min.getMonth() && year == min.getFullYear() )
		from = min.getMonth();
	
	if ( to > max.getMonth() && year == max.getFullYear() )
		to = max.getMonth();
	
	for ( var i = from; i < to + 1; i++ )
		HTML += 
			"				<option value=\"" + i + "\"" + ( i == month ? " selected=\"selected\"" : "") + ">" + months[i] + "</option>\r\n";
	
	HTML += 
			"			</select>\r\n" + 
			"		</td>\r\n" + 
			"		<td colspan=\"3\" align=\"center\" style=\"padding:0px 0px;\">\r\n" + 
			"			<select onchange=\"" + this.pGetRef() + ".setYear( this );\" style=\"width:100%\">\r\n";
	
	from = date.getFullYear() - 75;
	to   = date.getFullYear() + 75;
	
	if ( from < min.getFullYear() )
		from = min.getFullYear();
	
	if ( to > max.getFullYear() )
		to = max.getFullYear();
	
	for ( var i = from; i < to + 1; i++ )
		HTML += 
			"				<option value=\"" + i + "\"" + ( i == year ? " selected=\"selected\"" : "") + ">" + i + "</option>\r\n";
	
	HTML += 
			"			</select>\r\n" + 
			"		</td>\r\n" + 
			"	</tr>\r\n" + 
			"	<tr id=\"trButtons\" style=\"font-size:90%;\">\r\n" + 
			"		<td style=\"padding:0px 0px;\"><button type=\"button\"" + prior + " onclick=\"" + this.pGetRef() + ".priorMonth( this, event );\" style=\"width:100%; margin:0px;\">&lt;</button></td>" + 
			"		<td colspan=\"6\" align=\"center\">" + date.formatString("MMMM yyyy") + "</td>\r\n" + 
			"		<td style=\"padding:0px 0px;\"><button type=\"button\"" + next  + " onclick=\"" + this.pGetRef() + ".nextMonth( this, event );\" style=\"width:100%; margin:0px;\">&gt;</button></td>\r\n" + 
			"	</tr>\r\n" + 
			"	<tr height=\"20\" style=\"font-size:90%;\">\r\n" + 
			"		<td><img src=\"img/default/pixTrans.gif\" height=\"1\" class=\"calWeekNo\" /></td>\r\n";
	
	for ( var i = Date.formatInfo.firstDay; i < 7; i++ )
		HTML += 
			"		<td class=\"calDayHeader\"><img src=\"img/default/pixTrans.gif\" height=\"1\" class=\"calDayHeader\" /><br/>" + days[i].substr(0, 2) + "</td>\r\n";
	
	for ( var i = 0; i < Date.formatInfo.firstDay; i++ )
		HTML += 
			"		<td class=\"calDayHeader\"><img src=\"img/default/pixTrans.gif\" height=\"1\" class=\"calDayHeader\" /><br/>" + days[i].substr(0, 2) + "</td>\r\n";
	
	HTML += 
			"	</tr>\r\n" + 
			"	<tr style=\"font-size:90%;\">\r\n" + 
			"		<td class=\"calWeekNo\" style=\"cursor:default;\">" + bDate.priorDay( dayNo ).weekNo() + "</td>\r\n";
	
	for ( var i = dayNo; i > 0; i-- )
	{
		var
			prior = bDate.priorDay( i );
		
		HTML += 
			"		<td" + this.td( prior ) + ">" + prior.formatString("%d") + "</td>\r\n";
	}
	
	while ( bDate < eDate )
	{
		HTML += 
			"		<td" + this.td( bDate ) + ">" + bDate.formatString("%d") + "</td>\r\n";
		
		bDate = bDate.nextDay();
		dayNo = this.dayNo( bDate );
		
		if ( bDate < eDate && dayNo == 0 )
			HTML += 
			"	</tr>\r\n" + 
			"	<tr style=\"font-size:90%;\">\r\n" + 
			"		<td class=\"calWeekNo\" style=\"cursor:default;\">" + bDate.weekNo() + "</td>";
	}
	
	if ( dayNo )
	{
		for ( var i = 0; i < 20 && dayNo < 7; bDate = bDate.nextDay(), i++ )
		{
			HTML += "<td" + this.td( bDate ) + ">" + bDate.formatString("%d") + "</td>";
			dayNo++;
		}
	}
	
	HTML +=
			"	</tr>\r\n" + 
			"</table>";
	
	this.div.innerHTML = HTML;
}
//=================================================================================================
//	Misc. functions
//=================================================================================================
function isDate( value )
{
	if ( typeof( value.age ) == "function")
		return value;
	
	if ( new String( value ).length == 0 )
		return true;
	
	var
		date   = new Date(), 
		fields = new String( value ).split( Date.formatInfo.dateSeparator.trim() );
	
	if ( fields.length < 2 || fields.length > 3 )
		return false;
	
	for ( var i = 0; i < fields.length; i++ )
	{
		while ( fields[i].startsWith("0") )
			fields[i] = fields[i].substr( 1 );
		
		if ( fields[i] == "")
			fields[i] = "0";
	}
	
	var 
		day   = fields.length > 0 ? parseInt( fields[0] ) : null, 
		month = fields.length > 1 ? parseInt( fields[1] ) : null, 
		year  = fields.length > 2 ? parseInt( fields[2] ) : date.getYear();
	
	if ( isNaN( day ) || day == null )
		return false;
	
	if ( isNaN( month ) || month == null )
		return false;
	
	if ( isNaN( year ) )
		return false;
	
	if ( day != Number( fields[0] ) )
		return false;
	
	if ( month != Number( fields[1] ) )
		return false;
	
	if ( fields.length > 2 && year != Number( fields[2] ) )
		return false;
	
	var
		format = Date.formatInfo.shortDatePattern;
	
	if ( format.search("y") < format.search("m") && format.search("m") < format.search("d") )
	{
		var
			old = year;
		
		year = day;
		day  = old;
	}
	else if ( format.search("m") < format.search("d") )
	{
		var
			old = month;
		
		month = day;
		day   = old;
	}
	
	if ( day < 1 || month < 1 || month > 12 )
		return false;
	
	if ( year < 50 ) 
		year += 2000;
	else if ( year < 100 )
		year += 1900;
	
	if ( year < 1753 || year > 9999 ) 
		return false;
	
	switch ( month )
	{
		case 2:
			if ( year % 4 == 0 && (year % 100 != 0 || year % 1000 == 0) ) 
			{
				if ( day > 29 ) 
					return false;
			}
			else if ( day > 28 )
				return false;
			
			break;
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			if ( day > 31 ) 
				return false;
			
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			if ( day > 30 ) 
				return false;
			
			break;
		default:
			return false;
	}
	
	return new Date( year, month - 1, day, 0, 0, 0 );
}
//=================================================================================================
function isTime( value )
{
	if ( typeof( value.age ) == "function")
		return value;
	
	if ( new String( value ).length == 0 )
		return true;
	
	try
	{
		var
			date    = new Date(), 
			fields  = new String( value ).split( new RegExp("[" + Date.formatInfo.timeSeparator + " ]", "gi") );
		
		if ( fields.length < 2 || fields.length > 3 )
			return false;
		
		for ( var i = 0; i < fields.length; i++ )
		{
			while ( fields[i].startsWith("0") )
				fields[i] = fields[i].substr( 1 );
			
			if ( fields[i] == "")
				fields[i] = "0";
		}
		
		var
			hours   = fields.length > 0 ? Number( fields[0] ) : null, 
			minutes = fields.length > 1 ? Number( fields[1] ) : null, 
			seconds = fields.length > 2 ? Number( fields[2] ) : 0, 
			AMPM    = fields.length > 3 ? fields[3]           : null;
		
		if ( isNaN( hours ) || hours == null )
			return false;
		
		if ( isNaN( minutes ) || minutes == null )
			return false;
		
		if ( isNaN( seconds ) )
		{
			if ( new RegExp("(AM|PM)").test( fields[2] ) )
			{
				AMPM    = fields[2].toUpperCase();
				seconds = 0;
			}
			else
				return false;
		}
		
		if ( AMPM == "PM" && hours < 12 )
			hours += 12;
		
		if ( hours < 0 || hours > 23 )
			return false;
		
		if ( minutes < 0 || minutes > 59 ) 
			return false;
		
		if ( seconds < 0 || seconds > 59 ) 
			return false;
		
		return new Date( 1900, 0, 1, hours, minutes, seconds );
	}
	catch ( error )
	{
		return false;
	}
}
//=================================================================================================
function isDateTime( value )
{
	if ( typeof( value.age ) == "function")
		return value;
	
	var
		date = new Date();
	
	value = value.split( /\s+/gi );
	
	if ( value.length > 1 )
	{
		for ( var i = 2; i < value.length; i++ )
			value[1] += " " + value[i];
		
		var
			date = isDate( value[0] ), 
			time = isTime( value[1] );
		
		if ( date != false && time != false )
		{
			date.setHours( time.getHours() );
			date.setMinutes( time.getMinutes() );
			date.setSeconds( time.getSeconds() );
			
			return date;
		}
		else
		{
			var
				value = value.join(" ");
			
			time = isTime( value );
			
			if ( time != false )
				return time;
			else
				return false;
		}
	}
	else if ( value[0].indexOf( Date.formatInfo.dateSeparator ) > -1 )
		return isDate( value[0] );
	else if ( value[0].indexOf( Date.formatInfo.timeSeparator ) > -1 )
		return isTime( value[0] );
	else
		return false;
}
//=================================================================================================
function getIllegalDateMessage()
{
	var
		format  = Date.formatInfo, 
		pattern = "'" + format.getDateDisplayPattern() + "'", 
		message = getMessage( 19 );
	
	if ( message )
		return message.text.replace("D-M-JJJJ", pattern );
	else
		return "De ingevoerde datum is niet correct. Er wordt een datum met het volgende formaat verwacht: " + pattern + ".";
}
//=================================================================================================