function FloatingCal(mainId)
{
	this.mainId = mainId;
	this.limit = null;
	FloatingCal.instances[ this.mainId ] = this;
}

FloatingCal.instances = new Array();
FloatingCal.openInstance = null;
FloatingCal.notifyChange = null;

FloatingCal.prototype.init = function(target, fmt, floatBy, offX, offY, tilde, months, weekdays, ws)
{
	this.months = months;
	this.weekdays = weekdays;
	this.weekStarts = ws;
	
	this.floref = document.getElementById( floatBy );
	this.field = document.getElementById( target );
	this.vformat = fmt;
	this.offX = offX;
	this.offY = offY;
	
	this.top = document.createElement( "DIV" );
	this.top.id = this.mainId;

	var today = new Date();
	
	this.current = {
		d : today.getDate(),
		m : today.getMonth() + 1,
		y : today.getFullYear()
	};
	
	var caption = document.createElement( "DIV" );
	caption.innerHTML = tilde;
	this.setClass( caption, "captionBar" );
	this.top.appendChild( caption );
	
	var closebar = document.createElement( "DIV" ); 
	this.setClass( closebar, "closeBar" );
	closebar.innerHTML = "<A class=\"closeBar\" href=\"javascript:FloatingCal.instances['" + this.mainId + "'].onClose(false);\">&nbsp;</A>";
	this.top.appendChild( closebar );
	
	this.monthyear = document.createElement( "DIV" );
	this.setClass( this.monthyear, "labelMonthYear" );
	this.top.appendChild( this.monthyear );
	
	var i = ws;
	
	for( var j = 0; j < 7; j ++ ) {
		var div = document.createElement( "DIV" );
		this.setClass( div, "weekdayName" );
		div.innerText = weekdays[i];
		
		if( j == 6 ) {
			div.style.borderRight = "none";
			div.style.width = "24px";
		}
		
		this.top.appendChild( div );
		
		if( ++i >= this.weekdays.length )
			i = 0;
	}
	
	this.dayMatrix = new Array();
	
	for( var j = 0; j < 6; j ++ ) {
		this.dayMatrix[ j ] = new Array();
		
		for( var i = 0; i < 7; i ++ ) {
			this.dayMatrix[ j ][ i ] = document.createElement( "DIV" );
			this.setClass( this.dayMatrix[ j ][ i ], "monthDay" );
			if( i == 6 ) {
				this.dayMatrix[ j ][ i ].style.borderRight = "none";
				this.dayMatrix[ j ][ i ].style.width = "24px";
			}
			this.top.appendChild( this.dayMatrix[ j ][ i ] );
		}
	}
	
	document.body.appendChild( this.top );
	
	this.shadows = new Array();
	this.field.setAttribute( "readOnly", "readonly" );
}

FloatingCal.prototype.setClass = function(el, name)
{
	if( el.className !== undefined )
		el.className = name;
	else if( el.getAttribute )
		el.setAttribute( "class", name );
}

FloatingCal.prototype.getClass = function(el)
{
	if( el.className !== undefined )
		return el.className;
	else if( el.getAttribute )
		return el.getAttribute( "class" );

	return "";
}

FloatingCal.prototype.draw = function(month, year)
{
	var currentDate = new Date();
	var baseDate = new Date()
	baseDate.setFullYear( year, month - 1, 1 );
	
	var mback = month - 1;
	var yback = year;
	var mforth = month + 1;
	var yforth = year;
	
	if( mback <= 0 ) {
		mback = 12;
		yback --;
	}
	
	if( mforth > 12 ) {
		mforth = 1;
		yforth ++;
	}
	
	if( this.limit != null )
		currentDate = this.limit;
	
	this.monthyear.innerHTML = "<A class=\"goMonthBack\" href=\"javascript:FloatingCal.instances['" + 
							   this.mainId + 
							   "'].draw(" + mback + 
							   "," + yback +
							   ");\">&nbsp;</A><SPAN class=\"titleMonthYear\">" +
							   this.months[ month - 1 ] + 
							   " " + year +
							   "</SPAN><A class=\"goMonthForth\" href=\"javascript:FloatingCal.instances['" + 
							   this.mainId + 
							   "'].draw(" + mforth + 
							   "," + yforth +
							   ");\">&nbsp;</A>";
	
	while( baseDate.getDay() != this.weekStarts ) { // sunday == 0
		baseDate.setTime( baseDate.getTime() - (24 * 60 * 60 * 1000) );
	}
		
	for( var j = 0; j < 6; j ++ ) {
		for( var i = 0; i < 7; i ++ ) {
			this.setClass( this.dayMatrix[ j ][ i ], "monthDay" );

			if( currentDate.getTime() < baseDate.getTime() ) {
				this.dayMatrix[ j ][ i ].innerHTML = "<A href=\"javascript:FloatingCal.instances['" +
													 this.mainId + 
													 "'].onChoose({d:" + 
													 baseDate.getDate() + 
													 ",m:" + 
													 (baseDate.getMonth() + 1) + 
													 ",y:" + 
													 baseDate.getFullYear() + 
													 "});\">" + 
													 baseDate.getDate() + 
													 "</A>";
			} else {
				this.dayMatrix[ j ][ i ].innerHTML = baseDate.getDate();
				this.setClass( this.dayMatrix[ j ][ i ], "disabledMonthDay" );
			}

			if( (baseDate.getMonth() == (this.current.m - 1)) &&
				(baseDate.getDate() == this.current.d) &&
				(baseDate.getFullYear() == this.current.y) ) {
				this.setClass( this.dayMatrix[ j ][ i ], "selectedMonthDay" );
			} else if( baseDate.getMonth() != (month - 1) ) {
				this.setClass( this.dayMatrix[ j ][ i ], "otherMonthDay" );
			}
			
			if( i == 6 ) {
				this.dayMatrix[ j ][ i ].style.borderRight = "none";
			}
			
			if( j == 5 ) {
				this.dayMatrix[ j ][ i ].style.borderBottom = "none";
			}

			baseDate.setTime( baseDate.getTime() + (24 * 60 * 60 * 1000) );
		}
	}
}

FloatingCal.prototype.onChoose = function(d)
{
	this.current = d;
	this.onClose( true );
}

FloatingCal.formatDate = function(fmt, x)
{
	var res = "";
	
	for( j = 0; j < fmt.length; j ++ ) {
		switch( fmt.charAt( j ) ) {
			case "d"	:
				res += ((x.d < 10) ? "0" : "") + x.d;
				break;

			case "m"	:
				res += ((x.m < 10) ? "0" : "") + x.m;
				break;

			case "y"	:
				res += x.y;
				break;
				
			default:
				res += fmt.charAt( j );
				break;
		}
	}
	
	return res;		
}

FloatingCal.prototype.onClose = function(dosave)
{
	if( dosave ) {
		var nv = FloatingCal.formatDate( this.vformat, this.current );

		if( FloatingCal.notifyChange != null ) {
		    if( !FloatingCal.notifyChange( this.mainId, nv ) ) {
			return false;
		    }
		}

		this.field.value = nv;
	}
	
	this.top.style.display = "none";
	
	for( var j = 0; j < this.shadows.length; j ++ ) {
		document.body.removeChild( this.shadows[ j ] );
	}
	
	this.shadows.length = 0;
	FloatingCal.openInstance = null;
	this.limit = null;
}

FloatingCal.parseDate = function(fmt, t)
{
	var value = t;
	var index = 0;
	var buff = "";
	var res = { d:0, m:0, y:0 };
	
	if( (value != null) && (value !== undefined) && (value != "") ) {
		for( j = 0; j < fmt.length; j ++ ) {
			switch( fmt.charAt( j ) ) {
				case "d"	:
					buff = value.charAt( index++ );
					buff += value.charAt( index++ );
					res.d = new Number( buff );
					break;
	
				case "m"	:
					buff = value.charAt( index++ );
					buff += value.charAt( index++ );
					res.m = new Number( buff );
					break;
	
				case "y"	:
					buff = value.substr( index, 4 );
					index += 4;
					res.y = new Number( buff );
					break;
					
				default:
					index ++;
					break;
			}
		}
	}
	
	return res;
}

FloatingCal.prototype.onOpen = function()
{
	window.onbeforeunload = null;

	if( FloatingCal.openInstance != null ) {
		FloatingCal.openInstance.onClose();
	}
	
	if( !this.field ) return false;

	var value = this.field.value;

	this.current = FloatingCal.parseDate( this.vformat, value );
	
	var xy = getPageCoords( this.floref );
	
	this.draw( this.current.m, this.current.y );
	this.top.style.display = "block";
	this.top.style.position = "absolute";
	this.top.style.left = (xy.x + this.offX) + "px";
	this.top.style.top = (xy.y + this.offY) + "px";
	
	for( var j = 0; j < 7; j ++ ) {
		this.shadows[ j ] = document.createElement( "DIV" );
		this.setClass( this.shadows[ j ], "calendarShadow" );
		this.shadows[ j ].style.position = "absolute";
		this.shadows[ j ].style.display = "block";
		this.shadows[ j ].style.left = ((xy.x + this.offX) - (j + 1)) + "px";
		this.shadows[ j ].style.top = ((xy.y + this.offY) - (j + 1)) + "px";
		this.shadows[ j ].style.padding = ((j+1)*2) + "px " + ((j+1)*2) + "px " + "0px 0px";

		document.body.appendChild( this.shadows[ j ] );
	}
	
	FloatingCal.openInstance = this;
	return false;
}
