//--- Search in an array for a value ------------------------------------------
Array.prototype.find = function (element) {
	for (var keys in this) {
		if (this[keys] == element) {
			return keys;
			break;
		}
	}
	return false;
}

//--- Search for object on ID -------------------------------------------------
function getElement(pId, pElem) {
	if (pId) {
		if (pElem == null) pElem = document;
		return (pElem.getElementById) ? pElem.getElementById(pId) : pElem.all[pId];
	} else {
		return null;
	}
}

//--- Search for object on tagname --------------------------------------------
function searchElements(pTagName, pElem) {
	if (pTagName) {
		if (pElem == null) pElem = document;
		return (pElem.getElementsByTagName) ? pElem.getElementsByTagName(pTagName) : null;
	} else {
		return null;
	}
}

//--- Hide all selectboxes (only for IE 6!) -----------------------------------
function hideSelects() {
	if ((myBrowser[1] == "MSIE") && (myBrowser[2] < 7)) {
		var allSelect = searchElements('select', document);
		for (idx = 0; idx < allSelect.length; idx++) {
			if (getCurrentStyle(allSelect[idx], "visibility") != "hidden") {
				allSelect[idx].prevVisibility = getCurrentStyle(allSelect[idx], "visibility");
				allSelect[idx].style.visibility = 'hidden';
			}
		}
	}
}

//--- Show all selectboxes (only for IE 6!) -----------------------------------
function showSelects() {
	if ((myBrowser[1] == "MSIE") && (myBrowser[2] < 7)) {
		var allSelect = searchElements('select', document);
		for (idx = 0; idx < allSelect.length; idx++) {
			if (allSelect[idx].prevVisibility) allSelect[idx].style.visibility = allSelect[idx].prevVisibility;
		}
	}
}

//--- Open a new window -------------------------------------------------------
function openWindow(pUrl, pName, pHeight, pWidth, pPosition) {
	var myPosition;
	if (pPosition == null) {
		myPosition = new Array("center", "center");
	} else {
		myPosition = pPosition.split(" ");
		if (myPosition[1] == "") myPosition[1] = "center";
	}
	var myTop = 0;
	var myLeft = 0;
	if (myPosition[0] == "center") {
		myLeft = Math.max(0, parseInt((screen.availWidth-pWidth) / 2));
	} else if (myPosition[0] == "left") {
		myLeft = windowOffsetLeft();
	}
	if (myPosition[1] == "center") {
		myTop = Math.max(0, parseInt((screen.availHeight-(pHeight+80)) / 2));
	} else if (myPosition[1] == "top") {
		myTop = windowOffsetTop();
	}
	return window.open(pUrl, pName, "resizable=yes,scrollbars=yes,status=yes,menubar=no,left=" + myLeft + ",top=" + myTop + ",height=" + pHeight + ",width=" + pWidth);
}

//--- Get window offset left of screen ----------------------------------------
function windowOffsetLeft() {
	var myOffsetleft = 0;
	if (window.screenLeft) {
		myOffsetleft = window.screenLeft;
	} else if (window.screenX) {
		myOffsetleft = window.screenX;
	}
	return myOffsetleft;
}

//--- Get window offset top of the screen -------------------------------------
function windowOffsetTop() {
	var myOffsettop = 0;
	if (window.screenTop) {
		myOffsettop = window.screenTop;
	} else if (window.screenY) {
		var myMenubar = 0;
		if (window.outerHeight && window.innerHeight) {
			myMenubar = (window.outerHeight - window.innerHeight);
			if (window.statusbar) myMenubar -= 25;
		}
		myOffsettop = window.screenY + w_menubar;
	}
	return myOffsettop;
}

//--- Get window height -------------------------------------------------------
function windowHeight() {
	if (typeof(window.innerHeight) == 'number') {
		return window.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) {
		return document.documentElement.clientHeight;
	} else if (document.body && document.body.clientHeight) {
		return document.body.clientHeight;
	} else {
		return 0;
	}
}

//--- Get window width --------------------------------------------------------
function windowWidth() {
	if (typeof(window.innerWidth) == 'number') {
		return window.innerWidth;
	} else if (document.documentElement && document.documentElement.clientWidth) {
		return document.documentElement.clientWidth;
	} else if (document.body && document.body.clientWidth) {
		return document.body.clientWidth;
	} else {
		return 0;
	}
}

//--- Calculate offset left of an object --------------------------------------
function objectOffsetLeft(pObject, pStop) {
	var myOffsetLeft = pObject.offsetLeft;
	if (pStop) {
		var myParent = pObject.offsetParent;
		while (myParent != null) {
			if (getCurrentStyle(myParent, 'position') == pStop) break;
			myOffsetLeft += myParent.offsetLeft;
			myParent = myParent.offsetParent;
		}
	}
	return myOffsetLeft;
}

//--- Calculate offset left of an object --------------------------------------
function objectOffsetTop(pObject, pStop) {
	var myOffsetTop = pObject.offsetTop;
	if (pStop) {
		var myParent = pObject.offsetParent;
		while (myParent && myParent.offsetTop != null) {
			if (getCurrentStyle(myParent, 'position') == pStop) break;
			myOffsetTop += myParent.offsetTop;
			myParent = myParent.offsetParent;
		}
	}
	return myOffsetTop;
}

//--- Get a current / computed style ------------------------------------------
function getCurrentStyle(pElem, pStyle) {
	if (pElem) {
		var myValue = false;
		if (pElem.currentStyle) {
			var ar = pStyle.match(/\w[^-]*/g);
			var s = ar[0];
			
			for(var i = 1; i < ar.length; ++i) {
				s += ar[i].replace(/\w/, ar[i].charAt(0).toUpperCase());
			}			
			
			myValue = pElem.currentStyle[s];
		} else {
			myValue = document.defaultView.getComputedStyle(pElem, null).getPropertyValue(pStyle);
		}
		return myValue;
	} else {
		return false;
	}
}

//--- Underline labels accesskey for forms ------------------------------------
function underlineAccKeys(pObject) {
	var myLabels = searchElements("LABEL", pObject);
	if ((myLabels != null) && (myLabels.length > 0)) {
		var labelText;
		var myRegexp;
		for (var idx=0; idx < myLabels.length; idx++) {
			if (myLabels[idx].accessKey != "") {
				myRegExp = new RegExp(myLabels[idx].accessKey, "i");
				myUnderline = myLabels[idx].innerHTML.replace(myRegExp, "<span style='text-decoration: underline;'>" + myLabels[idx].innerHTML.match(myRegExp) + "</span>");
				myLabels[idx].innerHTML = myUnderline;
			}
		}
	}
}

//--- Check for selected checkbox ---------------------------------------------
function chkCheckBox(pObject) {
	if (pObject.length) {
		for (var idx=pObject.length; idx > 0; idx--) {
			if (pObject[idx-1].checked) break;
		}
		return (idx == 0 ? false : pObject[idx-1].value);
	} else {
		return (pObject.checked ? pObject.value : false);
	}
}

//--- Get all selected checkbox values ----------------------------------------
function getCheckbox(pObject) {
	if (pObject != null) {
		if (pObject.length) {
			var values = new Array();
			for (var idx=0; idx < pObject.length; idx++) {
				if (pObject[idx].checked) values[values.length] = pObject[idx].value;
			}
			return values;
		} else {
			return (pObject.checked ? new Array(pObject.value) : new Array());
		}
	} else {
		return new Array();
	}
}

//--- Find selected radio object ]---------------------------------------------
function getRadioObject(pObject) {
	if (pObject.length) {
		for (var idx=pObject.length; idx > 0; idx--) {
			if (pObject[idx-1].checked) break;
		}
		return (idx == 0 ? false : pObject[idx-1]);
	} else {
		return (pObject.checked ? pObject : false);
	}
}

//--- Get the key value from the event ----------------------------------------
function getKey(pEvent) {
	var myKey;
	if (pEvent) {
		myKey = pEvent.keyCode;
	}
	if (myKey == null) myKey = 0;
	return myKey;
}

//--- Remove whitespaces from input fields ------------------------------------
function trim(pObject) {
	var expression = new RegExp(/^\s*|\s*$/g);
	if (typeof(pObject) == "string") {
		return pObject.replace(expression, "");
	} else {
		pObject.value = pObject.value.replace(expression, "");
		return pObject.value;
	}
}

//--- Implement disabled options for < IE8 ------------------------------------
// Note: you need to call this function using IE's behaviours for the disabled
//       option(s). You need to check the selected option's disabled status
//       on your FORM's submit trigger since it IS possible that the disabled
//       option has been selected! (same goes for Firefox!)
function ieOptionDisabled(object) {
	if (object.parentNode.onpropertychange == null) {
		object.parentNode.oldSelectedIndex = object.parentNode.selectedIndex;
		object.parentNode.onpropertychange = function () {
			if (this.options[this.selectedIndex].disabled) {
				this.selectedIndex = this.oldSelectedIndex;
			} else if (this.oldSelectedIndex != this.selectedIndex) {
				this.oldSelectedIndex = this.selectedIndex;
			}
		}
	}
}

//--- Create an AJAX request --------------------------------------------------
function createRequest() {
	var myRequest = false;
	try {
		myRequest = new XMLHttpRequest();
	} catch (microsoft1) {
		try {
			myRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (microsoft2) {
			try {
				myRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (failed) {
				myRequest = false;
			}
		}
	}
	return myRequest;
}

function catchError(msg, url, linenumber) {
	alert(
		"An error occured during the execution of the javascript.\n\n" +
		"The message was: '" + msg + "', found on line " + linenumber + ".\n" +
		"It was found on URL: " + url + "\n\n" +
		"Please notify the administrator with this information."
	);
	errorEvent.cancel = true;
	if (errorEvent.stopPropagation) errorEvent.stopPropagation();
	if (errorEvent.preventDefault)  errorEvent.preventDefault();
	return true;
}

///////////////////////////////////////////////////////////////////////////////
// LOOKUP CLASS
//
function WOLookup(pElem, pLookupid, pListSize, pMinlength, pMaxhits, pAjaxHandler, pLinkObjects) {
	this.allowClose = 1;
	this.inputElement = pElem;
	this.lookupId = pLookupid;
	this.listSize = pListSize;
	this.minLength = pMinlength;
	this.maxHits = pMaxhits;
	this.ajaxHandler = pAjaxHandler;
	this.linkObjects = pLinkObjects ? pLinkObjects.split(",") : null;
	this.specKeys = new Array(9, 13, 16, 18, 27, 35, 36, 37, 38, 39, 40);

	this.objContainer = document.createElement('DIV');
	this.objContainer.className = 'hits';
	this.objContainer.style.display = 'none';
	this.objContainer.style.position = 'absolute';
	this.objContainer.style.top = (this.inputElement.offsetHeight) + "px";
	this.objContainer.style.left = "0px";
	this.objContainer.style.zIndex = '999';
	this.inputElement.parentNode.appendChild(this.objContainer);

	this.objContainer.lookup = this;
	this.objContainer.onmouseover = function () { this.lookup.setAllowClose(0); }
	this.objContainer.onmouseout = function () { this.lookup.setAllowClose(1); }	
}

//--- Set the allow close -----------------------------------------------------
WOLookup.prototype.setAllowClose = function (pAllowClose) {
	this.allowClose = pAllowClose;
}

//--- Find values for a Lookup field ------------------------------------------
WOLookup.prototype.doLookup = function (pEvent) {
	var myKey = getKey(pEvent);
	// Do nothing for cursor, tab, escape, etc.
	if (this.inputElement != null && this.specKeys.find(myKey) === false) {
		// Length must be at least the minimum length
		if (this.inputElement.value.toString().length >= this.minLength) {
			var myReq = createRequest();
			if (myReq) {
				// Tijdelijke final variabele die gebruikt kan worden in de onreadystatechange function
				var final_lookup = this;
				myReq.onreadystatechange = function() {
					if ((myReq.readyState == 4) && (myReq.status == 200)) {
						try {
							var myList = eval("(" + myReq.responseText + ")");
						} catch (e) {
							alert("JSON Object Error: '" + myReq.responseText + "'" + e.message);
							final_lookup.inputElement.blur();
						}
						if (myList != null) {
							if (myList.result == "ERROR") {
							} else {
								// Do not show the list when it's NOT triggered with a key and only one item matches exactly with value
								if (((myKey == 0) && (myList.matches.length == 1) && (myList.matches[0] == final_lookup.inputElement.value)) == false) {
									final_lookup.showLookup(myList.matches);
								}
							}
						}
					}
				}

				var queryString = "todo=LOOKUP&lookupid=" + this.lookupId + "&maxhits=" + this.maxHits + "&match=" + encodeURIComponent(this.inputElement.value);
				if (this.linkObjects && this.linkObjects.length) {
					for (var idx=0; idx < this.linkObjects.length; idx++) {
						try {
							var myObject = eval(this.linkObjects[idx]);
							queryString = queryString + "&" + myObject.name + "=" + myObject.value;
						} catch (e) {
							alert(e.description);
						}
					}
				}
				myReq.open("POST", this.ajaxHandler, true);
				myReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + myCharSet);
				myReq.send(queryString);
			}
		// Force removal of the lookup box
		} else {
			this.showLookup(new Array());
		}
	}
}

WOLookup.prototype.showLookup = function (pMatches) {
	var myHTML = "";
	if ((pMatches.length > 0) && (this.listSize > 0)) {
		myHTML += '<ul>';
		for (var idx=0; idx < pMatches.length; idx++) {
			myHTML += "<li onmouseover=\"this.className='current'\" onmouseout=\"this.className=''\" onclick=\"WOLookup.selectLookup(this);\">" + pMatches[idx] + "</li>";
		}
		myHTML += "</ul>";
		this.objContainer.innerHTML = myHTML;
		this.objContainer.style.display = "block";
		this.objContainer.parentNode.style.position = "relative";
		var forceWidth = this.objContainer.parentNode.offsetWidth + parseInt(getCurrentStyle(this.objContainer.previousSibling, "border-left-width"), 10) + parseInt(getCurrentStyle(this.objContainer.previousSibling, "border-right-width"), 10);
		this.objContainer.style.width = forceWidth + "px";
		if (pMatches.length > this.listSize) {
			var myItemHeight = parseInt(this.objContainer.firstChild.firstChild.offsetHeight, 10);
			this.objContainer.style.height = (this.listSize * myItemHeight) + "px";
			this.objContainer.style.overflowY = "scroll";
		} else {
			this.objContainer.style.height = "auto";
			this.objContainer.style.overflowY = "hidden";
		}
	} else if (this.objContainer.style.display != "none") {
		this.objContainer.innerHTML = myHTML;
		this.objContainer.style.display = "none";
		this.objContainer.parentNode.style.position = "static";
	}
}

//--- Check for navigation through the lookup field match list ----------------
WOLookup.prototype.chkLookup = function (pEvent) {
	// Key event should be known
	if (pEvent) {
		var myKey = getKey(pEvent);
		// Tab out or escape: hide match list
		if ((myKey == 9) || (myKey == 27)) {
			this.showLookup(new Array());
		// Cursor up or down: move highlight
		} else if ((myKey == 38) || (myKey == 40)) {
			var myList = searchElements("LI", this.objContainer);
			if ((myList != null) && (myList.length > 0)) {
				// Find current highlight and remove it
				for (var idx=myList.length-1; idx > -1; idx--) {
					if (myList[idx].className == "current") break;
				}
				if (idx > -1) myList[idx].className = "";
				// Determine new item to highlight;
				var newCurrent;
				if (myKey == 38) {
					newCurrent = (idx > 0) ? (idx - 1) : (myList.length - 1);
				} else if (myKey == 40) {
					newCurrent = (idx < (myList.length-1)) ? (idx + 1) : 0;
				}
				myList[newCurrent].className = "current";
				var myBorderTopHeight    = parseInt(getCurrentStyle(this.objContainer, "border-top-height"), 10) || 0;
				var myBorderBottomHeight = parseInt(getCurrentStyle(this.objContainer, "border-bottom-height"), 10) || 0;
				var myContainerHeight    = this.objContainer.offsetHeight + myBorderTopHeight + myBorderBottomHeight;
				if (objectOffsetTop(myList[newCurrent]) < this.objContainer.scrollTop) {
					this.objContainer.scrollTop = objectOffsetTop(myList[newCurrent]);
				} else if ((objectOffsetTop(myList[newCurrent]) + myList[newCurrent].offsetHeight) > (this.objContainer.scrollTop + myContainerHeight)) {
					this.objContainer.scrollTop = objectOffsetTop(myList[newCurrent]) + myList[newCurrent].offsetHeight;
				}
			}
		}
	// No key event: hide matches list
	} else if (this.allowClose == 1) {
		this.showLookup(new Array());
	}
}

//--- Handle lookup field enter key ]------------------------------------------
WOLookup.prototype.handleLookup = function (pEvent) {
	var myKey = getKey(pEvent);
	if (myKey == 13) {
		if (this.objContainer.style.display == "block") {
			pEvent.returnValue = false;
			pEvent.cancel = true;
			if (pEvent.stopPropagation) pEvent.stopPropagation();
			if (pEvent.preventDefault) pEvent.preventDefault();
			var myList = searchElements("LI", this.objContainer);
			if ((myList != null) && (myList.length > 0)) {
				for (var idx=0; idx < myList.length; idx++) {
					if (myList[idx].className == "current") break;
				}
				if (idx < myList.length) this.selectValue(myList[idx]);
			}
		}
	}
}

//--- Select lookup field selection (by either enter key or click) ------------
WOLookup.prototype.selectValue = function (pElem) {
	// Copy text node contents to input value and hide match list
	this.inputElement.value = pElem.firstChild.nodeValue;
	this.objContainer.style.display = 'none';
	this.objContainer.parentNode.style.position = "static";
}


//--- Create the new lookup field ---------------------------------------------
WOLookup.createLookup = function (pElem, pLookupid, pListSize, pMinlength, pMaxhits, pAjaxHandler, pLinkObjects) {
	if (!pElem.lookup) {
		//alert('Create lookup');
		pElem.lookup = new WOLookup(pElem, pLookupid, pListSize, pMinlength, pMaxhits, pAjaxHandler, pLinkObjects);
	}
	pElem.lookup.doLookup(null);
}

//--- Handle lookup field selection (by either enter key or click) ------------
WOLookup.selectLookup = function (pElem) {
	// Find the lookup container object
	var myLookup = pElem.parentNode;
	while (myLookup != null) {
		if ((myLookup.className == "hits") && (myLookup.tagName == "DIV")) {
			break;
		}
		myLookup = myLookup.parentNode;
	}

	// Copy text node contents to input value and hide match list
	if (myLookup != null) {
		myLookup.lookup.selectValue(pElem);
		//myLookup.firstChild.style.display = "none";
	}
}

///////////////////////////////////////////////////////////////////////////////
// CALENDAR CLASS
//
function WOCalendar(pInputElem, pMonths, pDays, pMultiple, pPHPParser) {
	this.objInputElem = pInputElem;
	this.arrMonths = pMonths.split(',', 12);
	this.arrDays = pDays.split(',', 7);
	this.multiple = (pMultiple == "multiple");
	this.phpparser = (pPHPParser ? pPHPParser : null);
	this.allowClose = 1;
	this.isShown = false;
	this.arrDate = null;
	this.arrDates = new Array();
	this.currentMonth = -1;
	this.currentYear = -1;
	this.monthSelector = null;
	
	this.objContainer = document.createElement('DIV');
	this.objContainer.className = 'calendar';
	this.objContainer.style.position = 'absolute';
	this.objContainer.style.display = 'block';
	this.objContainer.style.zIndex = '+999';
	this.objContainer.style.top = (this.objInputElem.offsetHeight) + 'px';
	this.objContainer.style.left = '0px';
	this.objContainer.calendar = this;
	this.objContainer.onmouseover = function () { this.calendar.setAllowClose(0); }
	this.objContainer.onmouseout = function () { this.calendar.setAllowClose(1); }	
}

WOCalendar.prototype.setAllowClose = function(pAllow) {
	this.allowClose = pAllow;
}

WOCalendar.prototype.show = function() {
	if (this.isShown) return;
	this.isShown = true;

	var myDate = new Date();
	trim(this.objInputElem);

	// If there is input: read it and parse it.
	if (this.objInputElem != "") {
		var inputDates = (this.multiple) ? this.objInputElem.value.split(/,|;/) : [ this.objInputElem.value ];
		if (this.phpparser) {
			var myReq = createRequest();
			if (myReq) {
				var parsedDates = null;
				myReq.open("POST", this.phpparser, false);
				myReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + myCharSet);
				myReq.send("todo=parsedates&dates=" + inputDates.join(","));
				if ((myReq.readyState == 4) && (myReq.status == 200)) {
					try {
						parsedDates = eval("(" + myReq.responseText + ")");
					} catch (e) {
						alert("Error parsing JSON object. The response text was:\n" + myReq.responseText + "\nPlease note this and contact the administrator.");
					}
				} else {
					alert("An error occured while calling the AJAX object.\nReady state: " + myReq.readyState + "\nStatus: " + myReq.status + "\nPlease note this and contact the administrator.");
				}
				if ((parsedDates != null) && parsedDates.length) {
					this.arrDates = parsedDates;
				}
			}
		} else {
			var myDateTime = null;
			for (var idx=0; idx < inputDates.length; idx++) {
				myDateTime = Date.parse(inputDates[idx]);
				if (isNaN(myDateTime) == false) this.arrDates[this.arrDates.length] = myDateTime;
			}
		}
	}

	// If there is more than one date: sort the list of dates
	if (this.arrDates.length > 1) this.arrDates.sort(
		function (num1, num2) {
			return (num1-num2);
		}
	);

	// Determine which month and year to show initially
	if (this.arrDates.length > 0) myDate.setTime(this.arrDates[0]);
	this.currentMonth = myDate.getMonth();
	this.currentYear = myDate.getFullYear();
	this.buildCalendar();
}

WOCalendar.prototype.hide = function() {
	if (this.isShown && this.allowClose == 1) {
		this.objInputElem.calendar = null;
		this.objContainer.parentNode.removeChild(this.objContainer);
		this.objInputElem.parentNode.style.position = 'static';
		if (/MSIE 6/.test(myBrowser)) showSelects();
		return true;
	}
	return false;
}

WOCalendar.prototype.buildCalendar = function () {
	// Date object for the currently selected Month, Year (first day)
	var myDate = new Date(this.currentYear, this.currentMonth, 1);
	//	
	// Because we start the week with monday, we search backwards to monday of current week
	// Notes:	if we do setDate(0), than date will go back 1 day, setDate(-1) means 2 days back, etc
	// 			Sunday == 0, Monday == 1, Tuesday == 2, ...
	var diffdate = 2 - myDate.getDay();
	if (diffdate > 1) diffdate = -5;
	myDate.setDate(diffdate);
	
	////////////////////////////////////////////////////////////////////////////////////////////////
	// Create the needed html code
	//
	var strhtml = "";
	
	// Start with the header: Prev, Month, Next
	strhtml += '<table border="0" cellpadding="0" cellspacing="0" class="caltable">';
	strhtml += '<tr class="buttonbar">';
	strhtml += '<td><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.showPrevYear(); return false;">&lt;&lt;</a></td>';
	strhtml += '<td><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.showPrevMonth(); return false;">&lt;</a></td>';
	strhtml += '<td colspan="3"><div class="monthselector" style="position:relative;">';

	strhtml += '<div style="position:absolute;display:none;">';
	strhtml += '<table cellpadding="0" cellspacing="0" class="monthselector">';
	for (idxmonth = 0; idxmonth < this.arrMonths.length; idxmonth++) {
		if (idxmonth % 3 == 0) strhtml += '<tr>';
		strhtml += '<td><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.showMonth('+idxmonth+'); return false;">';
		strhtml += this.arrMonths[idxmonth];
		strhtml += '</a></td>';
		if (idxmonth % 3 == 2) strhtml += '</tr>';
	}
	strhtml += '</table>';
	strhtml += '</div>';

	strhtml += '<a href="#" onclick="var mycal = WOCalendar.getCalendar(this); mycal.toggleMonthSelector(this); return false;" id="btnSelectMonth_'+this.objInputElem.name+'">'+this.arrMonths[this.currentMonth] + '&nbsp;' + this.currentYear+'</a>';
	strhtml += '</div></td>';
	strhtml += '<td><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.showNextMonth(); return false;">&gt;</a></td>';
	strhtml += '<td><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.showNextYear(); return false;">&gt;&gt;</a></td>';
	strhtml += '</tr>';
	
	// First the header (day letters)
	strhtml += "<tr>";
	for (idxday = 0; idxday < this.arrDays.length; idxday++) {
		strhtml += "<td>" + this.arrDays[idxday] + "</td>";
	}
	strhtml += "</tr>";

	var myToday = new Date();
	myToday.setHours(0);
	myToday.setMinutes(0);
	myToday.setSeconds(0);
	myToday.setMilliseconds(0);

	// Than the days (numbers)
	for (var idx=0; idx < 56; idx++) {
		// Monday, start of week
		if (myDate.getDay() == 1) strhtml += '<tr>';

		// Determine class name
		var myClass = new Array();	
		if (myToday.getTime() == myDate.getTime()) {
			myClass[myClass.length] = 'today';
		}
		if (this.arrDates.find(myDate.getTime())) {
			myClass[myClass.length] = 'selected';
		}
		if (this.currentMonth == myDate.getMonth()) {
			strhtml += '<td class="active"><a href="#" onclick="this.blur(); var mycal = WOCalendar.getCalendar(this); mycal.selectDate(' + myDate.getTime() + '); return false;" class="' + myClass.join(' ') + '">' + myDate.getDate() + '</a></td>';
		} else {
			strhtml += '<td class="inactive">' + myDate.getDate() + '</td>';
		}
		// Sunday, end of week
		if (myDate.getDay() == 0) strhtml += '</tr>';
		
		myDate.setDate(myDate.getDate() + 1);
		if ((this.currentMonth - myDate.getMonth() == -1 || this.currentMonth - myDate.getMonth() == 11) && myDate.getDay() == 1) break;
	}

	strhtml += '</table>';
	
	////////////////////////////////////////////////////////////////////////////////////////////////
	// Show the calendar
	//
	this.objContainer.innerHTML = strhtml;
	this.objInputElem.parentNode.appendChild(this.objContainer);
	this.objInputElem.parentNode.style.position = 'relative';
	if (/MSIE 6/.test(myBrowser)) hideSelects();
}

WOCalendar.prototype.toggleMonthSelector = function (pElem) {
	if (this.monthSelector == null) {
		this.monthSelector = pElem.previousSibling;
		this.monthSelector.style.display = 'block';
	}else{
		this.monthSelector.style.display = 'none';
		this.monthSelector = null;
	}
}

WOCalendar.prototype.showMonth = function (month) {
	this.currentMonth = month;
	this.buildCalendar();	
	this.monthSelector.style.display = 'none';
	this.monthSelector = null;
}

WOCalendar.prototype.showPrevMonth = function () {
	this.currentMonth--;
	if (this.currentMonth < 0) {
		this.currentMonth = 11;
		this.currentYear--;
	}
	this.buildCalendar();
}

WOCalendar.prototype.showNextMonth = function () {
	this.currentMonth++;
	if (this.currentMonth > 11) {
		this.currentMonth = 0;
		this.currentYear++;
	}
	this.buildCalendar();
}

WOCalendar.prototype.showPrevYear = function () {
	this.currentYear--;
	this.buildCalendar();
}

WOCalendar.prototype.showNextYear = function () {
	this.currentYear++;
	this.buildCalendar();
}

WOCalendar.prototype.selectDate = function (pTime) {
	var myDate = new Date();

	if (this.multiple == false) {
		this.arrDates[0] = pTime;
	} else if (this.arrDates.find(pTime)) {
		this.arrDates.splice(this.arrDates.find(pTime),1);
	} else {
		this.arrDates[this.arrDates.length] = pTime;
		this.arrDates.sort(
			function (num1, num2) {
				return (num1-num2);
			}
		);
	}

	var selDates = new Array();
	for (var idx=0; idx < this.arrDates.length; idx++) {
		myDate.setTime(this.arrDates[idx]);
		selDates[selDates.length] = (myDate.getDate() < 10 ? '0' : '') + myDate.getDate() + ' ' + this.arrMonths[myDate.getMonth()] + ' ' + myDate.getFullYear();
	}

	this.objInputElem.value = selDates.join(',');
	if (this.objInputElem.onchange) {
		objInputElem = this.objInputElem;
		setTimeout(function() { objInputElem.onchange(); }, 100);
	}

	if (this.multiple) {
		this.buildCalendar();
	} else {
		this.allowClose = 1;
		this.hide();
	}
}

WOCalendar.showCalendar = function (pInputElem, pMonths, pDays, pMultiple, pPHPParser) {
	pInputElem.calendar = new WOCalendar(pInputElem, pMonths, pDays, pMultiple, pPHPParser);
	pInputElem.calendar.show();
}
		
WOCalendar.hideCalendar = function (pInputElem) {
	if (pInputElem.calendar) {
		if (pInputElem.calendar.hide()) pInputElem.calendar = null;
	}
}

WOCalendar.toggleCalendar = function (pInputElem, pMonths, pDays, pMultiple, pPHPParser) {
	if (pInputElem.calendar) {
		// Close it
		pInputElem.calendar.setAllowClose(1);
		WOCalendar.hideCalendar(pInputElem);
	}else{
		// Open it
		WOCalendar.showCalendar(pInputElem, pMonths, pDays, pMultiple, pPHPParser);
	}
}

WOCalendar.getCalendar = function (objElem) {
	idx = 0;
	while (objElem != null && objElem.tagName != 'HTML' && idx < 100) {
		idx++;
		if (objElem.tagName == 'DIV' && /calendar/.test(objElem.className)) {
			return objElem.calendar;
		}
		objElem = objElem.parentNode;
	}
	return null;
}

var myRegExp = new RegExp(/(MSIE|Safari|Firefox|Opera|Chrome)[/|\s]([0-9]*)\.([0-9\.]*)/i);
var myBrowser = myRegExp.exec(navigator.userAgent) || new Array("UNKNOWN 0.0", "UNKNOWN", 0, 0);

var errorEvent = null;
var ajax_error = new Array();
ajax_error[404] = "URL object not found (404).";
var allowClose = 1;
var myCharSet = "ISO-8859-1";
if (document.charset) {
	myCharSet = document.charset;
} else if (document.characterSet) {
	myCharSet = document.characterSet;
}
