// Title: Tigra Calendar
// URL: http://www.softcomplex.com/products/tigra_calendar/
// Version: 3.2 (European date format)
// Date: 10/14/2002 (mm/dd/yyyy)
// Feedback: feedback@softcomplex.com (specify product title in the subject)
// Note: Permission given to use this script in ANY kind of applications if
//    header lines are left unchanged.
// Note: Script consists of two files: calendar?.js and calendar.html
// About us: Our company provides offshore IT consulting services.
//    Contact us at sales@softcomplex.com if you have any programming task you
//    want to be handled by professionals. Our typical hourly rate is $20.

// if two digit year input dates after this year considered 20 century.
var NUM_CENTYEAR = 30;
// is time input control required by default
var BUL_TIMECOMPONENT = false;
// are year scrolling buttons required by default
var BUL_YEARSCROLL = true;

var calendars = [];
var RE_NUM = /^\-?\d+$/;

function calendar1(obj_target) {

	// assing methods
	this.gen_date = cal_gen_date1;
	this.gen_time = cal_gen_time1;
	this.gen_tsmp = cal_gen_tsmp1;
	this.prs_date = cal_prs_date1;
	this.prs_time = cal_prs_time1;
	this.prs_tsmp = cal_prs_tsmp1;
	this.popup    = cal_popup1;

	// validate input parameters
	if (!obj_target)
		return cal_error("Error calling the calendar: no target control specified");
	if (obj_target.value == null)
		return cal_error("Error calling the calendar: parameter specified is not valid tardet control");
	this.target = obj_target;
	this.time_comp = BUL_TIMECOMPONENT;
	this.year_scroll = BUL_YEARSCROLL;

	// register in global collections
	this.id = calendars.length;
	calendars[this.id] = this;
}

function cal_popup1 (str_datetime) {
	this.dt_current = this.prs_tsmp(str_datetime ? str_datetime : this.target.value);
	if (!this.dt_current) return;

	var obj_calwindow = window.open(
		'/js/helpers/calendar.html?datetime=' + this.dt_current.valueOf()+ '&id=' + this.id,
		'Calendar', 'width=200,height='+(this.time_comp ? 215 : 190)+
		',status=no,resizable=no,top=200,left=200,dependent=yes,alwaysRaised=yes'
	);
	obj_calwindow.opener = window;
	obj_calwindow.focus();
}

// timestamp generating function
function cal_gen_tsmp1 (dt_datetime) {
	return(this.gen_date(dt_datetime) + ' ' + this.gen_time(dt_datetime));
}

// date generating function
// 16.03.2004 EF änderung auf yyyy-mm-dd (array [0] -> [2] ; [2] -> [0])
function cal_gen_date1 (dt_datetime) {
	var asd =	dt_datetime.getFullYear() + "-"
				+ (dt_datetime.getMonth() < 9 ? '0' : '') + (dt_datetime.getMonth() + 1) + "-"
				+ (dt_datetime.getDate() < 10 ? '0' : '') + dt_datetime.getDate()
	return asd;
}
// time generating function
function cal_gen_time1 (dt_datetime) {
	return (
		(dt_datetime.getHours() < 10 ? '0' : '') + dt_datetime.getHours() + ":"
		+ (dt_datetime.getMinutes() < 10 ? '0' : '') + (dt_datetime.getMinutes()) + ":"
		+ (dt_datetime.getSeconds() < 10 ? '0' : '') + (dt_datetime.getSeconds())
	);
}

// timestamp parsing function
function cal_prs_tsmp1 (str_datetime) {
	// if no parameter specified return current timestamp
	if (!str_datetime || str_datetime == ' ')
		return (new Date());

	// if positive integer treat as milliseconds from epoch
	if (RE_NUM.exec(str_datetime))
		return new Date(str_datetime);

	// else treat as date in string format
	var arr_datetime = str_datetime.split(' ');
	return this.prs_time(arr_datetime[1], this.prs_date(arr_datetime[0]));
}

// date parsing function
// 16.03.2004 EF änderung auf yyyy-mm-dd (array [0] -> [2] ; [2] -> [0])
function cal_prs_date1 (str_date) {

	var arr_date = str_date.split('-');

	if (arr_date.length != 3) return cal_error ("Invalid date format: '" + str_date + "'.\nFormat accepted is dd-mm-yyyy.");
	if (!arr_date[2]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo day of month value can be found.");
	if (!RE_NUM.exec(arr_date[2])) return cal_error ("Invalid day of month value: '" + arr_date[2] + "'.\nAllowed values are unsigned integers.");
	if (!arr_date[1]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo month value can be found.");
	if (!RE_NUM.exec(arr_date[1])) return cal_error ("Invalid month value: '" + arr_date[1] + "'.\nAllowed values are unsigned integers.");
	if (!arr_date[0]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo year value can be found.");
	if (!RE_NUM.exec(arr_date[0])) return cal_error ("Invalid year value: '" + arr_date[0] + "'.\nAllowed values are unsigned integers.");

	var dt_date = new Date();
	dt_date.setDate(1);

	if (arr_date[1] < 1 || arr_date[1] > 12) return cal_error ("Invalid month value: '" + arr_date[1] + "'.\nAllowed range is 01-12.");
	dt_date.setMonth(arr_date[1]-1);

	if (arr_date[0] < 100) arr_date[0] = Number(arr_date[0]) + (arr_date[0] < NUM_CENTYEAR ? 2000 : 1900);
	dt_date.setFullYear(arr_date[0]);

	var dt_numdays = new Date(arr_date[0], arr_date[1], 0);
	dt_date.setDate(arr_date[2]);
	if (dt_date.getMonth() != (arr_date[1]-1)) return cal_error ("Invalid day of month value: '" + arr_date[2] + "'.\nAllowed range is 01-"+dt_numdays.getDate()+".");

	return (dt_date)
}

// time parsing function
function cal_prs_time1 (str_time, dt_date) {

	if (!dt_date) return null;
	var arr_time = String(str_time ? str_time : '').split(':');

	if (!arr_time[0]) dt_date.setHours(0);
	else if (RE_NUM.exec(arr_time[0]))
		if (arr_time[0] < 24) dt_date.setHours(arr_time[0]);
		else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed range is 00-23.");
	else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed values are unsigned integers.");

	if (!arr_time[1]) dt_date.setMinutes(0);
	else if (RE_NUM.exec(arr_time[1]))
		if (arr_time[1] < 60) dt_date.setMinutes(arr_time[1]);
		else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed range is 00-59.");
	else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed values are unsigned integers.");

	if (!arr_time[2]) dt_date.setSeconds(0);
	else if (RE_NUM.exec(arr_time[2]))
		if (arr_time[2] < 60) dt_date.setSeconds(arr_time[2]);
		else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed range is 00-59.");
	else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed values are unsigned integers.");

	dt_date.setMilliseconds(0);
	return dt_date;
}

function cal_error (str_message) {
	alert (str_message);
	return null;
}



/********************************************************************/
/*** Calendar                                                     ***/
/********************************************************************/

function Calendar( idCalendar, idField, dateString )
	{
	this.idCalendar = idCalendar;
	this.Field = idField;
	this.Date = dateString;

	this.getDays = getDays;
	this.getToday = getToday;
	this.setDate = setDate;
	this.getDate = getDate;
	this.setDisplay = setDisplay;
	this.setCalendar = setCalendar;
	this.setBusyDays = setBusyDays;

	this.increaseYear = increaseYear;
	this.decreaseYear = decreaseYear;
	this.increaseMonth = increaseMonth;
	this.decreaseMonth = decreaseMonth;

	this.today = new getToday();
	this.yearFrom = this.today.year - 5;
	this.yearTo = this.today.year + 5;
	this.busyDays = "";

	this.year = -1;
	this.month = -1;
	this.day = -1;

	this.yearWeek = -1;
	this.monthWeek = -1;
	this.dayWeek = -1;

	return this;
	};

function setBusyDays( busyDays )
	{
	if( busyDays )
		this.busyDays = busyDays;

	this.setCalendar();
	};

function setDisplay( yearFrom, yearTo, busyDays )
	{
	if( yearFrom )
		this.yearFrom = yearFrom;
	if( yearTo )
		this.yearTo = yearTo;
	if( busyDays )
		this.busyDays = busyDays;

	this.elementField = document.getElementById( this.Field );

	this.elementCalendar = document.getElementById( "Calendar|" + this.idCalendar );
	this.elementDisplay = document.getElementById( "Calendar|" + this.idCalendar + "|Display" );
	this.elementYear = document.getElementById( "Calendar|" + this.idCalendar + "|Year" );
	this.elementMonth = document.getElementById( "Calendar|" + this.idCalendar + "|Month" );
	this.elementDay = document.getElementById( "Calendar|" + this.idCalendar + "|Day" );
	this.elementBox = document.getElementById( "Calendar|" + this.idCalendar + "|Box" );

	if( this.elementBox )
		{
		if( this.elementBox.style.display == "none" )
			{
			this.setDate();
			this.setCalendar();

			this.elementBox.style.display = "inline";
			setWidth( "Calendar|" + this.idCalendar + '|Frame', getOffsetWidth( "Calendar|" + this.idCalendar ) );
			setHeight( "Calendar|" + this.idCalendar + '|Frame', getOffsetHeight( "Calendar|" + this.idCalendar + '|Height' ) );
			}
		else
			this.elementBox.style.display = "none";
		}
	else
		{
		this.setDate();
		this.setCalendar();
		};
	};

var _DaysMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

function getDays( _Month, _Year )
	{
	// Test for leap year when February is selected.

	if( _Month == 1 )
		return( ( _Year % 4 == 0 ) && ( ( _Year % 100 ) != 0 ) ) || ( _Year % 400 == 0 ) ? 29 : 28;
	else
		return _DaysMonth[_Month];
	};

function getToday()
	{
	// Generate today's date.

	this.now = new Date();
	this.year = this.now.getFullYear();
	this.month = this.now.getMonth();
	this.day = this.now.getDate();
	};

function setCalendar()
	{
	var parseYear = ( this.elementYear ? parseInt( this.elementYear[ this.elementYear.selectedIndex ].text ) : this.year );
	var parseMonth = ( this.elementMonth ? parseInt( this.elementMonth.selectedIndex ) : this.month );
	var newCal = new Date( parseYear, parseMonth, 1 );
	var startDay = ( newCal.getDay() + 6 ) % 7;

	if( startDay == 0 )
		startDay = 7;

	if( parseMonth > 0 )
		{
		var previousYear = parseYear;
		var previousMonth = parseMonth - 1;
		}
	else
		{
		var previousYear = parseYear - 1;
		var previousMonth = 11;
		};
	var previousCal = new Date( previousYear, previousMonth, 1 );
	var previousDay = getDays( previousCal.getMonth(), previousCal.getFullYear() ) - startDay + 1;

	if( parseMonth >= 11 )
		{
		var nextYear = parseYear + 1;
		var nextMonth = 0;
		}
	else
		{
		var nextYear = parseYear;
		var nextMonth = parseMonth + 1;
		};
	var nextCal = new Date( nextYear, nextMonth, 1 );
	var nextDay = 1;

	var dayset = -1;
	var weekset = -1;
	var day = -1;
	var daily = 0;

	var today = new getToday(); // 1st call
	if( ( today.year == newCal.getFullYear() ) && ( today.month == newCal.getMonth() ) )
		day = today.day;

	if( ( this.year == newCal.getFullYear() ) && ( this.month == newCal.getMonth() ) )
		dayset = this.day;
	if( ( this.yearWeek == newCal.getFullYear() ) && ( this.monthWeek == newCal.getMonth() ) )
		weekset = getWeekNumber( new Date( this.yearWeek, this.monthWeek, this.dayWeek ) );
	else if( ( this.yearWeek == previousCal.getFullYear() ) && ( this.monthWeek == previousCal.getMonth() ) )
		weekset = getWeekNumber( new Date( this.yearWeek, this.monthWeek, this.dayWeek ) );
	else if( ( this.yearWeek == nextCal.getFullYear() ) && ( this.monthWeek == nextCal.getMonth() ) )
		weekset = getWeekNumber( new Date( this.yearWeek, this.monthWeek, this.dayWeek ) );

	// Cache the calendar table's tBody section, dayList.
	var tableCal = this.elementDay;

	var intDaysInMonth =
	   getDays( newCal.getMonth(), newCal.getFullYear() );

	var thisDate = newCal.getTime();

	for( var intWeek = 0; intWeek < tableCal.rows.length; intWeek++ )
		{
		var weekNumber = 0;
		var weekCell = null;

		for( var intDay = 0; intDay < tableCal.rows[intWeek].cells.length; intDay++ )
			{
			var cell = tableCal.rows[intWeek].cells[intDay];
			var thisDay = intDay + ( 7 - tableCal.rows[intWeek].cells.length );

			if( thisDay < 0 )
				{
				if( thisDay == -1 )
					{
					weekNumber = getWeekNumber( new Date( thisDate ) );
					cell.className = 'weekNumber';
					cell.innerHTML = weekNumber;
					weekCell = cell;
					};
				}
			else
				{
				// Start counting days.
				if( ( daily == 0 ) && ( thisDay == startDay || intWeek > 0 ) )
					daily = 1;

				// Output the day number into the cell.
				if( ( daily > 0 ) && ( daily <= intDaysInMonth ) )
					{
					dateString = newCal.getFullYear() + "-" + ( newCal.getMonth() < 9 ? '0' : '' ) + ( newCal.getMonth() + 1 ) + "-" + ( daily < 10 ? '0' : '' ) + daily;
					cell.className = ( ( dayset == daily || weekset == weekNumber ) ? ( ( day == daily ) ? 'daySetToday' : 'daySet' ) : ( ( day == daily ) ? 'dayToday' : 'dayOn' ) );
					cell.style.fontWeight = "";
					if( this.busyDays.search( dateString ) != -1 )
						cell.style.fontWeight = "bold";
					cell.setAttribute( "day", dateString );
					cell.innerHTML = daily++;
					}
				else if( daily == 0 )
					{
					dateString = previousCal.getFullYear() + "-" + ( previousCal.getMonth() < 9 ? '0' : '' ) + ( previousCal.getMonth() + 1 ) + "-" + ( previousDay < 10 ? '0' : '' ) + previousDay;
					cell.className = ( ( dayset == daily || weekset == weekNumber ) ? 'daySetOff' : ( ( day == daily ) ? 'dayToday' : 'dayOff' ) );
					cell.style.fontWeight = "";
					if( this.busyDays.search( dateString ) != -1 )
						cell.style.fontWeight = "bold";
					cell.setAttribute( "day", dateString );
					cell.innerHTML = previousDay++;
					}
				else
					{
					dateString = nextCal.getFullYear() + "-" + ( nextCal.getMonth() < 9 ? '0' : '' ) + ( nextCal.getMonth() + 1 ) + "-" + ( nextDay < 10 ? '0' : '' ) + nextDay;
					cell.className = ( ( dayset == daily || weekset == weekNumber ) ? 'daySetOff' : ( ( day == daily ) ? 'dayToday' : 'dayOff' ) );
					cell.style.fontWeight = "";
					if( this.busyDays.search( dateString ) != -1 )
						cell.style.fontWeight = "bold";
					cell.setAttribute( "day", dateString );
					cell.innerHTML = nextDay++;
					};

				thisDate += ( 24 * 60 * 60 * 1000 );

				if( weekCell )
					{
					if( thisDay == 0 )
						weekCell.setAttribute( "week", cell.getAttribute( "day" ) );
					else if( thisDay == 6 )
						weekCell.setAttribute( "week", weekCell.getAttribute( "week" ) + "," + cell.getAttribute( "day" ) );
					};
				};
			};
		};

	if( this.elementDisplay && this.elementMonth && this.elementYear )
		this.elementDisplay.innerHTML = this.elementMonth[ this.elementMonth.selectedIndex ].text + " " + this.elementYear[ this.elementYear.selectedIndex ].text;
	};

function getWeekNumber( newCal )
	{
	var d = new Date(newCal.getFullYear(), newCal.getMonth(), newCal.getDate(), 0, 0, 0);
	var DoW = d.getDay();
	d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
	var ms = d.valueOf(); // GMT
	d.setMonth(0);
	d.setDate(4); // Thu in Week 1
	return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
	};

function setDate( _Today )
	{
	_Year = this.today.year;
	_Month = this.today.month;
	_Day = this.today.day;

	if( !_Today )
		{
		_DateFrom = "";
		_DateTo = "";
		if( this.elementField.value.length && this.elementField.value != " " )
			{
			_Date = this.elementField.value.split( "," );
			_DateFrom = _Date[0].split( "-" );

			if( _Date.length > 1 )
				_DateTo = _Date[1].split( "-" );
			}
		else if( this.Date != undefined && this.Date.length && this.Date != " " )
			_DateFrom = this.Date.split( "-" );

		if( _DateFrom.length )
			{
			_Year = _DateFrom[0];
			_Month = _DateFrom[1] - 1;
			_Day = _DateFrom[2];

			this.year = _Year;
			this.month = _Month;
			this.day = _Day;
			};

		if( _DateTo.length )
			{
			this.yearWeek = _DateTo[0];
			this.monthWeek = _DateTo[1] - 1;
			this.dayWeek = _DateTo[2];
			}
		else
			{
			this.yearWeek = -1;
			this.monthWeek = -1;
			this.dayWeek = -1;
			};
		};

	if( this.elementCalendar )
		this.elementCalendar.style.display = "inline";
	if( this.elementYear )
		this.elementYear.selectedIndex = _Year - this.yearFrom;
	if( this.elementMonth )
		this.elementMonth.selectedIndex = _Month;
	};

function getDate( _Date, bClose )
	{
	// This code executes when the user clicks on a day
	// in the calendar.

	if( _Date != "" )
		{
		// this.elementField.value = _Date;
		// ds always fires onChange event
		if( this.elementField )
			{
			this.elementField.value = _Date;

			if( this.elementField.onchange )
				this.elementField.onchange();
			};

		if( bClose == undefined )
			bClose = true;
		if( this.elementCalendar && bClose )
			this.elementCalendar.style.display = "none";
		};
	};

function decreaseYear()
	{
	if( this.elementYear )
		if( this.elementYear.selectedIndex )
			this.elementYear.selectedIndex--;
		else
			return false;

	return true;
	};

function increaseYear()
	{
	if( this.elementYear )
		if( this.elementYear.selectedIndex < ( this.elementYear.length - 1 ) )
			this.elementYear.selectedIndex++;
		else
			return false;

	return true;
	};

function decreaseMonth()
	{
	if( this.elementMonth )
		if( this.elementMonth.selectedIndex )
			this.elementMonth.selectedIndex--;
		else
			{
			if( this.decreaseYear() )
				this.elementMonth.selectedIndex = 11;
			else
				return false;
			};

	return true;
	};

function increaseMonth()
	{
	if( this.elementMonth )
		if( this.elementMonth.selectedIndex < ( this.elementMonth.length - 1 ) )
			this.elementMonth.selectedIndex++;
		else
			{
			if( this.increaseYear() )
				this.elementMonth.selectedIndex = 0;
			else
				return false;
			};

	return true;
	};

function isDate( yyyy, mm, dd )
	{
	var d = new Date( yyyy, mm - 1, dd );

	if( ( d.getFullYear() == yyyy ) && ( d.getMonth() == ( mm - 1 ) ) && ( d.getDate() == dd ) )
        return true;
    else
        return false
	};

function jsDate( textDate, textTime, getUTC, daylightsaving )
	{
	if( textDate && textDate.length > 0 )
		{
		var ds = textDate.split( "-" );

		if( ds.length >= 3 && isNumeric( ds[0] ) && isNumeric( ds[1] ) && isNumeric( ds[2] ) )
			{
			var hh = "00";
			var mm = "00";
			var ss = "00";

			if( textTime && textTime.length > 0 )
				{
				var ts = textTime.split( ":" );

				if( ts.length >= 3 )
					{
					hh = ts[0];
					mm = ts[1];
					ss = ts[2];
					}
				else if( ts.length == 2 )
					{
					hh = ts[0];
					mm = ts[1];
					}
				else if( ts.length == 1 )
					{
					hh = ts[0];
					};
				};

			if( getUTC )
				if(daylightsaving == true)	{
					return( Date.UTC( ds[0], ds[1] - 1, ds[2], hh-1, mm, ss ) );
				}
				else	{
					return( Date.UTC( ds[0], ds[1] - 1, ds[2], hh, mm, ss ) );
				}
			else
				return( new Date( ds[0], ds[1] - 1, ds[2], hh, mm, ss ) );
			};
		};

	return null;
	};

function isNumeric( n )
    {
	var v = 1.0 * n;

	if( v == 0.0 || isNaN(v) )
		return false;
	else
		return true;
    };

function formatNumber( n, nn )
	{
	if( n.length >= nn )
		return n;

	for( var i = 1; i < nn; i++ )
		n = "0" + n;

	return n;
	};

function formatDate( o, yf, yt )
	{
	var r = false;

	d = o.value;
	d = d.replace( /[.\/]/g, '-' );
	d = d.replace( /[.\/]/g, '-' );

	ds = d.split( '-' );

	if( ds.length == 3 && isNumeric( ds[0] ) && isNumeric( ds[1] ) && isNumeric( ds[2] ) )
		{
		if( ds[0].length == 4 )
			{
			if( isDate( ds[0], ds[1], ds[2] ) && ds[2] <= getDays( ds[1] - 1, ds[0] ) )
				{
				if( ds[0] >= yf && ds[0] <= yt )
					{
					d = formatNumber( ds[0], 4 );
					d = d + "-";
					d = d + formatNumber( ds[1], 2 );
					d = d + "-";
					d = d + formatNumber( ds[2], 2 );

					r = true;
					}
				else	// not valid date
					d = "";
				}
			else	// not valid date
				d = "";
			}
		else if( ds[2].length == 4 )
			{
			if( isDate( ds[2], ds[1], ds[0] ) && ds[0] <= getDays( ds[1] - 1, ds[2] ) )
				{
				if( ds[2] >= yf && ds[2] <= yt )
					{
					d = formatNumber( ds[2], 4 );
					d = d + "-";
					d = d + formatNumber( ds[1], 2 );
					d = d + "-";
					d = d + formatNumber( ds[0], 2 );

					r = true;
					}
				else	// not valid date
					d = "";
				}
			else	// not valid date
				d = "";
			}
		else	// not valid date
			d = "";
		}
	else	// not valid date
		d = "";

	o.value = d;

	return r;
	};
	 