/**
* @copyright ScanFrame 2005-2010, All Rights Reserved.
* @author avo <dvlp@scanframe.nl>
* @package ScanFrame
* @category Page Classes
* @version $Revision: 1.38 $
* @cvs_source $Source: /export/cvs/primo/com/jscripts/commonlib.js,v $
* @cvs_author $Author: arjan $
* @purpose Common library for commmon javascript functions.
*/
//---------------------------------------------------------------------------
/**
* Static class to determine the type of browwser.
* @type Object
*/
var BrowserDetect =
{
	/**
	* Holds the browser name after initialization.
	* @type string
	*/
	browser: null,
	/**
	* Holds the browser version after initialization.
	* @type string
	*/
	version: null,
	/**
	* Holds the browser operatin system after initialization.
	* @type string
	*/
	OS: null,
	/**
	* Initializes this instance.
	* @returns void
	*/
	init: function ()
	{
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data)
	{
		for (var i = 0; i < data.length; i++)
		{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString)
			{
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
		return "";
	},
	searchVersion: function (dataString)
	{
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1)
			return 0;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser:
	[
		{
			string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Chrome/",
			identity: "Chromium",
			versionSearch: "Chrome"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS:
	[
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
// Initialize the BrowserDetect class.
BrowserDetect.init();
//---------------------------------------------------------------------------
/**
* Holds the debugout put until it can be shown.
* @type string
*/
var DebugOutBackLog = "";
/**
* Debugging function that appends to a part of the document en HTML
* encodes the message.
* @param string msg
* @param boolean alert_it
* @return boolean
*/
function DebugOut(msg, alert_it)
{
	if (opener != null && opener != window)
		/*return*/ opener.DebugOut(msg);
	var elem = document.getElementById('debug_info_javasccript');
	if (elem)
			elem.innerHTML += htmlEncode(msg + "\n", true, 3);
	else
	{
		// Start event when loaded only once when the backlog is still empty.
		if (!DebugOutBackLog.length)
			window.setTimeout('DebugOut(DebugOutBackLog)', 0);
		// Attach to the back log.
		DebugOutBackLog += msg + "\n";
	}
	// Should the message be alerted.
	if (alert_it)
		alert((msg!=null)?msg.replace(/\t/g,'   '):'<<empty message>>');
	// To prevent having to use a scope.
	return false;
}
//---------------------------------------------------------------------------
/**
* Function to make anchor tags do nothing.
* @return void
*/
function Void()
{
}
//-----------------------------------------
/**
* Holds the value an the unit.
* @constructor
* @param number
* @param string
*/
function TValueUnit(value, unit)
{
	/**
	* Holds the number part.
	* @public
	* @type number
	*/
	this.Value = value;
	/**
	* Holds the unit part.
	* @public
	* @type string
	*/
	this.Unit = unit;
	/**
	* Returns the assembled value and unit sting using a multiplier.
	* @param number Defaults to 1.
	*/
	this.String = function (mult)
	{
		if (typeof mult != 'number')
			mult = 1;
		return '' + (this.Value * mult) + this.Unit;
	}
	/**
	* Assign the instance using a string wich is split into a value and unit.
	* @param string/number String like '12px' or '3em'. When the type is a number the unit defaults to 'px'.
	* @param string/number Default when the first param is not a string or number.
	* @returns TValueUnit
	*/
	this.Assign = function (value_unit, def)
	{
		// Depending on the type process.
		switch (typeof value_unit)
		{
			// When undefined or null return the default when a default is given.
			default:
			case 'undefined':
				return def ? (new TValueUnit()).Assign(def) : null;
			// When it is a string a unit is always present.
			case 'string':
				{
					var value = value_unit.match(/^([0-9]+|[0-9]+\.[0-9]+)(%|px|pt|em)$/);
					if (value)
						return new TValueUnit(parseInt(value[1]), value[2]);
					else
						DebugOut("Error: clould not split value '" + value_unit + "'");
				}
			// When a numner a pixel unit is assumed.
			case 'number': return new TValueUnit(value_unit, 'px');
		}
		// Signal failure using the null object.
		return null;
	}
}
//-----------------------------------------
/**
* Splits the a position or size value into a value and a unit by returning
* a TValueUnit instance.
* @see TValue
* @param string/number
* @param string/number
*/
function GetValueUnit(value_unit, def)
{
	return new TValueUnit().Assign(value_unit, def);
}
//---------------------------------------------------------------------------
/**
* Returns the class name of the passed instance and false on failure.
* @returns string/boolean
*/
function get_class(obj)
{
	if (!(obj instanceof Array)
		&& !(obj instanceof Function) && obj.constructor && obj != window)
	{
		var arr = obj.constructor.toString().match(/function\s*(\w+)/);
		if (arr && arr.length == 2)
		  return arr[1];
	}
	// Signal failure.
	return false;
}
//---------------------------------------------------------------------------
/**
* Function : Dump()
* Arguments: The data - array,hash(associative array),object
*    The level - OPTIONAL
* Returns  : The textual representation of the array.
* This function was inspired by the print_r function of PHP.
* This will accept some data as the argument and return a
* text that will be a more readable version of the
* array/hash/object that is given.
*
*/
function Dump(arr, level)
{
	var dumped_text = "";
	if(!level)
		level = 0;
	if (level > 1)
		return "";
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j = 0; j < level + 1; j++)
		level_padding += "   ";
	//Array/Hashes/Objects
	if (typeof(arr) == 'object')
	{
		var first_item = null;
		for (var item in arr)
		{
			// Hack to break infinite loop.
			if (first_item == null)
				first_item = item;
			else if (first_item == item)
				break;
			//
			var value = null;
			try
			{
				value = arr[item];
			}
			catch(err)
			{
				return dumped_text;
			}
			//If it is an array,
			if (typeof(value) == 'object')
			{
				if (value === null)
					dumped_text += level_padding + "'" + item + "' => null\n";
				else
				{
					dumped_text += level_padding + "'" + item + "' ...\n";
					dumped_text += Dump(value, level + 1);
				}
			}
			else
			{
				switch (item)
				{
					case 'outerText':
					case 'innerText':
					case 'textContent':
					case 'innerHTML':
					case 'outerHTML':
						break;

					default:
						dumped_text += level_padding + "'" + item + "' => \"" +
							('' + value).replace(/\n/g, '\n' + level_padding) + "\"\n";
						break;
				}
			}
		}
	}
	else
	{
		//Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}
//---------------------------------------------------------------------------
/**
* Opens a new browser window.
* @param string URL of the page to open.
* @param string name of the browser tab window top open.
*/
function OpenBrowserTab(url, trgname)
{
	var form_name = '__link_form';
	var link_form = document.forms[form_name];
	// Check if the form exists.
	if (!link_form)
	{
		// If not create the form.
		link_form = document.createElement('FORM');
		document.body.appendChild(link_form);
		link_form.name = form_name;
		// Set post method to have the action have some meaning.
		link_form.method = "POST";
	}
	// Assign the url.
	link_form.action = url;
	// Set the target name.
	link_form.target = trgname;
	if (BrowserDetect.browser == 'Explorer' && !event.ctrlKey)
	{
		alert('Press now the \'Ctrl\'-key for this link to open it in a new Tab?');
		if (!event.ctrlKey)
			return;
	}
	// Submit and open the browser in a new tab.
	link_form.submit();
}
//---------------------------------------------------------------------------
/**
* Opens a new browser window.
*/
function OpenBrowser(url, trgname, w_width, w_height)
{
	// When negative use the screen width.
	if (w_width < 0)
		w_width = screen.width * 0.6;
	if (w_height < 0)
		w_height = screen.height * 0.6;
	//
	if (BrowserDetect.browser == 'Firefox')
	{
		// Center on the main window.
		w_left = window.screenX + ((window.outerWidth - w_width) / 2)
		w_top = window.screenY + ((window.outerHeight - w_height) / 2)
	}
	else
	{
		w_left = (screen.width - w_width) / 2;
		w_top = (screen.height - w_height) / 2;
	}
	// Assemble the options,
	var opts = "alwaysRaised";
//	if (w_width != 0)
	{
		opts += "width=" + w_width;
		opts += ",left=" + w_left;
	}
//	if (w_height != 0)
	{
		opts += ",height=" + w_height;
		opts += ",top=" + w_top;
	}
	opts += ",scrollbars=yes";
	opts += ",status=yes";
	opts += ",location=yes";
	opts += ",copyhistory=no";
	opts += ",menubar=yes";
	opts += ",toolbar=yes";
	opts += ",directories=no";
	opts += ",resizable=yes";
	//DebugOut("window.open options: " + opts);
	return window.open(url, trgname, opts);
}

//---------------------------------------------------------------------------
/**
* Opens a new clean browser window used as an application extension.
*/
function OpenWindow(url, trgname, w_width, w_height)
{
	// Set the default target name when none is passed.
	if (typeof(trgname) == 'undefined')
		trgname = '_blank';
	// When negative use the screen width.
	if (typeof(w_width) == 'undefined' || w_width < 0)
		w_width = screen.width * 0.8;
	if (typeof(w_height) == 'undefined' || w_height < 0)
		w_height = screen.height * 0.8;
	//
	if (BrowserDetect.browser == 'Firefox')
	{
		// Center on the main window.
		w_left = window.screenX + ((window.outerWidth - w_width) / 2)
		w_top = window.screenY + ((window.outerHeight - w_height) / 2)
	}
	else
	{
		w_left = (screen.width - w_width) / 2;
		w_top = (screen.height - w_height) / 2;
	}
	// Assemble the options,
	var opts = "";
	opts += "width=" + w_width;
	opts += ",height=" + w_height;
	opts += ",left=" + w_left;
	opts += ",top=" + w_top;
	opts += ",alwaysRaised";
	opts += ",scrollbars=yes";
	opts += ",status=yes";
	opts += ",location=no";
	opts += ",copyhistory=no";
	opts += ",directories=no";
	opts += ",menubar=no";
	opts += ",toolbar=no";
	opts += ",resizable=yes";
	//DebugOut("window.open options: " + opts);
	var win = window.open(url, trgname, opts);
	// Focus the opened dialog in case it was already opened by a previous call.
	if (win)
		win.focus();
	return win;
}
//---------------------------------------------------------------------------
/**
* Opens a new clean browser window used as an application dialog extension.
*/
function OpenDialog(url, trgname, w_width, w_height)
{
	// Set the default target name when none is passed.
	if (typeof(trgname) == 'undefined')
		trgname = '_blank';
	// When negative use the screen width.
	if (typeof(w_width) == 'undefined' || w_width < 0)
		w_width = screen.width * 0.8;
	if (typeof(w_height) == 'undefined' || w_height < 0)
		w_height = screen.height * 0.8;
	//
	if (BrowserDetect.browser == 'Firefox')
	{
		// Center on the main window.
		w_left = window.screenX + ((window.outerWidth - w_width) / 2)
		w_top = window.screenY + ((window.outerHeight - w_height) / 2)
	}
	else
	{
		w_left = (screen.width - w_width) / 2;
		w_top = (screen.height - w_height) / 2;
	}
	// Assemble the options,
	var opts = "";
	opts += "width=" + w_width;
	opts += ",height=" + w_height;
	opts += ",left=" + w_left;
	opts += ",top=" + w_top;
	opts += ",alwaysRaised";
	opts += ",scrollbars=no";
	opts += ",status=no";
	opts += ",location=no";
	opts += ",menubar=no";
	opts += ",toolbar=no";
	opts += ",copyhistory=no";
	opts += ",directories=no";
	opts += ",resizable=no";
	//DebugOut("window.open options: " + opts);
	var win = window.open(url, trgname, opts);
	// Focus the opened dialog in case it was already opened by a previous call.
	win.focus();
	return win;
}
//---------------------------------------------------------------------------
/**
* Returns the inner width of the passed browser window.
* @param window
* @returns integer
*/
function GetWindowInnerWidth(window)
{
	// Window dimensions:
	if (window.innerWidth)
		width = window.innerWidth;
	else if (window.document.documentElement && window.document.documentElement.clientWidth)
		width = window.document.documentElement.clientWidth;
	else if (window.document.body)
		width = window.document.body.clientWidth;
	//
	return width;
}
//---------------------------------------------------------------------------
/**
* Returns the inner height of the passed browser window.
* @param window
* @returns integer
*/
function GetWindowInnerHeight(window)
{
	if (window.innerHeight)
		height = window.innerHeight;
	else if (window.document.documentElement && window.document.documentElement.clientHeight)
		height = window.document.documentElement.clientHeight;
	else if (window.document.body)
		height = window.document.body.clientHeight;
	//
	return height;
}
//---------------------------------------------------------------------------
/**
* Returns the width of scrollbar.
* @returns integer
*/
var __GetScrollBarWidthResult__ = null;
//
function GetScrollBarWidth()
{
	if (__GetScrollBarWidthResult__ == null)
	{
		var inner = document.createElement('p');
		inner.style.width = '100%';
		inner.style.height = '200px';

		var outer = document.createElement('div');
		outer.style.position = 'absolute';
		outer.style.top = '0px';
		outer.style.left = '0px';
		outer.style.visibility = 'hidden';
		outer.style.width = '200px';
		outer.style.height = '150px';
		outer.style.overflow = 'hidden';
		outer.appendChild (inner);

		document.body.appendChild (outer);
		var w1 = inner.offsetWidth;
		outer.style.overflow = 'scroll';
		var w2 = inner.offsetWidth;
		if (w1 == w2) w2 = outer.clientWidth;

		document.body.removeChild(outer);
		__GetScrollBarWidthResult__ = (w1 - w2)
	}
	return __GetScrollBarWidthResult__;
};
//---------------------------------------------------------------------------
/**
* Toggles displaying of a container (f.e. a form, fieldset or div)
*
* @param  string elem_id ID of the element which is toggle displaying.
* @return boolean Returns true when visibale false when invisible.
*/
function ToggleDisplay(elem)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
		elem.style.display = (elem.style.display == '') ? 'none' : '';
	return (elem.style.display == '');
}
//---------------------------------------------------------------------------
/**
* Reports if element is displayed or not.
* You can pass the element or the id.
*/
function IsDisplayed(elem)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
		return (elem.style.display == '') ? true : false;
	return false;
}
//---------------------------------------------------------------------------
/**
* Reports if element is displayed or not.
* You can pass the element or the id.
*/
function Display(elem, show)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
	{
		if (show)
			elem.style.display = '';
		else
			elem.style.display = 'none';
		return true;
	}
	return false;
}
//---------------------------------------------------------------------------
/**
* Toggles displaying of a container (f.e. a form, fieldset or div)
*
* @param  string elem_id ID of the element which is toggle displaying.
* @return boolean Returns true when visible false when invisible.
*/
function ToggleVisibility(elem)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
	{
		if (IsVisible(elem))
			elem.style.visibility = 'hidden';
		else
			elem.style.visibility = 'visible';
	}
	return (elem.style.visibility == 'visible');
}
//---------------------------------------------------------------------------
/**
* Reports if element is displayed or not.
* You can pass the element or the id.
*/
function IsVisible(elem)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
		return (elem.currentStyle.visibility != 'hidden');
	return false;
}
//---------------------------------------------------------------------------
/**
* Reports if element is displayed or not.
* You can pass the element or the id.
*/
function Visibility(elem, show)
{
	if (typeof elem != 'object')
		elem = document.getElementById(elem);
	if (elem)
	{
		if (show)
			elem.style.visibility = 'visible';
		else
			elem.style.visibility = 'hidden';
		return true;
	}
	return false;
}
//---------------------------------------------------------------------------
/**
* Checks/unchecks all checkbox in given conainer (f.e. a form, fieldset or div)
*
* @param   string   container_id
* The container id
* @param   boolean  state
* New value for checkbox (true or false)
* When not passed or null the first inverse value of the check box in the list is used.
* When -1 a question is asked.
* @return  boolean  always true
*/
function SetCheckboxes(container_id, state, msg)
{
	if (state == -1)
	{
		state = confirm(msg);
	}
	var checkboxes = document.getElementById(container_id).getElementsByTagName('input');
	for ( var i = 0; i < checkboxes.length; i++ )
		if ( checkboxes[i].type == 'checkbox' )
		{
			// When state is not passed use the first check pox to initialize it.
			if (state == null)
				state = !checkboxes[i].checked;
			checkboxes[i].checked = state;
		}
	return true;
}
//---------------------------------------------------------------------------
/**
*
*/
function GetCheckboxes(container_id)
{
	var retval = Array();
	var checkboxes = document.getElementById(container_id).getElementsByTagName('input');
	for (var cb in checkboxes)
		if (cb.type == 'checkbox')
			retval.push(cb);
	return retval;
}
//---------------------------------------------------------------------------
/**
* Extend the string class with trim functions.
*/
String.prototype.trim = function()
{
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function()
{
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function()
{
	return this.replace(/\s+$/,"");
}
//---------------------------------------------------------------------------
/**
* Returns an array of elements which tagnames are in the passed string array.
* prototype key word is not implemented.
* @param HTMLElement
* @param string[]
* @returns HTMLElement[]
*/
function GetElementsByTagNames(parentNode, tagnames)
{
	if (typeof tagnames != 'object')
		return false;
	// Initialize the return value.
	var retval = Array();
	// Iterate through the type names.
	for (var j in tagnames)
	{
		// Push all found elements in the returned array.
		var elems = parentNode.getElementsByTagName(tagnames[j]);
		for (var i = 0; i < elems.length; i++)
			retval.push(elems[i]);
	}
	//
	return retval;
}
//---------------------------------------------------------------------------
/**
* Extends the array class
* Is not working gives eception in any browser.
*/
/*
Array.prototype.in_array = function(p_val)
{
	for(var i = 0, l = this.length; i < l; i++)
		if(this[i] == p_val)
			return true;
	return false;
}
*/
function in_array(p_val, arr)
{
	for(var i = 0, l = arr.length; i < l; i++)
		if(arr[i] == p_val)
			return true;
	return false;
}
//---------------------------------------------------------------------------
/**
* support microsoft's styleFloat
* mimic microsoft's pixel representations of left/top/width/height
* the getters only work for values that are already pixels
*/
if (BrowserDetect.browser != 'Explorer')
{
	// Add IE compatibility in Firefox.
	HTMLElement.prototype.__defineGetter__("currentStyle", function()
	{
		//return document.defaultView.getComputedStyle(this, null);
		return window.getComputedStyle(this, null);
	});
	CSSStyleDeclaration.prototype.__defineGetter__("styleFloat", function()
	{
	 return this.cssFloat;
	});
	CSSStyleDeclaration.prototype.__defineSetter__("styleFloat", function($value)
	{
	 this.cssFloat = $value;
	});
	CSSStyleDeclaration.prototype.__defineGetter__("pixelLeft", function()
	{
	 return parseInt(this.left) || 0;
	});
	CSSStyleDeclaration.prototype.__defineSetter__("pixelLeft", function($value)
	{
	 this.left = $value + "px";
	});
	CSSStyleDeclaration.prototype.__defineGetter__("pixelHeight", function()
	{
	 return parseInt(this.height) || 0;
	});
	CSSStyleDeclaration.prototype.__defineSetter__("pixelHeight", function($value)
	{
	 this.height = $value + "px";
	});
	CSSStyleDeclaration.prototype.__defineGetter__("pixelTop", function()
	{
	 return parseInt(this.top) || 0;
	});
	CSSStyleDeclaration.prototype.__defineSetter__("pixelTop", function($value)
	{
	 this.top = $value + "px";
	});
	CSSStyleDeclaration.prototype.__defineGetter__("pixelWidth", function()
	{
	 return parseInt(this.width) || 0;
	});
	CSSStyleDeclaration.prototype.__defineSetter__("pixelWidth", function($value)
	{
	 this.width = $value + "px";
	});
	Event.prototype.__defineGetter__("offsetX", function($value)
	{
	 	return this.layerX;
	});
	Event.prototype.__defineGetter__("offsetY", function($value)
	{
	 	return this.layerY;
	});
	Event.prototype.__defineGetter__("srcElement", function()
	{
	 return this.target;
	});
}
//---------------------------------------------------------------------------
/**
* Function to overcome problem with event or listner attaching between browsers.
*/
function AddEvent(obj, evtype, fn)
{
	if (obj.addEventListener)
	{
		obj.addEventListener(evtype, fn, true);
		return true;
	}
	else if (obj.attachEvent)
	{
		var r = obj.attachEvent("on"+evtype, fn);
		return r;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
/**
* Function to overcome problem with event or listner attaching between browsers.
*/
function RemoveEvent(obj, evtype, fn)
{
	if (obj.removeEventListener)
	{
		obj.removeEventListener(evtype, fn, true);
		return true;
	}
	else if (obj.detachEvent)
	{
		var r = obj.detachEvent("on"+evtype, fn);
		return r;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
/**
* Object to call a function on another object.
* @example
* Usage:
*  new Closure({o:myobj, f:'MyMemberFunc'})
*  new Closure(myobj, 'MyMemberFunc')
*  new Closure('MyFunc')
*  AddEvent(window, 'resize', new Closure(this, 'EvResize').Call);
* @constructor
* @param object/string obj
* @param string/void func
*/
function Closure(obj, func)
{
	/*
	* Trick to access this objects members from the Call() function.
	* @private
	*/
	var self = this;
	// When the obj param is a string it is the function name.
	if (typeof obj != 'string')
	{
		// Object on which the function Func is called.
		this.Object = (typeof func == 'string') ? obj : obj.o;
		// Name of the function.
		this.Func = (typeof func == 'string') ? func : obj.f;
		// Create function which is called by the setTimeout() or addEventListner()
		this.Call = function(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)
			{return eval("self.Object." + self.Func + "(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)");}
	}
	else
	{
		// Assign the function name.
		this.Func = obj;
		// Create function which is called by the setTimeout() or addEventListner()
		this.Call = function(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)
			{return eval(self.Func + "(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)");}
	}
}
//---------------------------------------------------------------------------
/**
* Retrieve the child by id starting from the passed node.
* @param HTMLElement Node in the HTML DOM.
* @param string 'id' attribute of the element.
* @returns HTMLElement
*/
function GetChildById(node, id)
{
	if (node.getAttribute)
		if (node.getAttribute('id') == id)
			return node;
	//
	for (var i = 0; i < node.childNodes.length; i++)
	{
		var c = GetChildById(node.childNodes[i], id);
		if (c != null)
			return c;
	}
	return null;
}
//---------------------------------------------------------------------------
/**
* Retrieve the first child of this node from the passed type.
* @param HTMLElement Node in the HTML DOM.
* @param string 'type' attribute of the element.
* @returns HTMLElement
*/
function GetChildByType(node, type)
{
	if (node.getAttribute)
		if (node.getAttribute('type') == type)
			return node;
	//
	for (var i = 0; i < node.childNodes.length; i++)
	{
		var c = GetChildByType(node.childNodes[i], type);
		if (c != null)
			return c;
	}
	return null;
}
//---------------------------------------------------------------------------
/**
* Focusses the first visible none hidden form input.
* @param HTMLFormElement Form element.
* @returns HTMLInputElement
*/
function FormFirstInputFocus(form)
{
	// When a string lookup the form name.
	if (typeof form == 'string')
		form = document.forms.namedItem(form);
	// When not valid bail out.
	if (!form)
		return null;
	//
	for (var i = 0; i < form.length; i++)
	if (!form[i].disabled && form[i].type != 'hidden' &&
		RegExpMatch(form[i].type, '/text|radio|select|checkbox/i'))
	{
		form[i].focus();
		return form[i];
	}
	//
	return null;
}
//---------------------------------------------------------------------------
/**
* Get the parent of the specified tag.
* @param HTMLElement Node in the HTML DOM.
* @param string tagName of the element.
* @returns HTMLElement
*/
function GetParentByTag(node, tagname)
{
	if (!node)
		return null;
	node = node.parentNode;
	while (node && typeof node != 'undefined')
	{
		//DebugOut("Probing (" + typeof node + ")TAG: " + node.tagName + ' ID:' + node.id);
		if (node.tagName && node.tagName.toUpperCase() != tagname.toUpperCase())
			node = node.parentNode;
		else
			return node;
	}
	return null;
}
//---------------------------------------------------------------------------
/**
* Retrieve the first child of this node from the passed type.
* @param HTMLElement Node in the HTML DOM.
* @param string tagName of the element.
* @param integer Index of the child element.
* @returns HTMLElement
*/
function GetChildByTag(node, tagname, index)
{
	// When idex is not passed assign zero.
	if (typeof index == 'undefined')
		index = 0;
	// Iterate throgh the elements child nodes.
	for (var i = 0; i < node.childNodes.length; i++)
		// If a child node is of element.
		if (node.childNodes[i].tagName && node.childNodes[i].tagName.toUpperCase() == tagname.toUpperCase())
			// Decrement the index until it is zero and return the child.
			if (!index--)
				return node.childNodes[i];
	//
	return null;
}
//---------------------------------------------------------------------------
/**
* Function to create an xml http object and returns it.
* @returns XMLHttpRequest
*/
function CreateXmlHttpObject()
{
	var xmlhttp;
	// This below is no comment !!!!!!
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	try
	{
		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 	}
	catch (e)
	{
		try
		{
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (E)
		{
		 xmlhttp=false;
		}
 	}
	@else
	xmlhttp = false
	@end @*/

	if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
	{
		try
		{
			xmlhttp = new XMLHttpRequest();
		}
		catch (e)
		{
			xmlhttp = null;
		}
	}
	//
	if (!xmlhttp && window.createRequest)
	{
		try
		{
			xmlhttp = window.createRequest();
		}
		catch (e)
		{
			xmlhttp = null;
		}
	}
	return xmlhttp;
}
/**
* Checks if a XmlHttp is available for the browser.
*/
function XmlHttpAvailable()
{
	var xmlhttp = CreateXmlHttpObject();
	if (xmlhttp == false)
	{
		document.write("Your browser doesn't support XML HTTP objects. Please enable javascript, or find a decent browser.");
		return false;
	}
	return true;
}
//---------------------------------------------------------------------------
/**
* Returns the content of a post request or false on failure.
* When a callback function has n=been passed the call is asynchrone and an
* object is returned. This object has a Cancel() function to cancel a
* pending call. It returns true whe a pending call was in deed cancelled.
* @param string url
* @param string to_post
* @param function callback
* @return boolean
*/
function GetByHttpPost(url, to_post, callback)
{
	var o =
	{
		// Determine if a function or closure was passed.
		async: (callback ? true : false) && typeof callback == 'function',
		url: url,
		to_post: to_post,
		callback: callback,
		result: false,
		counter: 10000,
		timer: null,
		xmlhttp: new CreateXmlHttpObject(),
		// Returns true when a pending call was cancelled.
		Cancel: (function()
		{
			clearTimeout(this.timer);
			this.xmlhttp = null;
			return !this.result;
		})
	};
	// Check if request object is available.
	if (!o.xmlhttp)
		return false;
	// Intercept exception.
	try
	{
		// Initialize.
		o.xmlhttp.open(o.to_post ? 'POST' : 'GET', o.url, o.async);
		// Only add headers when posting.
		if (o.to_post)
		{
			// Set the request headers.
		  o.xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
		  o.xmlhttp.setRequestHeader('Connection', 'close');
		  o.xmlhttp.setRequestHeader('Content-length', o.to_post ? o.to_post.length : 0);
		}
		// Post the actual data
		o.xmlhttp.send(o.to_post);
	}
	catch(e)
	{
		DebugOut(e.message + "\nException: " + e.name + "\nURI: " + o.url);
		return false;
	}
	// Syncronous request.
	if (!o.async)
		// Return the infor from the HTTP request.
		return o.xmlhttp.responseText;
	//
	function CheckReady()
	{
		// Clear the timer when it stil exists.
		if (o.timer)
		{
			clearTimeout(o.timer);
			o.timer = null;
		}
		// When cancelled.
		if (o.xmlhttp == null)
			return;
		//
		if (o.xmlhttp.readyState == 4 || o.counter-- < 0)
		{
			o.status = o.counter > 0;
			if (o.callback)
				o.callback(o.xmlhttp.responseText, o);
			o.xmlhttp = null;
		}
		else
			o.timer = window.setTimeout(CheckReady, 10);
	};
	// Assign handler any way.
	o.xmlhttp.onreadystatechange = CheckReady;
	// Check if ready info not schedule a call to check it until timed out.
	CheckReady();
	// Return object.
	return o;
}
//---------------------------------------------------------------------------
/**
* Returns true when the passed string buffer contains a
* @param string Buffer containing partial HTML
* @param string url
* @param string post
* @return object (Raw, Result, Context)
*/
function ContainsHtmlDocType(buf, notify, url)
{
	// When not a string return false.
	if (typeof buf != 'string')
		return false;
	// Check for an error by checking the HTML start tag.
	if (buf.indexOf("<!DOCTYPE ", 0) >= 0 || buf.substr(0, 1) == '<')
	{
		if (notify)
		{
			if (!url)	url = '???';
			DebugOut("Unexpected HTML in result in call to: '" + url + "'!\n\n" + buf.substr(0, 400), 1);
		}
		return true;
	}
	return false;
}
//---------------------------------------------------------------------------
/**
* Returns a resulting object of a HTTP call.
* @param string url
* @param string post
* @return object (Raw, Result, Context)
*/
function GetResultByHttpPost(url, post)
{
	// Create an empty object.
	var retval = new function()
	{
		this.Raw = null;
		this.Result = null;
		this.Context = null
	};
	// Get the raw result using a post.
	retval.Raw = GetByHttpPost(url, post);
	// Check for an error by looking for the DOCTYPE start tag.
	if (ContainsHtmlDocType(retval.Raw, true))
		return null;
	// Split the result from the message.
	var result = retval.Raw.split("\n\n");
	// If the result is empty signal by not returning null.
	if (result.length == 0)
		return null;
	// Assign the result value.
	retval.Result = result.shift().split("\n");
	// When a single result return only this one but not an array.
	if (retval.Result.length == 1)
		retval.Result = retval.Result[0];
	// Assemble the context of the result.
	if (result.length >= 1)
		retval.Context = result.join("\n\n");
	else
	{
		retval.Context = '';
		DebugOut(retval.Raw);
	}
	//
	return retval;
}
//---------------------------------------------------------------------------
/**
* Sets the innerHTML of an element.
* @param string/HTMLElement ID of the elemen object itself can be passed.
* @param string HTML content.
* @returns boolean
*/
function SetInnerHtml(elem_id, content)
{
	if (typeof elem_id == 'string')
		elem_id = document.getElementById(elem_id);
	if (typeof elem_id == 'object')
	{
		elem_id.innerHTML = content;
		return true;
	}
	DebugOut("Element '" + elem + "' could not be found!", true);
	return false;
}
//---------------------------------------------------------------------------
/**
* Posts parameters to the passed url and sets the inner html of an element.
* @param string/HTMLElement ID of the elemen object itself can be passed.
* @param string URL to the content.
* @param string Parameters to post.
* @returns boolean
*/
function SetInnerHtmlByHttpPost(elem_id, url, to_post)
{
	if (BrowserDetect.browser != 'Explorer')
	{
		// Element is removed when SetInnerHtml is called.
		var elem = WaitOverlay.CreateElement(elem_id);
		var html = GetByHttpPost(url, to_post);
		WaitOverlay.RemoveElement(elem);
		if (ContainsHtmlDocType(html, true, url))
			return false;
		return SetInnerHtml(elem_id, html);
	}
	// Regular for IE no fancy wait overlay.
	return SetInnerHtml(elem_id, GetByHttpPost(url, to_post));
}
//---------------------------------------------------------------------------
/**
* Replaces the current document using the returned content of the post.
* @param string URL to the content.
* @param string Parameters to post.
* @returns void
*/
function SetDocumentByHttpPost(url, to_post)
{
	var content = GetByHttpPost(url, to_post);
	var newdoc = document.open("text/html", "replace");
	//newdoc.write("<!-- Generated from within other -->");
	newdoc.write(content);
	newdoc.close();
}
//---------------------------------------------------------------------------
/**
* URL-encodes string
* @param string
* @returns string
*/
function RawUrlEncode(str)
{
	var hash_map = {}, unicodeStr='', hexEscStr='';
	var ret = str.toString();
	var replacer = function (search, replace, str)
	{
		var tmp_arr = [];
		tmp_arr = str.split(search);
		return tmp_arr.join(replace);
	};
	// The hash_map is identical to the one in urldecode.
	hash_map["'"] = '%27';
	hash_map['('] = '%28';
	hash_map[')'] = '%29';
	hash_map['*'] = '%2A';
	hash_map['~'] = '%7E';
	hash_map['!'] = '%21';
	hash_map['\u20AC'] = '%80';
	hash_map['\u0081'] = '%81';
	hash_map['\u201A'] = '%82';
	hash_map['\u0192'] = '%83';
	hash_map['\u201E'] = '%84';
	hash_map['\u2026'] = '%85';
	hash_map['\u2020'] = '%86';
	hash_map['\u2021'] = '%87';
	hash_map['\u02C6'] = '%88';
	hash_map['\u2030'] = '%89';
	hash_map['\u0160'] = '%8A';
	hash_map['\u2039'] = '%8B';
	hash_map['\u0152'] = '%8C';
	hash_map['\u008D'] = '%8D';
	hash_map['\u017D'] = '%8E';
	hash_map['\u008F'] = '%8F';
	hash_map['\u0090'] = '%90';
	hash_map['\u2018'] = '%91';
	hash_map['\u2019'] = '%92';
	hash_map['\u201C'] = '%93';
	hash_map['\u201D'] = '%94';
	hash_map['\u2022'] = '%95';
	hash_map['\u2013'] = '%96';
	hash_map['\u2014'] = '%97';
	hash_map['\u02DC'] = '%98';
	hash_map['\u2122'] = '%99';
	hash_map['\u0161'] = '%9A';
	hash_map['\u203A'] = '%9B';
	hash_map['\u0153'] = '%9C';
	hash_map['\u009D'] = '%9D';
	hash_map['\u017E'] = '%9E';
	hash_map['\u0178'] = '%9F';
	// Begin with encodeURIComponent, which most resembles PHP's encoding functions
	ret = encodeURIComponent(ret);
	for (unicodeStr in hash_map)
	{
		hexEscStr = hash_map[unicodeStr];
		ret = replacer(unicodeStr, hexEscStr, ret); // Custom replace. No regexing
	}
	// Uppercase for full PHP compatibility
	return ret.replace(/(\%([a-z0-9]{2}))/g, function (full, m1, m2){return "%"+m2.toUpperCase();});
}
//---------------------------------------------------------------------------
/**
* Escapes all charaters excluding the '+' sign.
* @param string
* @returns string
*/
function EscapeUrl(s)
{
	if (typeof(s) != 'string')
		return '';
	s = s.split('+');
	for (var i in s)
		s[i] = RawUrlEncode(s[i]);
	return s.join('%2B');
}
//---------------------------------------------------------------------------
/**
* Unescapes characters into HTML entities.
* @param string
* @returns string
*/
function UnescapeHtml(html)
{
	var htmlNode = document.createElement('div');
	htmlNode.innerHTML = html;
	if(htmlNode.innerText)
		return htmlNode.innerText; // IE
	return htmlNode.textContent; // FF
}
//---------------------------------------------------------------------------
/**
* Builds a query string of the passed form.
* @param HTMLFormElement/string Form element or id string.
* @returns string
*/
function GetFormPostQuery(theform)
{
	// When a string is passed look the form name up.
	if (typeof(theform) == 'string')
	{
		var s = theform;
		theform = document.forms[theform];
		if (!theform)
			return DebugOut("Form '" + s + "' does not exist.", true);
	}
	//
	var qs = '';
	if (!theform)
		return DebugOut("Form does not exist.")
	else
	{
		// Cannot be replace using for ... in statement!!!!
		for (e = 0; e < theform.elements.length; e++)
		{
			// Only inputs with a type ar eallowed and so filtering fieldset tags.
			if (typeof theform.elements[e].type == 'undefined')
				continue;
			// Only inputs with the name set are allowed.
			if (theform.elements[e].name == '' || theform.elements[e].disabled)
				continue;
			// Only get the one radio that is checked.
			if (theform.elements[e].type == 'radio' && !theform.elements[e].checked)
				continue;
			// Only get the one radio that is checked.
			if (theform.elements[e].type == 'checkbox' && !theform.elements[e].checked)
				continue;
			// Append the name and encoded value to the returned query string.
			var name = theform.elements[e].name;
			qs += (qs == '') ? '' : '&';
			qs += name + '=' + RawUrlEncode(theform.elements[e].value);
		}
	}
	return qs;
}
//---------------------------------------------------------------------------
/**
* Function to limit the maximum amount of characters in a text area field.
* @param HTMLAreaElement
* @returns void
*/
function CheckTextAreaLength(self, lengthmax)
{
	if (self.value.length > lengthmax)
	{
		//alert("Maximum toegestane lengte van (" + lengthmax + ") is overschreden!");
		self.value = self.value.substr(0, lengthmax);
	}
}
//---------------------------------------------------------------------------
/**
/**
* HTML-Encode the supplied input
*
* Parameters:
*
* (String)  source    The text to be encoded.
*
* (boolean) display   The output is intended for display.
*
*                     If true:
*                     * Tabs will be expanded to the number of spaces
*                       indicated by the 'tabs' argument.
*                     * Line breaks will be converted to <br />.
*
*                     If false:
*                     * Tabs and linebreaks get turned into &#____;
*                       entities just like all other control characters.
*
* (integer) tabs      The number of spaces to expand tabs to.  (Ignored
*                     when the 'display' parameter evaluates to false.)
*
* v 0.3 - January 4, 2006
*
*
*/
function htmlEncode(source, display, tabs)
{
	function special(source)
	{
		var result = '';
		for (var i = 0; i < source.length; i++)
		{
			var c = source.charAt(i);
			if (c < ' ' || c > '~')
				c = '&#' + c.charCodeAt() + ';';
			result += c;
		}
		return result;
	}

	function format(source)
	{
		// Use only integer part of tabs, and default to 4
		tabs = (tabs >= 0) ? Math.floor(tabs) : 4;
		// split along line breaks
		var lines = source.split(/\r\n|\r|\n/);
		// expand tabs
		for (var i = 0; i < lines.length; i++)
		{
			var line = lines[i];
			var newLine = '';
			for (var p = 0; p < line.length; p++)
			{
				var c = line.charAt(p);
				if (c === '\t')
				{
					var spaces = tabs - (newLine.length % tabs);
					for (var s = 0; s < spaces; s++)
					{
						newLine += ' ';
					}
				}
				else
				{
					newLine += c;
				}
			}
			// If a line starts or ends with a space, it evaporates in html
			// unless it's an nbsp.
			newLine = newLine.replace(/(^ )|( $)/g, '&nbsp;');
			lines[i] = newLine;
		}
		// re-join lines
		var result = lines.join('<br />')
		if (BrowserDetect.browser == 'Explorer')
			result += '<br />';
		// break up contiguous blocks of spaces with non-breaking spaces
		result = result.replace(/  /g, ' &nbsp;');
		// tada!
		return result;
	}
	// Bailout when the source parameter is not a string.
	if (typeof source != 'string')
		return '';
	//
	var result = source;
	// ampersands (&)
	result = result.replace(/\&/g,'&amp;');
	// less-thans (<)
	result = result.replace(/\</g,'&lt;');
	// greater-thans (>)
	result = result.replace(/\>/g,'&gt;');
	//
	if (display)
	{
		// format for display
		result = format(result);
	}
	else
	{
		// Replace quotes if it isn't for display,
		// since it's probably going in an html attribute.
		result = result.replace(new RegExp('"','g'), '&quot;');
	}
	// special characters
	result = special(result);
	// tada!
	return result;
}
//---------------------------------------------------------------------------
/**
* Object handling the resizing of the background image of the given element.
* @constructor
* @param string/HTMLElement ID of the elemen object itself can be passed.
* @param function
* @param number Pixel width.
* @param number Pixel height.
* @param string Optional options passed to the funciton.
*/
function TBackgroundImageResizer(elem_id, urlfunc, width, height, options)
{
	if (typeof elem_id != 'string')
	{
		alert('TBackgroundBgImageResizer(): Needs an element ID!');
	}
	/**
	* Assign the function.
	* @type function
	*/
	this.UrlFunc = urlfunc;
	/**
	* @type string
	*/
	this.Options = options;
	/**
	* Holds the pixel height of the image.
	* @type number
	*/
	this.Height = height;
	/**
	* Holds the pixel width of the image.
	* @type number
	*/
	this.Width = width;
	/**
	* Holds the timer index.
	* @type integer
	*/
	this.Timer = null;
	/**
	* Holds the element having the background image.
	* @type string
	*/
	this.ElemId = elem_id;
	/**
	* Handle the windows resize event.
	* @param event Build-in event class.
	*/
	this.EvResize = function(ev)
	{
		// If a timeout is pending clear it.
		if (this.Timer != null)
		{
			clearTimeout(this.Timer);
			this.Timer = null;
		}
		this.Resize();
	}
	/**
	* Function call resize manually.
	* @public
	* @returns void
	*/
	this.Resize = function()
	{
		var elem = document.getElementById(this.ElemId);
		if (this.Height)
		{
			if (typeof this.Height == 'number')
				this.Height = '' + this.Height + 'px';
			elem.style.height = this.Height;
		}
		elem.style.backgroundRepeat = 'no-repeat';
		elem.style.padding = '0px';
		this.Timer = window.setTimeout(new Closure(this, 'DoResize').Call, 300);
	}
	/**
	* Private function.
	* @returns void
	*/
	this.DoResize = function()
	{
		var elem = document.getElementById(this.ElemId);
		if (elem)
		{
			// Only when the tab is visible update the image.
			if (IsVisible(elem) && IsVisible(elem.parentNode))
			{
				// Retrieve the url for the image.
				var url = this.UrlFunc(this.ElemId, elem.clientWidth, elem.clientHeight, this.Options);
				// Assign the url for the image.
				elem.style.backgroundImage = "url('" + url + "')";
			}
		}
	}
	// Attach event handler using closure for resizing this image.
	AddEvent(window, 'resize', new Closure(this, 'EvResize').Call);
}
//---------------------------------------------------------------------------
/**
* @class Reduces the amount events like resize in the internet explorer.
* @constructor
* @param function Callback function
* @param integer Defaults to 100
*/
function TEventReducer(callback, time)
{
	// When time param was not passed default it to 100 ms.
	if (typeof time == 'undefined') time = 100;
	/*
	* Trick to access this objects members from the Call() function.
	* @private
	*/
	var self = this;
	/**
	* Store the passed params.
	* @private
	* @type integer
	*/
	this.Time = time;
	/**
	* Store the passed params.
	* @private
	* @type integer
	*/
	this.Callback = callback;
	/**
	* Holds the timer index.
	* @type integer
	*/
	this.Timer = null;
	/**
	* Handles the event call and sets or resets a timer.
	* @param event Build-in event class.
	* @public
	*/
	this.Call = function (ev)
	{
		// Store the event info.
		self.Event = ev;
		// If a timeout is pending clear it.
		if (self.Timer != null)
		{
			clearTimeout(self.Timer);
			self.Timer = null;
		}
		// Set a new timer event.
		//this.TheClosure.Call
		self.Timer = window.setTimeout((function(){self.Callback(self.Event)}), self.Time);
	}
	//
	return this;
}
//---------------------------------------------------------------------------
/**
* @class Class for handling validation of input values.
* @type Validator
* @example
* // Example to reimplement a valdition handler.
* // Make a copy of the previous handler.
* Validator.Validate_regexp_old = Validator.Validate_regexp;
* // Overload the original function.
* Validator.Validate_regexp = function (input, required, val_opts)
* {
*   this.Validate_regexp_old(input, required, val_opts);
* };
*/
var Validator =
{
	/**
	* Input which is actually visible when a hidden one is evaluated.
	* @constructs
	*/
	VisibleInput: null,
	/**
	* Element which needs to be colored too.
	* @public
	* @type HTMLElement
	*/
	ColorElem: null,
	/**
	* Submits a form by simulating a click of a submit button even when hidden.
	*/
	SubmitForm: function (theform)
	{
		var submit_elem = null;
		//
		for (var inp in theform.elements)
		{
			if (theform.elements[inp] && theform.elements[inp].type == 'submit')
			{
				submit_elem = theform.elements[inp];
				break;
			}
		}
		// When an element was found.
		if (submit_elem)
		{
			// Store current disabled state.
			var disabled = submit_elem.disabled = false;
			submit_elem.click();
			// Restore disabled state.
			submit_elem.disabled = disabled;
		}
		else
			DebugOut("Validator.SubmitForm(): Could not find \'submit\' input in form '" +
				 theform.name + "'!", 1);
	},
	/**
	* Returns true when the form inputs are validated succesfully.
	*/
	CheckForm: function (theform, notify)
	{
		var form  = null;
		// See if the name of the form was passed.
		if (typeof(theform) == 'string')
			form = document.forms[theform];
		// Asume the object was passed.
		else if (typeof(theform) == 'object')
			form = theform;
		// Check if
		if (form == null)
		{
			DebugOut("Validator.CheckForm('" + theform + "'): The passed form does not exist.", true);
			return false;
		}
		var retval = true;
		var msg = '';
		for (var i = 0; i < form.elements.length; i++)
		{
			if (typeof(form.elements[i]) == 'object')
			{
				if (form.elements[i].getAttribute('validate') != null)
				{
					if (this.CheckInput(form.elements[i]) == false)
					{
						retval = false;
						msg += "\n\t(" + form.elements[i].name + '): ' + this.VisibleInput.title;
					}
				}
			}
		}
		if (!retval && notify)
			DebugOut("Input error(s):" + msg, true);
		return retval;
	}
	,
	CheckInput: function(input, focused)
	{
		// Initialize the data member for this call.
		this.VisibleInput = input;
		this.ColorElem = null;
		// Check if the uinput is required.
		var required = input.getAttribute('required') != null;
		// See if this input needs validated or not depending on the attribute.
		var validate = input.getAttribute('validate');
		// When no validation filter has been set use the default one.
		if (validate == null || validate.length == 0)
			validate = 'default:'
		var retval = true;
		// Split the attribute up in two values.
		if (validate.indexOf(':') == -1)
			var val_type = validate;
		else
			var val_type = validate.substring(0, validate.indexOf(':'));
		var val_opts = validate.substring(validate.indexOf(':') + 1, validate.length);
		// Look for a handler for the button clicked.
		var func = 'this.Validate_' + val_type;
		if (eval('typeof(' + func + ')') == 'function')
			retval = (eval(func + '(input, required, val_opts)'))
		else
			DebugOut("Member function 'Validator.Validate_" + val_type + "' does not exist.", true);
		//
		var errcolbg = this.VisibleInput.getAttribute('errcolbg');
		if (errcolbg == null)	errcolbg = '#FFC0C0';
		var errcolborder = this.VisibleInput.getAttribute('errcolborder');
		if (errcolborder == null)	errcolborder = '#C000C0';
		// Set colors depending on the validation.
		if (retval || focused)
		{
			this.VisibleInput.style.backgroundColor = '';
			this.VisibleInput.style.borderColor = '';
			if (this.ColorElem)
			{
				this.ColorElem.style.backgroundColor = '';
				this.ColorElem.style.borderColor = '';
			}
		}
		else
		{
			this.VisibleInput.style.backgroundColor = errcolbg;
			this.VisibleInput.style.borderColor = errcolborder;
			if (this.ColorElem)
			{
				this.ColorElem.style.backgroundColor = errcolbg;
				this.ColorElem.style.borderColor = errcolborder;
			}
		}
		//
		//DebugOut("Validated [" + retval + "] field ' " + input.name + "' with type '" + val_type + "' and options.'" + val_opts + "'");
		return retval;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_default: function (input, required, val_opts)
	{
		// When this value is required blank is not accepted.
		if (required && input.value == '')
			return false;
		// Accept the input.
		return true;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_regexp: function (input, required, val_opts)
	{
		// When this value is required blank is not accepted.
		if (required && input.value == '')
			return false;
		// When not required an the value is empty it is accepted.
		if (!required && input.value == '')
			return true;
		DebugOut("Options: " + val_opts);
		return RegExpMatch(input.value, val_opts);
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_range_int: function (input, required, val_opts)
	{
		var value = input.value.trim();
		// When this value is required blank is not accepted.
		if (required && value == '')
			return false;
		// When not required and the value is not empty.
		if (!required && !value.length)
			return value;
		// Convert string to integer value.
		var value = parseInt(value);
		// Check if a integer was parsed correctly.
		if (('' + value) == 'NaN')
			return false;
		// Separate the options.
		var opts = val_opts.split(',');
		var minval = parseInt(opts[0]);
		var maxval  = parseInt(opts[1])
		// Update the input value with a clipped value when configured.
		if (parseInt(opts[2]))
			input.value = Math.min(Math.max(minval, value), maxval);;
		// When not required and the value is empty it is accepted.
		if (value >= parseInt(opts[0]) &&  value <= parseInt(opts[1]))
			return true;
		//
		return false;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_range_float: function (input, required, val_opts)
	{
		var value = input.value.trim();
		// When this value is required blank is not accepted.
		if (required && value == '')
			return false;
		// When not required and the value is not empty.
		if (!required && !value.length)
			return value;
		// Convert string to floating point value.
		var value = parseFloat(value);
		// Check if a floating point was parsed correctly.
		if (('' + value) == 'NaN')
			return false;
		// Separate the options.
		var opts = val_opts.split(',');
		var minval = parseFloat(opts[0]);
		var maxval  = parseFloat(opts[1])
		// Update the input value with a clipped value when configured.
		if (parseInt(opts[2]))
			input.value = Math.min(Math.max(minval, value), maxval);;
		// When not required and the value is empty it is accepted.
		if (value >= parseInt(opts[0]) &&  value <= parseInt(opts[1]))
			return true;
		//
		return false;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_select: function (input, required, val_opts)
	{
		// When the internet explorer is active the color must also be changed of the parentNode.
		if (input.getAttribute('usediv') != null)
			this.ColorElem = input.parentNode;
		// When this value is required blank is not accepted.
		if (required);
			return input.value != '';
		return true;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_radio: function (input, required, val_opts)
	{
		var selected = false;
		// Get the last element.
		var last_elem = null;
		for( var i=0; i < input.form.elements.length; i++)
		{
			var elem = input.form.elements[i];
			//
			if (elem.type == 'radio' && input.name == elem.name)
			{
				last_elem = elem;
				// If an input is selected set the local variable.
				if (elem.checked)
					selected = true;
			}
		}
		// Only act on the last radio element.
		if (last_elem == null || last_elem != input)
			return true;
		// Set the color element which is the parent.
		if (input.getAttribute('usediv') != null)
		{
			this.ColorElem = input.parentNode;
			while (this.ColorElem.getAttribute('usediv') != null)
				this.ColorElem = this.ColorElem.parentNode;
		}
		// When this value is required blank is not accepted.
		if (required)
			return selected;
		return true;
	},
	/*
	* Returns true when a passed value checks out.
	*/
	Validate_selectdlg: function (input, required, val_opts)
	{
		if (input.type == 'hidden')
			this.VisibleInput = GetChildByTag(this.VisibleInput.parentNode, 'INPUT');
		// When this value is required blank is not accepted.
		if (required);
			return input.value != '';
		return true;
	},
	/*
	* Returns true when a passed element is validated bank account number.
	*/
	Validate_banknum: function(input, required, val_opts)
	{
		// Check if number is a valid 7 digit 'Postbank' giro number (optionally prefixed with 'P'),
		// or more general 13 digit bank-number. Adds 'P' to 7 digit numbers.
		var text = input.value;
		if (!text.length)
			return !required;
		// Keep only the numbers.
		text = text.replace(/[^0-9]/gi,'');
		// Postbank.
		if (text.length == 7)
	//	if (text.length >= 3 && text.length <= 7)
		{
			input.value = 'P' + text;
			return true;
		}
		input.value = text;
		// Do the 11-test.
		if (text.length != 9)
		{
			DebugOut("Banknnumber length error.");
			return false;
		}
		Sum = 0;
		Factor = 9;
		for (i=0; i < 9; i++)
		{
			Digit = parseInt(text.substring(i,i+1));
			Sum += parseInt(Factor*Digit);
			Factor = Factor-1;
		}
		if ((Sum % 11) != 0)
		{
			DebugOut("Banknumber 11-check error!");
			return false;
		}
		return true;
	}
}
//---------------------------------------------------------------------------
/**
* Imports/Replaces a javascript dynamically. Only functions and variables
* with a same name in the script are replaced.
* Beware a new decalred or replaced function can only be called after control
* is relinguised to the browser. IE and FF differ a bit but this rule
* applies to both. Use setTimeOut function to make a call in the same script.
* @param string Relative or absolute url to the script file.
* @param string Tag ID of the script in the header.
* @returns string
*/
function javascript_import(url, id)
{
	var script = null;
	var replace_script = null;
	// Find the element ID when defined.
	if (typeof id != 'undefined')
		replace_script = document.getElementById(id);
	// When an url is specified create a new or replace the script element.
	if (url)
	{
		// Create a element when not found.
		var script = document.createElement('script');
		script.type = 'text/javascript';
		//script.src = url;
		// Set the ID when exists.
		if (typeof id != 'undefined')
			script.id = id;
	}
	//
	if (script)
	{
		// When the to be replaced script exists.
		if (replace_script)
		{
			document.getElementsByTagName('head')[0].replaceChild(script, replace_script);
			// Assigning script url here will trigger executing the script.
			script.src = url;
		}
		else
		{
			document.getElementsByTagName('head')[0].appendChild(script);
			// Assigning script url here will trigger executing the script.
			script.src = url;
		}
	}
	else
	{
		if (replace_script)
		{
			document.getElementsByTagName('head')[0].removeChild(replace_script);
		}
	}
	//
	return script;
}
//---------------------------------------------------------------------------
/**
* Returns the base URL of the passed full URL string.
* When left empty the document location is used for passing the full URL.
* @param string (optional)
* @returns string
*/
function get_base_url(href)
{
	var s, p;
	if (typeof href == 'string')
		s = href;
	else
		s = location.href;
	// Look for the start of parameters if it is there.
	p = s.indexOf('?');
	// When found strip the parameters.
	if (p >= 0)
		s = s.substring(0, p);
	// Find the last
	p = s.lastIndexOf('/');
	// When found strip the parameters.
	if (p >= 0)
		s = s.substring(0, p + 1)
	//
	return s;
}
//---------------------------------------------------------------------------
/**
* Imports/Replaces a link tag dynamically. Only functions and variables
* @param string url Relative or absolute url to the link file.
* @param string id Tag ID of the link in the header.
* @returns void
*/
function stylesheet_import(url, id)
{
	var link = null;
	var replace_link = null;
	// Find the element ID when defined.
	if (typeof id != 'undefined')
		replace_link = document.getElementById(id);
	// When an url is specified create a new or replacement link element.
	if (url)
	{
		// Create a element when not found.
		var link = document.createElement('link');
		link.type = 'text/css';
		link.rel = 'stylesheet';
		link.media = 'screen';
		// Set the ID when exists.
		if (typeof id != 'undefined')
			link.id = id;
	}
	//
	if (link)
	{
		// When the to be replaced link exists.
		if (replace_link)
		{
			document.getElementsByTagName('head')[0].replaceChild(link, replace_link);
			// Assigning link url here will trigger reading the link.
			link.href = url;
		}
		else
		{
			document.getElementsByTagName('head')[0].appendChild(link);
			// Assigning link url here will trigger reading the link.
			link.href = url;
		}
	}
	else
	{
		if (replace_link)
		{
			document.getElementsByTagName('head')[0].removeChild(replace_link);
		}
	}
	//
	return link;
}
//---------------------------------------------------------------------------
/**
* Tells if a key code is to ignore.
* @param event Buit-In key event.
* @returns boolean
*/
function IsKeyEventToIgnore(ev)
{
	return ev.keyCode >= 16 && ev.keyCode <= 18;
}
//---------------------------------------------------------------------------
/**
* Returns the name of the key so it can be used in a case statment.
* @param event Buit-In key event.
* @returns string
*/
function GetKeyName(ev)
{
	var s = '';
	//
	if (ev.shiftKey) s += 'S+';
	if (ev.ctrlKey) s += 'C+';
	//if (altKey) s += 'A+';
	//
	switch(ev.keyCode)
	{
		case 8: s += 'Backspace';break;
		case 9: s += 'Tab';break;
		case 13: s += 'Enter';break;
		case 16: s += 'Shift';break;
		case 17: s += 'Ctrl';break;
		case 18: s += 'Alt';break;
		case 19: s += 'Pause';break;
		case 27: s += "Esc";break;
		case 33: s += "PgUp";break;
		case 34: s += "PgDown";break;
		case 35: s += "End";break;
		case 36: s += "Home";break;sss
		case 37: s += "Left";break;
		case 38: s += "Up";break;
		case 39: s += "Right";break;
		case 40: s += "Down";break;
		case 45: s += "Insert";break;
		case 46: s += "Delete";break;
		case 112: s += "F1";break;
		case 113: s += "F2";break;
		case 114: s += "F3";break;
		case 115: s += "F4";break;
		case 116: s += "F5";break;
		case 117: s += "F6";break;
		case 118: s += "F7";break;
		case 119: s += "F8";break;
		case 120: s += "F9";break;
		case 121: s += "F10";break;
		case 122: s += "F11";break;
		case 123: s += "F12";break;
		default:
			{
				if (BrowserDetect.browser == 'Explorer')
				{
					if (ev.keyCode)
					{
						if (ev.keyCode >= 32 && ev.keyCode <= 127)
							s += String.fromCharCode(ev.keyCode).toUpperCase();
						else
							s += ev.keyCode;
					}
					else
						s += ev.keyCode;
				}
				else
				{
					if (ev.keyCode)
					{
						if (ev.keyCode >= 32 && ev.keyCode <= 127)
							s += String.fromCharCode(ev.keyCode).toUpperCase();
						else
							s += ev.keyCode;
					}
					else
						s += String.fromCharCode(ev.charCode).toUpperCase();
				}
			}
			break;
	}
	return s;
}
//---------------------------------------------------------------------------
/*
* Function to control the tabs of the tab control.
* @param HTMLElement
* @return boolean
*/
function ActivateTabPage(self)
{
	var selected = -1;
	// Get all the list items in a list.
	var elems = self.parentNode.parentNode.getElementsByTagName('LI');
	for (var i = 0; i < elems.length; i++)
	{
		// Deactivate the tab list item.
		elems.item(i).className = '';
		// When the item is the one clicked make it active.
		if (elems.item(i) == self.parentNode)
		{
			selected = i;
			self.parentNode.className = 'tabctrl_active';
			self.blur();
		}
	}
	var i = 0;
	if (selected < 0)
		return false;
	// Iterate through all the <div>'s contained by the parent of the <ul> tag.
	var nodes = self.parentNode.parentNode.parentNode.childNodes;
	for (var j = 0; j < nodes.length; j++)
		if (nodes.item(j).tagName == 'DIV')
			nodes.item(j).className = (i++ == selected) ? 'tabctrl_tab_active' : 'tabctrl_tab';
	return true;
}
//---------------------------------------------------------------------------
/**
* Installs a key event handler.
* @pram function Callback function.
*/
function AddKeyEventHandler(func)
{
	AddEvent(document, 'keydown', func);
}
//---------------------------------------------------------------------------
/**
* Stops propagation of the event.
* @param event Build-In event class.
* @returns boolean
*/
function StopPropagation(ev)
{
	// When event is handled stop further processing.
	if (BrowserDetect.browser == 'Explorer')
		ev.returnValue = false;
	else if (ev.preventDefault)
		ev.preventDefault();
	else if (ev.stopPropagation)
		ev.stopPropagation();
	// Return false by default so this function can be used in a return of a function for IE.
	return false;
}
//---------------------------------------------------------------------------
/**
* Evaluates an event handler
* Make an assigned event handler be called by evaluting the attached code.
* @param fucntion Event handler like 'elem.onclick'.
* @returns void
*/
function EvalEventHandler(handler)
{
	// Make the handler a string type.
	handler = '' + handler;
	var i = handler.indexOf('{');
	if (i >= 0)
		eval(handler.substring(i, handler.length));
}
//---------------------------------------------------------------------------
/**
* Returns true when a string is validated.
* the expression can be in the form i.e. /^[a-z]*$/i or ^[a-zA-Z]*$
* @param string Haystack.
* @param string Regular expression.
* @returns boolean
*/
function RegExpMatch(s, exp)
{
	var opts = '';
	// Check for delimiters and remove them preserving the options.
	if (exp.charAt(0) == '/')
	{
		var i = exp.lastIndexOf('/');
	 	opts = exp.substring(i + 1, exp.length);
	 	exp = exp.substring(1, i);
	}
	try
	{
		var regexp = new RegExp(exp, opts);
		var res = regexp.exec(s);
		return res ? (res.length > 0) : false;
	}
	catch (e)
	{
		DebugOut('Regular expression error "' + exp + '" ' + e + '!', 1);
		return false;
	}
}
//---------------------------------------------------------------------------
/**
* Returns the property of the current style of an element.
* Only for none IE browsers.
*/
function GetStyleProperty(elem, prop)
{
	if (BrowserDetect.browser == 'Explorer')
	{
		var path = prop.split('-');
		// Make a IE version CSS property name.
		for (var i = 1; i < path.length; i++)
		{
    	var f = path[i].charAt(0).toUpperCase();
    	path[i] = f + path[i].substr(1, path[i].length-1);
		}
		return elem.currentStyle[path.join('')];
	}
	//return document.defaultView.
	return window.getComputedStyle(elem, null).getPropertyValue(prop);
}
//---------------------------------------------------------------------------
/**
* Shows the generated source of the current window in a new browser.
*/
function ShowGeneratedSource(target, width, height)
{
	var win = OpenWindow('', target, width, height)
	win.document.write('<html><head><title>Generated Source</title>');
	win.document.write('<head/><body style="font-family:monospace;font-size:10pt">');
	win.document.write(htmlEncode(window.document.body.outerHTML, true, 2));
	win.document.write('</body></html>');
}
//---------------------------------------------------------------------------
/**
* When IE this function can return the clipboard content.
* @return string
*/
function GetClipboard()
{
	if ('undefined' != typeof(document.execCommand))
	{
		var elem = document.getElementById('__cliptext');
		if (!elem)
		{
			elem = document.createElement('textarea');
			elem.id = '__cliptext';
			elem.style.position = 'absolute';
			elem.style.left = '-100px'
			elem.style.height = '1px'
			elem.style.width = '1px'
			document.getElementsByTagName('body')[0].appendChild(elem);
		}
		if (elem.createTextRange)
		{
			elem.createTextRange().execCommand('paste');
			return elem.value;
		}
	}
	return null;
}
//---------------------------------------------------------------------------
/**
* Return the browser language as a language ISO code like en, nl or de.
* @returns string
*/
function GetBrowserLanguage()
{
	if (BrowserDetect.browser == 'Explorer')
	{
		//navigator.userLanguage;
		//navigator.systemLanguage;
		return navigator.browserLanguage;
	}
	else
	{
		return navigator.language;
	}
}
//---------------------------------------------------------------------------
/**
* @class Static class to hold static parameters.
* @type WaitOverlay
*/
var WaitOverlay =
{
	//----------------------------------------
	/**
	* Holds the style name.
	* @static
	* @type string
	*/
	StyleName: 'wait_overlay',
	/**
	* Holds the background style entry.
	* When null the back ground is not taken into the style.
	* @static
	* @type string
	*/
	Background: "center top repeat-y url('images/wait.gif') #FFF",
	/**
	* Holds the background color.
	* When null the border is not taken into the style.
	* @static
	* @type string
	*/
	Border: "1px dotted darkgray",
	/**
	* Holds opacity of the element.
	* When null the opacity is not taken into the style.
	* @static
	* @type float
	*/
	Opacity: 0.6,
	/**
	* Holds the style element when created and functions as a flag to create it only once.
	* @static
	* @type HTMLStyleElement
	*/
	StyleElement: null,
	//----------------------------------------
	/**
	* Creates the needed style element.
	* @private
	* @param string Stylename
	* @return string Style class name.
	*/
	CreateStyle: function()
	{
		// When the style element does not exist create one.
		if (!this.StyleElement)
		{
			// Assemble the rules for IE and FF.
			var rules = "";
			rules += "\n\tposition:absolute;";
			rules += "\n\tz-index:10000;";
			rules += "\n\ttop:0;";
			rules += "\n\tleft:0;";
			rules += "\n\twidth:99.5%;";
			rules += "\n\theight:99.5%;";
			rules += "\n\toverflow:hidden;";
			if (this.Background != null)
				rules += "\n\tbackground: " + this.Background + ";";
			if (this.Border != null)
				rules += "\n\tborder: " + this.Border + ";";
			if (this.Opacity != null)
			{
				rules += "\n\t-moz-opacity:" + this.Opacity + ";";
				rules += "\n\topacity:" + this.Opacity + ";";
			}
			//
			var style = null;
			var head = document.getElementsByTagName('head')[0];
			// Detect Explorer as the browser.
			if (BrowserDetect.browser == 'Explorer')
			{
				style = document.createStyleSheet();
				// Add rule for explorer because generates an warning in Firefox
				if (this.Opacity != null)
					rules += "\n\tfilter: alpha(opacity=" + (this.Opacity * 100) + ");";
				style.addRule("DIV." + this.StyleName, rules);
			}
			else if (BrowserDetect.browser == 'Chromium' || BrowserDetect.browser == 'Safari')
			{
				style = document.createElement('style');
				style.setAttribute('type', 'text/css');
				head.appendChild(style);
				document.styleSheets[document.styleSheets.length - 1].addRule("DIV." + this.StyleName, rules);
			}
			else
			{
				style = document.createElement('style');
				style.setAttribute('type', 'text/css');
				style.innerHTML = "DIV." + this.StyleName + "\n{\n" + rules + "\n}";
				head.appendChild(style);
			}
			this.StyleElement = style;
		}
		// Return the class name of the style.
		return this.StyleName;
	},
	//----------------------------------------
	/**
	* Removes the passed element from its parent child list.
	*/
	RemoveElement: function (elem)
	{
		if (elem && elem.parentNode)
		{
			// Restore the previous
			var style = elem.parentNode.getAttribute('__style_position');
			if (style != null)
				elem.parentNode.style.position = style;
			// Do the actual removal.
			elem.parentNode.removeChild(elem);
		}
	},
	//----------------------------------------
	/**
	* Creates a over lay div on the parent.
	* @param HTMLElement Parent node to attach the lement to.
	*/
	CreateElement: function(parent)
	{
		// Convert string to HTMLElement.
		if (typeof parent == 'string')
			parent = document.getElementById(parent);
		// Needs this to limit the size of the overlay.
		if (parent.currentStyle.position == 'static')
		{
			// Store the original style position.
			parent.setAttribute('__style_position', parent.style.position);
			// Set the needed relative position.
			parent.style.position = 'relative';
		}
		// Create element that is used as the overlay.
		var elem = document.createElement('div');
		// Set the class for the element.
		elem.setAttribute('class', WaitOverlay.CreateStyle());
		elem.setAttribute('style', 'position:absolute');
		// When the parent has no height give the element zome hieght.
		height = GetValueUnit(parent.currentStyle.height);
		if (!height.Value || (height.Value < 30 && height.Unit == 'px'))
		{
			elem.style.height = '7em';
		}
		// Append when a parent was passed.
		if (typeof parent == 'object')
			parent.appendChild(elem)
		// Return the created element.
		return elem;
	}
	//----------------------------------------
}
//---------------------------------------------------------------------------
javascript_import('jscripts/wddx.js', 'wddx');
javascript_import('jscripts/htmledit.js', 'htmledit');
//javascript_import('jscripts/calendar.js', 'htmledit');
//javascript_import('jscripts/calculator.js', 'htmledit');
