/*
 * JDC Javascript Date Controls
 * var rcsid = '$Id: jdc.js,v 1.2 2006/03/11 20:47:41 dread Exp dread $'
 */

/* 
 * $Log: jdc.js,v $
 */

/*extern str2Date, y2k, padString, getElementsByTagClass, getElementsByTagNameRegex */

var pDivId = 'jdc_p_div';
var pSelId = 'jdc_p_sel';
var inp1Id = 'jdc_1_inp';
var inp2Id = 'jdc_2_inp';
var fmtId = 'jdc_fmt';

var NEXTMON = '>';
var PREVMON = '<';

var jdcInpId = null;
var jdcISOId = null;
var jdcDivId = null;

var jdcFmt = 'I';

if (typeof today == 'undefined') {
	var today = new Date();
}

var begDate = today;
var endDate = today;

/*
 * string jdc_FormatDate(fmt, [Date | [ d [, m [,y]]]);
 * returns formatted string 
 */

function jdc_FormatDate(fmt, arg) {
	var  sfmt = '%F';
	var td = new Date;						// initialize
	if (arg) {
		if (arg instanceof Date) {
			td = arg;
		} else {
			var redPat = /\d+[-\/\.]+\d+[-\/\.]+\d+\s?/;
			var s = arguments[2];
			if (s.match(redPat)) {
				td = str2Date(s);
			} else {
				switch (arguments.length) {
					case 4:td.setFullYear(y2k(arguments[4]));
					case 3:td.setMonth(-1 + arguments[3]);
					case 2:td.setDate(arguments[2]);
				}
			}
		}
	}

	switch (fmt) {
		case 'F': sfmt = '%A, %B %Ee %Y'; break;
		case 'A': sfmt = '%m/%d/%Y'; break;
		case 'a': sfmt = '%m/%d/%y'; break;
		case 'E': sfmt = '%d.%m.%Y'; break;
		case 'e': sfmt = '%d.%m.%y'; break;
		case 'Z':
		case 'z': sfmt = '%Y%m%d'; break;
		case 'I':
		default : sfmt = '%Y-%m-%d'; break;
	}
	return td.strftime(sfmt);
}

function jdc_ctlNumber(str) {
	var m = null;

	if (str.match(/^jdc_\w+/)) {
		m = str.match(/^jdc_(\d)_/);
		if (m) 
			return m[1];

		m = str.match(/^jdc_(\w+)/);
		if (m) 
			return m[1];
		return null;
	}
	return str;
}

function jdc_Name(idname, ext) {
	var a = new Array();
	if (idname) {
		if (idname.match(/^jdc_[p1234]_/)) {
			var m = idname.split('_');
			var base = m[0] + '_' + m[1] + '_';
			if (ext) {
				var n = base + ext;
				return n;
			}
			a[0] = base + 'iso';
			a[1] = base + 'inp';
			a[2] = base + 'sel';
			a[3] = base + 'div';
		}
	}
	return a;
}

function jdc_makeNames(idname) {
	jdcInpId = jdcISOId = jdcDivId = null;
	if (idname) {
		var a = jdc_Name(idname);
		if (a) {
			jdcISOId = a[0];
			jdcInpId = a[1];
			jdcDivId = a[3];
			return true;
		}
	}
}

function createDiv() {
	var el, txt, elInp;

	el = document.createElement('div');
	el.setAttribute('id', jdcDivId);
	/* el.setAttribute((document.all) ? 'className' : 'class', 'jdc');       /* IE kludge */
	el.className = 'jdc';
	
	txt = document.createTextNode('Calendar here');
	el.appendChild(txt);
	
	elInp = document.getElementById(jdcInpId);
	if (elInp) {
		var pos = getAbsolutePos(elInp);
		pos.y = pos.y + elInp.offsetHeight + 2;
		el.style.left = pos.x + 'px';
		el.style.top = pos.y + 'px';
		// el.style.position = 'fixed';
		el.style.display = 'none';
		elInp.parentNode.insertBefore(el, elInp.nextSibling);
	}
	return el;
}

function jdc_initControl(idname) {
	var date = getControlDate(idname);
	if (! date)
		date = new Date();
	setControlDate(idname, date);
}

function getControlDate(idname) {
	var str=null, date=null;
	var names = jdc_Name(idname);
	for (var i=0; i < names.length; i++) {
		var id = names[i];
		var el = document.getElementById(id);
		if (el) {
			switch (id) {
				case 'jdc_1_iso' : 
				case 'jdc_2_iso' : date = str2Date(el.value); break;
			}
		}
	}
	return date;
}

function setControlDate(idname, date) {
	var names = jdc_Name(idname);
	for (var i=0; i < names.length; i++) {
		var id = names[i];
		var el = document.getElementById(id);
		if (el) {
			switch (id) {
				case 'jdc_p_div':
				case 'jdc_1_div': 
				case 'jdc_2_div': el.innerHTML = jdc_drawCalendar(id, date); break;

				case 'jdc_1_iso': 
				case 'jdc_2_iso': el.value = jdc_FormatDate('I', date); break;

				case 'jdc_1_inp': 
				case 'jdc_2_inp': 
									el.value = jdc_FormatDate(jdcFmt, date);
									el.title = jdc_FormatDate('F', date);
									hideDiv(jdc_Name(idname, 'div'));
									break;
			}
			switch (id) {
				case 'jdc_1_iso': begDate = date;break;
				case 'jdc_2_iso': endDate = date;break;
				case 'jdc_1_div':
				case 'jdc_2_div': hideDiv(el);break;

			}
		}
	}
}

function get_jdcTarget(evt) {
	var targ = null;

	if ((evt.target) && (evt.target.id.match(/^jdc_/))) {
		targ = evt.target;
	} else if ((evt.srcElement) && (evt.srcElement.id.match(/^jdc_/))) {
		targ = evt.srcElement;
	} else if ((evt.originalTarget) && (evt.originalTarget.id.match(/^jdc_/))) {
		targ = evt.originalTarget;
	}
	if (targ) {
		if (targ.nodeType == 3)		// Safari allows text as events
			targ = targ.parentNode;
	}
	return targ;
}

function jdcToggle(e) {
	var txt = null, id = null;

	var evt = (e) ? e : window.event;
	var targ = get_jdcTarget(evt);

	if (targ) {
		switch (targ.nodeName) {
			case 'INPUT':
			case 'A' : 
			case 'DIV' : jdc_makeNames(targ.id); break;
		}
		if (jdcDivId) {
			var el = document.getElementById(jdcDivId);
			if (! el)
				el = createDiv();
			if (el.style.display == 'block') {
				jdc_divClose(jdcDivId);
			} else {
				jdc_divOpen(jdcDivId);
			}
			evt.cancelBubble = true;
			if (evt.stopPropagation) evt.stopPropagation();
		}
	}
	return false;
}

function jdc_divOpen(idname) {
	jdc_makeNames(idname);
	var el = document.getElementById(jdcDivId);
	if (! el) 
		el = createDiv();
	var d = getControlDate(idname);
	// el.innerHTML = jdc_drawCalendar(jdcInpId, d);
	el.innerHTML = jdc_drawCalendar(jdcDivId, d);
	el.onclick = jdc_calClick;
	el.style.display = 'block';

	jdc_makeNames(null);
}

function jdc_divClose(idname) {
	jdc_makeNames(idname);
	var el = document.getElementById(jdcDivId);
	if (el) {
		el.click = null;
		el.style.display = 'none';
	}
	el = document.getElementById(jdcInpId);
	if (el)
		el.focus();
	jdc_makeNames(null);
}

function jdc_checkForm() {
	// 	var a = getElementsByTagClass('INPUT', 'jdc');
	var a = getElementsByTagNameRegex('INPUT', '^jdc_[1]_iso');
	var len = a.length;
	for (var i = 0; i < len; i++) {
		var el = a[i]
		if ((el.nodeName == 'INPUT') && (el.id.search('iso'))) {
			if (! str2Date(el.value)) {
				jdc_divOpen(targ.id);
				return false;
			}
		}
	}
	if (begDate > endDate) {
		var d = getControlDate(inp2Id);
		setControlDate(inp2Id, begDate);
		setControlDate(inp1Id, d);
		enableGroup('Action', true);
		return false;
	}
	return true;
}

function jdc_checkControl(e) {
	var ok = false;

	var evt = (e) ? e : window.event;

	if (evt.nodeName == 'FORM')
		return jdc_checkForm();

	var targ = get_jdcTarget(evt); 
	if (targ) {
		s = targ.value;
		var date = jdc_parseDate(s); 		// sets the Format
		if (date) {
			ok = true;
			setControlDate(targ.id, date);
			if (! ok) {
				jdc_divOpen(targ.id);
			} else {
				jdc_divClose(targ.id);
			}
		}
	}
	enableGroup('Action', ok);
	return ok;
}

function jdc_parseDate(str) {
	var fmt = guessFormat(str);
	if (! fmt)
		return null;

	jdcFmt = fmt;
	return str2Date(str);
}


/*
	jdc_1_div_M_4
	jdc_1_div_03
	jdc_1_div_T
	jdc_1_div_W_
*/

function parseCalId(id) {
	var date=null, n;

	var m = id.split('_');							
	var idname = [m[0], m[1], m[2]].join('_');

	// Intialize date
	var el = document.getElementById(idname + '_S');
	if (el) 
		date = str2Date(el.getAttribute('name'));
	if (date) {
		switch (m[3]) {
			case 'T': date = today; break;
			case 'M': n = parseInt(m[4], 10); date.setMonth(n); break;
			case 'W': date.setDate(1); break;						// whole month
			default: n = parseInt(m[3], 10); date.setDate(n);
		}
		setControlDate(idname, date);
		switch (m[3]) {
			case 'M': return null;
			default: return date;
		}
	}
	return date;
}

function jdc_calClick(e) {
	var ok = false, date;
	
	var evt = (e) ? e : window.event;
	var targ = get_jdcTarget(evt);

	if (targ) {
		date = parseCalId(targ.id);
		if (date)  
			ok = true;

		if (ok) {
			jdc_divClose(targ.id);
		} else {
			jdc_divOpen(targ.id);
		}
		enableGroup('Action', ok);
	}
	return false;
}

var dblclick = 0;

function clearDblClick() {
	dblclick = 0;
}

function jdc_pcalClick(e) {
	var evt = (e) ? e : window.event;
	var targ = get_jdcTarget(evt);

	if (targ) {
		var date = parseCalId(targ.id);
		if (date) { 
			if (dblclick) {
				setControlDate(inp1Id, date);
				setControlDate(inp2Id, date);
			} else {
				var ctlName = inp1Id;
				if (evt.altKey) 
					ctlName = inp2Id;
				setControlDate(ctlName, date);
			}
			if (targ.id.indexOf('_W_') != -1) {
				setControlDate(inp1Id, date);
				date.setDate(date.getDaysInMonth());
				setControlDate(inp2Id, date);
			}
		}
		evt.cancelBubble = true;
		if (evt.stopPropagation) 
			evt.stopPropagation();
	}
	dblclick = 1;
	setTimeout(clearDblClick, 250);
	return false;
}

function jdc_pselChange(e) {
	var y, m, d;
	var evt = (e) ? e : window.event;
	var targ = get_jdcTarget(evt);

	if (targ) {
		var s = targ.value;
		var redPat = /(\d+).(\d+).(\d+)\D+(\d+).(\d+).(\d+)/;
		var a = s.match(redPat);
		if (a) {
			y = parseInt(a[1], 10); m = parseInt(a[2], 10); d = parseInt(a[3], 10);
			y = y2k(y);
			m--;
			var d1 = new Date(y, m, d);

			y = parseInt(a[4], 10); m = parseInt(a[5], 10); d = parseInt(a[6], 10);
			y = y2k(y);
			m--;
			var d2 = new Date(y, m, d);
			setControlDate(inp1Id, d1);
			setControlDate(inp2Id, d2);
			setControlDate(pSelId, d1);
		}
	}
	evt.cancelBubble = true;
	return false;

}

function initializejdc() {
	var el = document.getElementById(inp1Id);
	if (el) {
		jdc_initControl(inp1Id);
		el.onclick = jdcToggle;
		el.onchange = jdc_checkControl;
		el = document.getElementById(inp2Id);
		if (el) {
			jdc_initControl(inp2Id);
			el.onclick = jdcToggle;
			el.onchange = jdc_checkControl;
		}
		var pDiv = document.getElementById(pDivId);				// permanent calendar ?
		if (pDiv) {
			var date = getControlDate(inp1Id);
			if (! date)
				date = new Date;
			setControlDate(pDivId, date);;
			pDiv.onclick = jdc_pcalClick;
		}
		var pSel = document.getElementById(pSelId);				// Select list ?
		if (pSel) 
			pSel.onchange = jdc_pselChange;
	}
}

function jdc_drawCalendar(idname, date) {
	var out = '', isCurMonth = false;

	if (! date)
		date = new Date();

	var yr = date.getFullYear();
	var mn = date.getMonth();
	var dy = date.getDate();
	yr = y2k(yr);

	if ((today.getFullYear() == yr) && (today.getMonth() == mn)) 
		isCurMonth = true;

	var calDate = new Date(yr, mn, 1);
	var dptr = calDate.getDay();
	var lastdate = calDate.getDaysInMonth();

	var caldays = fillArray(0, 42, '');
	
	for (var i=1; i <= lastdate; i++) 
		caldays[dptr++] = padString(i, 2, '0');
	
	var calrows = new Array();

	while (caldays.length > 0) {
		var r = caldays.splice(0, 7);
		var s = '<td>' + r.join('</td><td>') + '</td>';
		calrows.push(s);
	}
	var zblk = '<tr>' + calrows.join('</tr><tr>') +'</tr>END';

	/* 
	 * set classes 
	 */

	var rePat = /<tr><td>(\d+)/gi;								 // Mark weekend days with class 'we'
	var reRep = '<tr><td we >$1';
	zblk = zblk.replace(rePat, reRep);

	rePat = /<td>(\d+)<\/td><\/tr>/gi;
	reRep = '<td we >$1</td></tr>';
	zblk = zblk.replace(rePat, reRep);

	rePat = new RegExp('>(' + padString(dy, 2, '0') + ')<');		// Mark current selected date with class 'sel'
	reRep = ' sel >$1<';
	zblk = zblk.replace(rePat, reRep);

																	// TODO Mark events with class 'mk'


	if (isCurMonth) {												// Mark todays date with class 'tdy'
		rePat = new RegExp('>(' + padString(today.getDate(), 1, '0') + ')<', "m");
		reRep = ' tdy >$1<';
		zblk = zblk.replace(rePat, reRep);
	}

										// cleanup 
	rePat = /\s+/mg;
	zblk = zblk.replace(rePat, ' ');
	rePat = /<td\s+/mgi;
	zblk = zblk.replace(rePat, '<td class="');
	rePat = /\s+>/mg;
	zblk = zblk.replace(rePat, '">');

	// Set ids to click on

	var calset = '<a href="#" id="' + idname + '_';

	rePat = />(\d+)</mg;
	reRep = '>' + calset + '$1">$1</a><';
	zblk = zblk.replace(rePat, reRep);

	if (! isCurMonth) {
		var tlabel = today.strftime('%b %d');
		var tclick = calset + 'T">';

		rePat = new RegExp('<td></td><td></td><td></td></tr>END');
		reRep = '<td colspan="3" style="text-align: right;" title="Today">' + tclick + tlabel + '</a></td></tr>';
		zblk = zblk.replace(rePat, reRep);										// Link to today
	}

	zblk = zblk.replace('END', '');
	rePat = />0/mg;
	zblk = zblk.replace(rePat, '>&nbsp;');							// remove leading '0'


	var mlabel = calDate.strftime('%b %Y');
	var setid = ' id="' + idname + '_W_01"';

	var clkPrev = calset + 'M_' + (mn-1) + '" title=" ' +  calDate.getMonthName(mn-1) + ' ">' + PREVMON;

	var clkNext = '<th>' + calset + 'M_' + (mn+1) + '" title=" ' +  calDate.getMonthName(mn+1) + ' ">' + NEXTMON;

	var head = '<tr><th>' + clkPrev + '</th><th colspan="5"' + setid + '>' + mlabel + clkNext + '</th></tr>';

	setid = ' id="' + idname + '_S" name="' + date.strftime('%F') + '"';

	out = '<table class="jdc"' + setid + ">\r\n" + head + "\r\n" + zblk + "</table>\r\n";

    return out;
}
				
								 
addLoadEvent(initializejdc);

