//	Version 07.08.2010 // มกราคม
//	new calenderObject(lang, css)
//	this.init = function(Node, nMonth, Title, msel) {
//  this.getSelected = function (raw) {
/* ====================================== */
/* toDo:
	keyboard ctrl:  left/right etc... day,   ctrl+right ... month
	keyboard: space = enter = select
*/
var calenderObjectCount = 0;
function calenderObject(lang, css) { // language, add.CSS
	calenderObjectCount += 1;
	var calINS = "_I" + calenderObjectCount;
	if (typeof lang == "undefined") lang = "en";
	if (typeof css  == "undefined") css  = null;
	switch (lang) {
		case "th":	this.monthList = ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน','กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม']; ;
					this.weekDays  = ['อา','จ','อ','พ','พฤ','ศ','ส']; break
		case "de":	this.monthList = ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember']; 
					this.weekDays  = ['So','Mo','Di','Mi','Do','Fr','Sa']; break
		case "en":
		default  :	this.monthList = ['January','February','March','April','May','June','July','August','September','October','November','December'];
					this.weekDays  = ['Su','Mo','Tu','We','Th','Fr','Sa'];
	}	

	var that = this; // for event closures
	var NodeID = null;
	var calMonths = 1;
	var cssDefault = "div.calClass { font-family:Arial; font-size:11px; color:#000000; text-align:left; border-color:#C0C0C0; background-color:#FFFFFF }\n" + 
					  "div.calClass .calMonth { border: 2px solid #C0C0C0; margin:3px }\n" + // border-collapse:collapse;
			    	  ".calClass a { text-decoration:none; color:#0000FF }\n .calClass a:hover { color:#FF0000 }\n" +
			    	  ".calClass td { text-align:center; border: 1px solid #D8D8D8; padding:1px 0; cursor:pointer; width:20px; }\n" +
			    	  ".calClass .calHead { background-color:#E0E0E0; }\n .calClass .calTitle { background-color:#FFFFCC }\n" +
			    	  ".calClass .calSelect { background-color:#C0FFC0 }\n" +
			    	  ".calClass input { width:100%; font-size:11px }\n" +
					  ".calClass input.calButton { border-style:inset; background-color:silver; color:HighlightText; }\n" +
			    	  ".calClass .hidden { display:none }\n .calClass .shown {}\n";
	var curDate     = [0,0,0,null]; // today's date;  4th element is pointer to cell TD
	var keyDate     = [0,0,0,null]; // keyboard date; 4th element is pointer to cell TD
	var selDate     = [0,0,0,null]; // selected date; 4th element is pointer to cell TD
	var calDate     = new Array();  // d,m,y,tableId: [0,0,0,null] [0,0,0,null] 
	var calMark     = new Array();  // array if selected cell IDs
	var calMarkers  = new Array();  // clear-format of calMark
	this.clickDate  = null; // pointer to function which handles onClick[Date]
	this.clickTitle = null; // pointer to function which handles onClick[Title]

	this.dateSet = function (dat) {
		var newDate = [0,0,0,null];
		if (!dat) dat = new Date();
		newDate = [dat.getDate(),dat.getMonth() + 1,dat.getFullYear(),null]; // Month is range 0..11
		newDate[3] = 'T' + newDate[2] + (newDate[1] < 10 ? '0' : '') + newDate[1] + (newDate[0] < 10 ? '0' : '') + newDate[0] + calINS; 
		return newDate;
	}
	
	this.init = function(Node, nMonth, Title, msel, initDate) {
		if (typeof Title  == "undefined") Title = ''; 	// msel == 1 ?'select date(s)':''; //"<b>Calender</b>";
		if (typeof nMonth == "undefined") nMonth = 1;
		if (typeof msel   == "undefined") msel = 0;		// 0=onclick,1=mousemove
		if (typeof initDate == "undefined") initDate = new Date();
		calMonths = nMonth < 0 ? -nMonth : nMonth;
		if (calenderObjectCount == 1) {	
			var style = document.createElement('style');
			style.type = 'text/css';	
			if (style.styleSheet) { style.styleSheet.cssText = cssDefault; } 
							 else { style.appendChild(document.createTextNode(cssDefault)); }
			document.getElementsByTagName("head")[0].appendChild(style);
		}
		var html = '<div class="calClass">'; // open container
		if (css) html += '<div id="' + Node + calINS + '" class="' + css+ '">'; // open extra css
		var layout = nMonth < 0 ? ' style="float:left"' : '';
		keyDate = this.dateSet(initDate);
		curDate = this.dateSet(null);
		for (var j = 0; j < calMonths; j++) {	// tableID: T0_I1
			var tableID = "calT" + j + calINS;
			calDate[j] = [1,initDate.getMonth() + j,initDate.getFullYear(),tableID]; // Month is range 0..11
		    html += '<table class="calMonth"' + layout + ' id="' + tableID + '">';
	    	html += '<tr class="calHead"><td id="calH' + j + calINS + '" colspan="7" style="width:auto">' + Title + '</td></tr>';
		    html += '<tr class="calTitle">';
		    html+= '<td id="calP' + j + calINS + '" title="prev.month"><b>&lt;&lt;</b></td> '
		    html+= '<td id="calM' + j + calINS + '" colspan="5" style="width:auto"><b></b></td> '
		    html+= '<td id="calN' + j + calINS + '" title="next month"><b>&gt;&gt;</b></td></tr> '
		    for (var pos = 1, tr = 0; tr < 6; tr++)  {
		        html += '<tr>';
		        for (var td = 0; td < 7; td++, pos++) html+= '<td>.</td> '
		        html += '</tr>'; 
		        }
		    html += '<tr class="calTitle"><td style="color:#FF8000">';
		    for (var i=0; i<7; i++) html += i ? '<td>' + this.weekDays[i] + '</td>' : this.weekDays[i] + '</td>';
			html += '</tr>';
			
			button =  (msel == 1) ? '<input type="button" id="calB' + j + calINS + '" value="Select/Clear All">' : '';

	    	html += '<tr class="calHead"><td id="calF' + j + calINS + '" colspan="7" style="width:auto">' + button + '</td></tr>';
	    	html += '</table>';
	    }
		if (nMonth < 0) html = html + '<div style="clear:left"></div>'; // clear float if horizontal layout
		if (css) html += '</div>'; // close extra css
		html += '</div>'; // close container
		NodeID = getElement.Id(Node);
		if (!NodeID) return false;
		NodeID.innerHTML = html;
		this.disableTextSelection(NodeID);
		if (msel == 1) NodeID.onmousedown = that.calMouseDown;
		return this.calDraw();
	}

	this.calDraw = function () {
		p = this.getDateId(keyDate);
		if (p) { p.style.borderColor = ''; }
		for (var j = 0; j < calMonths; j++) {
			var cY = calDate[j][2]; 
			var cM = calDate[j][1]; 
			var today = new Date();
			today.setMonth(cM); today.setYear(cY); today.setDate(1);
			var m = getElement.Id("calM" + j + calINS); if (m) m.innerHTML = "<b>" + this.monthList[cM] + " " + cY + "</b>";
			var p = getElement.Id("calP" + j + calINS); if (p) p.onclick = function() { that.calMonth(-1); }	
			var p = getElement.Id("calN" + j + calINS); if (p) p.onclick = function() { that.calMonth(+1); }
			var wday = -(today.getDay()); // Su=0, Mo=1 .. Sa=6
			var days = [31,((!( cY % 4 ) && ( ( cY % 100 ) || !( cY % 400 ) ))?29:28),31,30,31,30,31,31,30,31,30,31][cM];
			var t = getElement.Id("calT" + j + calINS);	
			for (var r = 2; r < 8; r++) {
				for (c = 0; c < 7; c++, wday++) {
					var p = t.rows[r].cells[c];
					p.className = "";
					if (wday < 0 || wday >= days) {
						p.id = "";					
						p.innerHTML = "&nbsp;"
						if (!NodeID.onmouseover) p.onclick = function() { return false; };
					} else {
						p.id = 'T' + cY + (cM < 9 ? '0' : '') + (cM+1) + (wday < 9 ? '0' : '') + (wday+1) + calINS; 
						p.innerHTML = wday + 1;
						if (!NodeID.onmousedown && !o) p.onclick = function(event) { that.calClick(this,event); }
						var o = (p.id < curDate[3]);
						if (c==0) { p.style.color = o ? '#FFC0A0' : '#FF8000'; }
							 else { p.style.color = o ? '#C0C0C0' : '#000000'; }
					}
				}
			}
			p = getElement.Id("calH" + j + calINS); 
			if (p && this.clickTitle) p.onclick = function() { that.clickTitle(this); }
			p = getElement.Id("calB" + j + calINS); 
			if (p && NodeID.onmousedown) p.onclick = function() { that.calSelectAll(this); }
			if (p && NodeID.onmousedown) p.className = ""; 
		}
		if (selDate[3]) selDate[3].className = "";
		if (NodeID.onmousedown) for (var i = 0; i < calMark.length; i++) { 
			var p = getElement.Id(calMark[i]); if (p) p.className = "calSelect"; 
		}
		p = this.getDateId(keyDate);
		if (p) { p.style.borderColor = '#0000FF'; }
		return calDate;
	}

	this.calMonth = function (a) { // move calender 'a' month up/down (not over 12 month)
		if (a > 0) for (i = 0; i < calDate.length; i++) { calDate[i][1] += a; if (calDate[i][1] > 11) { calDate[i][1]= 0; calDate[i][2]++ }; }
		if (a < 0) for (i = 0; i < calDate.length; i++) { calDate[i][1] += a; if (calDate[i][1] <  0) { calDate[i][1]=11; calDate[i][2]-- }; }
		return that.calDraw();
	}

	this.calPress = function (oEvent) {
		if (oEvent == null) { oEvent = window.event; }
		var target = oEvent.target != null ? oEvent.target : oEvent.srcElement;
		console.log(target.nodeName);
		console.log(oEvent);
		return false;
	}	

	this.calMouseDown = function (oEvent) {
		if (oEvent == null) { oEvent = window.event; }
		var target = oEvent.target != null ? oEvent.target : oEvent.srcElement;
//		console.log(target.nodeName);
		that.calMarkDate(target,1);
		NodeID.onmouseover = that.calMouseOver;
		NodeID.onmouseup = that.calMouseUp;
		return false;
	}	

	this.calMouseOver = function (oEvent) {
		if (oEvent == null) { oEvent = window.event; }
		var target = oEvent.target != null ? oEvent.target : oEvent.srcElement;
//		console.log(target.nodeName);
		that.calMarkDate(target,0);
		return false;
	}	

	this.calMouseUp = function (oEvent) {
		if (oEvent == null) { oEvent = window.event; }
		var target = oEvent.target != null ? oEvent.target : oEvent.srcElement;
//		console.log(target.nodeName);
		NodeID.onmouseover = function() { return false; };
		return false;
	}	

	this.calMarkDate = function (target, click) {
		if (target.nodeName.toUpperCase() != 'TD') return false;
		if (target.id.length < 12) return false;
		var m  = this.getTableNum(target);
		var i  = calMark.indexOf(target.id);
		if (target.className && click) { 	// remove
			target.className = "";
			if (i >= 0) calMark.splice(i,1);
			var b = getElement.Id("calB" + m + calINS); if (b) b.className = "";
			} else {						// add
			target.className = "calSelect";
			if (i < 0) calMark.push(target.id);
			}
//		console.log(calMark);
		return calMark.length;	
	}

	this.calUnSelectAll = function () {
		calMark.length = 0;
		this.calDraw();
		return calMark.length;	
	}
	
	this.calSelectAll = function (button, onOff) {
		if (typeof mode == "undefined") onOff = button.className ? false : true;
		var m  = this.getTableNum(button);
		var cY = calDate[m][2]; 
		var cM = calDate[m][1]; 
		var days = [31,((!( cY % 4 ) && ( ( cY % 100 ) || !( cY % 400 ) ))?29:28),31,30,31,30,31,31,30,31,30,31][cM];
		for (cD = 1, cM++; cD <= days; cD++) {
			var p = this.getDateId([cD,cM,cY]);
			if (p) this.calMarkDate(p,!onOff);
		}
		button.className = onOff ? "calButton" : "";
		console.log(calDate[m]);
//		console.log([m,days]);
		return calMark.length;	
	}

	this.calClick = function (thefield,oEvent) {
		if (NodeID.onmousedown) return false; // disable onclick if onmousedown is used.
		var cD = thefield.innerHTML ? parseInt(thefield.innerHTML) : 0;
		if (!cD) return false;				// ignore cells which are not dates
		var m = this.getTableNum(thefield);
		var oldDate = selDate.slice(0);		// remember previous selected cell
		selDate = calDate[m].slice(0); 		// copy the array, not the pointer
		selDate[0]  = cD; selDate[1]++;		// adjust month value [0..11] to [1..12]
		selDate[3]  = thefield;
		console.log(selDate); 
//		console.log(oEvent);
		if (oldDate[3]) oldDate[3].className = "";
		thefield.className = "calSelect";
		if (that.clickDate) that.clickDate(selDate,oEvent);
		return false;
	}

	this.getSelected = function (raw) {
		if (typeof raw == "undefined") raw = 0;
		if (!NodeID.onmousedown) return selDate;
		if (raw) return calMark;
		calMark.sort();
		calMarkers.length = 0
	    for (var i = 0; i < calMark.length; i++) {
    		var cD = parseInt(calMark[i].slice(7,9),10); // Tyyyymmdd_I0
			var cM = parseInt(calMark[i].slice(5,7),10); // Tyyyymmdd_I0
			var cY = parseInt(calMark[i].slice(1,5),10); // Tyyyymmdd_I0
		    calMarkers[i] = [cD,cM,cY];
		} 
		console.log(calMarkers);
		return calMarkers;
	}
	
	this.getDateId = function (theDate) { // theDate is array [d,m,y]
		var tag = 'T' + theDate[2] + (theDate[1] < 10 ? '0' : '') + theDate[1] + (theDate[0] < 10 ? '0' : '') + theDate[0] + calINS; 
		return getElement.Id(tag);
	}

	this.objDate = function (arrDate) {
		var day = new Date(arrDate[2],arrDate[1]-1,arrDate[0]);
		return day;
	}

	this.calShowHide = function (mode) {
	    if (!NodeID) return false;
	    if (mode == 0) {
	       if (NodeID.style) NodeID.style.visibility = "hidden";
	       else if (NodeID.visibility) NodeID.visibility = "hide";
	    } else {
	       if (NodeID.style) NodeID.style.visibility = "visible";
	       else if (NodeID.visibility) NodeID.visibility = "show";
	    }
	    return true;
	}

	/* === helpers === */
	this.getTableNum = function (thefield) {
		var t = getElement.Table(thefield); 	// get the TABLE ID
		if (!t) t = thefield.offsetParent; 	// alternative
		var m = t ? parseInt(t.id.charAt(4)) : 0;   // calT0_I1
		return m;	
	}

	this.disableTextSelection = function(elem) {
		if (!elem) return false;
		elem.onselectstart = function() { return false; };
		elem.unselectable = "on";
		elem.style.MozUserSelect = "none";
		elem.style.cursor = "default";
	}

};


// Simulates PHP's date function
if (!Date.prototype.format) { 
Date.prototype.format = function(format) {
	var returnStr = '';
	var replace = Date.replaceChars;
	for (var i = 0; i < format.length; i++) {
		var curChar = format.charAt(i);
		if (replace[curChar]) {
			returnStr += replace[curChar].call(this);
		} else {
			returnStr += curChar;
		}
	}
	return returnStr;
};
Date.replaceChars = {
	shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
	longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
	shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
	longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
	
	// Day
	d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
	D: function() { return Date.replaceChars.shortDays[this.getDay()]; },
	j: function() { return this.getDate(); },
	l: function() { return Date.replaceChars.longDays[this.getDay()]; },
	N: function() { return this.getDay() + 1; },
	S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
	w: function() { return this.getDay(); },
	z: function() { return "Not Yet Supported"; },
	// Week
	W: function() { return "Not Yet Supported"; },
	// Month
	F: function() { return Date.replaceChars.longMonths[this.getMonth()]; },
	m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
	M: function() { return Date.replaceChars.shortMonths[this.getMonth()]; },
	n: function() { return this.getMonth() + 1; },
	t: function() { return "Not Yet Supported"; },
	// Year
	L: function() { return (((this.getFullYear()%4==0)&&(this.getFullYear()%100 != 0)) || (this.getFullYear()%400==0)) ? '1' : '0'; },
	o: function() { return "Not Supported"; },
	Y: function() { return this.getFullYear(); },
	y: function() { return ('' + this.getFullYear()).substr(2); },
	// Time
	a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
	A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
	B: function() { return "Not Yet Supported"; },
	g: function() { return this.getHours() % 12 || 12; },
	G: function() { return this.getHours(); },
	h: function() { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); },
	H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
	i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
	s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
	// Timezone
	e: function() { return "Not Yet Supported"; },
	I: function() { return "Not Supported"; },
	O: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + '00'; },
	P: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + ':' + (Math.abs(this.getTimezoneOffset() % 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() % 60)); },
	T: function() { var m = this.getMonth(); this.setMonth(0); var result = this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); this.setMonth(m); return result;},
	Z: function() { return -this.getTimezoneOffset() * 60; },
	// Full Date/Time
	c: function() { return this.format("Y-m-d") + "T" + this.format("H:i:sP"); },
	r: function() { return this.toString(); },
	U: function() { return this.getTime() / 1000; }
};
}


/* ====================================== */
// install a dummy function console.log() if no firebug installed
if (typeof console === "undefined") { 
    console = { log: function() { } }; 
}


// DOM helpers
if (typeof getElement === "undefined") { 
    getElement = { Id: function(tag) {     
    					if( document.layers ) { return document.layers[tag]; } //Netscape layers
					    if( document.getElementById ) { return document.getElementById(tag); } //DOM; IE5, NS6, Mozilla, Opera
					    if( document.all ) { return document.all[tag]; } //Proprietary DOM; IE4
					    if( document[tag] ) { return document[tag]; } //Netscape alternative
					    return false;
					} ,   
					Class: function (searchClass,node,tag) {
						var classElements = new Array();
						if ( node == null ) node = document;
						if ( tag  == null ) tag = '*';
						var els = node.getElementsByTagName(tag);
						var elsLen = els.length;
						var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
						for (i = 0, j = 0; i < elsLen; i++) {
							if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; }
						}
						return classElements;
					} ,	
					Table: function(obj) {	// find parent TABLE.id of object inside a table
						while (obj && !/table/i.test(obj.nodeName)){ obj = obj.parentNode; }
						return obj || null;
					}
			     }; 
}

// Extension for IE Browser
if (!Array.prototype.indexOf) { 
	Array.prototype.indexOf = function (obj, fromIndex) { 
	    if (fromIndex == null) { fromIndex = 0; } else if (fromIndex < 0) { 
	        fromIndex = Math.max(0, this.length + fromIndex); 
	    } 
	    for (var i = fromIndex, j = this.length; i < j; i++) { if (this[i] === obj) return i; } 
	    return -1; 
	}; 
} 


