﻿//Control calendario javascript:
//Es una variación del publicado en http://www.flooble.com/scripts/calendar.php

	//<Valores por defecto>
	//(en caso no se haya inicializado la localización en las páginas):
	var cal_defaultDateFormat = "dd/mm/yyyy";
	var cal_defaultTitle = "Calendario";
	var cal_defaultWeekDaysAbbrNames = new Array('Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sáb', 'Dom')
	var cal_defaultWeekDaysNames = new Array('Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo')
	var cal_defaultMonthAbbrNames = new Array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic');
	//</Valores por defecto>

	var calendars = Array();
	var cal_monthAbbrNames = null;
	var cal_weekDaysAbbrNames = null;
	var cal_weekDaysNames = null;
	var cal_openCal;
	var cal_stuffInitzed = false;
	var cal_title = "";

	var cal_calCount = 0;

	function initCalendarStuff()
	{
        cal_monthAbbrNames = (typeof(monthAbbrNames) != "undefined") ? monthAbbrNames : cal_defaultMonthAbbrNames;
		cal_title = (typeof(calendarTitle) != "undefined") ? calendarTitle : cal_defaultTitle;
		cal_weekDaysAbbrNames = (typeof(weekDaysAbbrNames) != "undefined") ? weekDaysAbbrNames : cal_defaultWeekDaysAbbrNames;
		cal_weekDaysNames = (typeof(weekDaysNames) != "undefined") ? weekDaysNames : cal_defaultWeekDaysNames;
		
		cal_stuffInitzed = true;
	}

	function getCalendar(fieldId)
	{
		var formElement = cal_getObj(fieldId);
		return ensureCalendarObject(formElement);
	}
	
	function displayCalendarFor(fieldId)
	{
		if(!cal_stuffInitzed)
			initCalendarStuff();

		var formElement = cal_getObj(fieldId);
		displayCalendar(formElement);
	}
	
	//<Gianluca Risi>:
	//Si no está creado ya el objeto asociado al elemento formElemen se crea
	//y se añade a la colección de calendarios de la página
	//</Gianluca Risi>
	function ensureCalendarObject(formElement)
	{
	    if (!formElement.id)
	    {
            formElement.id = cal_calCount++;
        }

		var cal = calendars[formElement.id];

		if (typeof(cal) == 'undefined')
		{
			cal = new calendarObject();
			cal.setElement(formElement);
			calendars[formElement.id] = cal;
		}
		
		return cal;
	}

	function displayCalendar(formElement)
	{
        var cal = ensureCalendarObject(formElement);
        
		if (cal.shown)
			cal.hide();
		else
			cal.show();
	}

	function display3FieldCalendar(me, de, ye)
	{
		if (!me.id)
			me.id = cal_calCount++;

		if (!de.id)
			de.id = cal_calCount++;

		if (!ye.id)
			ye.id = cal_calCount++;

		var id = me.id + '-' + de.id + '-' + ye.id;

		var cal = calendars[id];

		if (typeof(cal) == 'undefined')
		{
			cal = new calendarObject();
			cal.setElements(me, de, ye);
			calendars[id] = cal;
		}

		if (cal.shown)
			cal.hide();
		else
			cal.show();
	}

	//--Class Stuff--------------------------------------------------
	function calendarObject()
	{
		// Define Methods
		this.setElement = cal_setElement;
		this.setElements = cal_setElements;
		this.parseDate = cal_parseDate;
		this.generateHTML = cal_generateHTML;
		this.show = cal_show;
		this.hide = cal_hide;
		this.moveMonth = cal_moveMonth;
		this.setDate = cal_setDate;
		this.formatDate = cal_formatDate;
		this.setDateFields = cal_setDateFields;
		this.parseDateFields = cal_parseDateFields;
		
		//<Gianluca Risi>:
		//Gestor del evento "Fecha seleccionada"
    	//</Gianluca Risi>
		this.onDateSelected = null;

		this.shown = false;
	}

	function cal_setElement(formElement)
	{
		this.element = formElement;
		if(this.element.dateFormat)
			this.format = this.element.dateFormat;
		else
			this.format = cal_defaultDateFormat;
		this.value = this.element.value;
		this.id = this.element.id;
		this.mode = 1;
	}

	function cal_setElements(monthElement, dayElement, yearElement)
	{
		this.mElement = monthElement;
		this.dElement = dayElement;
		this.yElement = yearElement;
		this.id = this.mElement.id + '-' + this.dElement.id + '-' + this.yElement.id;
		this.element = this.mElement;

		if (cal_absoluteOffsetLeft(this.dElement) < cal_absoluteOffsetLeft(this.element))
			this.element = this.dElement;

		if (cal_absoluteOffsetLeft(this.yElement) < cal_absoluteOffsetLeft(this.element))
			this.element = this.yElement;

		if (cal_absoluteOffsetTop(this.mElement) > cal_absoluteOffsetTop(this.element))
			this.element = this.mElement;

		if (cal_absoluteOffsetTop(this.dElement) > cal_absoluteOffsetTop(this.element))
			this.element = this.dElement;

		if (cal_absoluteOffsetTop(this.yElement) > cal_absoluteOffsetTop(this.element))
			this.element = this.yElement;

		this.mode = 2;
	}

	//Parsea el campo de texto para inicializar el calendario:
	function cal_parseDate()
	{
		if (this.element.value)
		{
			this.date = new Date();
			var out = '';
			var token = '';
			var lastCh, ch;
			var start = 0;

			lastCh = this.format.substring(0, 1);

			for (i = 0; i < this.format.length; i++)
			{
				ch = this.format.substring(i, i+1);
				if (ch == lastCh)
					token += ch;
				else
				{
					cal_parseToken(this.date, token, this.element.value, start);
					start += token.length;
					token = ch;
				}
				lastCh = ch;
			}

			cal_parseToken(this.date, token, this.element.value, start);
		}
		else
			this.date = new Date();

		if ('' + this.date.getMonth() == 'NaN')
			this.date = new Date();
	}

	function cal_parseDateFields()
	{
		this.date = new Date();
		if (this.mElement.value)
			this.date.setMonth(cal_getFieldValue(this.mElement) - 1);

		if (this.dElement.value)
			this.date.setDate(cal_getFieldValue(this.dElement));

		if (this.yElement.value)
			this.date.setFullYear(cal_getFieldValue(this.yElement));

		if ('' + this.date.getMonth() == 'NaN')
			this.date = new Date();
	}

	function cal_setDate(d, m, y)
	{
		this.date.setYear(y);
		this.date.setMonth(m);
		this.date.setDate(d);

		if (this.mode == 1)
			this.element.value = this.formatDate();
		else
			this.setDateFields();
			
		this.hide();

        //<Gianluca Risi>:
        //Si desde fuera se ha definido un gestor de evento, este es el momento de llamarlo
    	//</Gianluca Risi>
        if(this.onDateSelected != null)
            this.onDateSelected();
	}

	function cal_setDateFields()
	{
		cal_setFieldValue(this.mElement, cal_zeroPad(this.date.getMonth() + 1));
		cal_setFieldValue(this.dElement, cal_zeroPad(this.date.getDate()));
		cal_setFieldValue(this.yElement, this.date.getFullYear());
	}

	function cal_formatDate()
	{
		var out = '';
		var token = '';
		var lastCh, ch;
		lastCh = this.format.substring(0, 1);

		for (i = 0; i < this.format.length; i++)
		{
			ch = this.format.substring(i, i+1);

			if (ch == lastCh)
				token += ch;
			else
			{
				out += cal_formatToken(this.date, token);
				token = ch;
			}

			lastCh = ch;
		}

		out += cal_formatToken(this.date, token);
		return out;
	}

	function cal_show()
	{
		if (typeof(cal_openCal) != 'undefined')
			cal_openCal.hide();

		if (this.mode == 1)
		{
			this.parseDate();
        }
		else
		{
			this.parseDateFields();
        }

		this.showDate = new Date(this.date.getTime());

		if (typeof(this.div) == 'undefined')
		{
			this.div = document.createElement('DIV');
			this.div.style.position = 'absolute';
			this.div.style.display = 'none';
			this.div.className = 'cal_main';
		    //En caso de browsers <> IE, es necesario que los valores pasados a .left y .top sean cadenas
		    //que especifiquen también la unidad de medida
		    this.div.style.left = cal_absoluteOffsetLeft(this.element) + "px";
			this.div.style.top = (cal_absoluteOffsetTop(this.element) + this.element.offsetHeight + 1) + "px";
			document.body.appendChild(this.div);
		}
		
		this.div.innerHTML = this.generateHTML();
		this.div.style.display = 'block';
		this.shown = true;
		cal_openCal = this;
	}

	function cal_generateHTML()
	{
		var html = '';
		html += '<table>';
		html += '	<tr>';
		html += '		<td class="cal_head" colspan="6">' + cal_title + '</td>';
		html += '		<td class="cal_button" onMouseover="this.className = \'cal_buttonHover\';" onMouseout="this.className=\'cal_button\';" onClick="getCalendar(\'' + this.id + '\').hide();"><b>X</b></td>';
		html += '	</tr>';
		html += '	<tr>';
		html += '		<td class="cal_button" onMouseover="this.className = \'cal_buttonHover\';" onMouseout="this.className=\'cal_button\';" onClick="getCalendar(\'' + this.id + '\').moveMonth(-12);"><b><<</b></td>';
		html += '		<td class="cal_button" onMouseover="this.className = \'cal_buttonHover\';" onMouseout="this.className=\'cal_button\';" onClick="getCalendar(\'' + this.id + '\').moveMonth(-1);"><b><</b></td>';
		html += '		<td colspan="3" class="cal_wk">' + cal_monthAbbrNames[this.showDate.getMonth()] + ' ' + cal_getYear(this.showDate) + '</td>';
		html += '		<td class="cal_button" onMouseover="this.className = \'cal_buttonHover\';" onMouseout="this.className=\'cal_button\';" onClick="getCalendar(\'' + this.id + '\').moveMonth(1);"><b>></b></td>';
		html += '		<td class="cal_button" onMouseover="this.className = \'cal_buttonHover\';" onMouseout="this.className=\'cal_button\';" onClick="getCalendar(\'' + this.id + '\').moveMonth(12);"><b>>></b></td>';
		html += '	</tr>';

		html += '	<tr>';
		for(var day=0;day<cal_weekDaysAbbrNames.length;day++)
		{
			var className = (day < 5) ? "cal_wk" : "cal_wknd";
			html += '		<td width="14%" class="' + className + '" title="' + cal_weekDaysNames[day] + '">' + cal_weekDaysAbbrNames[day] + '</td>';
		}
		html += '	</tr>';

		html += '	<tr>';

		var dow = 0;
		var i, style;
		var totald = cal_monthLength(this.showDate);

		for (i = 0; i < cal_firstDOW(this.showDate); i++)
		{
			dow++;
			html += '		<td class="cal_wk2">&nbsp;</td>';
		}

		for (i = 1; i <= totald; i++)
		{
			if (dow == 0)
				html += '	<tr>';

			if (this.showDate.getMonth() == this.date.getMonth() && this.showDate.getYear() == this.date.getYear() && this.date.getDate() == i)
				style = ' style="font-weight: bold;"';
			else
				style = '';

			html += '		<td class="cal_date" onMouseover="this.className = \'cal_dateHover\';" onMouseout="this.className=\'cal_date\';" onClick="getCalendar(\'' + this.id + '\').setDate(' + i + ', ' + this.showDate.getMonth() + ', ' + this.showDate.getFullYear() + ');" ' + style + '>' + i + '</td>';
			dow++;
			if (dow == 7)
			{
				html += '	</tr>';
				dow = 0;
			}
		}

		if (dow != 0)
			for (i = dow; i < 7; i++)
				html += '		<td class="cal_wk2">&nbsp;</td>';

		html +='	</tr>';
		html += '</table>';

		return html;
	}

	function cal_hide()
	{
		if (this.div != false)
			this.div.style.display = 'none';

		this.shown = false;
		cal_openCal = undefined;
	}

	function cal_moveMonth(amount)
	{
		var m = this.showDate.getMonth();
		var y = cal_getYear(this.showDate);
		if (amount == 1)
		{
			if (m == 11)
			{
				this.showDate.setMonth(0);
				this.showDate.setYear(y + 1);
			}
			else
			{
				this.showDate.setMonth(m + 1);
            }
		}
		else if (amount == -1)
		{
			if (m == 0)
			{
				this.showDate.setMonth(11);
				this.showDate.setYear(y - 1);
			}
			else
			{
				this.showDate.setMonth(m - 1);
            }
		}
		else if (amount == 12)
		{
			this.showDate.setYear(y + 1);
        }
		else if (amount == -12)
        {
			this.showDate.setYear(y - 1);
        }

		this.div.innerHTML = this.generateHTML();
	}

    //--Utils-------------------------------------------------------------
	function cal_absoluteOffsetTop(obj)
	{
		var top = obj.offsetTop;
		var parent = obj.offsetParent;

		while (parent != document.body && parent != null)
		{
			top += parent.offsetTop;
			parent = parent.offsetParent;
		}

		return top;
	}

	function cal_absoluteOffsetLeft(obj)
	{
		var left = obj.offsetLeft;
		var parent = obj.offsetParent;

		while (parent != document.body && parent != null)
		{
			left += parent.offsetLeft;
			parent = parent.offsetParent;
		}

		return left;
	}

	function cal_firstDOW(date)
	{
		var dow = date.getDay();
		var day = date.getDate();

		if (day % 7 == 0)
		{
			return dow;
        }

		return (7 + dow - (day % 7)) % 7;
	}

	function cal_getYear(date)
	{
		var y = date.getYear();

		if (y > 1900)
		{
			return y;
        }
        
		return 1900 + y;
	}

	function cal_monthLength(date)
	{
		var month = date.getMonth();
		var totald = 30;
		if (month == 0
			|| month == 2
			|| month == 4
			|| month == 6
			|| month == 7
			|| month == 9
			|| month == 11) totald = 31;

		if (month == 1)
		{
			var year = date.getYear();
			if (year % 4 == 0 && (year % 400 == 0 || year % 100 != 0))
				totald = 29;
			else
				totald = 28;
		}
		return totald;
	}

	function cal_formatToken(date, token)
	{
		var command = token.substring(0, 1);
		if (command == 'y' || command == 'Y')
		{
			if (token.length == 2)
				return cal_zeroPad(date.getFullYear() % 100);

			if (token.length == 4)
				return date.getFullYear();
		}

		if (command == 'd' || command == 'D')
		{
			if (token.length == 2)
				return cal_zeroPad(date.getDate());
		}

		if (command == 'm' || command == 'M')
		{
			if (token.length == 2)
				return cal_zeroPad(date.getMonth() + 1);

			if (token.length == 3)
				return cal_monthAbbrNames[date.getMonth()];
		}

		return token;
	}

	function cal_parseToken(date, token, value, start)
	{
		var command = token.substring(0, 1);
		var v;
		if (command == 'y' || command == 'Y')
		{
			if (token.length == 2)
			{
				v = value.substring(start, start + 2);
				if (v < 70)
					date.setFullYear(2000 + parseInt(v));
				else
					date.setFullYear(1900 + parseInt(v));
			}

			if (token.length == 4)
			{
				v = value.substring(start, start + 4);
				date.setFullYear(v);
			}
		}

		if (command == 'd' || command == 'D')
		{
			if (token.length == 2)
			{
				v = value.substring(start, start + 2);
				date.setDate(v);
			}
		}

		if (command == 'm' || command == 'M')
		{
			if (token.length == 2)
			{
				v = value.substring(start, start + 2);
				date.setMonth(v - 1);
			}

			if (token.length == 3)
			{
				v = value.substring(start, start + 3);
				var i;
				for (i = 0; i < cal_monthAbbrNames.length; i++)
				{
					if (cal_monthAbbrNames[i].toUpperCase() == v.toUpperCase())
						date.setMonth(i);
				}
			}
		}
	}

	function cal_zeroPad(num)
	{
		if (num < 10)
			return '0' + num;

		return num;
	}

	function cal_getObj(id)
	{
        return document.getElementById(id);
	}

	function cal_setFieldValue(field, value)
	{
		if (field.type.substring(0,6) == 'select')
		{
			var i;
			for (i = 0; i < field.options.length; i++)
			{
				if (cal_equals(field.options[i].value, value))
					field.selectedIndex = i;
			}
		}
		else
			field.value = value;
	}

	function cal_getFieldValue(field)
	{
		if (field.type.substring(0,6) == 'select')
			return field.options[field.selectedIndex].value;
		else
			return field.value;
	}

	function cal_equals(val1, val2)
	{
		if (val1 == val2)
			return true;

		if (1 * val1 == 1 * val2)
			return true;

		return false;
	}
