// SpryCalendar.js - version 1.0 (Based on Spry Pre-Release 1.6) modified by emehdy on 20100116


var Spry;
if (!Spry) Spry = {};
if (!Spry.Widget) Spry.Widget = {};

Spry.Widget.Calendar = function(input, opts)
{
	var defaultDate = new Date();
	this.auto=false;

	this.month = defaultDate.getMonth();
	this.year = defaultDate.getFullYear();
	this.calendarMonths = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
	this.enableKeyboardNavigation = true;
	this.hasFocus = null;
	this.numDays = null;
	this.headerRowId = null;
	this.selectedDate = null;
	this.selectedElement = null;
	this.focusedCell = null;
	this.callbackFunction = function(x){this.input.value=this.Ymd(x);this.hide();};

	
	// Navigation key codes
	this.previousDayKeyCode = Spry.Widget.Calendar.KEY_LEFT;
	this.nextDayKeyCode = Spry.Widget.Calendar.KEY_RIGHT;
	this.spaceKeyCode = Spry.Widget.Calendar.KEY_SPACE;
	
	// CSS
	this.calendarClass = "Calendar";
	this.foreignDayClass = "CalendarForeignDay";
	this.monthHeaderClass = "CalendarMonthHeader";
	this.navOverClass = "CalendarNavOver";
	this.dayHeaderClass = "CalendarDayHeader";
	this.dayClass = "CalendarDayCell";
	this.dayOverClass = "CalendarDayCellOver";
	this.todayClass = "CalendarTodayCell";
	this.selectedClass = "CalendarSelectedCell";
	this.focusedClass = "CalendarFocused";
	this.focusedCellClass = "CalendarFocusedDay";
	if(typeof input=="string")
	this.input=document.getElementById(input);
	else
	this.input=input;
	if(this.input==null) return;
	this.input.style.direction='ltr';
	
	this.defInputWidth=this.input.style.width;
	this.input.onclick="";
	this.setOptions(this, opts, true);
	this.init();
	this.show();
	this.first=this.auto?true:false;
	return this;
}

Spry.Widget.Calendar.KEY_LEFT = 37;
Spry.Widget.Calendar.KEY_RIGHT = 39;
Spry.Widget.Calendar.KEY_SPACE = 32;

Spry.Widget.Calendar.prototype.getElement = function(ele)
{
	if (ele && typeof ele == "string")
		return document.getElementById(ele);
	return ele;
};

Spry.Widget.Calendar.prototype.addClassName = function(ele, className)
{
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
		return;
	ele.className += (ele.className ? " " : "") + className;
};

Spry.Widget.Calendar.prototype.removeClassName = function(ele, className)
{
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))
		return;
	ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};

Spry.Widget.Calendar.prototype.hasClassName = function(ele, className)
{
	if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
		return false;
	return true;
};

Spry.Widget.Calendar.prototype.setOptions = function(obj, optionsObj, ignoreUndefinedProps)
{
	if (!optionsObj)
		return;
	for (var optionName in optionsObj)
	{
		if(optionName == "hasFocus" || optionName == "numDays" || optionName == "selectedElement" || optionName == "element" || optionName == "focusedCell")
			continue;
		if (ignoreUndefinedProps && optionsObj[optionName] == undefined)
			continue;
		obj[optionName] = optionsObj[optionName];
	}
};

Spry.Widget.Calendar.prototype.addEventListener = function(element, eventType, handler, capture)
{
	try
	{
		if (element.addEventListener)
			element.addEventListener(eventType, handler, capture);
		else if (element.attachEvent)
			element.attachEvent("on" + eventType, handler);
	}
	catch (err) {}
};

Spry.Widget.Calendar.prototype.removeEventListener = function(element, eventType, handler, capture)
{
	try
	{
		if (element.removeEventListener)
			element.removeEventListener(eventType, handler, capture);
		else if (element.detachEvent)
			element.detachEvent("on" + eventType, handler);
	}
	catch (err) {}
};

Spry.Widget.Calendar.prototype.attachBehaviors = function()
{
	this.addClassName(this.element, this.calendarClass)
	var navigators = this.getNavigators();
	var cells = this.getDayCells();
	// Add the event listeners for the monthly navigation.
	for(var i = 0; i < navigators.length; i++)
	{
		this.addNavigationListener(navigators[i]);
	}
	// Add the event listeners for the day cells.
	for(var i = 0; i < cells.length; i++)
	{
		this.addDateListener(cells[i]);
	}
	if (this.enableKeyboardNavigation) {
		var self = this;
		this.addEventListener(this.element, "focus", function(e) { return self.onFocus(e); }, false);
		this.addEventListener(this.element, "blur", function(e) { return self.onBlur(e); }, false);
		this.addEventListener(this.element, "keydown", function(e) { return self.onKeyDown(e); }, false);
	}
	
};

Spry.Widget.Calendar.prototype.focus = function()
{
	if (this.element && this.element.focus)
		this.element.focus();
};

Spry.Widget.Calendar.prototype.blur = function()
{
	if (this.element && this.element.blur)
		this.element.blur();
};

Spry.Widget.Calendar.prototype.onFocus = function(e)
{
	this.hasFocus = true;
	this.focus();
	this.addClassName(this.element, this.focusedClass);
	return false;
};

Spry.Widget.Calendar.prototype.onBlur = function(e)
{
	this.hasFocus = false;
	this.blur();
	this.removeClassName(this.element, this.focusedClass);
	return false;
};

Spry.Widget.Calendar.prototype.init = function()
{
	
	
	var span=document.createElement('span');
	span.style.direction='ltr';
	this.element=this._cal_tbl();
	span.appendChild(this.element); 
	document.body.appendChild(span);

	
	var self=this;
 		Spry.Utils.addEventListener(document.body,'click',function(a){if(!self.first &&self.element.style.display!='none'&&a.srcElement!=self.input)self.hide();self.first=false;},false);

	Spry.Utils.addEventListener(self.element,'click',function(a){TA.U.stopEvent(a);},false);
	Spry.Utils.addEventListener(self.input,'click',function(a){self.input_clicked(a)},false);
	
	
	
	
	
	this.setCalendarDate(this.year, this.month);
	if(this.callbackFunction && typeof(this.callbackFunction) != 'function')
		this.callbackFunction = null;
	this.attachBehaviors();	
}
Spry.Widget.Calendar.prototype.input_clicked=function(a)
{
	var self=this;
	self.show();
	if(/^\d{4}-\d{2}-\d{2}$/.test(self.input.value))
		self.setCalendarDate(self.input.value.substr(0,4),parseInt(self.input.value.substr(5,2))-1);
	if(a.srcElement==undefined)a.srcElement=self.input;
}
Spry.Widget.Calendar.prototype.getDayCells = function()
{
	var tds = this.element.getElementsByTagName("td");
	var cells = new Array();
	for(var i = 0; i < tds.length; i++)
	{
		if (!this.hasClassName(tds[i], this.dayClass)) continue;
		cells.push(tds[i]);
	}
	return cells;
}

Spry.Widget.Calendar.prototype.setCalendarDate = function(yr, mo)
{	
	var tmpDate = new Date();
	
	if(yr == undefined)
		yr = tmpDate.getFullYear();
	if(mo == undefined || mo < 0 || mo > 11)
		mo = tmpDate.getMonth();
	
		
	tmpDate.setDate(1);
	tmpDate.setMonth(mo);
	tmpDate.setFullYear(yr);
	
	this.numDays = tmpDate.getDaysInMonth();
	this.month = tmpDate.getMonth();
	this.year = tmpDate.getFullYear();
	this.populate();
	tmpDate = null;
	this.removeClassName(this.getFocusedElement(), this.focusedCellClass);
	this.focusedCell = null;
}

Spry.Widget.Calendar.prototype.populate = function()
{
	// Set the month/year text in the title row
	var titleRow = this.getHeaderRow();
	var titleCell = titleRow[1].innerHTML = (this.calendarMonths[this.month] + " " + this.year);
	
	// Get the cells used to hold the dates
	var cells = this.getDayCells();
	var filled = 0;
	var tmpDate = new Date(this.year,this.month,1);

	var today = new Date();

	// If the first day of the month does not fall on Sunday, we need to add the foreign day class to the first cells.
	if(tmpDate.getDay() != 0)
	{
		for(var i = 0; i < tmpDate.getDay(); i++)
		{
			//var ele = this.getElement(cells[i].id);
			var ele =cells[i];
			this.addClassName(ele, this.foreignDayClass);
			// Remove all class names (except the default).
			this.removeClassName(ele, this.todayClass);
			this.removeClassName(ele, this.selectedClass);
			this.removeClassName(ele, this.focusedCellClass);
			ele.innerHTML = '&nbsp;';
			filled++;
		}
	} 
	// Set the date text for each cell in the month.
	for(var i = 0; i <= this.numDays-1; i++)
	{
		var idx = i+1;
		var el = cells[filled];
		if(el.parentNode.style.display == 'none') el.parentNode.style.display = '';
		el.innerHTML = idx;
		// Remove the foreign day class if it exists for the cell.
		this.removeClassName(el, this.foreignDayClass);
		
		// Highlight today's date
		if(today.getFullYear() == tmpDate.getFullYear() && today.getMonth() == tmpDate.getMonth() && today.getDate() == idx) {
			this.addClassName(el, this.todayClass);
		} else {
			this.removeClassName(el, this.todayClass);
		}
		if(this.selectedDate && (this.selectedDate.getFullYear() == tmpDate.getFullYear() && this.selectedDate.getMonth() == tmpDate.getMonth() && idx == this.selectedDate.getDate())){
			this.addClassName(el, this.selectedClass);
			// Since it's possible to pre-populate the selected date, we may not have a selected element so we'll need to
			// set it so the class can be cleared if need be.
			if(!this.selectedElement)
				this.selectedElement = el;
		} else {
			this.removeClassName(el, this.selectedClass);
		}
		tmpDate.setDate(idx);
		filled++;
	}
	var lastDayCell = (filled-1);
	
	// Reset our tmpDate to the last day of the currently loaded month/year.
	tmpDate.setMonth(this.month);
	tmpDate.setDate(this.numDays);
	tmpDate.setFullYear(this.year);
	
	// Do we need to add foreign day class to any remaining cells?
	while(filled < cells.length){
		//var ele = this.getElement(cells[filled].id);
		var ele=cells[filled];
		this.addClassName(ele, this.foreignDayClass);
		// Remove all class names (except the default).
		this.removeClassName(ele, this.todayClass);
		this.removeClassName(ele, this.selectedClass);
		this.removeClassName(ele, this.focusedCellClass);
		ele.innerHTML = '&nbsp;';
		filled++;
	}
	
	// Get the tr tag of the last table cell tag that we filled.
	try{
	var e = cells[lastDayCell].parentNode.nextSibling.nextSibling;}catch(e){}
	
	// Do we need to hide the last table row(s)? We want to do this only if no day cells are being used.
	// Use DOM functions to get the last table row tag.
	var tRows = this.element.getElementsByTagName("tr");
	idx = null;
	for(var i = 0; i < tRows.length; i++)
	{
		if(!e || e && e.id != tRows[i].id && idx == null) continue;
		tRows[i].style.display = 'none';
		idx = i;
	}
}

Spry.Widget.Calendar.prototype.getNavigators = function()
{
	// Set the month/year text in the title row
	var titleRow = this.getHeaderRow();
	var navigators = new Array();
	for(var i = 0; i < titleRow.length; i++)
	{
		// The navigators should be the first and last cells of the header row, so skip the one with the month/year text.
		if(i == 1) continue;
		navigators.push(titleRow[i]);
	}
	return navigators;
}

Spry.Widget.Calendar.prototype.addDateListener = function(ele)
{
	var self = this;
	this.addEventListener(ele, 'mouseover', function(e) { return self.onDateMouseOver(e, ele); }, false);
	this.addEventListener(ele, 'mouseout', function(e) { return self.onDateMouseOut(e, ele); }, false);
	this.addEventListener(ele, 'click', function(e) { return self.onDateClick(e, ele); }, false);
}

Spry.Widget.Calendar.prototype.onDateMouseOver = function(evt, ele)
{
	if(this.hasClassName(ele, this.foreignDayClass))
		return true;
	this.addClassName(ele, this.dayOverClass);
	return false;
}

Spry.Widget.Calendar.prototype.onDateMouseOut = function(evt, ele)
{
	if(this.hasClassName(ele, this.foreignDayClass))
		return true;
	this.removeClassName(ele, this.dayOverClass);
	return false;
}

Spry.Widget.Calendar.prototype.onDateClick = function(evt, ele)
{	
	if (evt.preventDefault) evt.preventDefault();
	else evt.returnValue = false;
	if (evt.stopPropagation) evt.stopPropagation();
	else evt.cancelBubble = true;
	
	if(this.hasClassName(ele, this.foreignDayClass))
		return true;
	var tmpDate = new Date(this.year, this.month, parseInt(ele.innerHTML));
	// If this date is already selected, do nothing.
	if(this.selectedDate && (this.selectedDate.valueOf() == tmpDate.valueOf()))
		return true;
	this.removeClassName(this.focusedCell, this.focusedCellClass);
	this.removeClassName(this.selectedElement, this.selectedClass);
	
	this.focusedCell = ele;
	
	this.addClassName(ele, this.focusedCellClass);
	this.addClassName(ele, this.selectedClass);
	
	this.setSelectedDate(tmpDate);
	this.selectedElement = ele;
	
	if(this.callbackFunction){
		this.callbackFunction(this.selectedDate);
	}
	
	return false;
}

Spry.Widget.Calendar.prototype.addNavigationListener = function(ele)
{
	var self = this;
	this.addEventListener(ele, "mouseover", function(e) { return self.onNavMouseOver(e, ele); }, false);
	this.addEventListener(ele, "mouseout", function(e) { return self.onNavMouseOut(e, ele); }, false);
	this.addEventListener(ele, "click", function(e) { return self.onNavClick(e, ele); }, false);
	if (this.enablekeyboardnavigation) {
		
	}
}

Spry.Widget.Calendar.prototype.onNavMouseOver = function(evt, ele)
{
	this.addClassName(ele, this.navOverClass);
	return false;
}

Spry.Widget.Calendar.prototype.onNavMouseOut = function(evt, ele)
{
	this.removeClassName(ele, this.navOverClass);
	return false;
}

Spry.Widget.Calendar.prototype.onNavClick = function(evt, ele)
{
	if (evt.preventDefault) evt.preventDefault();
	else evt.returnValue = false;
	if (evt.stopPropagation) evt.stopPropagation();
	else evt.cancelBubble = true;
	
	var navigators = this.getNavigators();
	var tmpDate = new Date(this.year, this.month, 1);
	for(var i = 0; i < navigators.length; i++)
	{
		if(ele == navigators[i]){
			switch(i)
			{
				case 1:	 
					tmpDate.setMonth((this.month+1));
					break;
				default:
					tmpDate.setMonth((this.month-1));
					break;
			}
			break;
		}
	}

	this.removeClassName(this.focusedCell, this.focusedCellClass);
	this.setCalendarDate(tmpDate.getFullYear(), tmpDate.getMonth());
	
	return false;
}

Spry.Widget.Calendar.prototype.onKeyDown = function(e)
{
	if(!this.hasFocus || !this.enableKeyboardNavigation)
		return true;
		
	var key = e.keyCode;
	var cells = this.getDayCells();
	
	if(key == this.previousDayKeyCode){
		var keyString = "Previous day";
		if (!this.focusedCell) {
			for(var i = 0; i < cells.length; i++)
			{
				if(this.hasClassName(cells[i], this.foreignDayClass)) {
					continue;
				}
				this.focusedCell = cells[i];
				break;
			}
		} else {
			this.removeClassName(this.focusedCell, this.focusedCellClass);
			if(parseInt(this.focusedCell.innerHTML) == 1) {
				var mo = this.month == 0 ? 11 : (this.month-1);
				var yr = mo == 11 ? (this.year-1) : this.year;
				this.setCalendarDate(yr, mo);
				for(var i = (cells.length-1); i > 0; i--)
				{
					if(cells[i].innerHTML != this.numDays.toString()){
						continue;
					}
					this.focusedCell = cells[i];
					break;
				}
			} else if(parseInt(this.focusedCell.innerHTML) == this.numDays) {
				for(var i = (cells.length-1); i > 0; i-- ) {
					if(this.hasClassName(cells[i], this.foreignDayClass)){
						continue;
					}
					if(this.focusedCell == cells[i]){
						this.focusedCell = cells[(i-1)];
						break;
					}
				}
			}else{
				for(var i = (cells.length-1); i > 0; i--)
				{
					if (this.hasClassName(cells[i], this.foreignDayClass)) {
						continue;
					}
					if (this.focusedCell == cells[i]) {
						this.focusedCell = cells[(i-1)];
						break;
					}
				}
			}
			
		
		}
	}else if(key == this.nextDayKeyCode){
		var keyString = "Next day";
		if (!this.focusedCell) {
			for(var i = 0; i < cells.length; i++)
			{
				if(this.hasClassName(cells[i], this.foreignDayClass)) {
					continue;
				}
				this.focusedCell = cells[i];
				break;
			}
		} else {
			this.removeClassName(this.focusedCell, this.focusedCellClass);
			for(var i = 0; i < cells.length; i++)
			{
				if (cells[(i-1)] == this.focusedCell) {
					if(parseInt(this.focusedCell.innerHTML) == this.numDays) {
						var mo = this.month == 11 ? 0 : (this.month+1);
						var yr = mo == 0 ? (this.year+1) : this.year;
						this.setCalendarDate(yr, mo);
						i = 0;
						while(this.hasClassName(cells[i], this.foreignDayClass))
						{
							i++;
						}
						this.focusedCell = cells[i];
						break;
					}
					this.focusedCell = cells[i];
					break;
				}
			}
		}
	}else if(key == this.spaceKeyCode){
		if(this.focusedCell) {
			var tmpDate = new Date(this.year, this.month, parseInt(this.focusedCell.innerHTML));
			if(this.selectedElement){
				this.clearSelection();
			}
			var ele = this.getElement(this.focusedCell);
			this.addClassName(ele, this.selectedClass);
			this.setSelectedDate(tmpDate);
			this.selectedElement = ele;
			if(this.callbackFunction){
				this.callbackFunction(this.selectedDate);
			}
			return false;
		} else {
			return true;
		}
	}else{
		return true;
	}
	this.addClassName(this.focusedCell, this.focusedCellClass);
	return false;
}

Spry.Widget.Calendar.prototype.clearSelection = function()
{
	this.removeClassName(this.selectedElement, this.selectedClass);
	this.selectedDate = null;
	this.selectedElement = null;
	
}

Spry.Widget.Calendar.prototype.setSelectedDate = function(val)
{
	if(this.selectedDate && this.selectedDate == val)
		return;
		
	if(typeof(val) == 'string'){
		this.selectedDate = new Date(val);
	} else {
		this.selectedDate = val;
	}
}

Spry.Widget.Calendar.prototype.getSelectedDate = function()
{
	return this.selectedDate;
}

Spry.Widget.Calendar.prototype.getSelectedElement = function()
{
	return this.selectedElement;
}

Spry.Widget.Calendar.prototype.getFocusedElement = function()
{
	return this.focusedCell;
}

Spry.Widget.Calendar.prototype.getHeaderRow = function()
{
	if(!this.headerRowId){
		var headerRow = this.element.getElementsByTagName("tr")[0].getElementsByTagName("td");
	} else {
		var headerRow = document.getElementById(this.headerRowId).getElementsByTagName("td");
	}
	return headerRow;
}
Spry.Widget.Calendar.prototype.hide=function()
{
	this.element.style.display='none';
}
Spry.Widget.Calendar.prototype.show=function()
{
		var coord=TA.U.topLeft(this.input);
	if(1 )
	{
		this.element.style.top=coord[0]+coord[2]+2;
		this.element.style.left=coord[1]+1;
	}
	this.element.style.display='block';
	this.element.style.position='absolute';
}
// Helper function to count the number of days in a given month since Javascript doesn't have
// this functionality natively.

///////////////////////////////////////////////
//		written by Eng.MEM emehdy@gmail
///////////////////////////////////////////////


Spry.Widget.Calendar.prototype._cal_tbl= function()
{
	var _cal=document.createElement('table');
	//_cal.id=id;
	_cal.style.direction='ltr';
	var _bod=document.createElement('tbody');
	_bod.appendChild(this._cal_title_row());
	_bod.appendChild(this._cal_day_header());
	for(var w=1;w<=6;w++)
		_bod.appendChild(this._cal_week_row(w));
	_cal.appendChild(_bod);
	return _cal;
}
Spry.Widget.Calendar.prototype._cal_week_row= function(w)
{
	var week_row=this._cal_row('c1_Week'+w);
	for(var d=0;d<7;d++)
		week_row.appendChild(this._cal_td('c1_w'+w+'_d'+d,'CalendarDayCell','&nbsp;'));
	return week_row;
}
Spry.Widget.Calendar.prototype._cal_title_row= function()
{
	var titleRow=this._cal_row('titleRow');
	var header=['<a href="javascript:void(0)" class="previous">&nbsp;</a>','Calendar','<a href="javascript:void(0)" class="next">&nbsp;</a>'];
	for(var i=0;i<header.length;i++)
		titleRow.appendChild(this._cal_td('','CalendarMonthHeader',header[i]));
	titleRow.childNodes[1].colSpan=5;
	return titleRow;
}
Spry.Widget.Calendar.prototype._cal_day_header= function()
{
	var day_header=this._cal_row('day_header');
	var days=['S','M','T','W','T','F','S'];
	for(var i=0;i<days.length;i++)
		day_header.appendChild(this._cal_td('','CalendarDayHeader',days[i]));
	return day_header;
}
Spry.Widget.Calendar.prototype._cal_row= function(id,cls)
{
	var _cal_r=document.createElement('tr');
	if(id)_cal_r.id=id;
	if(cls)_cal_r.className=cls;
	return _cal_r;
}
Spry.Widget.Calendar.prototype._cal_td= function(id,cls,inn)
{
	var _cal_d=document.createElement('td');
	if(id)_cal_d.id=id;
	if(cls)_cal_d.className=cls;
	if(inn)_cal_d.innerHTML=inn;
	return _cal_d;
}
Spry.Widget.Calendar.prototype.Ymd=function(x)
{
	var m=x.getMonth();m++;if (m<10) m='0'+m;
	var d=x.getDate();if (d<10) d='0'+d;
	return x.getFullYear()+'-'+m+'-'+d;		
}







Date.prototype.getDaysInMonth = function()
{
	var curMonth = this.getMonth();
	var tmpDate = new Date(this.getFullYear(), this.getMonth(), 1);
	var count = 0;
	do
	{
		tmpDate.setDate((tmpDate.getDate()+1));
		count++;
	}while(tmpDate.getMonth() == curMonth); 
	return count--;
}
