
jaex.frm.datetime = function() {};

jaex.frm.datetime.DateCalender = function(tfId, mntId, yearId, fwdId, bckId, mntlId, bodyId) {
	this.id = tfId;
	this.tf = $(tfId);
	this.slmonth = $(mntId);
	this.tfyear = $(yearId);
	this.labelmonth = $(mntlId);
	this.linkfwd = $(fwdId);
	this.linkbck = $(bckId);
	this.tdfield = $(bodyId).getElementsByTagName("td");
	
	this.date;
	this.selectedLink;
	
	jaex.registerEvent(mntId, this.slmonth, 'onchange', this, 'controlChanged', 'true');
	jaex.registerEvent(yearId, this.tfyear, 'onchange', this, 'controlChanged', 'true');
	jaex.registerEvent(tfId, this.tf, 'onchange', this, 'extractTfDate', 'true');
	jaex.registerEvent(fwdId, this.linkfwd, 'onclick', this, 'incrementMonth', 'false');
	jaex.registerEvent(bckId, this.linkbck, 'onclick', this, 'decrementMonth', 'false');
	
	this.extractTfDate = function() {
		var newDate = jaex.util.datetime.dateStr2Date(this.tf.value);
		if(jaex.util.datetime.isDateValid(newDate)) this.date = newDate;
		this.updateElements();
	}
		
	this.controlChanged = function() {
		var newDate = jaex.util.clone(this.date);
		newDate.setMonth(this.slmonth.selectedIndex);
		newDate.setFullYear(this.tfyear.value);
		if(jaex.util.datetime.isDateValid(newDate))  {
			this.date = newDate;
		}
		this.updateElements();
	}
	
	this.incrementMonth = function() {
		this.date.setMonth(this.date.getMonth() + 1);		
		this.updateElements();
	}
	
	this.decrementMonth = function() {
		this.date.setMonth(this.date.getMonth() - 1);		
		this.updateElements();
	}
	
	this.updateElements = function() {		
		var month = this.date.getMonth();
		this.slmonth.selectedIndex = month;
		this.labelmonth.innerHTML = this.slmonth.options[month].innerHTML;
		this.tfyear.value = this.date.getFullYear();
		this.tf.value = jaex.util.datetime.date2DateStr(this.date);
				
		this.loadMonth();
	}
	
	this.changeToDay = function(_link) {
		this.selectedLink.className = "";
		_link.className = "selected";
		this.date.setDate(_link.innerHTML);
		this.selectedLink = _link;
		this.tf.value = jaex.util.datetime.date2DateStr(this.date);
	}
	
	this.loadMonth = function() {
		for(var tc = 0; tc < this.tdfield.length; tc++) {
			var td = this.tdfield[tc];
			if ( td.hasChildNodes() ) {
				td.removeChild( td.firstChild );
			}
		}
		
		var tmpdt = new Date(this.date.getFullYear(), this.date.getMonth(), 1);
		var tdfieldcounter = tmpdt.getDay() - 1;
		if(tdfieldcounter == -1) tdfieldcounter = 6;
		var end = tmpdt.lastDay();
		var selectedday = this.date.getDate();
		
		for(var dc = 1; dc <= end; dc++) {
			var link = document.createElement('a');
			if(dc == selectedday) {
				this.selectedLink = link;
				link.className = "selected";
			}
			link.href = "#";
			link.innerHTML = dc;
			this.tdfield[tdfieldcounter].appendChild(link);
			tdfieldcounter++;
			
			
			jaex.unregisterEvent(this.id + "cllink" + dc);
			jaex.registerEvent(this.id + "cllink" + dc, link, 'onclick', this, 'changeToDay', 'false');
		}
	}
	
	this.extractTfDate();
}


/**
* Extension of the JavaScript internal Date object to allow various formatting of
* date/time values.
* This implementation was designed to be compliant with the formatting of the
* Java class library's SimpleDateFormat object, with the addition of the 'x' format
* option to show number of seconds since the epoch (1/1/1970 00:00).
*
* See http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html for
* full details.
*
* This code can be used under the terms of the GNU General Public License, version 2 (http://www.gnu.org/licenses/gpl.txt).
* In the context of using the below code in a web application, it means that you may make this code,
* as-is unchanged and in its own source file, available on a web application and then have that application
* call methods defined here - regardless of what license the web application is distributed under.
* If you would like to distribute the below source included in a source file with other source not included
* here, and/or modify the the below source in anyway, then the resulting source file as a whole must
* be licensed under the GPL, as per the original license terms. All this relates of course only to distribution -
* Anyone may at any point use this source or parts of it, unmodified or otherwise, for any use as long
* as it is never distributed further. If the this source is included in a larger work which is then distributed,
* then the above terms must be adhered to.
*
* (c) Copyright 2006 - Oded Arbel
* (c) Portions copyright 2006 - Jack Slocum
*/

// Static definition of Month names
Date.MONTH_NAMES = [
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December" ];

// Static definition of weekday names
Date.WEEKDAY_NAMES = [
"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday",
"Saturday" ];

// clone the current date object and return a different object with identical value
Date.prototype.clone = function () {
return new Date(this.getTime());
}

// clear the time information from this date and return it
Date.prototype.clearTime = function () {
this.setHours(0); this.setMinutes(0);
this.setSeconds(0); this.setMilliseconds(0);
return this;
}

// return the last day of this month
Date.prototype.lastDay = function () {
var tempDate = this.clone();
tempDate.setMonth(tempDate.getMonth()+1);
tempDate.setDate(0);
return tempDate.getDate();
}

// return number of days since start of year
Date.prototype.getYearDay = function () {
var today = new Date(this);
today.setHours(0); today.setMinutes(0); today.setSeconds(0);
var tempDate = new Date(today);
// set start of year
tempDate.setDate(1);
tempDate.setMonth(0);
return Math.round(
(today.getTime() - tempDate.getTime())
/ 86400 / 1000) + 1; // Jan/1 is day 1
}

// add format() to Date
Date.prototype.format = function(formatString) {
var out = new String();
var token = ""
for (var i = 0; i < formatString.length; i++) {
if (formatString.charAt(i) == token.charAt(0)) {
token = token.concat(formatString.charAt(i));
continue;
}

out = out.concat(this.convertToken(token));
token = formatString.charAt(i);
}
return out + this.convertToken(token);
}

// internal call to map tokens to the date data
Date.prototype.convertToken = function (str) {
switch(str.charAt(0)) {
case 'y': // set year
if (str.length > 2)
return this.getFullYear();
return this.getFullYear().toString().substring(2);
case 'd': // set date
return Date.zeroPad(this.getDate(),str.length);
case 'D': // set day in year
return this.getYearDay();
case 'a':
return this.getHours() > 11 ? "PM" : "AM";
case 'H': // set hours
return Date.zeroPad(this.getHours(),str.length);
case 'h':
return Date.zeroPad(this.get12Hours(),str.length);
case 'm': // set minutes
return Date.zeroPad(this.getMinutes(),2);
case 's': // set secondes
return Date.zeroPad(this.getSeconds(),2);
case 'S': // set milisecondes
return Date.zeroPad(this.getMilliseconds(),str.length);
case 'x': // set epoch time
return this.getTime();
case 'Z': // set time zone
return (this.getTimezoneOffset() / 60) + ":" +
Date.zeroPad(this.getTimezoneOffset() % 60,2);
case 'M': // set month
if (str.length > 3) return this.getFullMonthName();
if (str.length > 2) return this.getShortMonthName();
return Date.zeroPad(this.getMonth()+1,str.length);
case 'E': // set dow
if (str.length > 3) return this.getDOWName();
if (str.length > 1) return this.getShortDOWName();
return this.getDay();
default:
return str;
}
}

// Retreive the month's name in english
Date.prototype.getFullMonthName = function() {
return Date.MONTH_NAMES[this.getMonth()];
}

// Retreive the abberviated month name in english
Date.prototype.getShortMonthName = function() {
return Date.MONTH_NAMES[this.getMonth()].substring(0,3);
}

// Retreive the week day name in english
Date.prototype.getDOWName = function () {
return Date.WEEKDAY_NAMES[this.getDay()];
}

// Retreive the abberviated week day name in english
Date.prototype.getShortDOWName = function () {
return Date.WEEKDAY_NAMES[this.getDay()].substring(0,3);
}

// Retreive the hour in a 12 hour clock (without the AM/PM specification)
Date.prototype.get12Hours = function () {
return this.getHours() == 0 ? 12 :
(this.getHours() > 12 ? this.getHours() - 12 : this.getHours());
}

// helper function to add required zero characters to fixed length fields
Date.zeroPad = function(num, width) {
num = num.toString();
while (num.length < width)
num = "0" + num;
return num;
}
