/*==============================================================================
	EZCalendar v0.9.1 Created by Stewart Orr (www.qodo.co.uk)
	http://www.qodo.co.uk/blog/javascript-pop-up-dhtml-calendar-using-css/
	Created: Oct 2006
	Updated: January 2008

	You are free to use this wherever you like, maybe you could contact me
	to let me know where/how you are using it.

	Usage:
		- Expects dates in the UK format DD/MM/YYYY.
		- Uses JS and CSS file to determine appearance
		- CSS File should have all necessary styles to ensure it appears
		correctly in YOUR page. Remember other CSS styles will affect this...

	To Do:
		- Position the calendar differently if it spills over the viewable space.
		- Improve Code
		- Allow different date separators
		- Allow different date formats (YYYY/MM/DD and MM/DD/YYYY)
		- Allow for date restrictions

	ChangeLog:
		- Jan 2008: Improvements to code and added fadeOut effect, added tooltips
		- March 2007: Added fading in effect
		- February 2007: Updated and improved coding
		- October 2006: created first version

==============================================================================*/

	var EZcalendar = false; 	// Loaded or not?
	var bCalendarFade = false;	// Fade in or not? Not suitable for slow machines
	var iCalendarFadeSpd = 5;	// Lower the number, faster it is.
	var selectedDate;			// whether the users cursor is over the calendar
	var target;					// the target element for the date value
	var dateSeparator = "/";	// date separator unit
	var overCalendar = false;	// whether the users cursor is over the calendar
	var selectPastDays = false;	// wether the users may select past days
	var calendarMinDate = new Date();	//Nuevo, se establece en la llamada a showCalendar()
	var showWeek = false;		// show week column or not?
	var showSelected = true;	// show selected date as highlighted instead of today's date?
	var language = "en";		// Default language

	// language strings
	var	fullMonthsStr = {
		es : new Array('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'),
		en : new Array('January','February','March','April','May','June','July','August','September','October','November','December'),
		de : new Array('Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'),
		it : new Array('Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre')
	};
	var	shortMonthsStr = {
		es : new Array('ENE','FEB','MAR','ABR','MAY','JUN','JUL','AGO','SEP','OCT','NOV','DIC'),
		en : new Array('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'),
		de : new Array('JAN','FEB','MRZ','APR','MAI','JUN','JUL','AUG','SEP','OKT','NOV','DEZ'),
		it : new Array('GEN','FEB','MAR','APR','MAG','GIU','LUG','AGO','SET','OTT','NOV','DIC')
	};
	var weekDaysStr = {
		es : new Array('L','M','M','J','V','S','D'),
		en : new Array('M','T','W','T','F','S','S'),
		de : new Array('M','D','M','D','F','S','S'),
		it : new Array('L','M','M','G','V','S','D')
	};
	var	previousMonthStr = {
		es : 'Mes anterior',
		en : 'Previous month',
		de : 'Vorigen Monat',
		it : 'Mese precedente'
	};
	var	nextMonthStr = {
		es : 'Mes siguiente',
		en : 'Next month',
		de : 'Nächste Monat',
		it : 'Mese prossimo'
	};
	var	previousYearStr = {
		es : 'Año anterior',
		en : 'Previous year',
		de : 'Voriges Jahr',
		it : 'Anno precedente'
	};
	var	nextYearStr = {
		es : 'Año siguiente',
		en : 'Next year',
		de : 'Nächstes Jahr',
		it : 'Anno prossimo'
	};

	// simply return an object by id
	function getID(id)
	{
		return document.getElementById(id);
	}

	// return a number with 2 digits ("2" becomes "02")
	function formatNumber(n)
	{
		return (n<10) ? "0"+n : n;
	}

	function getScrollFromTop()
	{
		if (self.pageYOffset) {
			return self.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop) {
			return document.documentElement.scrollTop;
		} else {
			return document.body.scrollTop;
		}
	}

	// return a number > 10 as one single digit ("09" becomes "9")
	function removeFormatNumber(n)
	{
		return (n.substr(0,1)=="0") ? n.substr(1,1) : n;
	}

	// return the on-screen LEFT(x) position of an element
	function getPageOffsetLeft(el)
	{
		return (el.offsetParent != null) ? el.offsetLeft + getPageOffsetLeft(el.offsetParent) : el.offsetLeft;
	}

	// return the on-screen TOP(y) position of an element
	function getPageOffsetTop(el)
	{
		return (el.offsetParent != null) ? el.offsetTop + getPageOffsetTop(el.offsetParent) : el.offsetTop;
	}

	// Checks a string to see if it in a valid date format
	// of (D)D/(M)M/(YY)YY and returns true/false
	function isValidDate(s)
	{
		// format D(D)/M(M)/(YY)YY
		var dateFormat = /^\d{1,2}\/\d{1,2}\/\d{2,4}$/;
		if (dateFormat.test(s)) {
			// remove any leading zeros from date values
			s = s.replace(/0*(\d*)/gi,"$1");
			var dateArray = s.split("/");
			// correct month value
			dateArray[1] = dateArray[1]-1;
			// correct year value
			if (dateArray[2].length<4) {
				// correct year value
				dateArray[2] = (parseInt(dateArray[2]) < 50) ? 2000 + parseInt(dateArray[2]) : 1900 + parseInt(dateArray[2]);
			}
			var testDate = new Date(dateArray[2], dateArray[1], dateArray[0]);
			if (testDate.getDate()!=dateArray[0] || testDate.getMonth()!=dateArray[1] || testDate.getFullYear()!=dateArray[2]) {
				return false;
			} else {
				return testDate;
			}
		} else {
			return false;
		}
	}


	// get the calendar week of a date
	function getWeek(d)
	{
		/* thanks to http://www.quirksmode.org/js/week.html */
		var today = new Date(d);
		Year = today.getFullYear();
		Month = today.getMonth();
		Day = today.getDate();
		now = Date.UTC(Year,Month,Day+1,0,0,0);
		var Firstday = new Date();
		Firstday.setYear(Year);
		Firstday.setMonth(0);
		Firstday.setDate(1);
		then = Date.UTC(Year,0,1,0,0,0);
		var Compensation = Firstday.getDay();
		if (Compensation > 3) Compensation -= 4;
		else Compensation += 3;
		NumberOfWeek =  Math.round((((now-then)/86400000)+Compensation)/7);
		return formatNumber(NumberOfWeek);
	}

	// change the calendar to the PREVIOUS month
	function prevMonth()
	{

		var months = getID("months");
		var years = getID("years");
		var today = new Date();
		if (!selectPastDays && months.value<=today.getMonth() && years.value<=today.getFullYear())
		{
			return false;
		}
		if (parseInt(months.value) - 1 >= 0) {
			months.value = parseInt(months.value) - 1;
		} else if (parseInt(years.value) > 1901) {
			months.value = 11;
			years.value = parseInt(years.value) - 1;
		}
		return updateCalendar();
	}

	// change the calendar to the NEXT month
	function nextMonth()
	{
		var months = getID("months");
		var years = getID("years");
		if (parseInt(months.value) + 1 < 12) {
			months.value = parseInt(months.value) + 1;
		} else if (parseInt(years.value) < 2099) {
			months.value = 0;
			years.value = parseInt(years.value) + 1;
		}
		updateCalendar();
	}

	// change the calendar to the PREVIOUS year
	function prevYear()
	{
		var years = getID("years");
		var today = new Date();
		if (!selectPastDays && years.value<=today.getFullYear())
		{
			return false;
		}
		if (parseInt(years.value) > 1901)
		{
			years.value = parseInt(years.value) - 1;
		}
		return updateCalendar();
	}

	// change the calendar to the NEXT year
	function nextYear()
	{
		var years = getID("years");
		if (parseInt(years.value) < 2099) {
			years.value = parseInt(years.value) + 1;
		}
		updateCalendar();
	}

	// update the calendars values
	// this changes the <a> tags innerHTML and href values
	function updateCalendar()
	{
		var today = new Date();			
		var y = getID("years");
		var m = getID("months");

		y = y.value;
		m = m.value;

		var selectedDate = (typeof target != "undefined") ? getID(target).value : '';
		var calendarDate = new Date(y,m,1);			
		var calDateStr = '';
		if (navigator.userAgent.indexOf('MSIE') > -1)
		{
			getID("EZcalendar_text").innerHTML =  "&nbsp;&nbsp;&nbsp;"+shortMonthsStr[language][calendarDate.getMonth()] + "" + calendarDate.getFullYear();
		}
		else
		{
			getID("EZcalendar_text").innerHTML =  shortMonthsStr[language][calendarDate.getMonth()] + " " + calendarDate.getFullYear();
		}



		var defaultMonth = calendarDate.getMonth();
		var difference = calendarDate.getDay()+6;

		calendarDate.setDate(calendarDate.getDate()-difference);

		for (var r=0; r < 6; r++)
		{
			if (showWeek)
			{
				getID("week"+r).innerHTML = getWeek(calendarDate);
			}

			for (var c=0; c < 7; c++)
			{
				calDateStr=formatNumber(calendarDate.getDate())+"/"+formatNumber(calendarDate.getMonth()+1)+"/"+calendarDate.getFullYear();

				if (calendarDate.getMonth()!=defaultMonth)
				{
					getID("cell"+r+c).className="outsideMonth";
				}
				else
				{
					getID("cell"+r+c).className="";
				}

				getID("cell"+r+c).href = "javascript:setDateValue('" + formatNumber(calendarDate.getDate()) + dateSeparator + formatNumber(calendarDate.getMonth()+1) + dateSeparator + calendarDate.getFullYear() + "')";

				// is it today's date?
				if (!showSelected && calDateStr==formatNumber(today.getDate())+"/"+formatNumber(today.getMonth()+1)+"/"+today.getFullYear())
				{
					getID("cell"+r+c).className="today";
				}
				else
				// is it the selected date?
				if (showSelected && calDateStr==selectedDate)
				{
					getID("cell"+r+c).className="selected";
				}
				else
				// is it a past date?
				//var now = new Date(); -> calendarMinDate
				if (!selectPastDays && (new Date(calendarMinDate.getFullYear(), calendarMinDate.getMonth(), calendarMinDate.getDate()) > new Date(calendarDate)))
				{
					getID("cell"+r+c).className="past";
					getID("cell"+r+c).href = "javascript:;";
				}

				getID("cell"+r+c).title = "";
				getID("cell"+r+c).innerHTML = calendarDate.getDate();
				getID("cell"+r+c).title = calendarDate.getDate() + " " + fullMonthsStr[language][calendarDate.getMonth()] + ", " + calendarDate.getFullYear();

				calendarDate.setDate(calendarDate.getDate()+1);
			}
		}
	}

	// when a user click the show calendar link, this function opens
	// the calendar and tries to show the correct calendar for the date in
	// the input field.
	function showCalendar(el, minDate)
	{
		//MOD
		if (typeof minDate != 'undefined')
			calendarMinDate = minDate;
		else
			calendarMinDate = Date();
		
		if (EZcalendar) {
			if (typeof el == "string") {
				el = getID(el);
			}
			target=el.id;
			var y = getID("years");
			var m = getID("months");
			var calendar = getID("EZcalendar");

			// test if string is valid date and if so, show calendar relative to the date they have chosen.
			var elementDate = isValidDate(el.value);
			if (calendarMinDate > elementDate) {
				m.value = calendarMinDate.getMonth();
				y.value = calendarMinDate.getFullYear();
			} else if (elementDate) {
				var elDate = el.value.replace(/0*(\d*)/gi,"$1");
				var dateArray = elDate.split(dateSeparator);
				// correct month value
				dateArray[1] = dateArray[1]-1;
				if (dateArray[2].length<4) {
					// correct year value
					dateArray[2] = (parseInt(dateArray[2]) < 50) ? 2000 + parseInt(dateArray[2]) : 1900 + parseInt(dateArray[2]);
				}
				m.value = dateArray[1];
				y.value = dateArray[2];
			} else {
				m.value = selectedDate.getMonth();
				y.value = selectedDate.getFullYear();
			}

			updateCalendar();

			var x = getPageOffsetLeft(el);
			var y = getPageOffsetTop(el) + el.clientHeight;
			calendar.style.top = (y+5)+"px";
			calendar.style.left = x+"px";
			if (bCalendarFade) {
				calendar.style.opacity = 0;
				calendar.style.filter = "alpha(opacity=0)";
				calendar.MozOpacity = 0;
				calendar.KhtmlOpacity = 0;
				setTimeout("fadeIn(5)",iCalendarFadeSpd);
			}
			calendar.style.display = "block";
		} else {
			alert("NOTICE:\n\nCalendar not finished loading, please wait...");
		}


	}

	/* When the user clicks, this function tries to detect
	if they have clicked outside the calendar and if so
	it tries to hide it. */
	function clickbg(e)
	{
		if (!overCalendar) {
			getID("EZcalendar").style.display="none";
		}
	}

	/* When a user click the calendar date, this function updates the input field */
	function setDateValue(d,el)
	{
		if (bCalendarFade) {
			setTimeout("fadeOut(95)",iCalendarFadeSpd);
		} else {
			getID("EZcalendar").style.display = "none";
		}
		getID(target).value=d;
		if (getID(target).onchange) getID(target).onchange();
	}

	/* Fading in the calendar in a nice way */
	function fadeIn(percentage)
	{
		var EZcalendar = getID("EZcalendar");
		// apply opacity for all browsers
		EZcalendar.style.opacity = percentage/100;
		EZcalendar.style.filter = "alpha(opacity="+percentage+")";
		EZcalendar.MozOpacity = (percentage / 100);
		EZcalendar.KhtmlOpacity = (percentage / 100);
		if (percentage<100) {
			setTimeout("fadeIn("+(percentage+5)+")",iCalendarFadeSpd);
		}
	}
	/* Fading in the calendar in a nice way */
	function fadeOut(percentage)
	{
		var EZcalendar = getID("EZcalendar");
		// apply opacity for all browsers
		EZcalendar.style.opacity = percentage/100;
		EZcalendar.style.filter = "alpha(opacity="+percentage+")";
		EZcalendar.MozOpacity = (percentage / 100);
		EZcalendar.KhtmlOpacity = (percentage / 100);
		if (percentage>0) {
			setTimeout("fadeOut("+(percentage-5)+")",iCalendarFadeSpd);
		} else {
			EZcalendar.style.display = "none";
		}
	}

	/* Loads the calendar for the first time by creating all the HTML */
	function initCalendar(lang)
	{
		// create our container DIV and add javascript to it
		var EZCalendarDIV = document.createElement('div');
		EZCalendarDIV.id = "EZcalendar";
		EZCalendarDIV.onmouseover = function() { overCalendar=true; }
		EZCalendarDIV.onmouseout  = function() { overCalendar=false; }

		// hide calendar by default
		EZCalendarDIV.style.display = "none";
		document.body.appendChild(EZCalendarDIV);

		// check if language exists
		if (typeof fullMonthsStr[lang] != "undefined") { language=lang; }

		selectedDate = new Date();

		var calendarHTML = "";

		calendarHTML += '<form action="#" method="get">';
		calendarHTML += '	<input id="months" name="months" type="hidden" value="' + selectedDate.getMonth() + '" />';
		calendarHTML += '	<input id="years" name="years" type="hidden" value="' + selectedDate.getFullYear() + '" />';
		calendarHTML += '	<div id="EZcalendar_table">';
		calendarHTML += '		<table border="1" cellpadding="0" cellspacing="0">';
		calendarHTML += '			<tr>';
		calendarHTML += '				<td><input type="button" value="&laquo;" onclick="prevYear()" title="' + previousYearStr[language] + '" /></td>';
		calendarHTML += '				<td><input type="button" value="&lsaquo;" onclick="prevMonth()" title="' + previousMonthStr[language] + '" /></td>';
		calendarHTML += '				<td colspan="' + (showWeek ? '4' : '3') + '" id="EZcalendar_text">' + shortMonthsStr[language][selectedDate.getMonth()] + " " + selectedDate.getFullYear() + '</td>';
		calendarHTML += '				<td><input type="button" value="&rsaquo;" onclick="nextMonth()" title="' + nextMonthStr[language] + '" /></td>';
		calendarHTML += '				<td><input type="button" value="&raquo;" onclick="nextYear()" title="' + nextYearStr[language] + '" /></td>';
		calendarHTML += '			</tr>';
		// build table using for loops...
		calendarHTML += '			<tr>';
		calendarHTML += showWeek ? '				<th scope="col">&nbsp;</th>' : '';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][0] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][1] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][2] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][3] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][4] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][5] + '</th>';
		calendarHTML += '				<th scope="col">' + weekDaysStr[language][6] + '</th>';
		calendarHTML += '			</tr>';

		for (var r=0; r<6; r++)
		{
			calendarHTML += '	<tr>';

			if (showWeek)
			{
				calendarHTML += '		<th scope="row" id="week' + r + '">00</th>';
			}

			for (var c=0; c<7; c++)
			{
				calendarHTML += '		<td><a href="#" id="cell'+ r + "" + c +'">00</a></td>';
			}
		}

		calendarHTML += '	</tr>';
		calendarHTML += '</table>';
		// ... end
		calendarHTML += '	</div>';
		calendarHTML += '	</form>';

		EZCalendarDIV.innerHTML = calendarHTML;
		EZcalendar = true;
		document.onmousedown = clickbg;
		updateCalendar();
	}