

// months as they appear in the selection list
var ARR_MONTHS = ["January", "February", "March", "April", "May", "June",
		"July", "August", "September", "Oktober", "November", "December"];
// week day titles as they appear on the calendar
var ARR_WEEKDAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
// day week starts from (normally 0-Su or 1-Mo)
var NUM_WEEKSTART = 0;
// path to the directory where calendar images are stored 
var STR_ICONSPATH = '../calendar/';
// in year selection box how many years to list relative to current year
var NUM_YEARSBEFORE = 0;
var NUM_YEARSAFTER  = 1;

var NUM_SECONDCALENDAROFFSET = 3; // days
// --------------------------------------------------------------------------------
var calendars = [];

// preload invisible icon
var cal_icon = new Image();
cal_icon = STR_ICONSPATH + "no_cal.gif";

// Constructor
function calendar (str_date, str_form_name, str_ctrl_name, str_min_date, str_max_date) {

	// assign methods
	this.get_html  = cal_get_html;
	this.repos = cal_repos;
	this.init  = cal_init;
	this.get_abspos = cal_get_abspos;
	this.get_body  = cal_get_body;
	this.set_year  = cal_set_year;
	this.set_month = cal_set_month;
	this.set_day   = cal_set_day;
	this.fill_years= cal_fill_years;
	this.validate  = cal_validate;
	this.show = cal_show;
	this.UA=U_A=new _UserAgent();

	this.update = cal_update;

	// register in global collections
	this.id = calendars.length;
	calendars[this.id] = this;

	// process input parameters
	var re_url = new RegExp('cal' + this.id + '_val=(\\d+)');
	var dt_params = (str_date ? cal_parse_date(str_date) : cal_date_only());

	this.dt_current = (re_url.exec(String(window.location))
		? new Date(new Number(RegExp.$1)) : dt_params);
	
	if (!str_form_name)
		return alert('Form name is required parameter of draw method.');
	if (!document.forms[str_form_name])
		return alert ("Form with name '" + this.form_name + "' can't be found in the document.");
	this.form_name = str_form_name;
	this.control_name = (str_ctrl_name ? str_ctrl_name : 'datetime_' + this.id);
	
	// set date limits
	var re_num = /^-?\d+$/;
	if (str_min_date != null)
		this.min_date = (re_num.exec(str_min_date)
			? new Date (dt_params.valueOf() - new Number(str_min_date * 864e5))
			: cal_parse_date(str_min_date)
		);
	if (str_max_date != null)
		this.max_date = (re_num.exec(str_max_date)
			? new Date (dt_params.valueOf() + new Number(str_max_date * 864e5))
			: cal_parse_date(str_max_date)
		);

	// print date input control
	document.write('<table cellpadding="0" cellspacing="0" border="0" width="170"><tr><td><input type="Text" readonly name="' + this.control_name + '" value="' + (str_date ? cal_generate_date(this.dt_current) : '') + '" class="calDatCtrl" maxlength="10" width="10" onclick="javascript:calendars[' + this.id + '].show();"></td>' + ((document.body && document.body.innerHTML) ? '<td><img src="'+ STR_ICONSPATH + 'pixel.gif" width="2" height="1" border="0"></td><td><a href="javascript:calendars[' + this.id + '].show();"><img src="'+ STR_ICONSPATH + 'cal.gif" width="16" height="16" border="0" alt="Klik og vælg dato i kalender" name="calicon' + this.id + '" id="calicon' + this.id + '"></a></td></tr><tr><td colspan="3"><img src="'+ STR_ICONSPATH + 'pixel.gif" width="1" height="1" border="0" name="calpos' + this.id + '" id="calpos' + this.id + '"></td>' : '') + '</tr></table>');
	this.posit = document.all ? document.all['calpos' + this.id] :
				document.images ? document.images['calpos' + this.id] :
				document.getElementById('calpos' + this.id);
				
	this.icon = document.all ? document.all['calicon' + this.id] :
				document.images ? document.images['calicon' + this.id] :
				document.getElementById('calicon' + this.id);
}
function cal_init () {
	document.write('<div id="caldiv' + this.id + '" style="position: absolute; left:0; top:0; width:170; height:170; visibility:hidden; z-index: ' + this.id + '">' + this.get_html() + '</div>');
	if (!document.body || !document.body.innerHTML)
		return;
	this.box_style = document.all
		? document.all['caldiv' + this.id].style
		: document.getElementById('caldiv' + this.id).style;
	this.mon_ctrl    = document.forms['calform' + this.id].elements['calmon'];
	this.year_ctrl   = document.forms['calform' + this.id].elements['calyear'];
	this.fill_years(this.dt_current.getFullYear());

	this.control_obj = document.forms[this.form_name].elements[this.control_name];
	this.repos();
}
function cal_get_html () {
	var dt_datetime = this.dt_current;
	var str_buffer =	
		'<form name="calform' + this.id + '"><table cellspacing="0" class="calOuterTable" border="0" width="100%" align="center" ><tr><td><table cellspacing="0" class="calSelectTable" width="100%" border="0"><tr><td><select name="calmon" class="calMonCtrl" onchange="return calendars[' + this.id + '].set_month();">';
	for (i = 0; i < 12; i++)
		str_buffer += '<option value="' + i + '"' + (i == dt_datetime.getMonth() ? ' selected' : '') + '>' + ARR_MONTHS[i] + '</option>';
		
	str_buffer += '</select></td><td align="right"><select name="calyear" class="calYearCtrl" onchange="return calendars[' + this.id + '].set_year();">';
	str_buffer += '</select></td></tr></table><div id="calbody' + this.id + '">' + this.get_body(dt_datetime) + '</div></td></tr></table></form>';

	return (str_buffer);
}
function cal_repos () {
    var smx=0, smy=0;
    if( this.UA.ie && this.UA.mac) {
		 if (document.body.leftMargin)  smx = document.body.leftMargin * 1; 
		 if (document.body.topMargin)  smy = document.body.topMargin * 1;  
	}
	this.box_style.left = this.posit.x ? this.posit.x : (this.get_abspos('Left')+smx);
	this.box_style.top  = this.posit.y ? this.posit.y : (this.get_abspos('Top')+smy);
	
}
function cal_get_abspos (s_coord) {
	var n_pos = 0,
		o_elem = this.posit;
	while (o_elem)	{
		n_pos += o_elem["offset" + s_coord];
		o_elem = o_elem.offsetParent;
		
	}
	return n_pos;
}
function cal_show() {
   
	var s_visib = String(this.box_style.visibility).toLowerCase();
	if (s_visib == 'visible' || s_visib == 'show') {
		this.box_style.visibility = 'hidden';
		this.icon.src = STR_ICONSPATH + 'cal.gif';
 	}
	else {
		this.repos();
		var dt_ctrl;
		if (this.control_obj.value) dt_ctrl = cal_parse_date(this.control_obj.value);
		if (!dt_ctrl) dt_ctrl = cal_date_only();
		if (this.dt_current.valueOf() != dt_ctrl.valueOf()) {
			this.dt_current = dt_ctrl;
			this.update(this.dt_current);
		}
		this.box_style.visibility = 'visible';
		this.icon.src = STR_ICONSPATH + 'no_cal.gif';
	}
};
function cal_update (dt_datetime) {
	this.dt_current = dt_datetime;
	var obj_container = (document.all ?
		document.all['calbody' + this.id] :
		document.getElementById('calbody' + this.id)
	);
	obj_container.innerHTML =  this.get_body(dt_datetime);
	this.mon_ctrl.selectedIndex = dt_datetime.getMonth(); 
	for (var i = 0; i < this.year_ctrl.options.length; i++)
		this.year_ctrl.options[i].selected = (this.year_ctrl.options[i].text == dt_datetime.getFullYear());
}
function cal_set_day (num_datetime) {
	var dt_newdate = new Date(num_datetime);
	if (this.validate(dt_newdate)) {
		this.control_obj.value = cal_generate_date(dt_newdate);
		this.show();
		if (!this.id && calendars[1]) {
			// first calendar sets second caleddar
			var dt_second = dt_newdate;
			dt_second.setDate(dt_second.getDate() + NUM_SECONDCALENDAROFFSET);
			calendars[1].control_obj.value = cal_generate_date(dt_newdate);
			calendars[1].min_date = dt_newdate;
		}
	}
	else
		this.update(this.dt_current);
}
function cal_set_month () {
	var dt_newdate = new Date(this.dt_current);
	var num_month = this.mon_ctrl.options[this.mon_ctrl.selectedIndex].value;
	
	dt_newdate.setMonth(num_month);
	if (num_month != dt_newdate.getMonth())
		dt_newdate.setDate(0);
	
	if (this.validate(dt_newdate))
		this.update(dt_newdate);
	else
		this.mon_ctrl.selectedIndex = this.dt_current.getMonth();
}
function cal_set_year () {
	var dt_newdate = new Date(this.dt_current);
	var str_year = this.year_ctrl.options[this.year_ctrl.selectedIndex].text;
	var str_scroll = this.year_ctrl.options[this.year_ctrl.selectedIndex].value;

	var num_year;
	if (str_scroll) {
		num_year = (str_scroll == '+'
			? this.dt_current.getFullYear() + NUM_YEARSAFTER
			: this.dt_current.getFullYear() - NUM_YEARSBEFORE
		);
	}
	else 
		num_year = new Number(str_year);
	dt_newdate.setFullYear(num_year);
	var num_month = this.mon_ctrl.options[this.mon_ctrl.selectedIndex].value;
	if (num_month != dt_newdate.getMonth())
		dt_newdate.setDate(0);

	if (!this.validate(dt_newdate)) {
		this.year_ctrl.selectedIndex =
			this.dt_current.getFullYear() - Number(this.year_ctrl.options[1].text) + 1;
		return;
	}

	if (str_scroll)
		this.fill_years(num_year);
	this.update(dt_newdate);
}

function cal_fill_years (num_year) {
		this.year_ctrl.length = 0;

		var num_begin_year = num_year - NUM_YEARSBEFORE,
			b_topscroll = true;
		if (this.min_date && num_begin_year <= this.min_date.getFullYear()) {
			num_begin_year = this.min_date.getFullYear();
			b_topscroll = false;
		}
		var num_end_year = num_year + NUM_YEARSAFTER,
			b_bottomscroll = true;
		if (this.max_date && num_end_year >= this.max_date.getFullYear()) {
			num_end_year = this.max_date.getFullYear();
			b_bottomscroll = false;
		}
		
		if (b_topscroll)
			this.year_ctrl.options[0] = new Option('<< ' + num_begin_year, '-');
		var num_idex = b_topscroll ? 1 : 0;
		for (var i = num_begin_year + num_idex; i < num_end_year + (b_bottomscroll ? 0 : 1); i++) {
			this.year_ctrl.options[num_idex] = new Option(i);
			this.year_ctrl.options[num_idex].selected = (i == num_year);
			num_idex++;
		}
		if (b_bottomscroll)
			this.year_ctrl.options[NUM_YEARSBEFORE + NUM_YEARSAFTER] = new Option((num_end_year) + ' >>', '+');
}

function cal_get_body (dt_datetime) {

	var dt_firstday = new Date(dt_datetime);
	dt_firstday.setDate(1);
	dt_firstday.setDate(1 - (7 + dt_firstday.getDay() - NUM_WEEKSTART) % 7);
	
	var str_buffer = new String (
	'<table cellspacing="1" cellpadding="2" class="calDaysTable" width="100%">');

	str_buffer += '<tr>';
	for (var n = 0; n < 7; n++)
		str_buffer += '<td class="calWTitle">' + ARR_WEEKDAYS[(NUM_WEEKSTART + n) % 7] + '</td>';
	str_buffer += "</tr>\n";

	var dt_current_day = new Date(dt_firstday);
	while (dt_current_day.getMonth() == dt_datetime.getMonth() ||
		dt_current_day.getMonth() == dt_firstday.getMonth()) {
		str_buffer += '<tr>';
		for (var n_current_wday = 0; n_current_wday < 7; n_current_wday++) {

				if (dt_current_day.getDate() == dt_datetime.getDate() &&
					dt_current_day.getMonth() == dt_datetime.getMonth())
					str_buffer += '<td class="calDayCurrent" align="center" valign="middle">';
				else if (dt_current_day.getDay() == 0 || dt_current_day.getDay() == 6)
					str_buffer += '<td class="calDayWeekend" align="center" valign="middle">';
				else
					str_buffer += '<td class="calDayWorking" align="center" valign="middle">';

				if (!this.validate(dt_current_day, true))
					str_buffer += '<span class="calForbDate">'
						+ dt_current_day.getDate() + '</span></td>';
				else if (dt_current_day.getMonth() == dt_datetime.getMonth())
					str_buffer += '<a href="javascript:calendars[' + this.id +
						'].set_day(' + dt_current_day.valueOf() + ');" class="calThisMonth">'
						+ dt_current_day.getDate() + '</a></td>';
				else 
					str_buffer += '<a href="javascript:calendars[' + this.id +
						'].set_day(' + dt_current_day.valueOf() + ');" class="calOtherMonth">'
						+ dt_current_day.getDate() + '</a></td>';

				dt_current_day.setDate(dt_current_day.getDate() + 1);
		}
		str_buffer += "</tr>\n";
	}
	str_buffer +=
		'</table>';

	return (str_buffer);
}
function cal_date_only (dt_datetime) {
	if (!dt_datetime)
		dt_datetime = new Date();
	dt_datetime.setHours(0);
	dt_datetime.setMinutes(0);
	dt_datetime.setSeconds(0);
	dt_datetime.setMilliseconds(0);
	return dt_datetime;
}
function cal_validate (dt_datetime, b_silent) {
	if (this.max_date && dt_datetime > this.max_date) {
		if (!b_silent)
			alert ('Last day is ' + cal_generate_date(this.max_date) + ' ');
		return false;
	}
	if (this.min_date && dt_datetime < this.min_date) {
		b_silent = 1;
		if (!b_silent)
			alert ('Vi åbner ' + cal_generate_date(this.min_date) + ' ');
		return false;
	}
	// more validation can be added here
	return true;
}

function _UserAgent() {
	var b = navigator.appName;
	var v = this.version = navigator.appVersion;
	var ua=this.uas = navigator.userAgent.toLowerCase();
	this.v = parseInt(v);
	this.mozilla=false;
	this.ns = (b == "Netscape");
	this.ie = (b == "Microsoft Internet Explorer");
	this.opera = ua.indexOf("opera")>0;
	if(ua.indexOf("netscape") < 0 && ua.indexOf("msie") < 0  && ua.indexOf("opera") < 0 && this.v >= 5) {
		this.mozilla = true;
		this.ns = false;
	}
	if (this.ns) {
		this.v = parseInt(v);
		this.ns4 = (this.v==4);
		this.ns6 = (this.v>=5);
	}
	else if (this.ie) {
		this.ie4 = this.ie5 = this.ie55 = this.ie6 = false;
		if (v.indexOf('MSIE 4') > 0) {this.ie4 = true; this.v = 4;}
		else if (v.indexOf('MSIE 5') > 0) {this.ie5 = true; this.v = 5;}
		else if (v.indexOf('MSIE 5.5') > 0) {this.ie55 = true; this.v = 5.5;}
		else if (v.indexOf('MSIE 6') > 0) {this.ie6 = true; this.v = 6;}
	}
	else if (this.opera || this.mozilla) {
		this.v = parseInt(v);
	}
	this.win32 = ua.indexOf("win")>-1;
	this.mac = ua.indexOf("mac")>-1;
	this.other = (!this.win32 && !this.mac);
}
