//
// calendar -- a javascript date picker designed for easy localization.
//
// $Id$
//
//
// Author: Per Norrman (pernorrman@telia.com)
// 
// Based on Tapestry 2.3-beta1 Datepicker by Paul Geerts
// 
// Thanks to:
//     Vladimir [vyc@quorus-ms.ru] for fixing the IE6 zIndex problem.
//
// The normal setup would be to have one text field for displaying the 
// selected date, and one button to show/hide the date picker control.
// This is  the recommended javascript code:
// 
//	<script language="javascript">
//		var cal;
//
//		function init() {
//			cal = new Calendar();
//			cal.setIncludeWeek(true);
//			cal.setFormat("yyyy-MM-dd");
//			cal.setMonthNames(.....);
//			cal.setShortMonthNames(....);
//			cal.create();
//			
//			document.form.button1.onclick = function() {
//				cal.toggle(document.form.button1);
//			}
//			cal.onchange = function() {
//				document.form.textfield1.value  = cal.formatDate();
//			}
//		}
//	</script>
//
// The init function is invoked when the body is loaded.
//
//

function Calendar(date) {
	if (arguments.length == 0) {
		this._currentDate = new Date();
		this._selectedDate = null;
	}
	else {
		this._currentDate = new Date(date);
		this._selectedDate = new Date(date);
	}

	// Accumulated days per month, for normal and for leap years.
	// Used in week number calculations.	
    Calendar.NUM_DAYS = [0,31,59,90,120,151,181,212,243,273,304,334];
    
    Calendar.LEAP_NUM_DAYS = [0,31,60,91,121,152,182,213,244,274,305,335];
    

	this._bw = new bw_check();
	this._showing = false;	
	this._includeWeek = false;
	this._hideOnSelect = true;
	this._alwaysVisible = false;
	
	this._dateSlot = new Array(42);
	this._weekSlot = new Array(6);
	
	this._firstDayOfWeek = 1;
	this._minimalDaysInFirstWeek = 4;
	
	this._monthNames = [	
		"January",		"February",		"March",	"April",
		"May",			"June",			"July",		"August",
		"September",	"October",		"November",	"December"
	];
	
	this._shortMonthNames = [ 
		"jan", "feb", "mar", "apr", "may", "jun", 
		"jul", "aug", "sep", "oct", "nov", "dec"
	];
	
	// Week days start with Sunday=0, ... Saturday=6
	this._weekDayNames = [
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" 
	];
	
	this._shortWeekDayNames = 
		["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ];
	
	this._defaultFormat = "yyyy-MM-dd";
	
	this._format = this._defaultFormat; 

	this._calDiv = null;
	
	
}

/**
 *	CREATE the Calendar DOM element
 */
Calendar.prototype.create = function() {
	var div;
	var table;
	var tbody;
	var tr;
	var td;
	var dp = this;
	
	// Create the top-level div element
	this._calDiv = document.createElement("div");
	this._calDiv.className = "calendar";
	this._calDiv.style.position = "absolute";
	this._calDiv.style.display = "none";
	this._calDiv.style.border = "1px solid WindowText";
	this._calDiv.style.textAlign = "center";
	this._calDiv.style.background = "Window";
	this._calDiv.style.zIndex = "400";
	
	
	// header div
	div = document.createElement("div");
	div.className = "calendarHeader";
	div.style.background = "ActiveCaption";
	div.style.padding = "3px";
	div.style.borderBottom = "1px solid WindowText";
	this._calDiv.appendChild(div);
	
	table = document.createElement("table");
	table.style.cellSpacing = 0;
	div.appendChild(table);
	
	tbody = document.createElement("tbody");
	table.appendChild(tbody);
	
	tr = document.createElement("tr");
	tbody.appendChild(tr);
	
	// Previous Month Button
	td = document.createElement("td");
	this._previousMonth = document.createElement("button");
	this._previousMonth.className = "prevMonthButton"
	this._previousMonth.appendChild(document.createTextNode("<<"));
	//this._previousMonth.appendChild(document.createTextNode(String.fromCharCode(9668)));
	td.appendChild(this._previousMonth);
	tr.appendChild(td);
	
	
	
	//
	// Create the month drop down 
	//
	td = document.createElement("td");
	td.className = "labelContainer";
	tr.appendChild(td);
	this._monthSelect = document.createElement("select");
    for (var i = 0 ; i < this._monthNames.length ; i++) {
        var opt = document.createElement("option");
        opt.innerHTML = this._monthNames[i];
        opt.value = i;
        if (i == this._currentDate.getMonth()) {
            opt.selected = true;
        }
        this._monthSelect.appendChild(opt);
    }
	td.appendChild(this._monthSelect);
	

	// 
	// Create the year drop down
	//
	td = document.createElement("td");
	td.className = "labelContainer";
	tr.appendChild(td);
	this._yearSelect = document.createElement("select");
	for(var i=1920; i < 2050; ++i) {
		var opt = document.createElement("option");
		opt.innerHTML = i;
		opt.value = i;
		if (i == this._currentDate.getFullYear()) {
			opt.selected = false;
		}
		this._yearSelect.appendChild(opt);
	}
	td.appendChild(this._yearSelect);
	
	
	td = document.createElement("td");
	this._nextMonth = document.createElement("button");
	this._nextMonth.appendChild(document.createTextNode(">>"));
	//this._nextMonth.appendChild(document.createTextNode(String.fromCharCode(9654)));
	this._nextMonth.className = "nextMonthButton";
	td.appendChild(this._nextMonth);
	tr.appendChild(td);
	
	// Calendar body
	div = document.createElement("div");
	div.className = "calendarBody";
	this._calDiv.appendChild(div);
	this._table = div;
	
	// Create the inside of calendar body	
	
	var text;
	table = document.createElement("table");
	//table.style.width="100%";
	table.className = "grid";
	table.style.font 	 	= "small-caption";
	table.style.fontWeight 	= "normal";
	table.style.textAalign	= "center";
	table.style.color		= "WindowText";
	table.style.cursor		= "default";
	table.cellPadding		= "3";
	table.cellSpacing		= "0";
	
    div.appendChild(table);
	var thead = document.createElement("thead");
	table.appendChild(thead);
	tr = document.createElement("tr");
	thead.appendChild(tr);
	
	// weekdays header
	if (this._includeWeek) {
		td = document.createElement("th");
		text = document.createTextNode("w");
		td.appendChild(text);
		td.className = "weekNumberHead";
		td.style.textAlign = "left";
		tr.appendChild(td);
	}
	for(i=0; i < 7; ++i) {
		td = document.createElement("th");
		text = document.createTextNode(this._shortWeekDayNames[(i+this._firstDayOfWeek)%7]);
		td.appendChild(text);
		td.className = "weekDayHead";
		td.style.fontWeight = "bold";
		td.style.borderBottom = "1px solid WindowText";
		tr.appendChild(td);
	}
	
	// Date grid
	tbody = document.createElement("tbody");
	table.appendChild(tbody);
	
	for(week=0; week<6; ++week) {
		tr = document.createElement("tr");
		tbody.appendChild(tr);

		if (this._includeWeek) {
			td = document.createElement("td");
			td.className = "weekNumber";
			td.style.fontWeight = "normal";
			td.style.borderRight = "1px solid WindowText";
			td.style.textAlign = "left";
			text = document.createTextNode(String.fromCharCode(160));
			td.appendChild(text);
            //setCursor(td);
            td.align="center";
			tr.appendChild(td);
			var tmp = new Object();
			tmp.tag = "WEEK";
			tmp.value = -1;
			tmp.data = text;
			this._weekSlot[week] = tmp;
		}

		for(day=0; day<7; ++day) {
			td = document.createElement("td");
			text = document.createTextNode(String.fromCharCode(160));
			td.appendChild(text);
            setCursor(td);
            td.align="center";
            td.style.fontWeight="normal";
            
			tr.appendChild(td);
			var tmp = new Object();
			tmp.tag = "DATE";
			tmp.value = -1;
			tmp.data = text;
			this._dateSlot[(week*7)+day] = tmp;
			
		}
	}
	
	// Calendar Footer
	div = document.createElement("div");
	div.className = "calendarFooter";
	this._calDiv.appendChild(div);
	
	table = document.createElement("table");
	//table.style.width="100%";
	table.className = "footerTable";
	table.cellSpacing = 0;
	div.appendChild(table);
	
	tbody = document.createElement("tbody");
	table.appendChild(tbody);
	
	tr = document.createElement("tr");
	tbody.appendChild(tr);

	//
	// The TODAY button	
	//
	td = document.createElement("td");
	this._todayButton = document.createElement("button");
	var today = new Date();
	var buttonText = today.getDate() + " " + this._monthNames[today.getMonth()] + ", " + today.getFullYear();
	this._todayButton.appendChild(document.createTextNode(buttonText));
	td.appendChild(this._todayButton);
	tr.appendChild(td);
	
	//
	// The CLEAR button
	//
	td = document.createElement("td");
	this._clearButton = document.createElement("button");
	var today = new Date();
	buttonText = "Clear";
	this._clearButton.appendChild(document.createTextNode(buttonText));
	td.appendChild(this._clearButton);
	tr.appendChild(td);
	
	
	this._update();
	this._updateHeader();
	


	// IE55+ extension		
	this._previousMonth.hideFocus = true;
	this._nextMonth.hideFocus = true;
	this._todayButton.hideFocus = true;
	// end IE55+ extension
	
	// hook up events
	// buttons
	this._previousMonth.onclick = function () {
		dp.prevMonth();
	};

	this._nextMonth.onclick = function () {
		dp.nextMonth();
	};

	this._todayButton.onclick = function () {
		dp.setSelectedDate(new Date());
		dp.hide();
	};

	this._clearButton.onclick = function () {
		dp.clearSelectedDate();
		dp.hide();
	};
	

	this._calDiv.onselectstart = function () {
		return false;
	};
	
	this._table.onclick = function (e) {
		// find event
		if (e == null) e = document.parentWindow.event;
		
		// find td
		var el = e.target != null ? e.target : e.srcElement;
		while (el.nodeType != 1)
			el = el.parentNode;
		while (el != null && el.tagName && el.tagName.toLowerCase() != "td")
			el = el.parentNode;
		
		// if no td found, return
		if (el == null || el.tagName == null || el.tagName.toLowerCase() != "td")
			return;
		
		var d = new Date(dp._currentDate);
		var n = Number(el.firstChild.data);
		if (isNaN(n) || n <= 0 || n == null)
			return;
		
		if (el.className == "weekNumber")
			return;
			
		d.setDate(n);
		dp.setSelectedDate(d);

		if (!dp._alwaysVisible && dp._hideOnSelect) {
			dp.hide();
		}
		
	};
	
	
	this._calDiv.onkeydown = function (e) {
		if (e == null) e = document.parentWindow.event;
		var kc = e.keyCode != null ? e.keyCode : e.charCode;

		if(kc == 13) {
			var d = new Date(dp._currentDate).valueOf();
			dp.setSelectedDate(d);

			if (!dp._alwaysVisible && dp._hideOnSelect) {
				dp.hide();
			}
			return false;
		}
			
		
		if (kc < 37 || kc > 40) return true;
		
		var d = new Date(dp._currentDate).valueOf();
		if (kc == 37) // left
			d -= 24 * 60 * 60 * 1000;
		else if (kc == 39) // right
			d += 24 * 60 * 60 * 1000;
		else if (kc == 38) // up
			d -= 7 * 24 * 60 * 60 * 1000;
		else if (kc == 40) // down
			d += 7 * 24 * 60 * 60 * 1000;

		dp.setCurrentDate(new Date(d));
		return false;
	}
	
	// ie6 extension
	this._calDiv.onmousewheel = function (e) {
		if (e == null) e = document.parentWindow.event;
		var n = - e.wheelDelta / 120;
		var d = new Date(dp._currentDate);
		var m = d.getMonth() + n;
		d.setMonth(m);
		
		
		dp.setCurrentDate(d);
		
		return false;
	}

	this._monthSelect.onchange = function(e) {
		if (e == null) e = document.parentWindow.event;
		e = getEventObject(e);
		dp.setMonth(e.value);
	}

	this._monthSelect.onclick = function(e) {
		if (e == null) e = document.parentWindow.event;
		e = getEventObject(e);
		e.cancelBubble = true;
	}
	
	this._yearSelect.onchange = function(e) {
		if (e == null) e = document.parentWindow.event;
		e = getEventObject(e);
		dp.setYear(e.value);
	}


	document.body.appendChild(this._calDiv);
	
	
	return this._calDiv;
}

Calendar.prototype._update = function() {


	// Calculate the number of days in the month for the selected date
	var date = this._currentDate;
	var today = toISODate(new Date());
	
	
	var selected = "";
	if (this._selectedDate != null) {
		selected = toISODate(this._selectedDate);
	}
	var current = toISODate(this._currentDate);
	var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
	var d2 = new Date(date.getFullYear(), date.getMonth()+1, 1);
	var monthLength = Math.round((d2 - d1) / (24 * 60 * 60 * 1000));
	
	// Find out the weekDay index for the first of this month
	var firstIndex = (d1.getDay() - this._firstDayOfWeek) % 7 ;
    if (firstIndex < 0) {
    	firstIndex += 7;
    }
	
	var index = 0;
	while (index < firstIndex) {
		this._dateSlot[index].value = -1;
		this._dateSlot[index].data.data = String.fromCharCode(160);
		this._dateSlot[index].data.parentNode.className = "";
		this._dateSlot[index].data.parentNode.style.fontWeight = "normal";
		this._dateSlot[index].data.parentNode.style.border= "none";
		index++;
	}
        
    for (i = 1; i <= monthLength; i++, index++) {
		this._dateSlot[index].value = i;
		this._dateSlot[index].data.data = i;
		this._dateSlot[index].data.parentNode.className = "";
		this._dateSlot[index].data.parentNode.style.fontWeight = "normal";
		this._dateSlot[index].data.parentNode.style.border= "none";
		if (toISODate(d1) == today) {
			this._dateSlot[index].data.parentNode.className = "today";
			this._dateSlot[index].data.parentNode.style.fontWeight = "bold";
		}
		if (toISODate(d1) == current) {
			this._dateSlot[index].data.parentNode.className += " current";
			this._dateSlot[index].data.parentNode.style.border= "1px dotted WindowText";
		}
		if (toISODate(d1) == selected) {
			this._dateSlot[index].data.parentNode.className += " selected";
			this._dateSlot[index].data.parentNode.style.border= "1px solid WindowText";
		}
		d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+1);
	}
	
	var lastDateIndex = index;
        
    while(index < 42) {
		this._dateSlot[index].value = -1;
		this._dateSlot[index].data.data = String.fromCharCode(160);
		this._dateSlot[index].data.parentNode.className = "";
		this._dateSlot[index].data.parentNode.style.fontWeight = "normal";
		this._dateSlot[index].data.parentNode.style.border= "none";
		++index;
	}
	
	// Week numbers
	if (this._includeWeek) {
		d1 = new Date(date.getFullYear(), date.getMonth(), 1);
		for (i=0; i < 6; ++i) {
			if (i == 5 && lastDateIndex < 36) {
				this._weekSlot[i].data.data = String.fromCharCode(160);
				this._weekSlot[i].data.parentNode.style.borderRight = "none";
			} else {
				week = weekNumber(this, d1);
				this._weekSlot[i].data.data = week;
				this._weekSlot[i].data.parentNode.style.borderRight = "1px solid WindowText";
			}
			d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+7);
		}
	}
}

Calendar.prototype.show = function(element) {
	if(!this._showing) {
		var p = getPoint(element);
		this._calDiv.style.display = "block";
		this._calDiv.style.top = (p.y + element.offsetHeight + 1) + "px";
		this._calDiv.style.left = p.x + "px";
		this._showing = true;
		
		/* -------- */
	   	if( this._bw.ie6 )
	   	{
	     	dw = this._calDiv.offsetWidth;
	     	dh = this._calDiv.offsetHeight;
	     	var els = document.getElementsByTagName("body");
	     	var body = els[0];
	     	if( !body ) return;
	 
	    	//paste iframe under the modal
		     var underDiv = this._calDiv.cloneNode(false); 
		     underDiv.style.zIndex="390";
		     underDiv.style.margin = "0px";
		     underDiv.style.padding = "0px";
		     underDiv.style.display = "block";
		     underDiv.style.width = dw;
		     underDiv.style.height = dh;
		     underDiv.style.border = "1px solid WindowText";
		     underDiv.innerHTML = "<iframe width=\"100%\" height=\"100%\" frameborder=\"0\"></iframe>";
		     body.appendChild(underDiv);
		     this._underDiv = underDiv;
	   }
		/* -------- */
		this._calDiv.focus();
		
	}
};

Calendar.prototype.hide = function() {   
	if(this._showing) {
		this._calDiv.style.display = "none";
		this._showing = false;
		if( this._bw.ie6 ) {
		    if( this._underDiv ) this._underDiv.removeNode(true);
		}
	}
}

Calendar.prototype.toggle = function(element) {
	if(this._showing) {
		this.hide(); 
	} else {
		this.show(element);
	}
}



Calendar.prototype.onchange = function() {};


Calendar.prototype.setCurrentDate = function(date) {
	if (date == null) {
		return;
	}

	// if string or number create a Date object
	if (typeof date == "string" || typeof date == "number") {
		date = new Date(date);
	}
	
	
	// do not update if not really changed
	if (this._currentDate.getDate() != date.getDate() ||
		this._currentDate.getMonth() != date.getMonth() || 
		this._currentDate.getFullYear() != date.getFullYear()) {
		
		this._currentDate = new Date(date);
	
		this._updateHeader();
		this._update();
		
	}
	
}

Calendar.prototype.setSelectedDate = function(date) {
	this._selectedDate = new Date(date);
	this.setCurrentDate(this._selectedDate);
	if (typeof this.onchange == "function") {
		this.onchange();
	}
}

Calendar.prototype.clearSelectedDate = function() {
	this._selectedDate = null;
	if (typeof this.onchange == "function") {
		this.onchange();
	}
}

Calendar.prototype.getElement = function() {
	return this._calDiv;
}

Calendar.prototype.setIncludeWeek = function(v) {
	if (this._calDiv == null) {
		this._includeWeek = v;
	}
}

Calendar.prototype.getSelectedDate = function () {
	if (this._selectedDate == null) {
		return null;
	} else {
		return new Date(this._selectedDate);
	}
}



Calendar.prototype._updateHeader = function () {

	// 
	var options = this._monthSelect.options;
	var m = this._currentDate.getMonth();
	for(var i=0; i < options.length; ++i) {
		options[i].selected = false;
		if (options[i].value == m) {
			options[i].selected = true;
		}
	}
	
	options = this._yearSelect.options;
	var year = this._currentDate.getFullYear();
	for(var i=0; i < options.length; ++i) {
		options[i].selected = false;
		if (options[i].value == year) {
			options[i].selected = true;
		}
	}
	
}

Calendar.prototype.setYear = function(year) {
	var d = new Date(this._currentDate);
	d.setFullYear(year);
	this.setCurrentDate(d);
}

Calendar.prototype.setMonth = function (month) {
	var d = new Date(this._currentDate);
	d.setMonth(month);
	this.setCurrentDate(d);
}

Calendar.prototype.nextMonth = function () {
	this.setMonth(this._currentDate.getMonth()+1);
}

Calendar.prototype.prevMonth = function () {
	this.setMonth(this._currentDate.getMonth()-1);
}

Calendar.prototype.setFirstDayOfWeek = function (nFirstWeekDay) {
	this._firstDayOfWeek = nFirstWeekDay;
}

Calendar.prototype.getFirstDayOfWeek = function () {
	return this._firstDayOfWeek;
}

Calendar.prototype.setMinimalDaysInFirstWeek = function(n) {
	this._minimalDaysInFirstWeek = n;
}


Calendar.prototype.getMinimalDaysInFirstWeek = function () {
	return this._minimalDaysInFirstWeek;
}

Calendar.prototype.setMonthNames = function(a) {
	// sanity test
	this._monthNames = a;
}

Calendar.prototype.setShortMonthNames = function(a) {
	// sanity test
	this._shortMonthNames = a;
}

Calendar.prototype.setWeekDayNames = function(a) {
	// sanity test
	this._weekDayNames = a;
}

Calendar.prototype.setShortWeekDayNames = function(a) {
	// sanity test
	this._shortWeekDayNames = a;
}

Calendar.prototype.getFormat = function() {
	return this._format;
}
	
Calendar.prototype.setFormat = function(f) {
	this._format = f;
}

Calendar.prototype.formatDate = function() {  
	if (this._selectedDate == null) {
		return "";
	}
	
    var bits = new Array();
    // work out what each bit should be
    var date = this._selectedDate;
    bits['d'] = date.getDate();
    bits['dd'] = pad(date.getDate(),2);
    bits['ddd'] = this._shortWeekDayNames[date.getDay()];
    bits['dddd'] = this._weekDayNames[date.getDay()];

    bits['M'] = date.getMonth()+1;
    bits['MM'] = pad(date.getMonth()+1,2);
    bits['MMM'] = this._shortMonthNames[date.getMonth()];
    bits['MMMM'] = this._monthNames[date.getMonth()];
    
    var yearStr = "" + date.getFullYear();
    yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
    bits['yyyy'] = yearStr;
    bits['yy'] = bits['yyyy'].toString().substr(2,2);

    // do some funky regexs to replace the format string
    // with the real values
    var frm = new String(this._format);
    var sect;
    for (sect in bits) {
      frm = eval("frm.replace(/\\b" + sect + "\\b/,'" + bits[sect] + "');");
    }

    return frm;
}
	
                                                                                                       
function isLeapYear(year) {
	return ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
}

function yearLength(year) {
	if (isLeapYear(year))
		return 366;
	else
		return 365;
}

function dayOfYear(date) {
	var a = Calendar.NUM_DAYS;
	if (isLeapYear(date.getFullYear())) {
		a = Calendar.LEAP_NUM_DAYS;
	}
	var month = date.getMonth();
	
	return a[month] + date.getDate();
}

// ---------------------------------------------
// Week number stuff
// ---------------------------------------------

function weekNumber(cal, date) {

	var dow = date.getDay();
	var doy = dayOfYear(date);
	var year = date.getFullYear();

	// Compute the week of the year.  Valid week numbers run from 1 to 52
	// or 53, depending on the year, the first day of the week, and the
	// minimal days in the first week.  Days at the start of the year may
	// fall into the last week of the previous year; days at the end of
	// the year may fall into the first week of the next year.
	var relDow = (dow + 7 - cal.getFirstDayOfWeek()) % 7; // 0..6
	var relDowJan1 = (dow - doy + 701 - cal.getFirstDayOfWeek()) % 7; // 0..6
	var week = Math.floor((doy - 1 + relDowJan1) / 7); // 0..53
	if ((7 - relDowJan1) >= cal.getMinimalDaysInFirstWeek()) {
		++week;
	}

	if (doy > 359) { // Fast check which eliminates most cases
		// Check to see if we are in the last week; if so, we need
		// to handle the case in which we are the first week of the
		// next year.
		var lastDoy = yearLength(year);
		var lastRelDow = (relDow + lastDoy - doy) % 7;
		if (lastRelDow < 0) {
			lastRelDow += 7;
		}
		if (((6 - lastRelDow) >= cal.getMinimalDaysInFirstWeek())
			&& ((doy + 7 - relDow) > lastDoy)) {
			week = 1;
		}
	} else if (week == 0) {
		// We are the last week of the previous year.
		var prevDoy = doy + yearLength(year - 1);
		week = weekOfPeriod(cal, prevDoy, dow);
	}

	return week;
}

function weekOfPeriod(cal, dayOfPeriod, dayOfWeek) {
	// Determine the day of the week of the first day of the period
	// in question (either a year or a month).  Zero represents the
	// first day of the week on this calendar.
	var periodStartDayOfWeek =
		(dayOfWeek - cal.getFirstDayOfWeek() - dayOfPeriod + 1) % 7;
	if (periodStartDayOfWeek < 0) {
		periodStartDayOfWeek += 7;
	}

	// Compute the week number.  Initially, ignore the first week, which
	// may be fractional (or may not be).  We add periodStartDayOfWeek in
	// order to fill out the first week, if it is fractional.
	var weekNo = Math.floor((dayOfPeriod + periodStartDayOfWeek - 1) / 7);

	// If the first week is long enough, then count it.  If
	// the minimal days in the first week is one, or if the period start
	// is zero, we always increment weekNo.
	if ((7 - periodStartDayOfWeek) >= cal.getMinimalDaysInFirstWeek()) {
		++weekNo;
	}

	return weekNo;
}




function getEventObject(e) {  // utility function to retrieve object from event
    if (navigator.appName == "Microsoft Internet Explorer") {
        return e.srcElement;
    } else {  // is mozilla/netscape
        // need to crawl up the tree to get the first "real" element
        // i.e. a tag, not raw text
        var o = e.target;
        while (!o.tagName) {
            o = o.parentNode;
        }
        return o;
    }
}

function addEvent(name, obj, funct) { // utility function to add event handlers

    if (navigator.appName == "Microsoft Internet Explorer") {
        obj.attachEvent("on"+name, funct);
    } else {  // is mozilla/netscape
        obj.addEventListener(name, funct, false);
    }
}


function deleteEvent(name, obj, funct) { // utility function to delete event handlers

    if (navigator.appName == "Microsoft Internet Explorer") {
        obj.detachEvent("on"+name, funct);
    } else {  // is mozilla/netscape
        obj.removeEventListener(name, funct, false);
    }
}

function setCursor(obj) {
   if (navigator.appName == "Microsoft Internet Explorer") {
        obj.style.cursor = "hand";
    } else {  // is mozilla/netscape
        obj.style.cursor = "pointer";
    }
}

function Point(iX, iY)
{
   this.x = iX;
   this.y = iY;
}


function getPoint(aTag)
{
   var oTmp = aTag;  
   var point = new Point(0,0);
  
   do 
   {
      point.x += oTmp.offsetLeft;
      point.y += oTmp.offsetTop;
      oTmp = oTmp.offsetParent;
   } 
   while (oTmp.tagName != "BODY");

   return point;
}

function toISODate(date) {
	var s = date.getFullYear();
	var m = date.getMonth() + 1;
	if (m < 10) {
		m = "0" + m;
	}
	var day = date.getDate();
	if (day < 10) {
		day = "0" + day;
	}
	return String(s) + String(m) + String(day);
	
}

function pad(number,X) {   // utility function to pad a number to a given width
	X = (!X ? 2 : X);
	number = ""+number;
	while (number.length < X) {
	    number = "0" + number;
	}
	return number;
}

function bw_check()
{
    var is_major = parseInt( navigator.appVersion );
    this.nver = is_major;
    this.ver = navigator.appVersion;
    this.agent = navigator.userAgent;
    this.dom = document.getElementById ? 1 : 0;
    this.opera = window.opera ? 1 : 0;
    this.ie5 = ( this.ver.indexOf( "MSIE 5" ) > -1 && this.dom && !this.opera ) ? 1 : 0;
    this.ie6 = ( this.ver.indexOf( "MSIE 6" ) > -1 && this.dom && !this.opera ) ? 1 : 0;
    this.ie4 = ( document.all && !this.dom && !this.opera ) ? 1 : 0;
    this.ie = this.ie4 || this.ie5 || this.ie6;
    this.mac = this.agent.indexOf( "Mac" ) > -1;
    this.ns6 = ( this.dom && parseInt( this.ver ) >= 5 ) ? 1 : 0;
    this.ie3 = ( this.ver.indexOf( "MSIE" ) && ( is_major < 4 ) );
    this.hotjava = ( this.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0;
    this.ns4 = ( document.layers && !this.dom && !this.hotjava ) ? 1 : 0;
    this.bw = ( this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera );
    this.ver3 = ( this.hotjava || this.ie3 );
    this.opera7 = ( ( this.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( this.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) );
    this.operaOld = this.opera && !this.opera7;
    return this;
};


