if (current_year==undefined) {
	var current_year = (new Date()).getFullYear();
}

if (current_month==undefined) {
	var current_month = (new Date()).getMonth() + 1;
}

//////////////////////////////////////////////////////////////////
//	string handling routines, custom made voor kinderopvang
//////////////////////////////////////////////////////////////////
/**
 *	haalt de 'quote-codes' uit een string weg en vervangt ze door de gepaste enkele of dubbele quotes
 * author:  DiVer
 *	*/
 function unescape_quotes(str){
 	var current_str = str.replace("//singlequote//","'");
 	current_str = current_str.replace("//doublequote//","\"");
 	return current_str;
 } 



//////////////////////////////////////////////////////////////////
// Generieke array als parameter
//////////////////////////////////////////////////////////////////
/**
 * Geeft waarde van een element uit een array
 * @param array options array met alle parameters
 * @param string parameter naam van op te halen parameter
 * @param mixed defaultvalue optioneel de standaardwaarde (default = reserved keyword in FF)
 */
function param(options, parameter, defaultvalue) {
	var value = defaultvalue;
	if (options && (options.constructor == Object || options.constructor == Array)) {
		Object.keys(options).each(function(key, index) {
			if (key == parameter) {
				value = Object.values(options)[index];
			}
		});
	}
	return value;
}


////////////////////////////////////////////////////////////////
// Loader
//////////////////////////////////////////////////////////////////
//
// Changelog
//
// RvL 20061107: Loader compleet herzien
//                 - Div's gebruikt i.p.v. tables 
//                 - Optie voor progressiebalk
//                 - Fouten opgelost bij het scrollen tijdens het laden

function blurSite(blur,cmt) {
	if (window.top.frames) {
		// als we de loader kunnen starten voor het hele scherm... doen
		try {
			if (window.top.location != window.location && window.top._setLoading) {
				_blurSite(blur,window.top);
				if (window.top.document.body.className=="wizard_fr_base") {
					//
					// Bij een wizard moeten we los het data-venster blurren en de z-index verhogen (ivm insitepopup)
					//
					var data = window.top.document.getElementById("data");
					if (data) {
						data.style.zIndex = blur ? "101" : "99";
					}
					_blurSite(blur,this);
				}
				return;
			}
		} catch (e) {
			//Niks
		}
		if (window.top.frames.length==0) {
			_blurSite(blur,this);
		} else {
			_blurSite(blur,this);
			for (var c=0; c<window.top.frames.length; c++) {
				//
				// RvL 20060328: We kunnen niet altijd bij alle frames
				// wijzigingen doorvoeren (zeker niet als de frame van
				// een andere site is...)
				//
				try {
					_blurSite(blur,window.top.frames[c]);
				} catch (e) { }
			}
		}
	} else {
		_blurSite(blur,this);
	}

}
function _blurSite(blur,frame) {
	window.onscroll = function () { fixLoader(); };
	window.onresize = function () { fixLoader(); };

	try {
		var ref = frame.document.getElementById("loaderBackground");
		if (ref) {
			if (isIE()) {
				ref.style.filter = "alpha(opacity=40)";
			}
			ref.style.display = blur ? "block" : "none";
		}
	} catch (e) { }

	try {
		if (frame.fixLoader) {
			frame.fixLoader();
		}
	} catch(e) {}	
}

/**
 * Geeft loading overlay weer (of verbergt deze)
 * @param state	wel of niet aan het laden
 * @param text sja... de tekst :)
 */
function setLoading(state,text) {
	if (window.top.frames) {
		// als we de loader kunnen starten voor het hele scherm... doen
		try {
			if (window.top.location != window.location && window.top._setLoading) {
				_setLoading(state,window.top,text);
				return;
			}
		} catch (e) {
			//Niks
		}
		if (window.top.frames.length==0) {
			_setLoading(state,this,text);
		} else {
			_setLoading(state,this,text);
			for (var c=0; c<window.top.frames.length; c++) {
				//
				// RvL 20060328: We kunnen niet altijd bij alle frames
				// wijzigingen doorvoeren (zeker niet als de frame van
				// een andere site is...)
				//
				try {
					_setLoading(state,window.top.frames[c],text);
				} catch (e) { }
			}
		}
	} else {
		_setLoading(state,this,text);
	}

	var popups = $$(".inSitePopup");

	popups.each(function(popup) {
		if (state && popup.visible() && popup.getStyle("z-index")>100) {
			popup.setStyle({zIndex: '99'});
		}
		if (!state && popup.visible() && popup.getStyle("z-index")<100) {
			blurSite(true);
			popup.setStyle({zIndex: '200'});
		}
	});
}

function changeLoaderText (text) {
  try {
    var ref = window.top.document.getElementById("loader");
  	if (ref && typeof(text)!="undefined") {
  		ref.getElementsByTagName("strong")[0].innerHTML = "Een moment geduld a.u.b.<br />" + text;
  	}
  	var ref = document.getElementById("loader");
	 if (ref && typeof(text)!="undefined") {
  		ref.getElementsByTagName("strong")[0].innerHTML = "Een moment geduld a.u.b.<br />" + text;
  	}
  } catch(e) { }
}

function changeLoaderGraph(pct, reden) {
	if (pct<0) pct = 0;
	if (pct>100) pct = 100;
	var width = Math.round((150/100) * pct);
	
	var loaderstr = reden+"<br />" + "<span style=\"display: block; height: 15px; overflow: hidden;\"><div style=\"float: left; width: 150px; height: 10px; margin-top: 3px; padding: 0px; border: 1px solid gray; overflow: hidden;\"><div style=\"padding: 0px; margin: 0px; width: "+width+"px; background-color: #AAFFAA; border: 0px; height: 1em;\"></div></div><span style=\"padding-top: 5px; font-size: 8pt;\">&nbsp;"+pct.toFixed(0)+"%</span></span>";
	
	var ref = window.top.document.getElementById("loader");
	if (ref) {
		ref.getElementsByTagName("strong")[0].innerHTML = loaderstr;
	}
	var ref = document.getElementById("loader");
	if (ref) {
		ref.getElementsByTagName("strong")[0].innerHTML = loaderstr;
	}
}

/**
 * Geeft aan of loaderBackground zichtbaar is (in andere woorden: of de pagina aan het laden is)
 *
 * @return true indien loaderBackground zichtbaar
 */  
function isLoading() {
	// Check of een inSitePopup open staat => isLoading dient dan false terug te geven!
	var result = true;
	var popups = $$(".inSitePopup");
	popups.each(function(popup) {if (popup.visible() && popup.getStyle("z-index")>100) {result = false;throw $break;}});
	if (!result) {return false;}

	var ref = document.getElementById("loaderBackground");
	if (ref && ref.style.display != "none") {	// Bufix, isLoading werkt nu ook goed als de buitenste loader actief is en de loader in het frame niet!
		return true;
	}
	var ref = window.top.document.getElementById("loaderBackground");
	if (ref) {
		return ref.style.display != "none";
	}
	return false;
}

/**
 * Retouneert false en voert een cancelBubble en stopPropagation uit.
 */  
function returnFalse(e) {
	if (!e) var e = window.event
	if (e) {
		if (e.cancelBubble) e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
	}
	return false;
}

/**
 * Veranderd de positie van de loader zodat deze na het scrollen weer op de juiste plek staat
 */ 
function fixLoader() {
	try {
		var height = 0;
		var width = 0;
		var top = 0;

		// body is groter dan scherm
		if (document.documentElement && document.documentElement.scrollTop) {
			top = document.documentElement.scrollTop;
			height = document.documentElement.scrollHeight;
			width = document.documentElement.scrollWidth;
		} else if (document.body) {
			top = document.body.scrollTop;
			height = document.body.scrollHeight;
			width = document.body.scrollWidth;
		}
	
		// body is kleiner dan scherm
		if (self.innerWidth) {
			height = Math.max(height,self.innerHeight);
			width = Math.max(width,self.innerWidth);
		} else if (document.documentElement && document.documentElement.clientWidth) {
			height = Math.max(height,document.documentElement.clientHeight);
			width = Math.max(width,document.documentElement.clientWidth);
		} else if (document.body) {
			height = Math.max(height,document.body.clientHeight);
			width = Math.max(width,document.body.clientWidth);
		}
	
		var ref = document.getElementById("loaderBackground");
		if (ref) {
			ref.style.position = "absolute";
			ref.style.left = "0px";
			ref.style.height = height+"px";
			if (isIE()) {
				ref.style.width = width+"px";
			} else {
				ref.style.width = "100%";
			}
		}

		var ref = document.getElementById("loader");
		if (ref) {
			ref.style.top = top+"px";
		}
	} catch (e) {
		// catch voor firebug... loader is niet van belang voor functionaliteit, dus toch doorgaan...
	}
}

/*
	IE heeft andere opacity mode
*/
function isIE() {
	var browser = navigator.appName;
	if (browser == "Microsoft Internet Explorer") {
		return true;
	};
	return false;
}


/**
 * Stelt van een frame de achtergrondkleur en de loader in
 * 
 * @param state wel of niet aan het laden
 * @param frame frame waarop actie uitgevoerd moet worden  
 */ 
function _setLoading(state,frame,text) {
	changeLoaderText(text);

	window.onscroll = function () { fixLoader(); };
	window.onresize = function () { fixLoader(); };

	try {
		var ref = frame.document.getElementById("loaderBackground");
		if (ref) {
			if (isIE()) {
				ref.style.filter = "alpha(opacity=40)";
			}
			ref.style.display = state ? "block" : "none";
		}
	} catch (e) { }

	try {
		var ref = frame.document.getElementById("loader");
		if (ref) {
			ref.style.display = state ? "block" : "none";
		}
	} catch (e) { }

	try {
		if (frame.fixLoader) {
			frame.fixLoader();
		}
	} catch(e) {}
}

//////////////////////////////////////////////////////////////////
// Form helpers
//////////////////////////////////////////////////////////////////
function toggle_legend_details(ref) {
  target = ref.nextSibling;
  display = target.style.display != 'block';
  target.style.display = display ? 'block': 'none';
}

function validateTime(time) {
	if( time == "24:00" ) return "24:00";
	time += ":";
	var tijd1=String(time).split(":")[0];
	var tijd2=String(time).split(":")[1];
	if(tijd1.indexOf('.')>-1 || tijd2.indexOf('.')>-1) { return false}
	if (isNaN(tijd1) || isNaN(tijd2)) {return false}
	if (Number(tijd1)>24 || Number(tijd1)<0) {return false}
	if (Number(tijd2)>59 || Number(tijd2)<0) {return false}
	return Fill(tijd1,2)+":"+Fill(tijd2,2);
}


//////////////////////////////////////////////////////////////////
// Popups
//////////////////////////////////////////////////////////////////
function window_popup(url,name,scrollbar,booReturn) {
	var width = 950;
	var height = 680;
	if(scrollbar == "" || scrollbar == null) scrollbar = false;
	win_defaults = 'status=no,scrollbars='+(scrollbar ? 'yes' : 'no')+',menubar=no,top='+(screen.availHeight-height)/2+',left='+(screen.availWidth-(width))/2+',width='+width+',height='+height+',dependent=yes,resizable=no,modal=yes';
	activepopup=window.open(url,name,win_defaults);
	// activepopup.focus();
	if (booReturn) return activepopup;
}
function message_popup(url,name,width,height,scrollbar) {
	var width = width?width:550;
	var height = height?height:400;
	var scrollbar = scrollbar?scrollbar:"no";
	win_defaults = 'status=no,scrollbars='+scrollbar+',menubar=no,top='+(screen.availHeight-height)/2+',left='+(screen.availWidth-(width))/2+',width='+width+',height='+height+',dependent=yes,resizable=no,modal=yes';
	var activepopup=window.open(url,name,win_defaults);
	activepopup.focus();
}

//////////////////////////////////////////////////////////////////
// Legenda
//////////////////////////////////////////////////////////////////
var DragObj, over, X, Y, legenda_visible = false;
var mvBoundaryLeft, mvBoundaryRight, mvBoundaryTop, mvBoundaryBottom;

function getBoundaries() {
	var scrollTopX = ((window.pageYOffset)?(window.pageYOffset):(document.body.scrollTop)?document.body.scrollTop:document.documentElement.scrollTop);
	var scrollLeftY = ((window.pageXOffset)?(window.pageXOffset):(document.body.scrollLeft)?document.body.scrollLeft:document.documentElement.scrollLeft);

	mvBoundaryLeft=0+scrollLeftY; 
	mvBoundaryRight=(window.innerWidth?window.innerWidth:document.body.clientWidth)+scrollLeftY;
	mvBoundaryTop=0+scrollTopX;
	mvBoundaryBottom=(window.innerHeight?window.innerHeight:document.body.clientHeight)+scrollTopX; 
}

function displayLegenda() {
	var legenda = document.getElementById("legenda");
	getBoundaries();
	if (!legenda_visible) {
		legenda.left = mvBoundaryLeft;
		legenda.top = mvBoundaryTop;
		legenda.style.display= document.all ? "block" : "table";
		legenda_visible = true;
	} else {
		hideLegenda();
	}
}

function hideLegenda()	{
	var legenda = document.getElementById("legenda");
	legenda.style.display="none";
	legenda_visible = false;
}

function legend_MD(e) {
	if (over) {
		var scrollTopX = ((window.pageYOffset)?(window.pageYOffset):(document.body.scrollTop)?document.body.scrollTop:document.documentElement.scrollTop);
		var scrollLeftY = ((window.pageXOffset)?(window.pageXOffset):(document.body.scrollLeft)?document.body.scrollLeft:document.documentElement.scrollLeft);
		if (!e) {
			DragObj = over;
			X=event.x-DragObj.offsetLeft+scrollLeftY;
			Y=event.y-DragObj.offsetTop+scrollTopX;
		} else {
			DragObj = over;
			X=e.layerX+scrollLeftY;
			Y=e.layerY+scrollTopX;
		}
	}
}

function legend_MM(e) {
	if (DragObj) {
		getBoundaries();
		if (!e) {
			// Microsoft Internet Explorer
			DragObj.style.pixelLeft = Math.max(Math.min(event.clientX-X + document.body.scrollLeft,mvBoundaryRight-DragObj.offsetWidth-16),mvBoundaryLeft);
			DragObj.style.pixelTop = Math.max(Math.min(event.clientY-Y + document.body.scrollTop,mvBoundaryBottom-DragObj.offsetHeight),mvBoundaryTop);
		} else {
			// W3C
			DragObj.style.left = Math.max(Math.min(e.pageX-X + window.pageXOffset,mvBoundaryRight-DragObj.offsetWidth-20),mvBoundaryLeft) + "px";
			DragObj.style.top = Math.max(Math.min(e.pageY-Y + window.pageYOffset,mvBoundaryBottom-DragObj.offsetHeight),mvBoundaryTop) + "px";
		}
	}
}

function legend_MU() {
	DragObj = null;
}


//////////////////////////////////////////////////////////////////
// Maandselectie
//////////////////////////////////////////////////////////////////

var allow_date_in_future_selection = false;
function init_date_selection(prefix) {
	if (!prefix) prefix = "";
	
	var container = $(prefix+"top_right_buttons");
	// Voor insitepopups...
	allow_year_selection = (typeof(allow_year_selection) != "undefined" && allow_year_selection) || container.readAttribute("allow_year_selection");
	allow_month_selection = (typeof(allow_month_selection) != "undefined" && allow_month_selection) || container.readAttribute("allow_month_selection");
	allow_date_in_future_selection = (typeof(allow_date_in_future_selection) != "undefined" && allow_date_in_future_selection) || container.readAttribute("allow_month_selection");

	if (allow_year_selection || allow_month_selection || allow_date_in_future_selection) {
		draw_date_selection(prefix);
	}
}

function draw_date_selection (prefix) {
	if (!prefix) prefix = "";
	var year_ref = $(prefix+"top_right_buttons").select("#date_select_year")[0];
	var month_ref = $(prefix+"date_select_month");
	var current = $(prefix+"date_select_current");

	//
	// Jaarselectie
	//
	var Today=new Date(); 
	var ThisYear=Today.getFullYear();

	if (allow_year_selection) {
		if (!year_ref) return;

		year_ref.innerHTML = "";
		var table = document.createElement("table");
		table.id = 'date_select_year_table';
		table.className = 'btnTable';
		table.style.fontSize="10pt";
		var tr = table.insertRow(-1);
		var td = tr.insertCell(-1);
		td.style.textAlign="center";
		td.style.fontWeight="bold";
		td.colSpan="3";
		td.innerHTML = "Selecteer jaar:";
		var tr = table.insertRow(-1);
		for (var c=-1; c<=1; c++) {
			var td = tr.insertCell(-1);
			var year = current_year + c;
			switch (c) {
				case -1: 	td.innerHTML = button("Back",String(year),"",true,"switch_year(-1,'"+prefix+"');"); break;
				case 0:  	td.innerHTML = button("",String(year),"",true,"");
				if (current) {
					current.innerHTML = String(year);
				}
				break;
				case 1:  
				if (!allow_date_in_future_selection) {
					if (year>ThisYear) {
						td.innerHTML = button("",String(year),"Forw",false,""); break;
					} else {
						td.innerHTML = button("",String(year),"Forw",true,"switch_year(+1,'"+prefix+"');"); break;
					}
				} else {
					td.innerHTML = button("",String(year),"Forw",true,"switch_year(+1,'"+prefix+"');"); break;
				}
			}
		}
		year_ref.appendChild(table);
	}

	//
	// Maandselectie
	//
	var Today=new Date(); 
	var ThisMonth=Today.getMonth()+1; 

	if (allow_month_selection) {
		if (!month_ref) return;

		month_ref.innerHTML = "";
		month_ref.align="center";
		var table = document.createElement("table");
		table.className="simple_table";
		table.style.fontSize="10pt";
		var tr = table.insertRow(-1);
		for (var month=1; month<=12; month++) {
			var td = tr.insertCell(-1);
			var month_str = new Array("jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec")[month-1];
			var month_full_str = new Array("januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december")[month-1];	
			if (month<current_month) {
				td.innerHTML = button("groenebol",month_str,"",true,"switch_month("+month+",'"+prefix+"');");
			} else if (month==current_month) {		
				td.innerHTML = button("Ok",month_str,"",true,"");
				if (current) {
					current.innerHTML = month_full_str+" "+current_year;
				}
			} else if (month>current_month) {
				td.innerHTML = button("groenebol",month_str,"",true,"switch_month("+month+",'"+prefix+"');");
			}			
		}
		month_ref.appendChild(table);
		month_ref.appendChild(document.createElement("br"));
	}
}

function switch_month (target, prefix) {
	if (!before_switch_month(prefix)) { return; }
	
	// eventueel inputs de-selecteren
	var inputs = document.getElementsByTagName("input");
	for (var c=0; c<inputs.length; c++) {
		var input = inputs[c];
		if (/_all$/.test(input.id)) {
			input.checked=false;
		}
	}

	current_month = target;

	$((prefix?prefix:"")+"date_select_month").fire("lijst:change");

	datetime_changed(prefix);
	after_switch_month(prefix);
	draw_date_selection(prefix);
}


function switch_year (offset, prefix) {
	if (!before_switch_year(prefix,offset)) { return false; }

	// eventueel inputs de-selecteren
	var inputs = document.getElementsByTagName("input");
	for (var c=0; c<inputs.length; c++) {
		var input = inputs[c];
		if (/_all$/.test(input.id)) {
			input.checked=false;
		}
	}

	current_year += offset;

	$((prefix?prefix:"")+"date_select_year").fire("lijst:change");

	datetime_changed(prefix,offset);
	after_switch_year(prefix,offset);
	draw_date_selection(prefix,offset);
	return true;
} 

function before_switch_year (prefix) {		 
    return true;		 
}		 
function before_switch_month (prefix) {		 
    return true;		 
}		 
function after_switch_year (prefix) {		 
 		 
}		 
function after_switch_month (prefix) {		 
 		 
}		 
function datetime_changed (prefix) {		 
 		 
}		 

function request_begindatum () {
	if (allow_year_selection) {
		if (allow_month_selection) {
			return current_year+(current_month<10?"0":"")+current_month+"01";
		} else {
			return current_year+"0101";
		}
	}
	return "00000000"
}

function request_einddatum () {
	if (allow_year_selection) {
		if (allow_month_selection) {
			return current_year+(current_month<10?"0":"")+current_month+daysInMonth((current_month-1),current_year);
		} else {
			return current_year+"1231";
		}
	}
	return "99999999"
}
/**
 * Geeft het aantal dagen in de maand terug.
 * @param: integer month nummer van de maand (januari = 0)
 * @param: integer year het jaartal
 * @return: integer aantal dagen in de maand
 */
function daysInMonth(month, year) {
	return 32 - new Date(year, month, 32).getDate();
}


///////////////////////////////////////////////////////////////////
// Input-validatie
//////////////////////////////////////////////////////////////////
//
// Roep voor werkende validatie init_input_validation() aan
//
// Voorbeeld: <input type="text" validation="number" options="negative,max=25,min=-100" />
//
//   +---------------+-----------------+-----------------------------------------------+
//   | Validatie     | Opties          | Validatie                                     |
//   +---------------+-----------------+-----------------------------------------------+
//   | number        |                 | Natuurlijke getallen                          |
//   |               | float           | getallen (met een ',')                        |
//   |               | separator=<.>   |          (met een opgegeven scheidingsteken)  |
//   |               | negative        | Negatieve getallen                            |
//   |               | max=<x>         | Maximum waarde van 'x'                        |
//   |               | min=<x>         | Minimale waarde van 'x'                       |
//   +---------------+-----------------+-----------------------------------------------+
//   | email         |                 | Geldig e-mailadres                            |
//   +---------------+-----------------+-----------------------------------------------+
//
// Formulier validatie
//
//   Gebruik een <form onsubmit='return validate_form(this)'> om alle elementen in het
//   formulier te valideren
//
//   +---------------+-----------------+-------------------------------------------------+
//   | Attribuut     | Opties          | Gevolg                                          |
//   +---------------+-----------------+-------------------------------------------------+
//   | required      |                 | Verplicht veld                                  |
//   | errormessage  |                 | Eventuele melding als het veld fout is ingevuld |
//   +---------------+-----------------+-------------------------------------------------+
//
function input_error (input, condition) {
	if (input.tagName=='SELECT') {
		if ($('pulldown_value_'+input.id)) {
			$('pulldown_value_'+input.id).style.backgroundColor = condition ? "#FFF0F0" : "";
		}
		if ($('pulldown_'+input.id)) {
			$('pulldown_'+input.id).style.backgroundColor = condition ? "#FFF0F0" : "";
			$('pulldown_'+input.id).style.borderColor = condition ? "red" : "";
		}
	} else if (input.tagName=='SPAN') {
		input.style.borderWidth = condition ? "1px" : "";
		input.style.borderStyle = condition ? "solid" : "";
		input.style.borderColor = condition ? "red" : "";
		input.style.backgroundColor = condition ? "#FFF0F0" : "";
	} else {
		input.style.borderColor = condition ? "red" : "";
		input.style.backgroundColor = condition ? "#FFF0F0" : "";
	}
}

var BGCOLOR_ERROR = "rgb(255, 128, 128)";

//
// Alle elementen in formulier controleren op valid=false
//
function validate_form(form) {
	var errStr = "";
	
	var inputs = form.getElementsByTagName("input");
	for (var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if (input.type=="text") {
		 	if (input.getAttribute("valid")=="false" || (input.getAttribute("required")=="required" && input.value=="")) {
				input.style.backgroundColor = BGCOLOR_ERROR;
				if (errStr == "") { input.focus(); }
				if (input.getAttribute("errormessage")) {
					errStr += "- " + input.getAttribute("errormessage")+"\n";
				} else {
					errStr += "- Het veld " + input.name +" is niet ingevuld of is ongeldig\n";
				}
			} else if (input.style.backgroundColor==BGCOLOR_ERROR) {
				input.style.backgroundColor = "";
			}
		}
	}
	if (errStr != "") {
		alert("Kan de gegevens niet verwerken, want:\n\n"+errStr+"\nVerbeter de fouten en probeer opnieuw");
		return false;
	}
	return true;
}

//
// Inialiseren van validaties:
//
//    - alle inputs met attribuut validation
//      voorzien van onchange en onkeyup
//
function init_input_validation() {
	var inputs = document.getElementsByTagName("input");
	for (var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if (input.type=="text" && input.getAttribute("validation")!="" && input.getAttribute("validation_events_set")!="true") {
			if (Event && Event.observe) {
				// prototype versie
				Event.observe(input, "change", validate_input);
				Event.observe(input, "keyup", validate_input);
			} else {
				input.onchange = validate_input;
				input.keyup = validate_input;
			}
			input.setAttribute("validation_events_set","true");
		}
		
		if (input.getAttribute("required")=="required" && input.getAttribute("star_added")!="true") {
			input.setAttribute("star_added","true");
			var star = input.parentNode.insertBefore(document.createElement("span"),input);
			input.parentNode.insertBefore(input,star);
			star.innerHTML = "&nbsp;<sup>*</sup>";
		}
	}
}

//
// De verschillende validaties uitvoeren
//
function validate_input (e) {
	if (!e) e = window.event;

	var src = e.target ? e .target : e.srcElement;
	if (!src) return true;
	
	switch (src.getAttribute("validation")) {
		case "number": validate_number(src); break;
		case "email": validate_email(src); break;
	}
}

function validate_number(src) {
	//
	// ook kommagetallen of 
	// negatieve getallen toestaan
	//
	if (has_option(src,"float") && has_option(src,"negative")) {
		var separator = ",";
		if (has_option(src,"separator")) {
			separator = option_value(src,"separator");
		}

		// . en , altijd vervangen door separator
		var newvalue = src.value.replace(/[\.\,]/g,separator);
		if (newvalue != src.value) src.value = newvalue;
		
		// bij foutieve string alles fixen
		// met een \d bleek niet helemaal goed te gaan? (dus [0-9] gebruikt...)
		var regexp = new RegExp("^[-0-9][0-9]*["+regescape(separator)+"]?[0-9]*$");
		if (!regexp.test(src.value)) {
			// verkeerde formaat
			var newvalue = src.value;
			
			// eerste karakter
			newvalue = newvalue.replace(/^[^-\d]/,"");
			
			// alles behalpe separator of getal
			var regexp = new RegExp("[^0-9"+regescape(separator)+"]","g");
			newvalue = newvalue.substr(0,1) + newvalue.substr(1).replace(regexp,"");
			
			// meerdere separators
			var regexp = new RegExp(regescape(separator));
			var arr = newvalue.split(separator);
			while (arr.length>2) {
				newvalue = newvalue.replace(regexp,"");
				arr = newvalue.split(separator);
			}
			
			if (newvalue != src.value) src.value = newvalue;
		}
	} else if (has_option(src,"float")) {
		var separator = ",";
		if (has_option(src,"separator")) {
			separator = option_value(src,"separator");
		}

		// . en , altijd vervangen door separator
		var newvalue = src.value.replace(/[\.\,]/g,separator);
		if (newvalue != src.value) src.value = newvalue;
		
		// bij foutieve string alles fixen
		// met een \d bleek niet helemaal goed te gaan? (dus [0-9] gebruikt...)
		var regexp = new RegExp("^[0-9]*["+regescape(separator)+"]?[0-9]*$");
		if (!regexp.test(src.value)) {
			// verkeerde formaat
			var newvalue = src.value;
			
			// alles behalpe separator of getal
			var regexp = new RegExp("[^0-9"+regescape(separator)+"]","g");
			newvalue = newvalue.replace(regexp,"");
			
			// meerdere separators
			var regexp = new RegExp(regescape(separator));
			var arr = newvalue.split(separator);
			while (arr.length>2) {
				newvalue = newvalue.replace(regexp,"");
				arr = newvalue.split(separator);
			}
			
			if (newvalue != src.value) src.value = newvalue;
		}
	} else if (has_option(src,"negative")) {
		// bij foutieve string alles fixen
		// met een \d bleek niet helemaal goed te gaan? (dus [0-9] gebruikt...)
		var regexp = new RegExp("^[-0-9][0-9]*$");
		if (!regexp.test(src.value)) {
			// verkeerde formaat
			var newvalue = src.value;
			
			// eerste karakter
			newvalue = newvalue.replace(/^[^-\d]/,"");
			
			// alles behalpe separator of getal
			newvalue = newvalue.substr(0,1) + newvalue.substr(1).replace(/[^0-9]/g,"");
			
			if (newvalue != src.value) src.value = newvalue;
		}

	} else {
		//
		// Alleen getallen
		//
		if (/\D/.test(src.value)) {
			src.value = src.value.replace(/\D/g,"");
		}
	}
	
	//
	// Min en max toepassen
	//
	if (has_option(src,"min")) {
		var min = option_value(src,"min");
		var value = parseFloat(src.value.replace(/,/,"."));
		if (value < min) {
			src.value = min;
		}
	}
	if (has_option(src,"max")) {
		var max = option_value(src,"max");
		var value = parseFloat(src.value.replace(/,/,"."));
		if (value > max) {
			src.value = max;
		}
	}
}

function validate_email(src) {
	if (src.value=="") {
		src.setAttribute("valid","true");
	} else {
		if (/^[a-z0-9][^\(\)\M\<\@\,\;\:\\\"\[\]]*\@[a-z0-9\-\.]*\.[a-z]{2,6}$/i.test(src.value)) {
			src.setAttribute("valid","true");
		} else {
			src.setAttribute("valid","false");
		}
	}
}

//
// Kijkt of input bepaalde optie heeft
//
function has_option (input,option) {
	var options = input.getAttribute("options");
	// options bestaat alleen uit, begint met
	// of eindigt met deze option
	var regexp1 = new RegExp("^"+option+"(\=.*?)?$");
	var regexp2 = new RegExp("^"+option+"(\=.*?)?,");
	var regexp3 = new RegExp(","+option+"(\=.*?)?$");
	if (regexp1.test(options) || regexp2.test(options) || regexp3.test(options)) {
		return true;
	}
	// option komt een keer voor in
	var regexp4 = new RegExp(","+option+"(\=.*?)?,");
	if (regexp4.test(options)) {
		return true;
	}
	return false;
}

//
// Geeft de waarde van een optie (achter de =) terug
//
function option_value (input,option) {
	var option_value = ""
	var options = input.getAttribute("options");

	// alleen deze optie komt voor
	var regexp = new RegExp("^"+option+"=([^,]*?)?$","g");
	if (regexp.test(options)) { return options.replace(regexp,"$1"); }
	
	// deze optie komt aan het begin van de opties voor
	var regexp = new RegExp("^"+option+"=([^,]*?)?,.*","g");
	if (regexp.test(options)) { return options.replace(regexp,"$1"); }
	
	// deze opties komt aan het eind van de opties voor
	var regexp = new RegExp(".*?,"+option+"=([^,]*?)?$","g");
	if (regexp.test(options)) { return options.replace(regexp,"$1"); }

	// deze optie komt ergens voor
	var regexp = new RegExp("^.*?,"+option+"=(.*?),.*$","g");
	if (regexp.test(options)) { return options.replace(regexp,"$1"); }
	
	// deze optie komt niet voor
	return "";
}

function regescape (str) {
	return str.replace(/([\.\,\(\)])/g,"\\$1")
}


//////////////////////////////////////////////////////////////////
// XML Functies
//////////////////////////////////////////////////////////////////


function XML2VolledigeKindNamen(Node, reversed) {
	var str = "";
	var KindNodes = selectNodes("./Kinderen/Kind",Node);
	var type = GetNodeValue(Node, "Type", "");

	for(var pos = 0;pos<KindNodes.length;pos++) {
		if(type != "Open") {
			str += "<div>"+XML2VolledigeKindNaam(KindNodes[pos])+"</div>";
		} else {
			str += "<div>Kind "+(pos+1)+"</div>";
		}
	}
	return str;
}


function XML2date(XML) {
	if (XML=='' || !XML) return "";
	if (String(XML).length>=8) {
		XMLdate = String(XML).substring(6,8) + '-' +
							String(XML).substring(4,6) + '-' +
							String(XML).substring(0,4);
		return XMLdate;
	} else if (String(XML).length==4) {
		XMLdate = String(XML).substring(2,4) + '-' +
							String(XML).substring(0,2);
		return XMLdate;
	}
}

// Maakt een xmlstr, xmlstr is optioneel
function get_xmldoc( xmlstr ) {
	var xmldoc = false;
	if (document.implementation && document.implementation.createDocument) {
		xmldoc = document.implementation.createDocument("", "", null);
	} else if (window.ActiveXObject) {
		xmldoc = new ActiveXObject("Microsoft.XMLDOM");
	}
	
	if( xmlstr ) {
		if(window.ActiveXObject) {
			xmldoc.loadXML( xmlstr );
		} else {
			xmldoc = (new DOMParser()).parseFromString(xmlstr, "text/xml");
		}

	}
	return xmldoc;
}


/** 
 * BUGFIX: toFixed rond anders af in IE dan in Firefox/Safari etc.
 *  - IE lijkt het goed te doen maar volgens de ECMA scripts doen de andere browsers het goed:
 *
 * Browsergedrag:
 *  - IE:  Number( 7.475 ).toFixed( 2 ) => 7.48
 *  - FF+andere:  Number( 7.475 ).toFixed( 2 ) => 7.47
 * 
 * Gedrag IE heeft de voorkeur, aangezien dit is wat je verwacht bij afronding!
 * @created RB @ 2008-09-19
 */
Number.prototype.originalToFixed = Number.prototype.toFixed
Number.prototype.toFixed = function( decimals ) {
	var factor = Math.pow( 10, decimals );
	var value  = this.valueOf() * factor;
	value = Math.round( value );
	return Number( value  / factor ).originalToFixed( decimals );
};



// Create the xml getter for Mozilla
if (window.DOMParser &&
	window.XMLSerializer &&
	window.Node && Node.prototype && Node.prototype.__defineGetter__) {
	Document.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
	Element.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
}

function getParseError(xmldoc) {
	var strErrMsg = "";
	// IE heeft het gemakkelijk; dat heeft een parseError object
	if(window.ActiveXObject) {
		return "Fout in regel "+xmldoc.parseError.line+":\n"+xmldoc.parseError.reason;
	} else {
		// Mozilla is uitgebreider, maar moeilijker. Het heeft wel een mooie reguliere expressie!
		var strErr = (new XMLSerializer()).serializeToString((new DOMParser()).parseFromString(xmldoc, "text/xml"));
//		var strErr = (new XMLSerializer()).serializeToString(xmldoc);
		var  A_nice_RegExp = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
		var reError = A_nice_RegExp.test(strErr);
		return "FOUT BIJ LADEN XML:\n"+
			"Omschrijving: "+RegExp.$1+" \n"+
			"Bestand: "+RegExp.$2+" \n" +
			"Regel: "+RegExp.$3+"\n" +
			"Positie: "+RegExp.$4+"\n"+
			"Broncode: "+RegExp.$5;
	}
}

function selectNodes(aExpr, aNode) {
	if (window.ActiveXObject || typeof(aNode.selectNodes) == "function") {
		return aNode.selectNodes( aExpr );
	} else if (window.XPathEvaluator) {
		var xpe = new XPathEvaluator();
		var nsResolver = xpe.createNSResolver(  aNode.ownerDocument ? aNode.ownerDocument.documentElement : aNode.documentElement );
		var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
		var found = [];
		while (res = result.iterateNext()) { found.push(res); }
		return found;
	} else {
		alert("Functie selectNodes wordt niet door uw browser ondersteund.");
		return false;
	}

}

function selectSingleNode(aExpr, aNode) {
	if (window.ActiveXObject ||  typeof(aNode.selectSingleNode) == "function")  {
		return aNode.selectSingleNode(aExpr);
	} else if(window.XPathEvaluator){
		var xpe = new XPathEvaluator();
		var nsResolver = xpe.createNSResolver(  aNode.ownerDocument ? aNode.ownerDocument.documentElement : aNode.documentElement );
		var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
		return result.iterateNext();
	} else {
		alert("Functie selectSingleNode wordt niet door uw browser ondersteund.");
	}
}

// function..: Retreive an Attribute Nodevalue
// Input.....: ElementNode, strAttributeName
// Output....: String / "" if node = null;
// Created by: Michiel In 't Velt
function GetNodeValue(ElementNode, strAttributeName, strValueIfEmpty) {
    if (ElementNode!=null) {
        return selectSingleNode("@"+strAttributeName,ElementNode)!=null?selectSingleNode("@"+strAttributeName,ElementNode).nodeValue:(strValueIfEmpty==null?"":strValueIfEmpty);
	} else {
        return (strValueIfEmpty==null?"":strValueIfEmpty);
	}
}

// function..: Retreive the text of a Node
// Input.....: ElementNode
// Output....: String / "" if node = null;
// Created by: Michiel In 't Velt
// 2 september 2005
function GetNodeText(ElementNode, strValueIfEmpty) {
    if (ElementNode!=null) return ElementNode.text;	else return (strValueIfEmpty==null?"":strValueIfEmpty);
}

// function..: Set an Attribute NodeValue for a node
// Input.....: ElementNode=node to use, strAttributeName = name of the attribute
//				strValue=value to set
// Output....: True if successful : otherwise the false
// Created by: Michiel In 't Velt
function SetNodeValue(ElementNode, strAttributeName, strValue) {
	if (ElementNode == null || strValue == null)
		return false;
	else {
		var tmpNewAttr = selectSingleNode("@"+strAttributeName,ElementNode);
		if (!tmpNewAttr) {
			ElementNode.attributes.setNamedItem(ElementNode.ownerDocument.createAttribute(strAttributeName));
			tmpNewAttr = selectSingleNode("@"+strAttributeName,ElementNode);
		}
		tmpNewAttr.nodeValue=strValue;
		return true;
	}
}

function getXMLHttpRequest() {
	var req = false;
    // branch for native XMLHttpRequest object
	if(window.XMLHttpRequest) {
		try {
			req = new XMLHttpRequest();
            if (req.overrideMimeType) {
                    req.overrideMimeType('text/xml');
            }
        } catch(e) {
			req = false;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
		try {
        	req = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) {
        	try {
          		req = new ActiveXObject("Microsoft.XMLHTTP");
        	} catch(e) {
          		req = false;
        	}
		}
    }
	if( req ) { IExhr_register( req ); }
    return req;
}

function SendXMLRequest(strURL, strRequest, XMLdoc) {
	if (strRequest) {
		try {
			var XMLRequest = get_xmldoc();
			XMLRequest.loadXML(strRequest);
		} catch(e) {
			var XMLRequest = (new DOMParser()).parseFromString(strRequest, "text/xml");
		}
	} else if (XMLdoc) {
		var XMLRequest = XMLdoc;
	} else {
		var XMLRequest = null;
	}
	
	var xmlhttp = new getXMLHttpRequest();

	if (XMLRequest) {
		xmlhttp.open("POST", strURL, false);
		xmlhttp.send(XMLRequest);
	} else {
		xmlhttp.open("GET", strURL, false);
		xmlhttp.send("");
	}
	
	if (!xmlhttp.responseXML) {
		return (new DOMParser()).parseFromString(xmlhttp.responseText, "text/xml");
	} else  {
		return xmlhttp.responseXML;
	}

}

/**
 * Deze functie voert een HTTP post actie uit m.b.v. een XML HTTP Request
 * SYNCHROON
 * TEST-functie!
 * Rick: bugfix: 2006-05-29: Nu gaat deze functie ook correct om met verschillende encodings!
 * NB! Alle synchrone XHR's zijn in staat om Firefox te bevriezen! 
 */
function SendHttpRequestPostSync( url, postdata, expectedRootNode, displayTextInDebugDivId ) {
	if (!expectedRootNode) {expectedRootNode='root'}

	var req = new getXMLHttpRequest();
	// Open an HTTP POST connection to the shopping cart servlet.
	req.open("POST", url, false);
	// Specify that the body of the request contains form data
	req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
	req.setRequestHeader("Charset", "UTF-8");

	// Send form encoded data stating that I want to add the
	// specified item to the cart.
	req.send( postdata );
	if( displayTextInDebugDivId ) {
		document.getElementById( displayTextInDebugDivId ).innerHTML = "textnode";
		document.getElementById( displayTextInDebugDivId ).firstChild.nodeValue = req.responseText;
	}

	IExhr_unregister( req );	// synchroon, dus mag hier worden verwijderd

	// http errrs status start at 400
	if (req.status >= 400) {
		if( !displayTextInDebugDivId ) {
			var w = window.open('','_blank');
			w.document.write(req.responseText );
			w.focus();
		}
		
		return false;
	} else {
		try {
			var outDoc = get_xmldoc();
			if (!req.responseXML) {
				outDoc.loadXML(req.responseText);
			} else {
				outDoc = req.responseXML;
			}
		} catch(e) {
			var outDoc = (new DOMParser()).parseFromString(req.responseText, "text/xml");
		}

		if( outDoc== null || (selectSingleNode("/"+expectedRootNode,outDoc) == null ) ) {
			// PAS OP: Een moeilijk te traceren fout die dit kan veroorzaken is de aanwezigheid van lege regels BUITEN de XML-tags! [RvG20060707]
			alert( "Ongeldige XML:" + req.responseText );
			if( !displayTextInDebugDivId ) {
				var w = window.open('','_blank');
				w.document.write(req.responseText );
				w.focus();
				return null;	// PARSE ERROR in Gecko based browser
			}
			return false;
		}
		return outDoc;
	}
}

/**
 * Dit object voert een HTTP post actie uit m.b.v. een asynchrone XMLHttpRequest
 * LET OP: Gebruik dit object als je geen Prototype library kun gebruiken. De prototype 
 * library heeft de voorkeur. Maar kan niet altijd zomaar wordne geinclude! 
 *
 * Wordt 
 *
 * Voorbeeld:
 * <pre>  
 * 	function callBack() {
 *   	if( xhr.isReady() ) {
 *			var xmldoc = xhr.getResponseXML();
 *   		var tekst = xhr.getResponseText();
 *  	}
 * 	}
 * 
 * var xhr = SendAjaxRequest( 'xhr.php', 'id=12&cmd=del', callback );
 * xhr.send(); 
 * 
 * </pre> 
 */
function SendAjaxRequest( url, postdata, callback ) { 
	this.onReadyStateChangeHandler = function() {
		// unregister jezelf
		if(this.isReady()) { IExhr_unregister( this.req ); }
		// voer de callback uit!
		this.callback();
	}

	this.req = getXMLHttpRequest();
	this.postdata = postdata;
	this.req.onreadystatechange = this.onReadyStateChangeHandler.bind( this );
	this.callback = callback;

	this.isReady = function() {
		return this.req.readyState == 4;
   	}
   	
   	this.getResponseXML = function() { 
   		return this.req.responseXML;
   	}
   	
   	this.getResponseText = function() {
   		return this.req.responseText;
   	}
   	
   	this.abort = function() { 
   		return this.req.abort();
   	}

	this.send = function() {
		// Open an HTTP POST connection 
		// Third parameter specifies request is asynchronous.
		this.req.open("POST", url, true);
		// Specify that the body of the request contains form data
		this.req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
		this.req.setRequestHeader("Charset", "UTF-8");
		this.req.send( this.postdata );		
	}
}

//
// functie om relatief pad van huidig document op te vragen
//
function base_path(page) {
	var current_base_path = null;
	var elements = document.getElementsByTagName('script');
	for (var i=0; i<elements.length; i++) {
		if (elements[i].src && (elements[i].src.indexOf(page) != -1)) {
			var src = elements[i].src;

			current_base_path = src.substring(0, src.lastIndexOf('/'));
			break;
		}
	}
	return current_base_path;
}

//function: XMLsafe
//Input:	code, string om om te zetten naar XML veilige string
//Output:	string die veilig in XML te gebruiken is.
//Last modified by Marcel Verbruggen 25-06-2004
//Functie returned nu een lege string als er een niet bestaand argument wordt meegegeven i.p.v.
//de string 'undefined'
function XMLsafe(code) {
	if(typeof(code) == 'undefined') {
		return '';
	}
    code = String(code).replace(/&/g,'&amp;');
    code = String(code).replace(/</g,'&lt;');
    code = String(code).replace(/>/g,'&gt;');
    code = String(code).replace(/"/g,'&#34;');
    code = String(code).replace(/'/g,'&#39;');
    return code;
}

//function: XMLsafe
//Input: string die veilig in XML te gebruiken is.	
//Output: code, string om om te zetten naar XML veilige string
//Last modified by Nicole Bekkers 20070911, 6 years after
//Functie returned nu een lege string als er een niet bestaand argument wordt meegegeven i.p.v.
//de string 'undefined'
function XMLunsafe(code) {
	if(typeof(code) == 'undefined') {
		return '';
	}
	code = String(code).replace(/&amp;/g, '&');
	code = String(code).replace(/&lt;/g, '<');
	code = String(code).replace(/&gt;/g, '>');
	code = String(code).replace(/&#34;/g, '"');
	code = String(code).replace(/&#39;/g, '\'');
    return code;
}

function xmlPrint( node, ip, level ) {
	var result = '';
	// alleen toevoegen als het een element is
	if( !node ) {return "&lt;&lt;null&gt;&gt;";}
	if( typeof( node ) == 'string' ) {
		node = get_xmldoc( node );		
	}
	if( node.documentElement ) {node = node.documentElement;}
	if( node.nodeType != 1 /*ELEMENT*/ ) {return XMLsafe( node.nodeValue );}	

	if( ip && ip.documentElement ) {ip = ip.documentElement;}

	// schrijf opening tag
	result += "<span style='"+((node == ip )?"background-color: #ffd; color: #000; border: 1px solid red;'":"")+"'>";
	result += "&lt;<b>"+node.nodeName+"</b>";
	if( node.attributes ) {
		for( var a=0; a < node.attributes.length; a++ ) {
			result += " "+node.attributes[a].nodeName+"="+ "'<i>"+XMLsafe(node.attributes[a].nodeValue)+"</i>'";
		}
	}

	if( node.childNodes.length == 0  ) { result += "/"; }
	result += "&gt;\r\n";
	result += "</span><br />";

	// schrijf kindjes
	if( node.childNodes.length > 0 ) {
		result += "<div style='border-left: 1px dotted #777; margin-left:10px; padding-left: 10px;'>";
		for( var i=0; i < node.childNodes.length; i++ ) {
			result += xmlPrint( node.childNodes[i], ip, level+1 );
		}
		result += "</div>";
		// schrijf end tag
		result += "&lt;/<b>"+node.nodeName+"</b>&gt;<br />\r\n";
	}
	// close pre at level 0
	return result;
}

////////////////////////////////////////////////////////////////////////////////
// Date object uitbreiding, a la Ruby on Rails
////////////////////////////////////////////////////////////////////////////////

/*
  Uitbreidingen op het javascript Date object. Dankzij deze uitbreidingen kan het
 Date object overweg met ANSI datum en tijden. (Kreet voor deze tijden bij KISS is XMLDates )
 Formaat hiervan is een integer in de vorm: YYYYMMDD (Y=year, M=month, d=day_of_month)
 Tijden worden in het formaat HHIISS opgeslagen. (H=hour, I=minute, S=second)
 Tevens komt in sommige gevallen het volledige gecombineerde formaat voor: YYYYMMDDHHIISS
 
 Algemene werkwijze: 
   
   var d = new Date(); 
   alert( d.xmldate() )
 
 of
 
   var d = Date.create( 20070326 );
   alert( d.to_s() );
   
 Ook zijn de prototypes van String en Number uitgebreid. 
   
    20050101.to_date().to_s() => 01-01-2005
	
    "01-02-2006".to_date().xmldate() => 20050101

 Historie:
 =========
 08-08-2007, Rick Blommers - Eerste versie.

 TODO:
 ====
  - Integreren functies om Datums / Tijden te kunnen zetten mbv string. Bijvoorbeeld  "12-01-2001"


*/

// RANTEN:
// Te mooi om waar te zijn: (Brakke IE ondersteund deze ECMA spec niet)
// Date.prototype.xmldate getter function() { return this.getFullYear() * 10000 + (this.getMonth()+1) * 100 + this.getDate() } ;
// (ouder gecko manier:) Date.prototype.__defineGetter__( "xmldate", function() { return this.getFullYear() * 10000 + (this.getMonth()+1) * 100 + this.getDate() } );

/** 
 * Haalt de huidige xmldatum op
 * @return de datum in het formaat YYYYMMDD
 */
Date.prototype.get_xmldate = function() { return this.getFullYear() * 10000 + (this.getMonth()+1) * 100 + this.getDate() } ;

/** 
 * Instellen huidige datum mbv een xmldatum
 * @param date een integer in de vorm YYYYMMDD
 */
Date.prototype.set_xmldate = function( date ) { 
	var year = Math.floor( date / 10000 )
	var month = Math.max( Math.floor( date / 100 ) % 100 - 1, 0 );
	var day = date % 100;
	this.setFullYear( year, month, day );
	this.setHours(0,0,0,0);  // alles op 0 zetten!
	return this;	// maakt het makkelijker om (new Date()).set_xmldate(...) ) aan te roepen
}


/** 
 * Een korte vorm om de datum te kunnen zetten of uitlezen
 * @param date optioneel. Formaat: YYYYMMDD Als deze wordt opgegeven dan wordt de datum aangepast
 * @return de huidige datum in de vorm:  YYYYMMDD
 */
Date.prototype.xmldate = function( date ) {
	if( !date ) return this.get_xmldate()
	return this.set_xmldate( date ).get_xmldate();
}

/** 
 * Maak een nieuwe datum aan, mbv een xml date
 * @param date een datum in het formaat YYYYMMDD
 */
Date.create = function( date ) {
	//if( d instanceof Date ) return new Date( d );
	var d = new Date();
	d.set_xmldate( date );
	return d;
}

/** 
 * De date FORMATS array wordt gebruikt om het Date object naar een string te vertalen. 
 */
Date.FORMATS = { 'default': function(date) { 
		var y = date.getFullYear(); var m = date.getMonth()+1; var d = date.getDate();
		m = ( m < 10 ? '0' + m : m ); d = ( d < 10 ? '0' + d : d );
		return d+"-"+m+"-"+y;
	}, 
	'time': function(date) {
		var hour = date.getHours(); var min = date.getMinutes(); 
		hour = ( hour < 10 ? '0' + hour : hour ); min = ( min < 10 ? '0' + min : min );
		return hour + ":" + min;
	}, 
	'date_time': function(date) { 
		var y = date.getFullYear(); var m = date.getMonth()+1; var d = date.getDate();
		var hour = date.getHours(); var min = date.getMinutes(); 
		m = ( m < 10 ? '0' + m : m ); d = ( d < 10 ? '0' + d : d );
		hour = ( hour < 10 ? '0' + hour : hour ); min = ( min < 10 ? '0' + min : min );
		return d+"-"+m+"-"+y + " " + hour + ":" + min;
	}
}

/** 
 * Vertaald de gegeven datum naar eens string.
 * @param format (optioneel) het weergave formaat dat moet worden gebruikt. Indien weggelaten dan wordt 'default' gebruikt
 */
Date.prototype.to_s = function( format ) { 
	if( !format ) format = 'default'
	if( !Date.FORMATS[ format ] ) throw "Date format niet gevonden!";
	return Date.FORMATS[ format ]( this );
}	


/**
 * Berekent een nieuwe datum, zonder de huidige datum aan te passen
 * 
 * @param what wat moet er bij worden opgeteld / afgetrokken?  Dit is een object met hierin 
 *         een van de volgende kolommen: years, months, weeks, days, hours, minutes of seconds
 *      Als voor deze parameter een number wordt gegeven, wordt dit geinterpreteerd als aantal dagen!
 * @return een nieuw datum object. 
 * 
 *	 
 *  Voorbeeld:   
 *    d = new Date( 20070301 )
 *    d.add( 1 ).to_s()  => 20070302
 *    d.add( { months: 2, days: -1 } ).to_s() => 20070501	 
 */
Date.prototype.add = function( what ) {
	if( !what ) what = '';
	if( !isNaN( Number( what ) ) ) what = { days: what } ;
	var years = what['years'] ? what['years'] : 0;
	var months = what['months'] ? what['months'] : 0;
	var days = what['days'] ? what['days'] : 0;
	days += what['weeks'] ? what['weeks'] * 7 : 0;	
	var hours = what['hours'] ? what['hours'] : 0;
	var minutes = what['minutes'] ? what['minutes'] : 0;
	var seconds = what['seconds'] ? waht['seconds'] : 0;
	var d = new Date( this.getFullYear() + years,this.getMonth() + months, this.getDate() + days, 
						this.getHours() + hours, this.getMinutes() + minutes, this.getSeconds() + seconds );
	return d
}

Date.prototype.addYears = function( what ) { return this.add( { years: what } ) };
Date.prototype.addYear = function( what ) {  return this.add( { years: what } ) };
Date.prototype.addMonths = function( what ) { return this.add( { months: what } ) };
Date.prototype.addMonth = function( what ) {  return this.add( { months: what } ) } ;
Date.prototype.addWeeks = function( what ) { return this.add( { weeks: what } ) };
Date.prototype.addWeek = function( what ) { return this.add( { weeks: what } ) };
Date.prototype.addDays = function( what ) { return this.add( { days: what } ) };
Date.prototype.addDay = function( what ) { return this.add( { days: what } ) };
Date.prototype.addHours = function( what ) { return this.add( { hours: what } ) };
Date.prototype.addHour = function( what ) { return this.add( { hours: what } ) };
Date.prototype.addMinutes = function( what ) { return this.add( { minutes: what } ) };
Date.prototype.addMinute = function( what ) { return this.add( { minutes: what } ) };
Date.prototype.addSeconds = function( what ) { return this.add( { seconds: what } ) };
Date.prototype.addSecond = function( what ) { return this.add( { second: what } ) };
Date.prototype.yesterday = function() { return this.add( { days: -1 } ) };
Date.prototype.tomorrow = function() { return this.add( { days: 1 } ) };

/**
 * Date to_date moet ook geen probleem mogen zijn ;-)
 */
Date.prototype.to_date = function() { return this; }

/** Geeft het aantal dagen in deze maand terug */
Date.prototype.days_in_month = function () {
	return new Date(this.getFullYear(), this.getMonth()+1, 0).getDate()
}

/** Geeft het aantal dagen in dit jaar terug */
Date.prototype.days_this_year = function() { 
	return ( new Date( this.getFullYear(), 11, 31 ) ).diff( new Date( this.getFullYear(), 0, 0 ) );
}

/** 
 * Geeft het verschil terug in de opgegeven eenheid. In GEHELE waardes!
 * @param date2 de datum waarmee moet worden vergeleken
 * @param unit (optioneel) de eenheid. Kan een van onderstaande eenheden zijn. Default waarde is 'days'
 * 		years, months, weeks, days, hours, minutes, seconds
 *	
 */
Date.prototype.diff = function ( date2, unit ) {
	if( !unit ) unit ='days';
	var divider = 1;
	switch( unit ) {
		case 'years': return Number( this.getFullYear() - date2.getFullYear() )
		case 'months': 	return Number( this.getFullYear() - date2.getFullYear()) * 12 + ( this.getMonth() - date2.getMonth() );
		case 'weeks': return Math.floor( ( this.valueOf() - date2.valueOf() ) / ( 24 * 60 * 60 * 1000 ) / ( 7 * 24 * 60 * 60 * 1000 ) );
		case 'days': return Math.floor( ( this.valueOf() - date2.valueOf() ) / ( 24 * 60 * 60 * 1000 ) );
		case 'hours': return Math.floor( ( this.valueOf() - date2.valueOf() ) / ( 60 * 60 * 1000 ) );
		case 'minutes': return Math.floor( ( this.valueOf() - date2.valueOf() ) / ( 60 * 1000 ) );
		case 'seconds': return Math.floor( ( this.valueOf() - date2.valueOf() ) / 1000 );
	}
	throw "Ongeldige unit meegegeven aan de functie Date.diff!!";
}

/**
 * bepaald de startdatum van een gegeven weeknummer. 
 * 
 */
Date.prototype.get_week_start_datum = function( jaar, week ) {
	if( !week && week !== 0 ) week = 1;     // week 0 moet ook worden ondersteund. Week 0, is de laatste week van vorig jaar :S
	
	// Bepaal de eerste week van het jaar:
	// - De week waar 4 januari in valt is de eerste week van het jaar
	var date = new Date( jaar, 0, 4 );
	var weekday = date.getDay();
	weekday = weekday ? weekday-1 : 6;		// maak zondag de laatste dag ipv de eerste
	
	// vervolgens de datum terugzetten zodat we de eerste dag van de week hebben.
	date.setTime( date.getTime() -  1000 * 60 * 60 * 24 * weekday );
	
	// nu hebben we de eerste dag van de week 1 te pakken, nu nog naar de juiste week gaan.
	date.setTime( date.getTime() + ( (week-1) * 7 * 24 * 60 * 60 * 1000 ) );
	return date;
}

/** 
 * Returns the week number for this date.  dowOffset is the day of week the week
 * "starts" on for your locale - it can be from 0 to 6. If dowOffset is 1 (Monday),
 * the week returned is the ISO 8601 week number.
 * @param int dowOffset
 * @return int 
 */
Date.prototype.getWeek = function (dowOffset) {
/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */
	dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 1; //default dowOffset to zero
	var newYear = new Date(this.getFullYear(),0,1);
	var day = newYear.getDay() - dowOffset; //the day of week the year begins on
	day = (day >= 0 ? day : day + 7);
	var daynum = Math.floor((this.getTime() - newYear.getTime() - 
	(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
	var weeknum;
	//if the year starts before the middle of a week
	if(day < 4) {
		weeknum = Math.floor((daynum+day-1)/7) + 1;
		if(weeknum > 52) {
			nYear = new Date(this.getFullYear() + 1,0,1);
			nday = nYear.getDay() - dowOffset;
			nday = nday >= 0 ? nday : nday + 7;
			/*if the next year starts before the middle of
 			  the week, it is week #1 of that year*/
			weeknum = nday < 4 ? 1 : 53;
		}
	}
	else {
		weeknum = Math.floor((daynum+day-1)/7);
	}
	return weeknum;
}

/**
 * Handigheidje om een getal direct naar een Date object te vertalen:
 * Voorbeeld:
 *   20060326.to_date().to_s() => 26-03-2007
 */ 
Number.prototype.to_date = function() {
	var v = this.valueOf();
	if( v == 0 ) return null;
	return Date.create( v );
}

	
/** 
 * Parsen van een string naar een Date Object! 
 * Ondersteunde formaten zijn op dit moment:
 * ( -, mag ook '/', of '.' zijn !!)
 *  yyyymmdd 
 *  yyyy-mm-dd / yyyy-mm-d / yyyy-m-dd / yyyy-m-d
 * 
 *  dd-mm-yyyy / d-mm-yyyy / dd-m-yyyy / d-m-yyyy
 *  d-m   (automatisch wordt het huidige jaar genomen)
 *  
 *  
 * Momenteel wordt alleen de string "DD.MM.YYYY" ondersteund (Waar '.' elk willekeurig teken kan zijn!)
 * TODO: Nette string-to-date routine schrijven.
 */
String.prototype.to_date = function() {
	var m;
	if( m = this.match( /^\d{8}$/ ) ) { return Date.create( this ); }
	if( m = this.match( /^(\d{4})[\-\/\.](\d{1,2})[\-\/\.](\d{1,2})$/ ) ) { return new Date( m[0], m[1]-1, m[2] ); }
	if( m = this.match( /^(\d{1,2})[\-\/\.](\d{1,2})[\-\/\.](\d{4})$/ ) ) { return new Date( m[2], m[1]-1, m[0] ); }
	return null;
}




////////////////////////////////////////////////////////////////////////////////
// Date functies
//////////////////////////////////////////////////////////////////////////////// 
function timestamp(datum) {
	if (datum == null || datum == '') {datum = new Date()}
	var year 		= Fill(datum.getFullYear(),4);
	var month 	= Fill(datum.getMonth()+1,2);
	var day 		= Fill(datum.getDate(),2);
	var hours   = Fill(datum.getHours(),2);
	var minutes = Fill(datum.getMinutes(),2);
	var seconds = Fill(datum.getSeconds(),2);
	var milli	  = Fill(datum.getMilliseconds(),3);
	return year+month+day+hours+minutes+seconds+milli;
}
function Fill(x,y) {
	while (String(x).length < y) {
		x="0"+x;
	}
	return String(x);
}
/******************************************************************************
  * Kijkt of een element in een Array zit.
  * @param elem mixed: het element
  * @param arr array: de array
  * @param bNumeric boolean: Optionele boolean. Als true, geef dan de index van 
  * het gevonden element terug in plaats van een boolean. NB: de functie indexOf
  * doet ongeveer hetzelfde in moz en opera. Niet te verwarren met de gelijknamige 
  * RegExp-functie.
  * @return mixed: true of een index als gevonden, false als niet gevonden.
  ****************************************************************************/
function inArray(elem,arr,bNumeric){
	if( arr==null || typeof(arr.length) == 'undefined') {
		return false;
	}
	if(typeof(bNumeric) == "undefined") {
		bNumeric = false;
	}
	for(var x=0;x<arr.length;x++){
		if(String(arr[x])==String(elem)) {
			return bNumeric ? String(x) :  true;
		}
	}
	return false;
}
function formatCurrency( value, decimals, group ) {
	if( decimals == null ) decimals = 2;
	if( group == null ) group = 0;	// geen duizentallen
	if (typeof(value)=='object') {value = value.value/100}
	if (isNaN(value)) {
		value = String(value).replace(/\./g,'');
		value = String(value).replace(/\,/g,'.');
	}
	if (isNaN(value)) {
		return false;
	}
	var value =  String(Number(value).toFixed(decimals)).replace(/\./g,",");
	if( group ) {
		var parts = value.split(",");
		var number = '';
		var count = 0;
		for( var i=parts[0].length-1; i >= 0; i-- ) {
			if ((count == 3 ) && (parts[0].charAt(i)!="-")) {
				count = 0 ;
				number = "." + number ;
			}
			number = parts[0].charAt(i) + number;
			count++;
		}
		return number + (parts.length > 1?","+parts[1]:"");
	}
	return value;
}
function trim( s ) {
	return ltrim(rtrim(s));
}
function rtrim( s ) {
	s = String(s);
	for( var i=s.length-1; i >= 0 && isWhiteSpace(s.charAt(i)); i-- );
	if( i < 0 ) return "";
	return s.substr(0,i+1);
}
function ltrim( s ) {
	s = String(s);
	for( var i=0; i < s.length && isWhiteSpace(s.charAt(i)); i++ ) ;
	if( i==s.length ) {
		return '';
	}
	return s.substr(i);
}
function FirstUp(sInput) {
	var sOutput = "";
	sInput = ltrim(sInput.toLowerCase());
	for (var i = 0; i < sInput.length; i++) {
		if (i == 0) {
			sOutput = sOutput + sInput.charAt(i).toUpperCase();
		} else {
			if ((sInput.charAt(i-1) == " ") || (sInput.charAt(i-1) == "-")) {
				sOutput = sOutput + sInput.charAt(i).toUpperCase();
			} else {
				sOutput = sOutput + sInput.charAt(i);
			}
		}
	}
	return sOutput;
}
function isWhiteSpace( c ) {
	return( c == ' ' || c=='\t' || c=='\n' || c=='\r' );
}

print_r_impl_id=0; 
function print_r_impl( item, depth, printFunctions, recursionPreventionStack ) { 
	// begin with the variables
	var typename 	= typeof( item );
	// object ?
	if( typename=='object' ) {
		// is this object alread placed on the stack
		for( var i=0; i < recursionPreventionStack.length; i++ ) {
			if( recursionPreventionStack[i] == item && item != null ) {
				return prefixText = " ** Preventing Recursion ** ";
			}
		}

		if( item == null ) return "NULL";

		recursionPreventionStack[recursionPreventionStack.length] = item;
		// make the prefix
		var prefixText  = "";
		for( var i=0; i < depth; i++ ) prefixText += "\t";
		// list all childs
		var result = ""; //prefixText;
		var objectType = "Object"
		var matches = (item.constructor.toString().match( /^\s*function\s+(.+?)\s*\(/i ) )
		if( matches && matches[1] != 'Object' ) objectType = matches[1];
		
		if( objectType == "Date" ) {
			result += "("+objectType+") " + item.to_s( 'date_time' );
		} else {
			result += objectType;
		}
		
		var itemcount = 0 ;
		var tmpResult = '';
		tmpResult+= prefixText + "{";
		try {
			for( name in item ) {
				if ( !printFunctions && typeof( item[name] ) == 'function') continue;	// skip this!				
				tmpResult += "\r\n"+prefixText + "\t"+ name + " =&gt; " + print_r_impl( item[name], depth+1, printFunctions,  recursionPreventionStack ) ;
				itemcount++;
			}			
		}
		catch( except ) {
			if( item.xml ) {
				print_r_impl_id++;
				return "<a href='#' onclick=\"var c=document.getElementById('print_r_div"+print_r_impl_id+"'); c.style.display=(c.style.display=='block'?'none':'block');return false;\">XMLDocument()...</a>"+
				"<div style='display:none;' id='print_r_div"+print_r_impl_id+"' >"+xmlPrint( item.xml )+"</div>";
			}
			return prefixText + "ActiveXObject??{ TODO: listing activex methods and members("+item.xml+"): " +except +" }\r\n";
		}
		tmpResult+= "\r\n" + prefixText + "}";
		
		if( itemcount == 0 ) {
			return result + ""; //"Object{}";// \r\n";
		} else {
			result += "\r\n" + tmpResult;
		
		}
		return result;
	}
	// function ?
	if( typename=='function'  ) {
		return " function()";
	} else {
		return "("+typename+") "+ item;
	}
}

function print_r( item, printFunctions ) {
	var recursionPreventionStack = new Array();   // recursion prevention stack
	var result = "<pre>";
	result += print_r_impl( item, 0, printFunctions, recursionPreventionStack );
	result += "</pre>";
	return result;
}
function XML2VolledigeNaam(PersoonNode,postfix) {
	retval = '';
	if (postfix==null) {postfix=''}
	if (GetNodeValue(PersoonNode,"Voorletters"+postfix) + GetNodeValue(PersoonNode,"Voorvoegsel"+postfix) + GetNodeValue(PersoonNode,"Achternaam"+postfix) != '') {
		if (GetNodeValue(PersoonNode,"Geslacht"+postfix)=="M") {
			retval+="Dhr. ";
		} else if (GetNodeValue(PersoonNode,"Geslacht"+postfix)=="V") {
			retval+="Mevr. ";
		} else {
			retval+="Dhr./Mevr. ";
		}
		if (GetNodeValue(PersoonNode,"Voorletters"+postfix)) {
			retval += GetNodeValue(PersoonNode,"Voorletters"+postfix)+" ";
		}
		if (GetNodeValue(PersoonNode,"Voorvoegsel"+postfix)) {
			retval += GetNodeValue(PersoonNode,"Voorvoegsel"+postfix)+" ";
		}
		if (GetNodeValue(PersoonNode,"Achternaam"+postfix)) {
			retval += GetNodeValue(PersoonNode,"Achternaam"+postfix);
		}
	}
	return retval;
}

function XML2VolledigeKindNaam(PersoonNode, reversed) {
	retval = '';
	if( reversed ) {
		if (GetNodeValue(PersoonNode,"Achternaam")) {
			retval += GetNodeValue(PersoonNode,"Achternaam")+" ";
		}
		if (GetNodeValue(PersoonNode,"Voorvoegsel")) {
			retval += GetNodeValue(PersoonNode,"Voorvoegsel");
		}
		if (GetNodeValue(PersoonNode,"Roepnaam")) {
			retval = trim(retval);
			retval += ", ";
			retval += GetNodeValue(PersoonNode,"Roepnaam");
		}
	} else {
		if (GetNodeValue(PersoonNode,"Roepnaam","")!= "") {
			retval += GetNodeValue(PersoonNode,"Roepnaam")+" ";
		}
		if (GetNodeValue(PersoonNode,"Voorvoegsel","")!= "") {
			retval += GetNodeValue(PersoonNode,"Voorvoegsel")+" ";
		}
		if (GetNodeValue(PersoonNode,"Achternaam","")!="") {
			retval += GetNodeValue(PersoonNode,"Achternaam");
		}
	}
	return retval;
}

function XML2VolledigAdres(AdresNode) {
	var retval = "";
	if(GetNodeValue(AdresNode,"Postcode","")!="" && GetNodeValue(AdresNode,"Nummer","")!="") {
		var strAdresImg = "../images/icons/"+GetNodeValue(AdresNode,"Soort","postadres")+".gif";
		retval += "<img src=\""+strAdresImg+"\"/>";
		retval += trim(GetNodeValue(AdresNode, "Straatnaam"))+"&nbsp;"+GetNodeValue(AdresNode, "Nummer");
		if (GetNodeValue(AdresNode, "Nummertoevoeging")!="") {
			retval += " ("+GetNodeValue(AdresNode, "Nummertoevoeging")+")";
		}
		retval += "<br />";
		retval += "&nbsp;&nbsp;&nbsp;&nbsp;"+GetNodeValue(AdresNode,"Postcode") + "&nbsp;"+GetNodeValue(AdresNode,"Plaatsnaam")+"<br />"
		if ( GetNodeValue(AdresNode,"Plaatsnaam") != GetNodeValue(AdresNode,"Gemeentenaam") ) {
			retval += "&nbsp;&nbsp;&nbsp;&nbsp;("+GetNodeValue(AdresNode,"Gemeentenaam")+")<br />";
		 }
		retval += "&nbsp;&nbsp;&nbsp;&nbsp;"+GetNodeValue(AdresNode,"Provincienaam")+"<br />";
	}
	return retval;
}

function XML2VolledigeAansluiting(aansluitingNode) {
	if(GetNodeValue(aansluitingNode, "Image")=="website.gif") {
		return  "<img src='../images/icons/"+GetNodeValue(aansluitingNode, "Image")+"' /><a href='http://"+GetNodeValue(aansluitingNode, "Nummer")+"' target='_blank'> "+GetNodeValue(aansluitingNode, "Nummer")+"</a>";
	} else if(GetNodeValue(aansluitingNode, "Image")=="mail.gif") {
		return  "<img src='../images/icons/"+GetNodeValue(aansluitingNode, "Image")+"' /><a href='mailto:"+GetNodeValue(aansluitingNode, "Nummer")+"' target='_blank'> "+GetNodeValue(aansluitingNode, "Nummer")+"</a>";
	} else {
		return  "<img src='../images/icons/"+GetNodeValue(aansluitingNode, "Image")+"' /> "+GetNodeValue(aansluitingNode, "Nummer");
	}
}

function isValidEmailAddress( adres ) {
	return String(adres).match(/^[a-z0-9][^\(\)\<\>\@\,\;\:\\\"\[\]]*\@[a-z0-9][a-z0-9\-\.]*\.[a-z]{2,6}$/i);
}
function intersection( begin1, eind1, begin2, eind2, exclusive ) {
	if(exclusive == null || exclusive == "") exclusive = false;
	begin1 = Number(begin1);
	begin2 = Number(begin2);
	eind1 = Number(eind1);
	eind2 = Number(eind2);
	// niet overlappen
	if( exclusive ) {
		if( eind1 <= begin2 ) return false;
		if( eind2 <= begin1 ) return false;
	} else {
		if( eind1 < begin2 ) return false;
		if( eind2 < begin1 ) return false;
	}
	return [Math.max(begin1,begin2),Math.min(eind1,eind2) ];
}
function intersectionArray( arrA, arrB, exclusive ) {
	// unions maken van input
	//arrA = unionArray(arrA);
	//arrB = unionArray(arrB);
	// kopieer arrA naar het resultaat
	var result = new Array();
	for( var i=0; i < arrA.length; i++ ){
		result[i] = arrA[i];
	}
	// Bereken de intersectie voor elk element
	for( var ia=0; ia<result.length;ia++ ) { //result.length
		var itemResult = false;
		for( var ib=0; ib < arrB.length; ib++ ) {
			var tmpResult = intersection( result[ia][0], result[ia][1], arrB[ib][0], arrB[ib][1],exclusive );
			if( tmpResult ) {
				if( !itemResult ) {
					itemResult = tmpResult;
				} else {
					result[result.length] = tmpResult;
				}
			}
		}
		result[ia] = itemResult;
	}
	// compress nu het resultaat
	var result2 = new Array();
	for( var i=0; i < result.length; i++ ) {
		if( result[i] ) {
			result2[ result2.length] = result[i];
		}
	}
	return result2;
}
function union( begin1, eind1, begin2, eind2 ) {
	// Overlappende periodes?
	begin1 = Number(begin1);
	begin2 = Number(begin2);
	eind1 = Number(eind1);
	eind2 = Number(eind2);
	if( intersection( begin1, eind1, begin2, eind2, false ) ) {
		return [ [Math.min(begin1,begin2), Math.max(eind1,eind2) ] ];
	}
	// anders geef de twee afzonderlijke periodes terug
	return [[begin1,eind1],[begin2,eind2]];
}
function unionArray( arr ) {
	// voor alle items
	var unionFound = false;
	do {
		unionFound = false;
		for( var i=0; i < arr.length; i++ ) {
			if( arr[i] == false ){  continue;	}// skip deleted items
			var rangeA = arr[i];
			for( var j=i+1; j < arr.length; j++ ) {
				if( arr[j] == false ) { continue;}	// skip deleted items
				var rangeB = arr[j];
				// Is er een union, vervang item 'i' dan door deze union en begin opnieuw
				// Vervang vervolgens item [j] door false...
				var newItems = union( rangeA[0], rangeA[1], rangeB[0], rangeB[1] );
				if( newItems.length == 1 )	{
					unionFound = true; 
					arr[i] =newItems[0];
					arr[j] = false; 
				}
			} // for j
		} // for i
	}
	while( unionFound );
	// bouw het resultaat (Negeer de false items)
	var result = new Array();
	for( var i=0; i < arr.length; i++ ) {
		if( arr[i] ) { result[result.length] = arr[i];}
	}
	return result;
}
function difference( begin1, eind1, begin2, eind2 ) {
	// 1: [             ]
	// 2:     [XXXXX]
	// =  [   ]     [   ]
	begin1 = Number(begin1);
	begin2 = Number(begin2);
	eind1 = Number(eind1);
	eind2 = Number(eind2);
	if( ( begin1 < begin2 && begin2 < eind1 ) && ( begin1 < eind2 && eind2 < eind1 ) ) {
		return [ [begin1,begin2], [eind2,eind1] ];
	}
	// 1:     [    ]
	// 2: [XXXXXXXXXXXXX]
	// =:    (leeg)
	if( ( begin2 <= begin1 && begin1 <= eind2 ) && ( begin2 <= eind1 && eind1 <= eind2 ) ) {
		return []; // LEEG !
	}
	// 1: [     ]
	// 2:    [XXXXXX]
	// =: [  ]
	if( begin1 < begin2 && begin2 < eind1 ) {
		return [[begin1,begin2]];
	}
	// 1:     [     ]
	// 2: [XXXXXX]
	// =:        [  ]
	if( begin1 < eind2 && eind2 < eind1 ) { 
		return [[eind2,eind1]];
	}
	// anders gewoon het inkomende
	return [[begin1,eind1]];
}

function differenceArray( arrA, arrB ) {
	// kopieer eerst arrA naar het resultaat.
	var result = new Array();
	for( var i=0; i < arrA.length; i++ ) {
		result[i] = arrA[i];
	}
	// bereken vervolgens voor ELK element in de array de difference!
	var ia=0;
	while(ia < result.length ) {
		var itemA = result[ia];
		if( itemA != false ) {
			for( var ib=0; ib < arrB.length; ib++ ) {
				// bereken de difference tussen deze twee items
				var itemA = result[ia]; // Opnieuw opvragen, kan veranderd zijn in deze loop
				var itemB = arrB[ib];
				var items = difference( itemA[0], itemA[1], itemB[0], itemB[1] );
				// twee resultaten? huidige vervangen en de tweede toevoegen
				if( items.length == 2 ) { 
					result[ia] = items[0];
					result[result.length] = items[1]; 
				}
				// een resultaat?
				else if( items.length == 1) {
					result[ia] = items[0];
				}
				// anders geen resultaat
				else if( items.length == 0 ) {
					result[ia] = false;
					ib = arrB.length;
				}
			}
		}
		ia++;
	}
	// 'verwijder' alle falses uit de array
	var result2 = new Array();
	for( var i=0; i < result.length; i++ ) {
		if( result[i] ) {
			result2[result2.length] = result[i];
		}
	}
	return result2;
}

function toNumber( val, defValue ) {
	val = String(val).replace(/\,/g,".");
	if( !defValue ) defValue=0;
	val = parseFloat(val);
	if( isNaN( val ) ) return defValue;
	return val;
}
function checkElfProef(value){
	value = String(value);
	var checksum = 0;
	var valuelength = value.length;
	for (var i = 0; i < valuelength ; i++){
		checksum += (value.charAt(i) * (valuelength - i));
	}
	checksum -= value.charAt(value.length);
	if (checksum % 11 != 0)	{ return false; }
	return true;
}
function checkElfProefBSN(value) {
	value = String(value);
	var checksum = 0;
	var valuelength = value.length;
	if (valuelength != 9) return false;
	for (var i = 0; i < valuelength-1; i++) {
		checksum += (value.charAt(i) * (9 - i));
	}
	checksum -= value.charAt(8);
	if (checksum % 11 != 0) {
		return false;
	}
	return true;
}

function newDate() {
	if (typeof(Session)=="undefined") {return new Date(); }
	else if(Session("currentDate")) { return XML2RealDate(Session("currentDate")) }
	//if (state_getVar("currentDate")) {return XML2RealDate(state_getVar("currentDate"))};  -- Ik heb geen state_getVar();
	return new Date();
}
function DateDiff(interval, date1, date2) {
	if (interval=="m")
		return Number(date1.getFullYear() - date2.getFullYear()) * 12 + (date1.getMonth() - date2.getMonth());
	else
		return Number(date1.valueOf() - date2.valueOf()) / (interval=="s"?1000:(interval=="n"?60000:(interval=="h"?3600000:86400000)));
}
function DateAdd(interval, number, date) {
	var Years=(interval=="y"?number:0),Months=(interval=="m"?number:0), Days=(interval=="d"?number:0), Hours=(interval=="h"?number:0), Mins=(interval=="n"?number:0), Secs=(interval=="s"?number:0);
//        Response.Write(date.getMonth() + Months + "<Br/>");

	return new Date(date.getFullYear() + Years, date.getMonth() + Months, date.getDate() + Days, date.getHours() + Hours, date.getMinutes() + Mins, date.getSeconds() + Secs);
}
function Monday(date) {
	date=(date=='' || date==null) ? new Date() : date;
	return DateAdd("d",-(date.getDay()>0?date.getDay():7)+1,date);
}
function newXMLDate() {
	var  dateObject = newDate();
	var year = dateObject.getFullYear();
	var month = dateObject.getMonth();
	var day = dateObject.getDate();
	return Number(year)*10000 + (Number(month)+1)*100 + Number(day);
}
function newXMLDatetime() {
	var dateObject = newDate();
	var year	= String(dateObject.getFullYear());
	var month	= String(dateObject.getMonth());
	var date	= String(dateObject.getDate());
	var hour	= String(dateObject.getHours());
	var mins	= String(dateObject.getMinutes());
	var secs	= String(dateObject.getSeconds());
	var msecs	= String(dateObject.getMilliseconds());

	return year + month + date + hour + mins + secs + msecs;
}
function validateDate(datum, jaar, maand) {
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/; // requires 4 digit year
	var dateStr = new String(datum);

	var matchArray = dateStr.match(datePat); // is the format ok?
	if (matchArray == null) {
		return ""; //false;
	}
	day = matchArray[1]; // parse date into variables
	month = matchArray[3];
	year = matchArray[4];
	if (month < 1 || month > 12) { // check month range
		return ""; //false;
	}
	if (day < 1 || day > 31) {
		return ""; //false;
	}
	if ((month==4 || month==6 || month==9 || month==11) && day==31) {
		return ""; //false;
	}
	if (month == 2) { // check for february 29th
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day>29 || (day==29 && !isleap)) {
			return ""; //false;
		}
	}
	day 	= String(day);
	month = (parseInt(maand)>0?maand:String(month));
	year	= (parseInt(jaar)>0?jaar:String(year));
	if (day.length < 2) {day = '0' + day}
	if (month.length < 2) {month = '0' + month}
	return day+"-"+month+"-"+year;
}
function validateDateWithAlert(datum){
	datum = validateDate(datum);
	if (!datum){
		alert('Ongeldige datum opgegeven, geef een datum op in het formaat: DD-MM-JJJJ');
		return '';
	}
	return datum;
}
function XML2date(XML) {
	if (XML=='' || !XML) return "";
	if (String(XML).length>=8) {
		XMLdate = String(XML).substring(6,8) + '-' +
							String(XML).substring(4,6) + '-' +
							String(XML).substring(0,4);
		return XMLdate;
	} else if (String(XML).length==4) {
		XMLdate = String(XML).substring(2,4) + '-' +
							String(XML).substring(0,2);
		return XMLdate;
	}
}
function XMLDateAdd(interval, number, date) {
	return DateAddXML(interval, number, date );
	//date = String(date);
	
	//var dateObject = XML2date( date );
	//DateAddXML('m', '1', datexml)
}

/** 
 * Geeft de dag van de week terug. 0=maandag ... 6=zondag!
 * @param xmldate XMLdate of Date object! 
 */ 
function getDayOfWeek( xmldate ) {
	if( typeof( xmldate ) != 'object' ) {
		xmldate = XML2RealDate( xmldate );
	}
	var day = xmldate.getDay()
	if( day == 0 ) return 6;
	return day - 1;
}

function getWeek(XMLDate) {
	var y = String(XMLDate).substring(0,4);
	var m = String(XMLDate).substring(4,6);
	var d = String(XMLDate).substring(6,8);
	var year = Number(y);
	var month = Number(m);
	var day = Number(d);
    	var a = Math.floor((14-(month))/12);
    	var y = year+4800-a;
    	var m = (month)+(12*a)-3;
	var jd = day + Math.floor(((153*m)+2)/5) +
                (365*y) + Math.floor(y/4) - Math.floor(y/100) +
                 Math.floor(y/400) - 32045;      // (gregorian calendar)
    //var jd = (day+1)+Math.Round(((153*m)+2)/5)+(365+y) +
    //                 Math.round(y/4)-32083;    // (julian calendar)

    //now calc weeknumber according to JD
   	var d4 = (jd+31741-(jd%7))%146097%36524%1461;
   	var L = Math.floor(d4/1460);
   	var d1 = ((d4-L)%365)+L;
	NumberOfWeek = Math.floor(d1/7) + 1;
   	return NumberOfWeek;
}
function date2XML(date) {
	date = String(date).replace(/^s+/,'').replace(/s+$/,'');  // trim spaces
	date = date.replace("/","-").replace(".","-").replace(" ","-");	// scheidings tekens kunnen zijn '-', '/' en ' '
	var items = date.split('-');
	if( items.length == 3) {
		return Number(items[0]) + Number(items[1])*100 + Number(items[2])*10000;
	}
	return 0;	// ongeldige datum
}

function date2text(date) {
	var year = date.getFullYear();
	var month = date.getMonth();
	var day = date.getDate();
	
	if(month < 10) {
		month = "0"+month;
	}
	
	if(day < 10) {
		day = "0"+day
	}
	
	return day + "-" + month + "-" + year;
}

function time2text(date) {
	var hours = date.getHours();
	var mins = date.getMinutes();
	
	if(hours<10) hours="0"+hours;
	if(mins<10) mins="0"+mins;
	
	return hours+":"+mins;
}

function DateAddXML(interval, number, datexml) {
	return RealDate2XML(DateAdd(interval, number, XML2RealDate(datexml)));
}
function validateDate2xml(date) {
	date = validateDate(date);
    if( !date ) return false;
    return date2XML(date);
}
function XML2RealDate(strDate) {
	return new Date(String(strDate).substr(0,4),Number(String(strDate).substr(4,2))-1,String(strDate).substr(6,2));
}
function RealDate2XML(date) {
	//return String( ( date.getFullYear()*10000 + (date.getMonth() + 1)*100 + date.getDate()*1));
	return String(date.getFullYear()*10000 + (date.getMonth() + 1)*100+ date.getDate()*1);
}

/**
* Zet een tijd om naar een leesbaar formaat. Wordt doorgaans gebruikt ICM bindcontrols.
* @param iTime mixed: ofwel een HTML-of XML-element ofwel een integer
* @rteurn string HH:MM
**/
function mtime2text(iTime) {
	if(iTime === "") { return iTime;}
	if(isNaN(iTime)) { iTime = iTime.value;}
	iTime = Number(iTime);
	return String((Math.floor(iTime / 60) < 10 ? "0" : "") + Math.floor(iTime / 60)) + ":" + String((Number(iTime)%60 < 10 ? "0": "") + Number(iTime)%60);
}
/**
* Zet een leesbare tijd om in ons tijdformaat ofwel aantal minuten van 0:00 uur.
* @param strTime mixed: XML-element of HTML-element of string
* return integer : minuten vanaf 12 uur des nachts of false als input verkeerd
**/
function text2mtime(strTime) {
	if(typeof(strTime)!="string") { strTime = strTime.value; }
	if(!strTime.match(/^\d{1,2}\:\d{2}$/)) {return false;}
	var arTime = strTime.split(":");
	if(Number(arTime[0]) < 0 || Number(arTime[0]) > 23) { return false; }
	if(Number(arTime[1]) < 0 || Number(arTime[1]) > 59) { return false; }
	return (Number(arTime[0]) * 60) + Number(arTime[1]); 
}
/* Tabs */
function showTab (tab) {
	tab = String(tab).replace(/\s/g,"");
	var block = $('tab_'+tab);
	var li = $('tab_li_'+tab);
	if (block) {
		var container = block.parentNode;
		var ul = li.parentNode;

		if (navigator && navigator.appVersion && navigator.appVersion.indexOf("MSIE") != -1) {
			version = parseFloat(navigator.appVersion.split("MSIE")[1]);
			if (version > 7) {
				block.style.marginTop = "12px";
			}
		}
		
		// tabs verbergen
		for (var c=0; c<container.childNodes.length; c++) {
			var child = container.childNodes[c];
			if (child && child.tagName && child.tagName.toLowerCase() == 'div') {
				child.style.display = "none";
			}
		}
		
		// links als niet-actief bestempelen
		for (var c=0; c<ul.childNodes.length; c++) {
			var child = ul.childNodes[c];
			if (child && child.tagName && child.tagName.toLowerCase() == 'li') {
				child.className = "";
			}
		}
		
		li.className = "active";
		block.style.display = "";

		var tabcontainers = document.getElementsByClassName("tabcontainer");
		for (var t=0; t<tabcontainers.length; t++) {
			tabcontainers[t].style.display = document.all ? "inline" : "block";
		}
		var tabs = document.getElementsByClassName("tabs");
		for (var t=0; t<tabs.length; t++) {
			tabs[t].style.display = document.all ? "inline" : "block";
		}

	}
}

function init_tabs () {
	// Bij de li een link toevoegen en de containers verbergen
	var tabs = document.getElementsByClassName("tabs");
	for (var t=0; t<tabs.length; t++) {
		var lis = tabs[t].getElementsByTagName("li");
		for (var l=0; l<lis.length; l++) {
			// link toevoegen
			var li = lis[l];
			var text = li.innerHTML.replace(/\s/g,"");
			li.id = "tab_li_" + text;
			li.innerHTML = "<a href='javascript:showTab(\"" + text + "\");'>" + li.innerHTML + "</a>";
			li.onmouseover = function() {
				if (!/active/.test(this.className)) {
					this.className = "hover";
				}
			}
			li.onmouseout = function() {
				if (!/active/.test(this.className)) {
					this.className = "";
				}
			}

			// container vergergen
			var tab = $('tab_' + text);
			if (tab) {
				tab.style.display = "none";
				if (tab.className!="") {
					tab.className = tab.className + " tab";
				} else {
					tab.className = "tab";
				}
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Automatic ~ IE XHR Bugfix
//
////////////////////////////////////////////////////////////////////////////////////////////////////////

	var IExhr_currentRequests = new Array();

	// Deze functie ruimt de openstaande Ajax.Requests op een nette wijze op...
	// Deze functie wordt aangeroepen in de onunload van elke lijst-pagina in verband met het ontbreken van een Garbage Controller in IE.
	function IExhr_runGarbageControl() {

		// alle xhr's canceleen!
		for(var x=0; x<IExhr_currentRequests.length; x++) {
			try {
				IExhr_currentRequests[x].onreadystatechange = function(){};	// IE Memory leak bugfix
				//IExhr_currentRequests[x].open(IExhr_currentRequests[x].method.toUpperCase(), IExhr_currentRequests[x].url, IExhr_currentRequests[x].options.asynchronous);
				IExhr_currentRequests[x].open("GET","dummy");
				IExhr_currentRequests[x] = null;
			//Tijdelijk irritante alert weggecommentarieerd. Zit veel test(er)s in de weg.
			// JH 20080129
			} catch(ex ) { /*if(document.all) {alert( ex.message );}*/}
		}		
	}

	// Effe controleren op prototype Ajax Object
	IExhr_initGarbageControl_inited = false
	function IExhr_initGarbageControl() {
		if( !IExhr_initGarbageControl_inited ) {
			// Registeren ajax responders
			if( typeof( Ajax ) == "object" )  {
				Ajax.Responders.register({
					onCreate: function(request) { IExhr_register(request.transport); 	},
					onComplete: function(request) { IExhr_unregister(request.transport); }
				});
			}
			IExhr_initGarbageControl_inited = true;
		}
	}       

	// register een ajax request 
	function IExhr_register( xhr ) {
		IExhr_currentRequests.push( xhr );
	}
	
	// unregister een ajax request
	function IExhr_unregister( xhr ) {
		for (var x=0; x<IExhr_currentRequests.length; x++) {
			if (IExhr_currentRequests[x] == xhr) {
				if (x<IExhr_currentRequests.length-1) {IExhr_currentRequests[x] = IExhr_currentRequests[IExhr_currentRequests.length-1];}
				break;
			}
		}
		IExhr_currentRequests.pop();
	}

	// register the event listener (helaas heb ik geen garantie data prototype al is geladen :-(
	function IExhr_RegisterEvent( element, name, method ) {
		if (element.addEventListener) {
			element.addEventListener( name, method, false );
		} else {
			element.attachEvent( "on" + name, method);
		}
	}
	// method binding (Veranderen van de scope van een functioncall). Noodzakelijk omdat prototype (misschien niet is geladen )
	if( !Function.prototype.bind  ) {
		Function.prototype.bind = function(obj) {
			var method = this;
			return function() {	return method.apply(obj, arguments); };
		} 	
	}	
	
	IExhr_RegisterEvent( window, "load", IExhr_initGarbageControl );		// initialisatie kan pas in de onload (omdat prototype misschien pas NA main.js is geinclude)
	IExhr_RegisterEvent( window, "unload", IExhr_runGarbageControl );	// Dit is de garbage collect fix
	
	
	/*****************************************************************
	 *     example 1: htmlspecialchars_decode("<p>this -&gt; &quot;</p>", 'ENT_NOQUOTES');
     *     returns 1: '<p>this -> &quot;</p>'
     *     example 2: htmlspecialchars_decode("&amp;quot;");
     *     returns 2: '&quot;'
	*****************************************************************/
	function htmlspecialchars_decode (string, quote_style) {
	    var optTemp = 0, i = 0, noquotes= false;
	    if (typeof quote_style === 'undefined') {
	        quote_style = 2;
	    }
	    string = string.toString().replace(/&lt;/g, '<').replace(/&gt;/g, '>');
	    var OPTS = {
	        'ENT_NOQUOTES': 0,
	        'ENT_HTML_QUOTE_SINGLE' : 1,
	        'ENT_HTML_QUOTE_DOUBLE' : 2,
	        'ENT_COMPAT': 2,
	        'ENT_QUOTES': 3,
	        'ENT_IGNORE' : 4
	    };
	    if (quote_style === 0) {
	        noquotes = true;
	    }
	    if (typeof quote_style !== 'number') { // Allow for a single string or an array of string flags
	        quote_style = [].concat(quote_style);
	        for (i=0; i < quote_style.length; i++) {
	            // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
	            if (OPTS[quote_style[i]] === 0) {
	                noquotes = true;
	            }
	            else if (OPTS[quote_style[i]]) {
	                optTemp = optTemp | OPTS[quote_style[i]];
	            }
	        }
	        quote_style = optTemp;
	    }
	    if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
	        string = string.replace(/&#0*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should
	        // string = string.replace(/&apos;|&#x0*27;/g, "'"); // This would also be useful here, but not a part of PHP
	    }
	    if (!noquotes) {
	        string = string.replace(/&quot;/g, '"');
	    }
	    // Put this in last place to avoid escape being double-decoded
	    string = string.replace(/&amp;/g, '&');

	    return string;
	}
