/* user interface  object */
	// main user interface  object
	function UserInterface(){
		/* properties */
		this.canvas			=	new Canvas(document.getElementById('parallax'));
		this.posters		=	new Sprites(document.getElementById('covers'), 150);
		this.titles			=	new Sprites(document.getElementById('titles'), 50);
		this.overlay		=	new Overlay(document.getElementById('overlay'));
		this.content		=	new Display(document.getElementById('content'));
		this.navigation		=	new Navigation(document.getElementById('navigation'));
		this.controls		=	new Controls(document.getElementById('controls'));
		this.banner			=	new Banner(document.getElementById('banner'));
		this.interval		=	null;
		/* methods */
		this.startUp 		= 	function(){
									// hide the scrollbar
									document.body.parentNode.style.overflow = "hidden";
									// start up the modules
									this.posters.start(-2);
									this.titles.start(-1);
									this.overlay.start();
									this.content.start();
									this.meta();
									this.navigation.start();
									this.controls.start();
									this.interval = setInterval("userInterface.update()",25);
									this.deep();
									this.canvas.start();
									this.banner.update();
								}
		this.update		=	function(){
									this.posters.update();
									this.titles.update();
									this.overlay.update();
									this.content.update();
									this.navigation.update();
									this.canvas.update();
									this.banner.update();
								}
		this.meta			=	function(){
									// give event handlers to the meta tags
									allMetas = document.getElementById('footer').getElementsByTagName('a');
									for(var a=0; a<allMetas.length; a++){
										allMetas[a].onclick = this.titles.open;
									}
									allMetas = document.getElementById('footer').getElementsByTagName('img');
									for(var a=0; a<allMetas.length; a++){
										allMetas[a].src = allMetas[a].src.replace('_active','_link');
									}
								}
		/* events */
		this.deep			=	function(){
									// check the href for a deeplink url
									url = classBehaviour.getQueryParameter('url', null);
									// check the href for a width
									width = classBehaviour.getQueryParameter('width', 1);
									// check the href for a height
									height = classBehaviour.getQueryParameter('height', 1);
									// check the href for a height
									styling = classBehaviour.getQueryParameter('style', 'normal');
									// invoke the show command
									if(url) this.content.show(unescape(url), width, height, styling);
								}
	}
		function Canvas(node){
			/* properties */
			this.node		=	node;
			/* methods */
			this.start		=	function(){
									this.node.className = "loaded";
								}
			this.update	=	function(){
									// get the screen height
									screenHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;
									// get the canvas height
									canvasHeight = 650;
									//calculate the offset to center
									offset = Math.round((screenHeight - canvasHeight)/2);
									// center the canvas
									document.body.style.paddingTop = (offset<0) ? '0px' : offset + 'px';
									// show the canvas
									this.node.parentNode.style.visibility = 'visible';
								}
		}
		function Banner(node){
			/* properties */
			this.node		=	node;
			/* methods */
			this.update		=	function(){
									// if a specific hidden input exist, show or hide the banner
									bannerObj = document.getElementById('banner');
									if (bannerObj == undefined) return;
									showBanner = document.getElementById('showTheBanner');
									bannerObj.style.display = (showBanner==null) ? 'block' : (showBanner.value=='false') ? 'none' : 'block' ;
								}
		}
		function Display(node){
			/* properties */
			this.node		=	node;
			this.opened	=	false;
			this.active	=	false;
			this.xPos		=	0;
			this.yPos		=	0;
			this.widths	=	new Array(300,600);
			this.heights	=	new Array(240,400);
			this.positions	=	new Array(110,50);
			/* methods */
			this.start		=	function(){
									// hide the content
									this.node.style.visibility = 'hidden';
									// add the button events
									allButtons = this.node.getElementsByTagName('a');
									allButtons[0].onclick = this.print;
									allButtons[1].onclick = this.email;
									allButtons[2].onclick = this.hide;
								}
			this.update	=	function(){
									// if the end position is not reached
									if(this.xPos<10 && this.active){
										// update the position
										this.xPos += 10;
										this.node.style.right = this.xPos + "px";
									}
								}
			/* events */
			this.show		=	function(url, width, height, style){
//									if(!this.opened){
										if(!this.opened){
											// set the iframe to the start position
											this.xPos = 0 - this.widths[width];
											this.node.style.right = this.xPos + "px";
										}
										// lock this function
										this.opened = true;
										// get the frame object
										contentIframe = this.node.getElementsByTagName('iframe')[0];
										// load the url from the iframe
										contentIframe.src = url;
										// size the iframe to the specified size
										if(contentIframe.style){
											contentIframe.style.width = this.widths[width] + "px";
											contentIframe.style.height = this.heights[height] + "px";
											this.node.style.top = this.positions[height] + "px";
										}else{
											contentIframe.width = this.widths[width];
											contentIframe.height = this.heights[height];
											this.node.style.top = this.positions[height] + "px";
										}
										// change the style of the iframe controls
										allControls = userInterface.content.node.getElementsByTagName('img');
										for(var a=0; a<allControls.length; a++){
											allControls[a].src = allControls[a].src.replace('_meta_', '_'+style+'_').replace('_normal_', '_'+style+'_');
										}
										// stop the scrolling
										userInterface.posters.paused = true;
										userInterface.titles.paused = true;
										// fade in the overlay
										userInterface.overlay.opacity = 70;
										// show the frame object
										this.node.style.visibility = 'visible';
										// roll in the frame object
										this.active = true;
//									}
								}
			this.hide		=	function(){
									// does the iframe have a document history
									if(parent.contentFrame.document.getElementById('referUrl')){
										userInterface.content.node.getElementsByTagName('iframe')[0].src = parent.contentFrame.document.getElementById('referUrl').value;
									}else{
									// else
										// hide the content frame
										userInterface.content.node.style.visibility = "hidden";
										// unload the iframe
										userInterface.content.node.getElementsByTagName('iframe')[0].src = "";
										// resume the scrolling
										userInterface.posters.paused = false;
										userInterface.titles.paused = false;
										// fade out the overlay
										userInterface.overlay.opacity = 0;
										// unlock this function
										userInterface.content.opened = false;
										// reset the meta links
										userInterface.meta();
										// show all sprites
										allLinks = document.getElementById('canvas').getElementsByTagName('A');
										for(var a=0; a<allLinks.length; a++)
											if(allLinks[a].parentNode.parentNode.className!='controls' && allLinks[a].parentNode.id!='navigation')
												allLinks[a].style.visibility = 'visible';
									}
									// cancel the click
									return false;
								}
			this.print		=	function(){
									// ask the content frame to print
									contentFrame.focus();
									contentFrame.print();
									// cancel the click
									return false;
								}
			this.email		=	function(){
									// take the url from the iframe
									contentIframe = userInterface.content.node.getElementsByTagName('iframe')[0];
									printUrl = "http://www.vdbj.nl/systemwide/mailtofriend.aspx?url=" + escape(contentIframe.src);
									// pass it to a new page
									userInterface.content.opened = false;
									userInterface.content.show(printUrl, 1, 1, 'normal');
									// cancel the click
									return false;
								}
		}
		function Overlay(node){
			/* properties */
			this.node		=	node;
			this.opacity	=	0;
			this.step		=	10;
			/* methods */
			this.start		=	function(){
									// set the starting opacity of the overlay
									classBehaviour.fader.setFade(this.node, 0);
								}
			this.update		=	function(){
									// get the current opacity of the overlay
									currentFade = classBehaviour.fader.getFade(this.node);
									// if the current opacity is not the required opacity add or substract a step
									if(this.opacity-currentFade > this.step){
										classBehaviour.fader.setFade(this.node, currentFade+this.step);
									}else if(this.opacity-currentFade < -1*this.step){
										classBehaviour.fader.setFade(this.node, currentFade-this.step);
									}else if(this.opacity!=currentFade){
										classBehaviour.fader.setFade(this.node, this.opacity);
									}
									// remove the layer if its fully invisible
									this.node.style.display = (currentFade==0) ? 'none' : 'block' ;
								}
		}
		function Navigation(node){
			/* properties */
			this.node		=	node;
			this.list		=	node.getElementsByTagName('ul')[0];
			this.closer		=	node.getElementsByTagName('a')[0];
			this.opener		=	node.getElementsByTagName('a')[1];
			this.width		=	170;
			this.size		=	0;
			this.sizes		=	new Array(170, 170);
			this.left		=	0;
			this.position	=	1;
			this.positions	=	new Array(-140, 0);
			this.previous	=	null;
			/* methods */
			this.start		=	function(){
									// set the close button
									this.closer.style.visibility = 'visible';
									this.closer.onclick = this.close;
									// set the open button
									this.opener.style.visibility = 'hidden';
									this.opener.onclick = this.open;
									// set the navigation to the correct size
									this.node.style.width = this.sizes[this.position] + 'px';
									this.node.style.left = this.positions[this.position] + 'px';
									// scan the navigation tree
									allLinks = this.list.getElementsByTagName('a');
									for(var a=0; a<allLinks.length; a++){
										// load into the iframe
										if(allLinks[a].className.indexOf('style')>-1 && allLinks[a].className.indexOf('importXml')<0) allLinks[a].onclick = this.load;
										// load into xml
										if(allLinks[a].className.indexOf('importXml')>-1) allLinks[a].onclick = this.importXml;
										// if the item has sub-items, give it the event handler to grow the menu
										node = allLinks[a].parentNode;
										subNodes = node.getElementsByTagName('ul');
										if(subNodes.length>0){
											subNodes[0].className = (node.getElementsByTagName('a')[0].className.indexOf('active')>-1) ? 'showThisNode' : "hideThisNode";
										}
									}
								}
			this.update		=	function(){
									nav = userInterface.navigation;
									// menu position
									if(this.left<this.positions[this.position]){
										this.left += 5;
										this.node.style.left = this.left + 'px';
										this.node.getElementsByTagName('ul')[0].style.display = 'block';
									}else if(this.left>this.positions[this.position]){
										this.left -= 5;
										this.node.style.left = this.left + 'px';
										this.node.getElementsByTagName('ul')[0].style.display = 'block';
									}else if(this.left==this.positions[0]){
										this.node.getElementsByTagName('ul')[0].style.display = 'none';
									}
									// menu size
									if(this.width<this.sizes[this.size]){
										this.width += 5;
										this.node.style.width = this.width + 'px';
									}else if(this.width>this.sizes[this.size]){
										this.width -= 5;
										this.node.style.width = this.width + 'px';
									}
								}
			this.activate	=	function(node){
									var nav = userInterface.navigation;
									// mark its peers inactive
									peers = node.parentNode.parentNode.childNodes;
									for(var a=0; a<peers.length; a++){
										if(peers[a].nodeName=='LI'){
											if(peers[a].getElementsByTagName('A').length>0) peers[a].getElementsByTagName('A')[0].className = peers[a].getElementsByTagName('A')[0].className.replace('active', 'link');
											if(peers[a].getElementsByTagName('UL').length>0) classBehaviour.hideThisNode.start(peers[a].getElementsByTagName('UL')[0]);
										}
									}
									// mark the item active
									node.className = node.className.replace('link', 'active');
									// mark the children inactive
									children = node.parentNode.getElementsByTagName('A');
									for(var a=1; a<children.length; a++) children[a].className = children[a].className.replace('active', 'link');
									// open any sub-node that may be there
									subNodes = node.parentNode.getElementsByTagName('ul');
									if(subNodes.length>0){
										classBehaviour.showThisNode.start(subNodes[0]);
									}
								}
			/* events */
			this.open		=	function(){
									userInterface.navigation.closer.style.visibility = 'visible';
									userInterface.navigation.opener.style.visibility = 'hidden';
									userInterface.navigation.position = 1;
								}
			this.close		=	function(){
									userInterface.navigation.closer.style.visibility = 'hidden';
									userInterface.navigation.opener.style.visibility = 'visible';
									userInterface.navigation.position = 0;
								}
			this.load		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var nav = userInterface.navigation;
									// get the url from the link
									url = objNode.href;
									// get the size preferences
									width = parseInt(classBehaviour.getClassParameter(objNode, 'width', '1'));
									height = parseInt(classBehaviour.getClassParameter(objNode, 'height', '1'));
									styling = classBehaviour.getClassParameter(objNode, 'style', 'normal');
									// call upon the iframe display
									setTimeout("userInterface.content.show('"+url+"', "+width+", "+height+", '"+styling+"')",100);
									// activate the link
									nav.activate(objNode);
									// cancel the click
									objNode.blur();
									return false;
								}
			this.importXml	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var nav = userInterface.navigation;
									// import new sprites using ajax
									classBehaviour.xmlDoc.addRequest(objNode.href, userInterface.navigation.processXml, userInterface.navigation.waitForXml, null, objNode);
									// activate the link
									nav.activate(objNode);
									// cancel the click
									objNode.blur();
									return false;
								}
			this.waitForXml	=	function(status){
									// status indicator here
							//		debug(status);
								}
			this.processXml	=	function(documentObj, referedNode, documentText){
									// stop the render engine
									userInterface.content.paused = true;
									userInterface.posters.paused = true;
									// remove the xml tags from the xml output
									inputHtml = documentText.replace('<?xml version="1.0"?>', '').replace('<root>', '').replace('/<root>', '');
									// get the titles html from the xml output
									titlesHtml = inputHtml.split('<ul id="covers">')[0].replace('</ul>', '').replace('<ul id="titles">', '');
									document.getElementById('titles').innerHTML = titlesHtml;
									// get the covers html from the xml output
									coversHtml = inputHtml.split('<ul id="covers">')[1].replace('</ul>', '');
									document.getElementById('covers').innerHTML = coversHtml;
									// restart the render engine
									userInterface.content.hide();
									userInterface.posters.start(-2);
									userInterface.titles.start(-1);
									userInterface.controls.restore();
									// re-activate the classbehaviours
									classBehaviour.parseDocument(document.getElementById('covers'));
								}
		}
		function Sprites(node, offset){
			/* properties */
			this.node		=	node;
			this.speed		=	-2;
			this.paused	=	false;
			this.list		=	new Array();
			this.index		=	0;
			this.next		=	1;
			this.offset	=	offset;
			/* methods */
			this.start 	= 	function(speed){
									this.speed = speed;
									// clear the list
									this.list = new Array();
									this.index = 0;
									this.next = 1;
									// all items
									allItems = this.node.getElementsByTagName('li');
									// for every item on the list
									for(var a=0; a<allItems.length; a++){
										// make a new sprite object
										this.list[a] = new Sprite(allItems[a]);
										// set the start position
										this.list[a].start(this.speed);
										// get the node's link
										itemLink = this.list[a].node.getElementsByTagName('a')[0];
										// set the even-handler for the click
										itemLink.onclick = this.open;
									}
									// trigger the update funtion once to give the sprites a starting position
									this.speed -= 50;
									for(var a=0; a<25; a++) this.update();
									this.speed += 50;
								}
			this.setIndex	=	function(){
									index = 0;
									// if the direction is positive
									if(this.speed<0){
										// find the first active element, the one with the highest xpos
										for(var a=0; a<this.list.length; a++) if(this.list[a].active && this.list[a].xPos>this.list[index].xPos) index = a;
									// else
									}else{
										// find the last active element, the one with the highest xpos
										for(var a=0; a<this.list.length; a++) if(this.list[a].active && this.list[a].xPos<this.list[index].xPos) index = a;
									}
									// set the value of the item index
									this.index = index;
								}
			this.update	=	function(){
									var lastActive = 0;
									var totalActive = 0;
									// if the list is not paused
									if(!this.paused){
										// for every sprite on the list
										for(var a=0; a<this.list.length; a++){
											// if its on screen
											if(this.list[a].active){
												// ask it to update its position
												this.list[a].update(this.speed);
												// store its index
												totalActive += 1;
											}else{
												this.list[a].reset(this.speed);
											}
										}
										// start the next index when there's space after the last one
										if(this.list.length>0){
											offset = (this.speed>0) ? this.list[this.index].xPos : this.list[this.index].xMax-this.list[this.index].xPos+this.list[this.index].xMin;
											if(offset>this.offset || totalActive==0){
												// pick the next one in row
												this.index = (this.speed<0) ? (this.list.length + this.index - 1) % this.list.length : (this.index + 1) % this.list.length;
												// if the item is not allready active
												if(!this.list[this.index].active){
													// set its initial position
													this.list[this.index].update(this.speed);
													// allow it to move
													this.list[this.index].active = true;
												}
											}
										}
									}
								}
			/* events */
			this.open		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the url from the link
									url = objNode.href;
									// get the size preferences
									width = parseInt(classBehaviour.getClassParameter(objNode, 'width', '1'));
									height = parseInt(classBehaviour.getClassParameter(objNode, 'height', '1'));
									styling = classBehaviour.getClassParameter(objNode, 'style', 'normal');
									// call upon the iframe display
									setTimeout("userInterface.content.show('"+url+"', "+width+", "+height+", '"+styling+"')",100);
									// disappear this icon
									allLinks = document.getElementById('canvas').getElementsByTagName('A');
									for(var a=0; a<allLinks.length; a++)
										if(allLinks[a].parentNode.parentNode.className!='controls' && allLinks[a].parentNode.id!='navigation')
											allLinks[a].style.visibility = 'visible';									
									objNode.style.visibility = (objNode.className.indexOf('doNotHide')<0) ? 'hidden' : 'visible' ;
									// cancel the click
									this.blur();
									return false;
								}
		}
			function Sprite(node){
				this.node		=	node;
				this.xPos		=	-1000;
				this.yPos		=	0;
				this.zPos		=	0;
				this.xMin		=	0 - this.node.offsetWidth;
				this.xMax		=	userInterface.canvas.node.offsetWidth;
				this.yMin		=	55;
				this.yMax		=	userInterface.canvas.node.offsetHeight - this.node.offsetHeight - 35;
				this.speed		=	0;
				this.active	=	false;
				this.start		=	function(speed){
										this.reset();
										this.update(speed);
										this.reset();
									}
				this.update	=	function(speed){
										// store the speed and direction
										this.speed = speed;
										//calculate the x-position
										this.xPos += speed;
										// calculate the limits
										this.xMin = (this.node.offsetWidth>0) ? 0 - this.node.offsetWidth : -130 ;
										this.xMax = (document.body.offsetWidth>0) ? document.body.offsetWidth : 160 ;
										// update the object if it's inside the screen otherwise reset it
										this.node.style.left = ((this.speed<0 && this.xPos>this.xMin) || (this.speed>0 && this.xPos<this.xMax)) ? Math.round(this.xPos) + 'px' : this.reset();
										this.node.style.top = this.yPos + 'px';
										// set  the visibility
										this.node.style.visibility = 'visible';
									}
				this.reset		=	function(){
										this.active = false;
										this.node.style.visibility = 'hidden';
										this.xMin = (this.node.offsetWidth>0) ? 0 - this.node.offsetWidth : -130 ;
										this.xMax = (document.body.offsetWidth>0) ? document.body.offsetWidth : 160 ;
										this.xPos = (this.speed<0) ? this.xMax : this.xMin;
										this.yPos = Math.round((this.yMax-this.yMin) * Math.random() + this.yMin);
										return Math.round(this.xPos) + 'px';
									}
			}
		function Controls(node){
			/* properties */
			this.node			=	node;
			this.speedDrag		=	false;
			this.speedIndex	=	2;
			this.directionIndex =	-1;
			this.speedBar		=	null;
			this.speedNodes	=	null;
			this.speeds		=	new Array(
										new Array( 0.002, 0.001),
										new Array( 1,	 0.5),
										new Array( 2,	 1),
										new Array( 3,	 1.5),
										new Array( 4,	 2)
									);
			this.colourIndex	=	0;
			this.colourBar		=	null;
			this.colourNodes	=	null;
			/* methods */
			this.start			=	function(){
										// get all speed buttons
										this.speedBar = document.getElementById('slider');
										this.speedNodes = this.speedBar.getElementsByTagName('img');
										// set the events for the slider
										this.speedBar.onmousedown = this.enable;
										document.onmouseup = this.disable;
										this.speedBar.onmousemove = this.drag;
										// set the events for the speed
										for(var a=0; a<this.speedNodes.length; a++){
											// this.speedNodes[a].onmouseover = this.hover;
											this.speedNodes[a].onclick = this.speed;
										}
										// set the events fotr the pause
										document.getElementById('pause').onclick = this.pause;
										// set the events for the direction
										document.getElementById('back').onclick = this.reverse;
										// set the events for the colours
										this.colourBar = document.getElementById('colours');
										this.colourNodes = this.colourBar.getElementsByTagName('dd');
										// set the events for the colours
										for(var a=0; a<this.colourNodes.length; a++){
											this.colourNodes[a].onclick = this.colour;
										}
										// set the initial values
										this.restore();
									}
			this.restore		=	function(){
										// get the settings string
										vdbjPrefs = getCookie('vdbjPrefs');
										// if there was a cookie
										if(vdbjPrefs){
											// restore speed settings
											speedSettings = vdbjPrefs.split('speed=');
											speedSettings = (speedSettings.length>1) ? parseFloat(speedSettings[1]) : 2 ;
											this.speed(this.speedNodes[speedSettings]);
											// restore the direction setting
											directionSettings = vdbjPrefs.split('direction=');
											directionSettings = (directionSettings.length>1) ? parseInt(directionSettings[1]) : -1 ;
											if(directionSettings>0) this.reverse(document.getElementById('back'));
											// restore the colour settings
											colourSettings = vdbjPrefs.split('colour=');
											colourSettings = (colourSettings.length>1) ? parseInt(colourSettings[1]) : 0 ;
											this.colour(this.colourNodes[colourSettings], true);
										}
									}
			this.saveSettings	=	function(){
										settingsString = "speed=" + userInterface.controls.speedIndex + "&direction=" + userInterface.controls.directionIndex + "&colour=" + userInterface.controls.colourIndex;
										setCookie('vdbjPrefs', settingsString, getDaysFromNow(30), "/", null, null);
									}
			/* events */
			this.enable		=	function(){
										userInterface.controls.speedDrag = true;
										return false;
									}
			this.disable		=	function(){
										userInterface.controls.speedDrag = false;
										return false;
									}
			this.drag			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if the mouse is down
										if(userInterface.controls.speedDrag){
											// get the mouse drag position
											mouseX = (typeof(event)!='undefined') ? event.x : that.layerX ;
											mouseY = (typeof(event)!='undefined') ? event.y : that.layerY ;
											// calculate the corresponding index
											speedIndex = Math.round(mouseX/60*userInterface.controls.speedNodes.length);
											// limits
											if(speedIndex>=userInterface.controls.speedNodes.length) speedIndex = userInterface.controls.speedNodes.length - 1;
											if(speedIndex<0) speedIndex = 0;
											// set the speed to the index
											userInterface.controls.speed(userInterface.controls.speedNodes[speedIndex]);
										}
										return false;
									}
			this.speed			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// what speed element has been pressed?
										speedIndex = parseInt(objNode.className.replace('speed',''));
										// set the indicators
										for(var a=0; a<userInterface.controls.speedNodes.length; a++){
											speedNode = userInterface.controls.speedNodes[a];
											speedNode.src = (a<=speedIndex) ? speedNode.src.replace('_link','_active') : speedNode.src.replace('_active','_link') ;
										}
										// get the dedined direction
										direction = (userInterface.posters.speed<0) ? -1 : 1 ;
										// set the defined speed
										userInterface.posters.speed = userInterface.controls.speeds[speedIndex][0] * direction;
										userInterface.titles.speed = userInterface.controls.speeds[speedIndex][1] * direction;
										// store the selected speed
										userInterface.controls.speedIndex = speedIndex;
										userInterface.controls.saveSettings();
									}
			this.colour		=	function(that, noReload){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// what speed element has been pressed?
										if(objNode){
											colourNode = objNode.getElementsByTagName('img')[0];
											colourIndex = parseInt(colourNode.className.replace('colour',''));
											// store the selected colour index
											userInterface.controls.colourIndex = colourIndex;
											userInterface.controls.saveSettings();
											// set the appropriate styles
											document.body.className = 'skin' + colourIndex;
											// change the appropriate images
											allImages = document.getElementsByTagName('img');
											for(var a=0; a<allImages.length; a++){
												if(navigator.userAgent.indexOf('MSIE 6')>-1) allImages[a].src = allImages[a].src.replace('skinT', 'skin0');
												allImages[a].src = allImages[a].src.replace(/skin+[0-9]/, 'skin' + colourIndex);
											}
											// set the indicators
											for(var a=0; a<userInterface.controls.colourNodes.length; a++){
												colourNode = userInterface.controls.colourNodes[a].getElementsByTagName('img')[0];
												colourNode.src = (a==colourIndex) ? colourNode.src.replace('_link','_active').replace('_hover','_active') : colourNode.src.replace('_active','_link') ;
											}
											// reload
											if(!noReload){
												url = userInterface.content.node.getElementsByTagName('iframe')[0].src;
												userInterface.content.node.getElementsByTagName('iframe')[0].src = '';
												userInterface.content.node.getElementsByTagName('iframe')[0].src = url;
											}
										}
										return false;
									}
			this.pause			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if the content pane isn't extended
										if(!userInterface.content.opened){
											// set the poster sprites to pause
											userInterface.posters.paused = !userInterface.posters.paused;
											// set the title sprites to pause
											userInterface.titles.paused = !userInterface.titles.paused;
											// set the pause button
											objNode.className = (userInterface.posters.paused) ? 'paused' : '' ;
										}
										// cancel the click
										return false;
									}
			this.reverse		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// reverse the posters direction
										userInterface.posters.speed = userInterface.posters.speed * -1;
										// reverse the titles direction
										userInterface.titles.speed = userInterface.titles.speed * -1;
										// switch the sprite index so the screen is filled from the other side
										userInterface.posters.setIndex();
										userInterface.titles.setIndex();
										// set the pause button
										objNode.className = (userInterface.posters.speed>0) ? 'reversed' : '' ;
										// store the selected direction
										userInterface.controls.directionIndex = (userInterface.posters.speed>0) ? 1 : -1 ;
										userInterface.controls.saveSettings();
										// cancel the click
										return false;
									}
		}
		
		function TransFrameLinks(){
			this.startUp		=	function(){
										// check if this frame is outside of its frameset
										this.orphaned();
										// <a href="./iframe_scroll.html" class="transFrameLink width_0 height_0">consectetur adipisicing elit</a>
										// get all links in this frame
										allLinks = document.getElementsByTagName('A');
										for(var a=0; a<allLinks.length; a++){
											// if this is a transframe link, set their event handler
											if(allLinks[a].className)
												if(allLinks[a].className.indexOf('transFrameLink')>-1)
													allLinks[a].onclick = this.click;
										}
										// get the skin from the cookie and apply it to the body of this frame
								//		if(document.body.className.indexOf('meta')>-1){
											vdbjPrefs = getCookie('vdbjPrefs');
											if(vdbjPrefs){
												colourPrefs = vdbjPrefs.split('colour=');
												colourPref = (colourPrefs.length>0) ? 'skin' + parseInt(colourPrefs[1]) : 'skin0' ;
												document.body.className += (document.body.className.indexOf('meta')>-1) ? ' meta' + colourPref : ' ' + colourPref ;
												allImages = document.getElementsByTagName('IMG');
												for(var a=0; a<allImages.length; a++) allImages[a].src = allImages[a].src.replace('skin0',colourPref);
											}
								//		}
									}
			this.orphaned		=	function(){
										if(parent==self){
											iframeWidth = classBehaviour.getClassParameter(document.body, 'width', '1');
											iframeHeight = classBehaviour.getClassParameter(document.body, 'height', '1');
											//  Exception for WIM preview
											exception = classBehaviour.getClassParameter(document.body, 'exception', '0');
											if (exception == 0)
											    document.location.replace('http://www.vdbj.nl/?url=' + document.location.href + '?width=' + iframeWidth + '&height=' + iframeHeight);
										}
									}
			this.click			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// get the url
										theUrl = objNode.href;
										// get the width preference
										theWidth = classBehaviour.getClassParameter(objNode, 'width', 0);
										// get the height preference
										theHeight = classBehaviour.getClassParameter(objNode, 'height', 0);
										// if the parent frames function exists
										if(top.userInterface){
											// call the oad function
											top.userInterface.content.opened = false;
											top.userInterface.content.show(theUrl, theWidth, theHeight, 'normal');
											// cancel the click
											return false;
										}
									}
		}
			
		// create the user interface object
		if(document.getElementById('parallax')) var userInterface = new UserInterface;
		if(document.body.className.indexOf('iframe')>-1) var transFrameLinks = new TransFrameLinks;
	
	
	/* stupid fix for MSIE 
	if(navigator.userAgent.indexOf('MSIE')>-1){
		function focuz(){
			this.focus();
		}
		allInputs = document.getElementsByTagName('input');
		for(var a=0; a<allInputs.length; a++){
			if(allInputs[a].className.indexOf('text')>-1) allInputs[a].onmousemove = focuz;
		}
		allInputs = document.getElementsByTagName('textarea');
		for(var a=0; a<allInputs.length; a++){
			allInputs[a].onmousemove = focuz;
		}
	}
	*/
	
	
/* stylesheet generator */

	// generates an empty stylesheet based on the html dom
	var strStyleSheet = "";
	var objBody = document.body;
	
	function isFormElement(node){
		return (('INPUT,SELECT,TEXTAREA,BUTTON').indexOf(node.nodeName)>-1);
	}
	
	function getNodeClasses(objNode, intRecursion, prefix){
		var strTabs = '';
		var idPrefix, classPrefix, tagPrefix, addPrefix;
		var newEntry = '';
		// for every recursion add one tab
		for(var intB=0; intB<intRecursion; intB++) strTabs += '\t';
		// get the child nodes
		var objChildNodes = objNode.childNodes;
		// for every childnode
		for(var intA=0; intA<objChildNodes.length; intA++){
			// reset prefixes
			idPrefix = '';
			classPrefix = '';
			tagPrefix = '';
			addPrefix = '';
			// if it has an id, but is not a form element
			if(typeof(objChildNodes[intA].id)!='undefined' && !isFormElement(objChildNodes[intA])){
				if(objChildNodes[intA].id!=''){
					// add class to stylesheet prototype
					newEntry = strTabs + '#' + objChildNodes[intA].id + ' {}\n'
						// strStyleSheet += strTabs + prefix + '#' + objChildNodes[intA].id + ' {}\n'
					// add this style only if there's not double
					if(strStyleSheet.indexOf(newEntry)<0) strStyleSheet += newEntry;
					// update the prefix
					idPrefix = '#' + objChildNodes[intA].id;
				}
			}
			// if it has a className
			if(typeof(objChildNodes[intA].className)!='undefined'){
				if(objChildNodes[intA].className!=''){
					// split the classnames
					allClasses = objChildNodes[intA].className.split(' ');
					// for all classes
					for(var b=allClasses.length-1; b>=0; b--){
						// add class to stylesheet prototype
						newEntry = strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ' {}\n';
						// add this style only if there's not double
						if(strStyleSheet.indexOf(newEntry)<0) strStyleSheet += newEntry;
						// update the prefix
						classPrefix = objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b];
					}
				}
			}
			// if it has neither
			if(
				objChildNodes[intA].className=='' && 
				(objChildNodes[intA].id=='' || isFormElement(objChildNodes[intA])) && 
				objChildNodes[intA].nodeName.indexOf('text')<0 && 
				objChildNodes[intA].nodeName.indexOf('comment')<0
			){
				// add class to stylesheet prototype
				newEntry = strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + ' {}\n';
				// add this style only if there's not double
				if(strStyleSheet.indexOf(newEntry)<0) strStyleSheet += newEntry;
				// update the prefix
				tagPrefix = objChildNodes[intA].nodeName.toLowerCase();
			}
			// if the last entry was a link
			if(newEntry.indexOf(' a {}')>-1){
				// repeat it four times with the mouseover states
				linkEntry = newEntry.replace('a {}','a:link,');
				if(strStyleSheet.indexOf(linkEntry)<0) strStyleSheet += '\t' + linkEntry;
				linkEntry = newEntry.replace('a {}','a:visited {}');
				if(strStyleSheet.indexOf(linkEntry)<0) strStyleSheet += '\t' + linkEntry;
				linkEntry = newEntry.replace('a {}','a:hover,');
				if(strStyleSheet.indexOf(linkEntry)<0) strStyleSheet += '\t' + linkEntry;
				linkEntry = newEntry.replace('a {}','a:active {}');
				if(strStyleSheet.indexOf(linkEntry)<0) strStyleSheet += '\t' + linkEntry;
				// and jump further in
				intRecursion += 1;
			}
			// if it has childNodes
			if(objChildNodes[intA].childNodes.length>0){
				// update the prefix
				if(idPrefix){
					addPrefix = idPrefix + ' ';
				}else if(classPrefix){
					addPrefix = prefix + classPrefix + ' ';
				}else if(tagPrefix){
					addPrefix = prefix + tagPrefix + ' ';
				}
				// recurse
				getNodeClasses(objChildNodes[intA], intRecursion+1, addPrefix);
			}
		}
	}

	function showNodeClasses(){
		document.body.style.textAlign = 'left';
		getNodeClasses(objBody, 0 , '');
		document.body.innerHTML = '<pre>' + strStyleSheet + '</pre>';	
	}

//	document.writeln('<a href="javascript:{showNodeClasses()}" style="position : absolute; left : 0px; top : 0px;">Click here to create an empty stylesheet for this markup.</a>');
	
	
	

	
	
	
	
	
	
	
	
	
	
/*
name			: Class Behaviour
update			: 20051129
author			: Xander Bindt, Frank van Rooijen, Maurice van Creij
dependencies		: lib_classbehaviour.js
info				: http://www.woollymittens.nl/content/details.asp?id=20040805133501
*/

	// MAIN
	// main class-behaviour object
	function ClassBehaviour(){
		/* properties */
			this.handlers			=	new Array();
		/* methods */
			// return a parameter from the url's query strings
			this.getQueryParameter 	= 	function(paramName, defaultValue){
											// split the query string at the parameter name
											var queryParameters = document.location.search.split(paramName+"=");
											// split the parameter value from the rest of the string
											var queryParameter = (queryParameters.length>1) ? queryParameters[1].split("&")[0] : null ;
											// return the value
											return (queryParameter!=null) ? queryParameter : defaultValue ;
										}
			// returns a string of parameters found in the classname which can be [eval]uated
			this.getClassParameter	=	function(targetNode, paramName, defaultValue){
											// get the class parameter from the classname
											var classParameter = targetNode.className;
											// split the classname between the parameter name
											classParameter = classParameter.split(paramName + '_');
											// split the second piece between spaces and take the first part,  if there are two pieces
											classParameter = (classParameter.length>1) ? classParameter[1].split(' ')[0] : null ;
											// return the value
											return (classParameter!=null) ? classParameter : defaultValue ;
										}
			// returns the visible display state needed for this element
			this.getVisibleState	=	function(node){
											// what kind of node is this
											switch(node.nodeName.toLowerCase()){
												case 'table' : visibleState='table' ; break;
												case 'thead' : visibleState='table-header-group' ; break;
												case 'tfoot' : visibleState='table-footer-group' ; break;
												case 'tbody' : visibleState='table-row-group' ; break;
												case 'tr' : visibleState='table-row' ; break;
												case 'td' : visibleState='table-cell' ; break;
												case 'th' : visibleState='table-cell' ; break;
												default : visibleState='block';
											}
											// apply the state
											return (document.all && navigator.userAgent.indexOf('Opera')<0) ? 'block' : visibleState;
										}
			// (cross)fader and pseudo event handler
			this.fader				=	new Fader;
			// xml interface
			this.xmlDoc				=	new XmlDoc;
			// get the previous node without worrying about text nodes
			this.nextNode			=	function(node){
											// look for the next html node
											do {
												node = node.nextSibling;
											} while(node.nodeName.indexOf('#text')>-1);
											// return it
											return node;
										}
			// get the next node without worrying about text nodes
			this.previousNode		=	function(node){
											// look for the previous html node
											do {
												node = node.previousSibling;
											} while(node.nodeName.indexOf('#text')>-1);
											// return it
											return node;
										}
			// parse the document for classnames
			this.parseDocument		=	function(node){
											target = (node) ? node : document;
											// get all document nodes
											var allNodes = (target.all) ? target.all : target.getElementsByTagName("*");
											// for all tags
											for(var a=0; a<allNodes.length; a++){ // for(var a=allNodes.length-1; a>=0; a--){
												// if the item has a className
												if(allNodes[a].className){
													// process the classname
													nodeClass = allNodes[a].className + ' ';
													// for all behaviours
													for(var b=0; b<this.handlers.length; b++){
														// if the behaviour's name exists in the class name, apply it's events
														if(nodeClass.indexOf(this.handlers[b].name+' ')>-1) this.handlers[b].start(allNodes[a]);
													}
												}
											}
										}						
	}
	// create the main class-behaviour object
	var classBehaviour = new ClassBehaviour;
	
	// UTILITIES
		function Fader(){
			/* properties */
			/* methods */
			this.getFade	=	function(node){
									var fadeValue = null;
									// get the fade value using the proper method
									if(typeof(node.style.MozOpacity)!='undefined')	fadeValue = Math.round(parseFloat(node.style.MozOpacity)*100);
									if(typeof(node.style.filter)!='undefined')		fadeValue = parseInt(node.filters.alpha.opacity);
									if(typeof(node.style.opacity)!='undefined')		fadeValue = Math.round(parseFloat(node.style.opacity)*100);
									// return the value
									return fadeValue;
								}
			this.setFade	=	function(node, amount){
									// set the fade value using the proper method
									if(typeof(node.style.MozOpacity)!='undefined')	node.style.MozOpacity = amount/100;
									if(typeof(node.style.filter)!='undefined')		node.style.filter = "alpha(opacity=" + amount + ")";
									if(typeof(node.style.opacity)!='undefined')		node.style.opacity = amount/100;
										/*
										filter:alpha(opacity=50);	imageobject.filters.alpha.opacity=opacity
										-moz-opacity: 0.5;			imageobject.style.MozOpacity=opacity/100
										opacity: 0.5;
										-khtml-opacity: 0.5;
										*/
								}
			this.fadeIn		=	function(idIn, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// get the fading object
									node = document.getElementById(idIn);
									// get the current fade
									fade = cf.getFade(node) + step;
									// if not 100%
									if((fade)<100){
										// set the new fade
										cf.setFade(node, fade);
										// next step
										cf.timeOut = setTimeout("classBehaviour.fader.fadeIn('"+idIn+"',"+step+","+delay+",'"+evalEvent+"')", delay);
									// else
									}else{
										// set the fade to 100%
										cf.setFade(node, 100);
										// trigger the end event
										eval(evalEvent);
									}
								}
			this.fadeOut	=	function(idOut, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// get the fading object
									node = document.getElementById(idOut);
									// get the current fade
									fade = cf.getFade(node) - step;
									// if not 100%
									if(fade>0){
										// set the new fade
										cf.setFade(node, fade);
										// next step
										cf.timeOut = setTimeout("classBehaviour.fader.fadeOut('"+idOut+"',"+step+","+delay+",'"+evalEvent+"')", delay);
									// else
									}else{
										// set the fade to 100%
										cf.setFade(node, 0);
										// trigger the end event
										eval(evalEvent);
									}
								}
			this.crossFade	=	function(idIn, idOut, amount, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// if the amount is not the end value yet
									if(amount<=100){
										// set the fade amounts
										if(idIn && idIn!="") cf.setFade(document.getElementById(idIn), amount);
										if(idOut && idOut!="") cf.setFade(document.getElementById(idOut), 100-amount);
										// unhide the new page
										document.getElementById(idIn).style.display = 'block';
										// construct the fade function
										var evalLoop = "classBehaviour.fader.crossFade('"+idIn+"', '"+idOut+"', "+(amount+step)+", "+step+", "+delay+", '"+evalEvent+"')";
										// repeat the fade
										setTimeout(evalLoop, delay);
									}else{
									// else
										// cancel the opacity style
										var node = document.getElementById(idIn);
										if(typeof(node.style.MozOpacity)!='undefined')	node.style.MozOpacity = 'auto';
										if(typeof(node.style.filter)!='undefined')		node.style.filter = 'none';
										if(typeof(node.style.opacity)!='undefined')		node.style.opacity = 'auto';
										// hide the old page
										if(idOut && idOut!="") document.getElementById(idOut).style.display = 'none';
										// trigger the end event
										cf.onEnd(evalEvent);
									}
								}
			/* events */
			this.onEnd		=	function(evalEvent){
									eval(evalEvent);
								}
		}
		
		function XmlDoc(){
			// properties
			this.queue			=	new Array();
			// utilities
			this.getNodeValue	=	function(objNode){
										strValue = (objNode.childNodes.length>0) ? objNode.firstChild.nodeValue : null ;
										return (isNaN(strValue) || strValue==null) ? strValue : parseInt(strValue);
									}
			this.setNodeValue	=	function(objNode,strValue){
										if(objNode.childNodes.length>0){
											objNode.firstChild.nodeValue = strValue;
										}else{
											var objNewNode = xmlDoc.createTextNode(strValue);
											objNode.appendChild(objNewNode);
										}
									}
			this.getChildNumber =	function(objNode){
										var objNodes = objNode.parentNode.childNodes;
										var intTextNodes = 0;
										for(var intA=0; intA<objNodes.length; intA++){
											if(objNodes[intA].nodeName == '#text') intTextNodes += 1;
											if(objNode==objNodes[intA]) return intA - intTextNodes;
										}
										return null;
									}
			// methods
			this.addRequest	=	function(url, loadHandler, progressHandler, post, eventObject){
										// get the first free slot in the que
										index = this.queue.length;
										// add new request to the end of the que
										this.queue[index] = new HttpRequest();
										// set request constants
										this.queue[index].idx			=	index;
										this.queue[index].url			=	url;
										this.queue[index].post			=	post;
										this.queue[index].method		=	(post) ? 'POST' : 'GET' ;
										// request events
										this.queue[index].doOnLoad		=	loadHandler;
										this.queue[index].doOnProgress	=	progressHandler;
										this.queue[index].referObject	=	eventObject;
										// ask the queue handler to handle the next queued item
										this.handleQueue();
									}
			this.makeRequest	=	function(queued){
										// branch for native XMLHttpRequest object
										if(window.XMLHttpRequest){
											queued.request = new XMLHttpRequest();
											queued.request.onreadystatechange = this.progress;
											queued.request.open(queued.method, queued.url, true);
											queued.request.send(queued.post);
										// branch for IE/Windows ActiveX version
										}else if(window.ActiveXObject){
											queued.request = new ActiveXObject("Microsoft.XMLHTTP");
											queued.request.onreadystatechange = this.progress;
											queued.request.open(queued.method, queued.url, true);
											queued.request.send(queued.post);
										// if all else fails: load the document in an iFrame
										}else if(window.frames){
											// create an iframe to read the document in
	 										objIframe = document.createElement("IFRAME");
	 										objIframe.src = queued.url;
	 										objIframe.id = "feedimport0";
	 										objIframe.name = "feedimport0";
											objIframe.style = "visibility : invisible;position : absolute;left : -1600px; top : -1600px;";
												//objIframe.onload = xmlDoc_load; // Doesn't work in Opera
											// append the iframe to the document
	 										document.body.appendChild(objIframe);
											// wait for the iframe to load
											this.wait();
										}
									}
			this.handleQueue	=	function(){
										queue = classBehaviour.xmlDoc.queue;
										// if the first item in the queue is a completed request
										if(queue.length>0){
											if(queue[0].ready==4 /*&& xmlDoc.queue[0].status==200*/){
												// remove the completed request
												queue.reverse();
												queue.length = queue.length - 1;
												queue.reverse();
											}
										}
										// if the first item in the queue isn't allready in progress
										if(queue.length>0){
											if(!(queue[0].ready<4 && queue[0].ready!=null)){
												this.makeRequest(queue[0]);
											}
										}
									}
			this.serialize		=	function serialize(xmlDoc){
										ser = new XMLSerializer();
										str = ser.serializeToString(xmlDoc);
										return(str);
									}
			// events
			this.progress		=	function(){
										queued = classBehaviour.xmlDoc.queue[0];
										// remember the readyState
										queued.ready = queued.request.readyState;
										// only if req shows "complete"
										if(queued.request.readyState == 4){
											// remember the status
											queued.status = queued.request.status;
											// only if "OK"
											if(queued.request.status == 200 || queued.request.status == 304){
												// update optional progress indicator code
												if(queued.doOnProgress) queued.doOnProgress(1, queued.referObject);
												// prepare the document
												queued.document = queued.request.responseXML;
												queued.text = queued.request.responseText;
												// trigger the load event
												if(queued.doOnLoad) queued.doOnLoad(queued.document, queued.referObject, queued.text);
												// request the next item in the queue to be handled
												classBehaviour.xmlDoc.handleQueue();
											}else{
												// update optional progress indicator code
												if(queued.doOnProgress) queued.doOnProgress(-1, queued.referObject);
											}
										}else{
											// update optional progress indicator code
											if(queued.doOnProgress) queued.doOnProgress(queued.request.readyState/4, queued.referObject);
										}
										// return the status if desired
										return queued.request.readyState;
									}
			this.wait			=	function(){
										queued = classBehaviour.xmlDoc.queue[0];
										// if the xml document has loaded in the iframe
										if(window.frames["feedimport0"]){
											// define the xml document object
											queued.document = window.frames["feedimport0"].document;
											queued.text = window.frames["feedimport0"].document.body.innerHTML;
											// what to do after the xml document loads
											queued.doOnLoad(queued.document, queued.referObject, queued.text);
										// else try again in a while
										}else{
											setTimeout("xmlDoc.wait()",256);
										}
									}
		}
			function HttpRequest(){
				// request constants
				this.idx			=	null;
				this.url			=	null;
				this.post			=	null;
				this.method			=	'GET';
				// request events
				this.doOnLoad		=	null;
				this.doOnProgress	=	null;
				this.referObject	=	null;
				// request properties
				this.request		=	null;
				this.document		=	null;
				this.text			=	null;
				this.ready			=	null;
				this.status			=	null;
			}

	// BEHAVIOURS
	// replace in class
		// define this class behaviour
		function ClassMouseHover(){
			/* properties */
			this.name 		= 	'classMouseHover';
			/* methods */
			this.start		=	function(node){
									node.onmouseover = this.addHover;
									node.onmouseout = this.remHover;
								}
			this.hasNoStateClass 	= 	function(objNode){
											return (objNode.className.indexOf('link')<0 && objNode.className.indexOf('hover')<0 && objNode.className.indexOf('active')<0);
										}
			/* events */
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace link by hover
									objNode.className = (cmh.hasNoStateClass(objNode)) ? 'hover ' + objNode.className : objNode.className.replace('link','hover') ;
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace hover by link
									objNode.className = (cmh.hasNoStateClass(objNode)) ? 'link ' + objNode.className : objNode.className.replace('hover','link') ;
								}
			this.addActive 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace link by active
									objNode.className = objNode.className.replace('link','active').replace('hover','active') ;
									// if there's still no active class
									if(cmh.hasNoStateClass(objNode)) objNode.className = 'active ' + objNode.className;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.classMouseHover = new ClassMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.classMouseHover;
		
	// replace in src sub-string
		// define this class behaviour
		function SrcMouseHover(){
			/* properties */
			this.name 			= 	'srcMouseHover';
			this.cache 			= new Array();
			/* methods */
			this.start			=	function(node){
										this.cacheImages(node);
										node.onmouseover = this.addHover;
										node.onmouseout = this.remHover;
									}
			this.cacheImages	 = 	function(that) {
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if this is not the image, it must be the parent
										if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
										// replace link by hover
										var cacheIdx = this.cache.length;
										// hover version
										this.cache[cacheIdx] = new Image();
										this.cache[cacheIdx].src = objNode.src.replace('_link','_hover');
										// active version
										this.cache[cacheIdx+1] = new Image();
										this.cache[cacheIdx+1].src = objNode.src.replace('_link','_active');
									}
			/* events */
			this.addActive 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(objNode.nodeName!='IMG') objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by active
									objNode.src = objNode.src.replace('_link','_active');
									// replace hover by active
									objNode.src = objNode.src.replace('_hover','_active');
								}
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by hover
									objNode.src = objNode.src.replace('_link','_hover');
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by hover
									objNode.src = objNode.src.replace('_hover','_link');
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.srcMouseHover = new SrcMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.srcMouseHover;

	// replace in src sub-string
		// define this class behaviour
		function FadeMouseHover(){
			/* properties */
			this.name 			= 'fadeMouseHover';
			this.cache 			= new Array();
			this.count			= 0;
			this.timeOut		= null;
			/* methods */
			this.start			=	function(node){
										this.cacheImages(node);
										// node.onload = this.setUpFader;
										this.setUpFader(node);
									}
			this.setUpFader		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var fmh = classBehaviour.fadeMouseHover;
										// give this image an id, if it doesn't have one
										if(!objNode.id) objNode.id = 'fadingImage' + fmh.count;
										fmh.count += 1;
										// set the active version of the image source as a background-image of the container
										objNode.parentNode.style.backgroundImage = 'url(' + objNode.src.replace('_link','_hover') + ')';
										// set the image as a block element
										objNode.parentNode.style.display = 'block';
										objNode.parentNode.style.width = objNode.width + 'px';
										objNode.parentNode.style.height = objNode.height + 'px';
										// set the default fade
										classBehaviour.fader.setFade(objNode, 100);
										// set up the events
										objNode.onmouseover = fmh.addHover;
										objNode.onmouseout = fmh.remHover;
									}
			this.cacheImages	 = 	function(that) {
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if this is not the image, it must be the parent
										if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
										// replace link by hover
										var cacheIdx = this.cache.length;
										// hover version
										this.cache[cacheIdx] = new Image();
										this.cache[cacheIdx].src = objNode.src.replace('_link','_hover');
									}
			/* events */
			this.addHover 	= 	function(that, id){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fmh = classBehaviour.fadeMouseHover;
									// if an id is passed. It overrides the event node
									if(id) objNode = document.getElementById(id);
									// if there's no fade active at the moment // fade out the image
									if(classBehaviour.fader.getFade(objNode)%100==0){
										classBehaviour.fader.fadeOut(objNode.id, 20, 50, '');
									// else try again in a bit
									}else{
										// fmh.timeOut = setTimeout("classBehaviour.fadeMouseHover.addHover(null, '" + objNode.id + "')",50);
									}
								}
			this.remHover 	= 	function(that, id){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fmh = classBehaviour.fadeMouseHover;
									// if an id is passed. It overrides the event node
									if(id) objNode = document.getElementById(id);
									// if there's no fade active at the moment // fade in the image
									if(classBehaviour.fader.getFade(objNode)%100==0){
										classBehaviour.fader.fadeIn(objNode.id, 20, 50, '');
									// else try again in a bit
									}else{
										fmh.timeOut = setTimeout("classBehaviour.fadeMouseHover.remHover(null, '" + objNode.id + "')",50);
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fadeMouseHover = new FadeMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fadeMouseHover;
		
	// hides nodes
		// hide the "hideThisNode" class behaviour by default 
		document.writeln("<style>.hideThisNode{overflow:hidden; visibility:hidden; height:1px;}</style>");
		// define this class behaviour
		function HideThisNode(){
			/* properties */
			this.name 		= 	'hideThisNode';
			/* methods */
			this.start		=	function(node){
									node.style.overflow = 'hidden';
									node.style.visibility = 'hidden';
									node.style.height = '1px';
									node.className = node.className.replace('showThisNode', 'hideThisNode');
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.hideThisNode = new HideThisNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.hideThisNode;
		
	// explicit opposite of a hidden node
		// define this class behaviour
		document.writeln("<style>.ShowThisNode{overflow:visible; visibility:visible; height:auto;}</style>");
		function ShowThisNode(){
			/* properties */
			this.name 		= 	'showThisNode';
			/* methods */
			this.start		=	function(node){
									node.style.overflow = 'visible';
									node.style.visibility = 'visible';
									node.style.height = 'auto';
									node.className = node.className.replace('hideThisNode', 'showThisNode');
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.showThisNode = new ShowThisNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.showThisNode;
		
	// show or hide a node
		// define this class behaviour
		document.writeln("<style>.toggleNextNode{cursor:pointer;}</style>");
		function ToggleNextNode(){
			/* properties */
			this.name 		= 	'toggleNextNode';
			this.nodes		=	new Array();
			this.step		=	10;
			this.delay		=	10;
			this.locked	=	false;
			/* methods */
			this.start		=	function(node){
									// set the event handlers for the source node
									node.onclick = this.toggle;
									// add this node to the node list
									this.nodes[this.nodes.length] = node;
									// give this node an id if it doesn't have one yet
									node.id = (node.id) ? node.id : this.name + this.nodes.length ;
								}
			this.shrink	=	function(label, container, finished){
									var t2n = classBehaviour.toggleNextNode;
									// deactivate the label
									label.className = label.className.replace('active','link');
									// if the container isn't shrunk completely
									if(container.offsetHeight>t2n.step){
										// reduce its height by an amount
										container.style.overflow = 'hidden';
										container.style.visibility = 'visible';
										container.style.height = (container.offsetHeight - t2n.step) + 'px';
										// mark the function as unfinished
										finished = false;
									}else{
										// close the container
										container.style.overflow = 'hidden';
										container.style.visibility = 'hidden';
										container.style.height = '1px';
										container.className = container.className.replace('showThisNode','hideThisNode');
									}
									// return the state
									return finished;
								}
			this.grow		=	function(label, container, finished){
									var t2n = classBehaviour.toggleNextNode;
									// activathe label
									label.className = label.className.replace('link','active').replace('hover','active');
									// measure the height of all the childnodes of the container
									totalHeight = 0;
									contents = container.childNodes;
									for(var a=0; a<contents.length; a++){
										totalHeight += (contents[a].offsetHeight) ? contents[a].offsetHeight : 0 ;
									}
									// if the container isn't grown completely
									if(targetContainer.offsetHeight<totalHeight-t2n.step){
										// reduce its height by an amount
										container.style.overflow = 'hidden';
										container.style.visibility = 'visible';
										container.style.height = (container.offsetHeight + t2n.step) + 'px';
										// mark the function as unfinished
										finished = false;
									}else{
										// open the container
										container.style.overflow = 'visible';
										container.style.visibility = 'visible';
										container.style.height = 'auto';
										container.className = container.className.replace('hideThisNode','showThisNode');
									}
									// return the state
									return finished;
								}
			/* events */
			this.toggle 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var t2n = classBehaviour.toggleNextNode;
									// if there isn't an animation in progress
									if(!t2n.locked){
										// lock the function
										t2n.locked = true;
										// get all information on this node
										targetLabel = objNode;
										targetContainerId = classBehaviour.getClassParameter(targetLabel, 'id', null);
										targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : classBehaviour.nextNode(targetLabel) ;
										targetGrows = (targetContainer.className.indexOf('hideThisNode')>-1)
										// call for the node to update
										t2n.update(targetLabel.id, targetGrows);
									}
								}
			this.update	=	function(id, grows){
									var t2n = classBehaviour.toggleNextNode;
									// finished marker
									finished = true;
									// get all information on this node
									targetLabel = document.getElementById(id);
									targetContainerId = classBehaviour.getClassParameter(targetLabel, 'id', null);
									targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : classBehaviour.nextNode(targetLabel) ;
									targetFamily = classBehaviour.getClassParameter(targetLabel, 'family', null);
									// for every node in the node-list
									for(var a=0; a<t2n.nodes.length; a++){
										// get its family
										peerLabel = t2n.nodes[a];
										peerContainerId = classBehaviour.getClassParameter(peerLabel, 'id', null);
										peerContainer = (peerContainerId) ? document.getElementById(peerContainerId) : classBehaviour.nextNode(peerLabel) ;
										peerFamily = classBehaviour.getClassParameter(peerLabel, 'family', null);
										// if this node belongs to the same family and is open but has a different id
										if(peerFamily==targetFamily && peerFamily!=null && peerContainer.className.indexOf('hideThisNode')<0 && peerLabel.id!=targetLabel.id){
											// close the container one step
											finished = this.shrink(peerLabel, peerContainer, finished);
										// else if this node has the same id and is open
										}else if(peerLabel.id==targetLabel.id && !targetGrows){
											// close the container one step
											finished = this.shrink(targetLabel, targetContainer, finished);
										// else 
										}else if(peerLabel.id==targetLabel.id && targetGrows){
											// open the container one step
											finished = this.grow(targetLabel, targetContainer, finished);
										}
									}
									// if any step marked the function as unfinished, repeat it
									if(!finished){
										setTimeout("classBehaviour.toggleNextNode.update('"+id+"',"+grows+")", t2n.delay);
									}else{
										t2n.locked = false;
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.toggleNextNode = new ToggleNextNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleNextNode;
		
	// Replaces all png's in the container with gif alternatives in Internet Explorer 6 and lower.
		// preload cosmetic tweak
		if(document.all && (navigator.userAgent.indexOf('MSIE 6.0')>-1 || navigator.userAgent.indexOf('MSIE 5')>-1) && navigator.userAgent.indexOf('Opera')<0)
				document.writeln("<style>.pngAlternative img {visibility:hidden;}</style>");
		// define this class behaviour
		function PngAlternative(){
			/* properties */
			this.name 		= 	'pngAlternative';
			this.lastNode	=	null;
			this.lastNext	=	null;
			/* methods */
			this.start		=	function(node){
									this.process(node);
								}
			/* events */
			this.process	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is a crappy browser
									if
									(
										(navigator.userAgent.indexOf('MSIE 6.0')>-1 || navigator.userAgent.indexOf('MSIE 5')>-1)
										&& navigator.userAgent.indexOf('Opera')<0
									)
									{
										// get all image tags
										var allImages = objNode.getElementsByTagName('img');
										// for all images
										for(var a=0; a<allImages.length; a++){
											// replace it with it's gif alternative
											allImages[a].src = allImages[a].src.replace('.png', '.gif');
											allImages[a].style.visibility = 'visible';
										}
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.pngAlternative = new PngAlternative;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.pngAlternative;
		
	// handle ondrag events
		// define this class behaviour
		function DragAndDrop(){
			/* properties */
			this.name 		= 	'dragAndDrop';
			this.node		=	null;
			this.grid		=	new Coordinates(16,16);
			this.minPos	=	new Coordinates();
			this.maxPos	=	new Coordinates();
			this.pickup	=	new Coordinates();
			this.mouse		=	new Coordinates();
			this.style		=	new Coordinates();
			this.onMove	=	null;
			/* methods */
			this.start		=	function(node){
									// event
									node.onmousedown 			= this.pickUp;
									document.onmouseup 			= this.dropDown;
										// document.onmousemove 		= this.moveAway;
									node.onmousemove 			= this.moveAway;
									// exctract the limits from the class parameters
									this.grid.x	=	parseInt(classBehaviour.getClassParameter(node, 'gridX', null));
									this.grid.y	=	parseInt(classBehaviour.getClassParameter(node, 'gridY', null));
									this.minPos.x	=	parseInt(classBehaviour.getClassParameter(node, 'limitLeft', null));
									this.minPos.y	=	parseInt(classBehaviour.getClassParameter(node, 'limitTop', null));
									this.maxPos.x	=	parseInt(classBehaviour.getClassParameter(node, 'limitRight', null));
									this.maxPos.y	=	parseInt(classBehaviour.getClassParameter(node, 'limitBottom', null));
									// saved position
									this.restore(node);
								}
			this.restore 	= 	function(objNode){
									// is lib_cookies available
									if(typeof(setCookie)!='undefined'){
										var strStyles, arrStyles;
										// retrieve styles string
										strStyles = getCookie('dragposition');					
										// were any styles recovered
										if(strStyles!=null){
											arrStyles = strStyles.split(',');
											// does the stored positions match the object
											if(arrStyles[0]==objNode.id && arrStyles.length>2){
												objNode.style.left = arrStyles[1];
												objNode.style.top = arrStyles[2];
											}
										}
									}
								}
			this.store 		= 	function(objNode){
									// is lib_cookies available
									if(typeof(setCookie)!='undefined'){
										// store styles
										setCookie('dragposition', objNode.id + ',' + objNode.style.left + ',' + objNode.style.top, null, '/', null, null);
									}
								}
			/* events */
			this.pickUp 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dnd = classBehaviour.dragAndDrop;
									// accept no new pickups before dropdown
									if(dnd.pickupObj==null){
										// store the object being picked up
										dnd.node = objNode;
										// store pickup location
										dnd.pickup.x = (typeof(event)!='undefined') ? event.clientX : that.clientX ;
										dnd.pickup.y = (typeof(event)!='undefined') ? event.clientY : that.clientY ;
										dnd.pickup.z = (objNode.style.zIndex=='') ? objNode.style.zIndex : 0;
										// default starting position if none was given
										if(objNode.style.position!='absolute') objNode.style.position = 'absolute';
										if(objNode.style.left=='') objNode.style.left = /*dnd.pickup.x +*/ '0px'; 
										if(objNode.style.top=='') objNode.style.top = /*dnd.pickup.y +*/ '0px';
										// promote z position
										objNode.style.zIndex = 1024;
									}
									// cancel browser mouse handler
									return false;
								}
			this.dropDown 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dnd = classBehaviour.dragAndDrop;
									// only if a pickup is active
									if(dnd.node!=null){
										// snap coordinates to grid
										if(dnd.grid.x>0) dnd.node.style.left = Math.round(parseInt(dnd.node.style.left)/dnd.grid.x)*dnd.grid.x + "px";
										if(dnd.grid.y>0) dnd.node.style.top = Math.round(parseInt(dnd.node.style.top)/dnd.grid.y)*dnd.grid.y + "px";
										// restore z position
										dnd.node.style.zIndex = dnd.pickup.z;
										// store the position in a cookie
										dnd.store(dnd.node);
										// release the picked up object
										dnd.node = null;
										// clear pickup location
										dnd.pickup.x = null;
										dnd.pickup.y = null;
										dnd.pickup.z = null;
									}
									// cancel browser mouse handler
									return false;
								}
			this.moveAway 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dnd = classBehaviour.dragAndDrop;
									// only if a pickup is active
									if(dnd.node!=null){
										// mouse position
										dnd.mouse.x = (typeof(event)!='undefined') ? event.clientX : that.clientX ;
										dnd.mouse.y = (typeof(event)!='undefined') ? event.clientY : that.clientY ;
										// current object position
										dnd.style.x = (dnd.node.style.left.indexOf('px')<0) ? 0 : parseInt(dnd.node.style.left) ;
										dnd.style.y = (dnd.node.style.top.indexOf('px')<0) ? 0 : parseInt(dnd.node.style.top) ;
										// calculate new object position
										var newXpos = dnd.style.x + dnd.mouse.x - dnd.pickup.x;
										var newYpos = dnd.style.y + dnd.mouse.y - dnd.pickup.y;
										// limit new object position
										if(newXpos<dnd.minPos.x) newXpos = dnd.minPos.x;
										if(newXpos>dnd.maxPos.x) newXpos = dnd.maxPos.x;
										if(newYpos<dnd.minPos.y) newYpos = dnd.minPos.y;
										if(newYpos>dnd.maxPos.y) newYpos = dnd.maxPos.y;
										// apply new object position
										if(dnd.pickup.x!=null) dnd.node.style.left = newXpos + 'px';
										if(dnd.pickup.y!=null) dnd.node.style.top = newYpos + 'px';
										// update pickup location
										dnd.pickup.x = dnd.mouse.x;
										dnd.pickup.y = dnd.mouse.y;
										// execute custom event handler
										if(dnd.onMove!=null) dnd.onMove(dnd.node);
									}
									// cancel browser mouse handler
									return false;
								}
		}
			function Coordinates(x,y,z){
				this.x = x;
				this.y = y;
				this.z = z;
			}
		// add this function to the classbehaviour object
		classBehaviour.dragAndDrop = new DragAndDrop;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.dragAndDrop;

	// Correlate a dragable object to an input value
		// define this class behaviour
		function SliderInput(){
			/* properties */
			this.name 			= 	'sliderInput';
			this.allowNudge	=	true;
			/* methods */
			this.start			=	function(node){
										// event
										node.parentNode.onclick	= this.nudgeInput;
										// get the target Id
										valueToId =	classBehaviour.getClassParameter(node, 'valueToId', null);
										// get the object
										valueToObject = document.getElementById(valueToId);
										// assign the event handler
										valueToObject.onchange = this.inputToSlider;
										// add the drag and drop classbehaviour and give it out event handlers
										classBehaviour.dragAndDrop.onMove = this.sliderToInput;
										classBehaviour.dragAndDrop.start(node); 
										// trigger the starting value
										this.inputToSlider(valueToObject);
										// allow nudging
										this.allowNudge = true;
									}
			/* events */
			this.inputToSlider = 	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var sli = classBehaviour.sliderInput;
										// get the the slider to sync with from the classname
										sliderTarget = objNode;
										sliderButtonId = classBehaviour.getClassParameter(sliderTarget, 'valueFromId', null);
										sliderButton = document.getElementById(sliderButtonId);
										// get the limit values from the slider
										curValue	=	parseFloat(sliderTarget.value);
										minValue	=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'minValue', null));
										maxValue	=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'maxValue', null));
										minPos		=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitLeft', null));
										maxPos		=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitRight', null));
										// correct improper input
										if(isNaN(curValue)){
											curValue = Math.round((maxValue-minValue)/2 + minValue);
											sliderTarget.value = curValue;
										}
										// apply limits
										if(curValue>maxValue){curValue = maxValue; sliderTarget.value = curValue;}
										if(curValue<minValue){curValue = minValue; sliderTarget.value = curValue;}
										// adjust slider
										sliderButton.style.left 	= 	Math.round(
																			(curValue - minValue) / (maxValue - minValue) * (maxPos - minPos) + minPos
																		) + 'px';
									}
			this.sliderToInput	= 	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dnd = classBehaviour.dragAndDrop;
										var sli = classBehaviour.sliderInput;
										// disable the onclick on the sliderTrack 
										sli.allowNudge = false ;
										// get the the input field to sync with from the classname
										sliderButton	=	objNode;
										sliderTargetId	=	classBehaviour.getClassParameter(sliderButton, 'valueToId', null);
										sliderTarget	=	document.getElementById(sliderTargetId);
										// get the limit values from the slider
										curValue	=	parseFloat(sliderTarget.value);
										minValue	=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'minValue', null));
										maxValue	=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'maxValue', null));
										minPos		=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitLeft', null));
										maxPos		=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitRight', null));
										// translate the slider value to the input box
										sliderTarget.value 	= 	Math.round(
																	(dnd.style.x - dnd.minPos.x) / (dnd.maxPos.x - dnd.minPos.x) * 
																	(maxValue - minValue) + minValue
																);
									}
			this.nudgeInput	=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dnd = classBehaviour.dragAndDrop;
										var sli = classBehaviour.sliderInput;
										// if nudging is allowed
										if(sli.allowNudge){
											// slider objects
											sliderTrack		=	objNode;
											sliderButton	=	sliderTrack.getElementsByTagName('div')[0];
											sliderTargetId	=	classBehaviour.getClassParameter(sliderButton, 'valueToId', null);
											sliderTarget	=	document.getElementById(sliderTargetId);
											// slider limits
											minPos			=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitLeft', null));
											maxPos			=	parseInt(classBehaviour.getClassParameter(sliderButton, 'limitRight', null));
											minValue		=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'minValue', null));
											maxValue		=	parseFloat(classBehaviour.getClassParameter(sliderButton, 'maxValue', null));
											// click position
											clickX = (typeof(event)!='undefined') ? event.x : that.layerX ;
											// slider position
											sliderX = (sliderButton.style.left.indexOf('px')<0) ? 0 : parseInt(sliderButton.style.left) ;
											// nudge the value of the slider closer towards the click
											newValue = Math.round(parseInt(sliderTarget.value) + ((clickX - sliderX) / (maxPos - minPos) * (maxValue - minValue)) / 2);
											// apply limits
											if(newValue>maxValue){newValue = maxValue; sliderTarget.value = curValue;}
											if(newValue<minValue){newValue = minValue; sliderTarget.value = curValue;}
											// adjust slider and input
											sliderTarget.value			=	newValue;
											sliderButton.style.left 	= 	Math.round(
																				(newValue - minValue) / (maxValue - minValue) * (maxPos - minPos) + minPos
																			) + 'px';
										// else the nudging was locked
										}else{
											// unlock the nudging
											sli.allowNudge = true;
										}
									}
		}
		// add this function to the classbehaviour object
		classBehaviour.sliderInput = new SliderInput;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.sliderInput;
		
	// Open print dialog
		// define this class behaviour
		function OpenAsPrintable(){
			/* properties */
			this.name 		= 	'openAsPrintable';
			/* methods */
			this.start		=	function(node){
									node.onclick = this.process;
								}
			this.process 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// If there is a demo popup
									if(document.getElementById('tgtPopTitle')){
										// copy the title to the print popup title
										document.getElementById('tgtPopTitle').innerHTML = document.getElementById('content').getElementsByTagName('h1')[0].innerHTML;
										// copy the content tot the print popup content
										document.getElementById('tgtPopText').innerHTML = (document.getElementById('content').innerHTML.indexOf('</h1>')>-1) ? document.getElementById('content').innerHTML.split('</h1>')[1] : document.getElementById('content').innerHTML.split('</H1>')[1];
										// show the print popup
										classBehaviour.openLayerPopUp.show(document.getElementById('popup0'));
										// open the print dialog
										setTimeout("window.print();",2048);
									}else{
										window.print();
									}
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.openAsPrintable = new OpenAsPrintable;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openAsPrintable;
		
	// Open links in a popup
		// define this class behaviour
		function OpenAsPopUp(){
			/* properties */
			this.name 		= 	'openAsPopUp';
			this.window		=	null;
			/* methods */
			this.start		=	function(node){
									node.onclick = this.process;
								}
			/* events */
			this.process 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var oap = classBehaviour.openAsPopUp;
									// get the parameters from the classname
									var strWidth 		= 'width=' + classBehaviour.getClassParameter(objNode, 'width', '630');
									var strHeight 		= ',height=' + classBehaviour.getClassParameter(objNode, 'height', '385');
									var strLeft			= ',left=' + classBehaviour.getClassParameter(objNode, 'left', '');
									var strTop			= ',top=' + classBehaviour.getClassParameter(objNode, 'top', '');
									var strToolbars 	= ',toolbar=' + classBehaviour.getClassParameter(objNode, 'toolbar', 'no');
									var strScrolling 	= ',scrollbars=' + classBehaviour.getClassParameter(objNode, 'scrollbars', 'no');
									var strStatus 		= ',status=' + classBehaviour.getClassParameter(objNode, 'status', 'no');
									var strResize 		= ',resizable=' + classBehaviour.getClassParameter(objNode, 'resizable', 'yes');
									var strLocation 	= ',location=' + classBehaviour.getClassParameter(objNode, 'location', 'no');
									var strMenu 		= ',menu=' + classBehaviour.getClassParameter(objNode, 'menu', 'no');
									var strName 		= classBehaviour.getClassParameter(objNode, 'name', 'popup');
									// open requested window
									oap.window = window.open(objNode.getAttribute('href'), strName, strWidth+strHeight+strScrolling+strToolbars+strStatus+strResize+strLocation+strMenu+strLeft+strTop);
									oap.window.focus();
									// cancel click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.openAsPopUp = new OpenAsPopUp;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openAsPopUp;
		
	// Triggers all validateInput class behaviours within a node after the onsubmit event.',
		// define this class behaviour
		function ValidateAllInput(){
			/* properties */
			this.name 		= 	'validateAllInput';
			/* methods */
			this.start		=	function(node){
									// set the form validation eventhandler
									node.onsubmit = classBehaviour.validateInput.all;
									// if there's a place for a summary store the id
									classBehaviour.validateInput.summaryId = classBehaviour.getClassParameter(node, 'summaryId', null);
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.validateAllInput = new ValidateAllInput;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateAllInput;

	// Validate the value of a for element to a predefined regular expression
		// define this class behaviour
		function ValidateInput(){
			/* properties */
			this.name 		= 	'validateInput';
			this.summaryId	=	null;
			/* methods */
			this.start	=	function(node){
								// was a summary requested?
								this.summaryId = classBehaviour.getClassParameter(node, 'summaryId', this.summaryId);
								// apply the event to all form-element childnodes
								var nodes = (this.isFormElement(node)) ? new Array(node) : node.getElementsByTagName('*');
								for(var a=0; a<nodes.length; a++){
									if(this.isFormElement(nodes[a])){
										// give it the event handler
										nodes[a].onfocus = this.clear;
										nodes[a].onblur = this.input;
										nodes[a].onchange = this.input;
										// if the form is small enough one could revalidate the whole thing at every change
											//nodes[a].onblur = this.all;
											//nodes[a].onchange = this.all;
										// and the parent's classname
										nodes[a].className = node.className;
									}
								}
								// if there's a greyed axplanation
								hasExplanation = classBehaviour.getClassParameter(node, 'explanation', 'no');
								if(hasExplanation=='yes'){
									// remove it if a value is restored by a form manager
									setTimeout("classBehaviour.validateInput.restore('"+node.id+"','"+node.value+"')", 1000);
								}
							}
			this.all 	= 	function(that){
								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
								var vi = classBehaviour.validateInput;
								var booPassed = true;
								// get all subnodes in the form
									//var objSubNodes = objNode.getElementsByTagName("*") ;
									var objSubNodes = document.getElementsByTagName("*") ;
								// for all nodes
								for(var intA=0; intA<objSubNodes.length; intA++){
									// Does this node have the validateInput put class? Invoke the validator function upon it.
									if(objSubNodes[intA].className.toLowerCase().indexOf('validateinput')>-1 && vi.isFormElement(objSubNodes[intA])) booPassed = (vi.input(objSubNodes[intA], false) && booPassed);
								}
								// is a summary required
								if(vi.summaryId){
									summaryObj = document.getElementById(vi.summaryId);
									summaryTxt = '';
									// for all nodes
									for(var a=0; a<objSubNodes.length; a++){
										// if this node a visible warning
										if(objSubNodes[a].className.indexOf('validationWarning')>-1 && objSubNodes[a].style.display!='none'){
											// copy it's contents to the summary text
											summaryTxt += '<li>' + objSubNodes[a].innerHTML + '</li>';
										}
									}
									// add the summary text to the summary
									summaryObj.innerHTML = (summaryTxt.length>0) ? '<ul>' + summaryTxt + '</ul>' : '' ;
								}
								// is the form valid enough?
								return booPassed;
							}
			this.input = 	function(that, override){
								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
								var vi = classBehaviour.validateInput;
								// default validator values
								var booEmptyValidator, booValueValidator;
								// get the type of validation required			
								strValidatorName	= classBehaviour.getClassParameter(objNode, 'type', '');
								allowEmpty			= classBehaviour.getClassParameter(objNode, 'allowEmpty', 'no');
								ifCheckedId			= classBehaviour.getClassParameter(objNode, 'ifCheckedId', null);
								hasExplanation 		= classBehaviour.getClassParameter(objNode, 'explanation', 'no');
								// check a special dependency on a parent checkbox
								if(ifCheckedId){
									if(!document.getElementById(ifCheckedId).checked) allowEmpty = 'yes';
								}
								// validation tests
									// empty test	objNode.value!=''
									booEmptyValidator = (allowEmpty=='yes' && (objNode.value=='' || hasExplanation=='yes'));
									// bizarre exception for MSIE 5.0
									if(navigator.appVersion.indexOf('MSIE 5.0')>-1 && strValidatorName=='money') strValidatorName = null;
									// test expressions
									switch(strValidatorName){
										// regular expression tests
										case 'email' : 
											booValueValidator = (objNode.value.match(/^[\w\.\-\,\+]+@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/)!=null);
											break;
										case 'phone' : 
											booValueValidator = (objNode.value.match(/(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\-\s]{10}$)/)!=null); 
											break;
										case 'dutchzipcode' : 
											booValueValidator = (objNode.value.match(/^[0-9]{4}\s{0,1}[a-zA-Z]{2}$/)!=null); 
											break;
										case 'date' : 
											booValueValidator = (objNode.value.match(/^\d{4}\-\d{1,2}\-\d{1,2}$/)!=null);
											// booRegExpValidator = (objNode.value.match(/^\d{1,2}\-\d{1,2}\-(\d{2}|\d{4})$/)!=null); 
											break;
										case 'number' : 
											booValueValidator = (objNode.value.match(/^[0-9]+$/)!=null); 
											break;
										case 'money' :
											booValueValidator = (objNode.value.match(/^[0-9]+(\.[0-9]{1,2})?$/)!=null); 
											break;
										case 'alphanumeric' :
											booValueValidator = (objNode.value.match(/^[a-zA-Z0-9]/)!=null);
											break;
										// custom tests
										case 'bankaccount' :
											booValueValidator = vi.bankAccount(objNode);
											break;
										case 'isradiochecked' :
											booValueValidator = vi.isRadioChecked(objNode);
											break;
										case 'anyofthesechecked' : 
											booValueValidator = vi.anyOfTheseChecked(objNode);
											break;
										case 'text' :
											booValueValidator = (objNode.value!="");
											break;
										default :
											booValueValidator = true;
									}
								// does the input validate when the field is not empty or not allowed to be empty
								validates = (!booEmptyValidator) ? (booValueValidator && hasExplanation=='no') : true ;
								// show or hide the warning message based on the validator's match
								vi.warning(objNode, validates);
								// return a pass of fail boolean to whoever may want to know the results of the test
								return (override!=null) ? validates : override;
							}
			this.warning =	function(objNode, status){
								var vi = classBehaviour.validateInput;
								// for all inputs with the same name
								allWithSameName = document.getElementsByName(objNode.name);
								for(var b=0; b<allWithSameName.length; b++){
									objNode = allWithSameName[b];
								// Show the foldout warning
									// is the warning node named?
									idWarningNode		= classBehaviour.getClassParameter(objNode, 'warningId', null);
									// check if the next node is for summaries
									nextNode 			= (objNode.nextSibling.nodeName.indexOf("text")<0) ? objNode.nextSibling : objNode.nextSibling.nextSibling ;
									// if there's an id given for thewarning message use it. Otherwise use the next node
									objWarningNode		= (idWarningNode) ? document.getElementById(idWarningNode) : nextNode ;
									// show or hide the warning, if the warning node was found
									if(objWarningNode) if(objWarningNode.className.indexOf('validationWarning')>-1) objWarningNode.style.display = (status) ? 'none' : 'block' ;
								// Highlight the label
									// get all labels
									allLabels = document.getElementsByTagName('label');
									// for all labels
									for(var a=0; a<allLabels.length; a++){
										// if the label matches this input
										if(allLabels[a].getAttributeNode('for').nodeValue == objNode.id){
											// add or remove the warning colour
											if(allLabels[a].parentNode.className.indexOf('noWarning')<0 && allLabels[a].className.indexOf('noWarning')<0) allLabels[a].className = (status) ? '' : 'warning' ;
										}
									}
								}
							}
			this.clear	=	function(objNode){
								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
								// if there was an explanation provides as a value
								hasExplanation = classBehaviour.getClassParameter(objNode, 'explanation', 'no');
								if(hasExplanation=='yes'){
									// clear the value
									objNode.value = '';
									// che change the class back to normal
									objNode.className = objNode.className.replace('explanation_yes', 'explanation_no');
								}
							}
			this.restore =	function(id, value){
								var objNode = document.getElementById(id);
								// if this input has a value which doesn't match the current value, a form manager has restored a value
								if(objNode.value!=value){
									objNode.className = objNode.className.replace('explanation_yes','explanation_no');
								}
							}
			/* utility functions */
			this.isFormElement		=	function(objNode){
											return (objNode.nodeName=='INPUT' || objNode.nodeName=='SELECT' || objNode.nodeName=='TEXTAREA');
										}
			/* custom validation functions */
			this.bankAccount 		= 	function(objNode){
											var intDeel, intRest;
											var strInput = objNode.value;
											var intTot=0;
											if (strInput.length!=9){
												return false;
											}else{
												for (i=0; i<strInput.length; i++) intTot += strInput.substr(i,1) * (9 - i);
												intDeel = intTot/11;
												intRest = intTot%11;
												return (intRest==0);
											}
										}
			this.isRadioChecked	=	function(objNode){
											// get all inputs with this name
											allInputs = document.getElementsByTagName('input');
											// for all inputs
											for(var a=0; a<allInputs.length; a++){
												// If the input has the same name. 
												if(allInputs[a].name == objNode.name){
													// If the input is checked set the validator to true
													if(allInputs[a].checked) return true;
												}
											}
											return false;
										}
			this.anyOfTheseChecked	=	function(objNode){
												// default validatie
												anyChecked = false;
												// get all inputs from the parentnode
												allChecks = objNode.parentNode.parentNode.getElementsByTagName('input');
												// for all inputs
												for(var a=0; a<allChecks.length; a++){
													// if this checkbox is checked remember is
													if(allChecks[a].checked) anyChecked = true;
												}
												return anyChecked;
											}
		}
		// add this function to the classbehaviour object
		classBehaviour.validateInput = new ValidateInput;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateInput;
		
	// Disable form elements during a submit, to avoid multiple submits on slow servers
		// define this class behaviour
		function DisableAfterSubmit(){
			// properties
			this.name 		= 	'disableAfterSubmit';
			// methods
			this.start		=	function(node){
									node.onsubmit = this.disable;
									// get all elements in this form
									allNodes = node.getElementsByTagName("*");
									// is this a form using microsoft's postbacks
									if(typeof(__doPostBack)!='undefined'){
										// for all nodes in this form
										for(var a=0; a<allNodes.length; a++){
											// if this form element has a _dopostback
											if(allNodes[a].onchange!=null){
												if(allNodes[a].onchange.toString().indexOf('__doPostBack')>-1){
													// overrule microsoft's postback event
													allNodes[a].onchange = this.disable;
												}
											}
											if(allNodes[a].onclick!=null){
												if(allNodes[a].onclick.toString().indexOf('__doPostBack')>-1){
													// overrule microsoft's postback event
													allNodes[a].onclick = this.disable;
												}
											}
										}
									}
									// if there's also a validation behaviour defined, trigger it
									if(node.className.indexOf('validateAllInput')>-1) classBehaviour.validateAllInput.start(node);
								}
			// events
			this.disable	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// trigger microsoft's postback
									if(typeof(__doPostBack)!='undefined') __doPostBack(objNode.id, objNode.value);
									// get all elements in this form
									allNodes = document.getElementsByTagName("*");
									// for all nodes in this form
									for(var a=0; a<allNodes.length; a++){
										// if this is a form element
										if(
											allNodes[a].nodeName.indexOf('INPUT')>-1 ||
											allNodes[a].nodeName.indexOf('SELECT')>-1 ||
											allNodes[a].nodeName.indexOf('TEXTAREA')>-1
										){
											// disable the form element
											allNodes[a].disabled = true;
											// deny focus
											allNodes[a].onfocus = blur;
										}
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.disableAfterSubmit = new DisableAfterSubmit;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.disableAfterSubmit;
		
	// Manage all event handler for an imagemap
		// define this class behaviour
		function ImageMap(){
			// properties
			this.name 		= 	'imageMap';
			this.map		=	new Map;
			this.areas		=	new Areas;
			// methods
			this.start		=	function(node){
									// start the storing of the map object
									node.onmouseover = this.map.over;
									this.map.over(node);
									// get all areas in this map
									areas = document.getElementById(this.map.name).getElementsByTagName('area');
									// for all areas in this map
									for(var a=0; a<areas.length; a++){
										// cache it's image equivalent
										this.cache(node.src.replace(this.map.passive, areas[a].id));
										// give the area event handlers
										areas[a].onmouseover = this.areas.over;
										areas[a].onmouseout = this.areas.out;
									}
								}
			// events
			this.cache		= 	function(url) {
										var imp = classBehaviour.imageMap;
										// preload the image into an array
										imp.map.images[imp.map.images.length] = new Image();
										imp.map.images[imp.map.images.length-1].src = url;
								}
		}
			function Map(){
				// properties
				this.object	=	null;
				this.name		=	null;
				this.passive	=	'nederland';
				this.images		=	new Array();
				// methods
				this.over		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var imp = classBehaviour.imageMap;
										// store the currently active map
										imp.map.object = objNode;
										imp.map.name = objNode.getAttributeNode('usemap').value.replace('#','');
									}
			}
			function Areas(){
				// methods
				this.over	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var imp = classBehaviour.imageMap;
									// apply the area id to the map's source
									imp.map.object.src = imp.map.object.src.replace(imp.map.passive, objNode.id);
								}
				this.out	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var imp = classBehaviour.imageMap;
									// apply the area id to the map's source
									imp.map.object.src = imp.map.object.src.replace(objNode.id, imp.map.passive);
								}
			}
		
		// add this function to the classbehaviour object
		classBehaviour.imageMap = new ImageMap;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.imageMap;

	// display the title of an image in a popup layer
		// define this class behaviour
		function TitleMouseHover(){
			// properties
			this.name 			= 	'titleMouseHover';
			this.cache 		= 	new Array();
			this.limitRight	=	9999;
			this.limitLeft		=	0;
			this.mouseX		=	0;
			this.mouseY		=	0;
			// methods
			this.start			=	function(node){
										this.cacheImages(node);
										node.onmouseover = this.addHover;
										node.onmouseout = this.remHover;
										node.onmousemove = this.positionHover;
										// set limits
										this.limitRight = parseInt(classBehaviour.getClassParameter(node, 'limitRight', '9999'));
										this.limitLeft = parseInt(classBehaviour.getClassParameter(node, 'limitLeft', '0'));
										// start mouse position manager, if present
										//if(setMouseHandler) setMouseHandler('hoverCanvas');
									}
			this.cacheImages	 = 	function(that) {
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// replace link by hover
										var cacheIdx = this.cache.length;
										// hover version
										this.cache[cacheIdx] = new Image();
										this.cache[cacheIdx].src = objNode.src.replace('_link','_hover');
										// active version
										this.cache[cacheIdx+1] = new Image();
										this.cache[cacheIdx+1].src = objNode.src.replace('_link','_active');
									}
			// events
			this.positionHover	=	function(that){
										tmh = classBehaviour.titleMouseHover;
										objHover = document.getElementById('hoverTitle');
										// mouse position
										tmh.mouseX = (typeof(event)!='undefined') ? event.clientX : that.clientX ;
										tmh.mouseY = (typeof(event)!='undefined') ? event.clientY : that.clientY ;
										// label position
										objHover.style.left = (tmh.mouseX>tmh.limitRight) ? tmh.limitRight + 'px' : tmh.mouseX + 'px';
										objHover.style.top =  tmh.mouseY + 'px';
									}
			this.addActive 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// replace link by active
									objNode.src = objNode.src.replace('_link','_active');
									// replace hover by active
									objNode.src = objNode.src.replace('_hover','_active');
								}
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var objHover = document.getElementById('hoverTitle');
									// replace link by hover
									objNode.src = objNode.src.replace('_link','_hover');
									// fill the label with the contents of the title attribute
									objHover.innerHTML = objNode.title.replace('{img:','<img src="').replace('}','" class="left"/>');
									// show the title div
									objHover.style.display = 'block';
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// replace link by hover
									objNode.src = objNode.src.replace('_hover','_link');
									// hide the title div
									objHover = document.getElementById('hoverTitle');
									objHover.style.display = 'none';
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.titleMouseHover = new TitleMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.titleMouseHover;
		
/* TODO: document this */
	// Defines something a layer popup and automaticaly opens it after a set time
		// define this class behaviour
		function ThumbnailToPhoto(){
			/* properties */
			this.name 		= 	'thumbnailToPhoto';
			this.busy		=	false;
			this.index		=	0;
			this.cache		=	new Array();
			/* methods */
			this.start		=	function(node){
									// set the event for this thumbnail
									node.onclick = this.showPhoto;
									// get the target buffers
									var targetId = classBehaviour.getClassParameter(node, 'id', 'photoTarget');
									var buffers = document.getElementById(targetId).getElementsByTagName('li');
									// give the buffers default id's
									buffers[0].id = 'thumbnailTarget' + this.index;
									buffers[1].id = 'thumbnailTarget' + this.index + 1;
									this.index += 2;
									// set the initial view state
									buffers[0].style.display = 'block';
									buffers[1].style.display = 'none';
									// cache the referenced image
									cacheIndex = this.cache.length;
									this.cache[cacheIndex] = new Image();
									this.cache[cacheIndex].src = node.href;
								}
			/* events */
			this.showPhoto	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var ttp = classBehaviour.thumbnailToPhoto;
									// set the thumbnails to passive
									thumbnails = objNode.parentNode.parentNode.getElementsByTagName('img');
									for(var a=0; a<thumbnails.length; a++) thumbnails[a].src = thumbnails[a].src.replace('_active','_link');
									// set the active thumbnail
									thumbnail = objNode.getElementsByTagName('img')[0];
									thumbnail.src = thumbnail.src.replace('_link','_active').replace('_hover','_active');
									// get the display buffers
									var targetId = classBehaviour.getClassParameter(objNode, 'id', 'photoTarget');
									bufferA = document.getElementById(targetId).getElementsByTagName('li')[0];
									bufferB = document.getElementById(targetId).getElementsByTagName('li')[1];
									// get the active buffer 
									bufferIn = (bufferA.style.display=='none') ? bufferA : bufferB;
									bufferOut = (bufferIn==bufferA) ? bufferB : bufferA ;
									// get the target values from the thumbnail
									targetAlt = objNode.parentNode.getElementsByTagName('div')[0].innerHTML;
									targetSrc = objNode.href;
									// if there is no fade in progress and the target os not the same as the current image
									if(!ttp.busy && targetSrc!=bufferOut.src){
										// position the incoming element 
										bufferOut.style.position = 'absolute';
										bufferOut.style.top = '0px';
										bufferOut.style.left = '0px';
										bufferOut.style.zIndex = '2000';
										bufferIn.style.position = 'relative';
										bufferIn.style.top = '0px';
										bufferIn.style.zIndex = '1000';
										// lock this function
										ttp.busy = true;
										// set the new source for the image from the clicked thumbnail
										bufferIn.getElementsByTagName('span')[0].innerHTML = targetAlt;
										bufferIn.getElementsByTagName('img')[0].src = targetSrc;
										// call the fader after the image has loaded
										bufferIn.getElementsByTagName('img')[0].onload = 	new function(){
																								// trigger the crossfade
																								classBehaviour.fader.crossFade(bufferIn.id, bufferOut.id, 0, 10, 50, 'classBehaviour.thumbnailToPhoto.unlock()');
																							};
									}
									// cancel the click
									return false;
								}
			this.unlock		=	function(){
									classBehaviour.thumbnailToPhoto.busy = false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.thumbnailToPhoto = new ThumbnailToPhoto;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.thumbnailToPhoto;
		
	// clear a form element filled with a help text
		// define this class behaviour
		function EmptyOnFocus(){
			/* properties */
			this.name 		= 	'emptyOnFocus';
			/* methods */
			this.start		=	function(node){
									node.onfocus = this.clear;
								}
			/* events */
			this.clear		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// clear the contents if this is the first time
									if(objNode.className.indexOf('wasEmptied')<0){
										// clear this field
										objNode.value = '';
										// mark this input as cleared
										objNode.className += ' wasEmptied';
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.emptyOnFocus = new EmptyOnFocus;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.emptyOnFocus;
		
	// Make fading menu
		// define this class behaviour
		function FadingMenu(){
			/* properties */
			this.name 		= 	'fadingMenu';
			this.current 	=	null;
			this.always		=	null;
			this.locked		=	false;
			this.timeout	=	null;
			/* methods */
			this.start		=	function(node){
									this.process(node);
								}
			this.process 	= 	function(objNode){
									var objNodes, objMatch;
									// apply events to all LIs
									objNodes = objNode.childNodes;
									for(var a=0; a<objNodes.length; a++){
										if(objNodes[a].nodeName=="LI"){
											// if this LI as a link
											objLinks = objNodes[a].getElementsByTagName('A');
											if(objLinks.length>0){
												// mouseover events
												objLinks[0].onmousemove	= this.open;
												objNode.onmouseout	= this.delay;
												// store the last link marked active
												this.always = (objLinks[0].className.indexOf('active')>-1) ? objLinks[0] : this.always ;
											}
											// if this LI has a child UL, give it a random id
											objLists = objNodes[a].getElementsByTagName('UL');
											if(objLists.length>0){
												objLists[0].id = 'sub_' + Math.round(Math.random() * 10000);
											}
										}
									}
									// open the starting node
									this.open(this.always, true);
								}
			/* events */
			this.open 		= 	function(that, noFade){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fm = classBehaviour.fadingMenu;
									// cancel the closing timer
									clearTimeout(fm.timeout);
									// if not locked
									if(!fm.locked && objNode!=fm.current){
										// PREVIOUS MENU
										if(fm.current){
											// deactivate the link
// TODO: stylesheet link
											// deactivate the image
											linkImage = fm.current.getElementsByTagName('IMG')[0];
											linkImage.src = linkImage.src.replace('_hover','_link');
											// store the sub-menu
											linkMenu = fm.current.parentNode.getElementsByTagName('UL');
											fadeCloseId = (linkMenu.length>0) ? linkMenu[0].id : '' ;
										}else{
											fadeCloseId = '';
										}
										// OPEN NEW MENU
										if(objNode){
											// deactivate the link
// TODO: stylesheet link
											// activate the image
											linkImage = objNode.getElementsByTagName('IMG')[0];
											linkImage.src = linkImage.src.replace('_link','_hover');
											// store the sub-menu
											linkMenu = objNode.parentNode.getElementsByTagName('UL');
											fadeOpenId = (linkMenu.length>0) ? linkMenu[0].id : '' ;
										}
										// store the current link 
										fm.current = objNode;
										// SET THE FADE
										if(noFade){
											if(fadeCloseId!='') document.getElementById(fadeCloseId).style.display = 'none';
											if(fadeOpenId!='') document.getElementById(fadeOpenId).style.display = 'block';
										}else{
											fm.locked = true;
											classBehaviour.fader.crossFade(fadeOpenId, fadeCloseId, 0, 10, 20, 'classBehaviour.fadingMenu.locked=false;');
										}
									}
								}
			this.delay		=	function(){
									var fm = classBehaviour.fadingMenu;
									// clear the previous delay
									clearTimeout(fm.timeout);
									// delay the closing
									fm.timeout = setTimeout('classBehaviour.fadingMenu.close()', 1024);
								}
			this.close 		= 	function(){
									var fm = classBehaviour.fadingMenu;
									// if not locked
									if(!fm.locked){
										fm.open(fm.always);
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fadingMenu = new FadingMenu;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fadingMenu;
	
	// scroll a list of options
		// define this class behaviour
		function ScrollList(){
			/* properties */
			this.name 		= 	'scrollList';
			this.list		=	null;
			this.focus		=	null;
			this.speed		=	1;
			this.idleTimer	=	null;
			/* methods */
			this.start		=	function(node){
									// add the right event handler to the button
									node.onmousedown = (classBehaviour.getClassParameter(node, 'scrollDirection', 'down')=='up') ? this.startUp : this.startDown ;
									node.onmouseover = this.cancel;
									node.onmouseup = this.cancel;
									node.onmouseout = this.cancel;
									// prepare the refered list
									id = classBehaviour.getClassParameter(node, 'id', 'scrollList0');
									this.prepareList(id);
								}
			/* events */
			this.startUp	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var sl = classBehaviour.scrollList;
									// reset all scrolling
									id = sl.reset(objNode);
									// start the scrolling
									sl.scrollUp(id);
								}
			this.startDown	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var sl = classBehaviour.scrollList;
									// reset all scrolling
									id = sl.reset(objNode);
									// start the scrolling
									sl.scrollDown(id);
								}
			/* methods */
			this.idle			=	function(id){
										classBehaviour.scrollList.speed = 1;
										classBehaviour.scrollList.scrollDown(id);
									}
			this.prepareList	=	function(id) {
										scroller = document.getElementById(id);
										// if this list has not has not been prepared before
										if(scroller.className.indexOf('doubled')<0){
											// copy the content twice
											scrollList = scroller.getElementsByTagName('UL')[0];
											scrollList.innerHTML += scrollList.innerHTML + scrollList.innerHTML;
											// set the scroller halfway
											var contentWidth = scrollList.offsetWidth;
											scrollList.style.marginLeft = '-' + Math.round(contentWidth/3) + 'px';
											// mark the list as prepared
											scroller.className += ' doubled';
											// start the idle scrolling
											classBehaviour.scrollList.idle(id);
										}
									}
			this.reset			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var sl = classBehaviour.scrollList;
										// clear the idle timer
										clearTimeout(sl.idleTimer);
										// stop the scrolling
										clearTimeout(sl.timeout);
										// reset the speed
										sl.speed = 5;
										// get the target id
										id = classBehaviour.getClassParameter(objNode, 'id', 'scrollList0');
										// set the mouseover
										objNode.src = objNode.src.replace('_link','_hover');
										// pass the id back
										return id;
									}
			this.cancel		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var sl = classBehaviour.scrollList;
										// clear the idle timer
										clearTimeout(sl.idleTimer);
										// stop the scrolling
										clearTimeout(sl.timeout);
										// release the focus
										sl.focus = null;
										// reset the mouseover
										objNode.src = objNode.src.replace('_hover','_link');
										// wait for a while, then start idle scrolling
										id = classBehaviour.getClassParameter(objNode, 'id', 'scrollList0');
										sl.idleTimer = setTimeout('classBehaviour.scrollList.idle("'+id+'")',2000);
									}
			this.scrollUp	=	function(id){
									var sl = classBehaviour.scrollList;
									// how high is the container
									var container = document.getElementById(id);
									var borderWidth = container.offsetWidth;
									// how heigh is the content
									var content = container.getElementsByTagName('UL')[0];
									var contentWidth = content.offsetWidth;
									// where is the content
									var contentScroll = (content.style.marginLeft) ? parseInt(content.style.marginLeft) : 0 ;
									// if the contant can still move
									loopPoint = 0
									resetPoint = -1 * Math.round(contentWidth/3);
									if(contentScroll<loopPoint){
										// move it
										content.style.marginLeft = (contentScroll + sl.speed) + 'px';
									// reset it back to the starting position
									}else{
										content.style.marginLeft = (resetPoint - sl.speed) + 'px';
									}
									// next step
									sl.timeout = setTimeout('classBehaviour.scrollList.scrollUp("' + id + '")', 40);
								}
			this.scrollDown	=	function(id){
									var sl = classBehaviour.scrollList;
									// how high is the container
									var container = document.getElementById(id);
									var borderWidth = container.offsetWidth;
									// how heigh is the content
									var content = container.getElementsByTagName('UL')[0];
									var contentWidth = content.offsetWidth;
									// where is the content
									var contentScroll = (content.style.marginLeft) ? parseInt(content.style.marginLeft) : 0 ;
									// if the contant can still move
									loopPoint = -2 * Math.round(contentWidth/3);
									resetPoint = -1 * Math.round(contentWidth/3);
									if(loopPoint<contentScroll){
										// move it
										content.style.marginLeft = (contentScroll - sl.speed) + 'px';
									// reset it back to the starting position
									}else{
										content.style.marginLeft = (resetPoint - sl.speed) + 'px';
									}
									// next step
									sl.timeout = setTimeout('classBehaviour.scrollList.scrollDown("' + id + '")', 40);
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.scrollList = new ScrollList;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.scrollList;
		
	// make a slideshow from a list of images
		// define this class behaviour
		function SlideshowList(){
			/* properties */
			this.name 		= 	'slideshowList';
			this.locked	=	false;
			/* methods */
			this.start		=	function(node){
									// get the next and previous buttons
									allImgs = node.getElementsByTagName('img');
									// set the event handlers
									allImgs[allImgs.length-1].onclick = this.next;
									allImgs[allImgs.length-2].onclick = this.previous;
								}
			/* events */
			this.next		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									if(!classBehaviour.slideshowList.locked){
										classBehaviour.slideshowList.locked = true;
										// get all slides
										allSlides = objNode.parentNode.getElementsByTagName('li');
										// for all slides
										var activeSlide, nextSlide;
										for(var a=0; a<allSlides.length; a++){
											// if the slide doesn't have an id, make one
											allSlides[a].id = (allSlides[a].id) ? allSlides[a].id : 'slide' + a;
											// if this slide is marked active
											if(allSlides[a].className.indexOf('active')>-1){
												// store the active slide
												activeSlide = allSlides[a];
												// store the next slide
												nextSlide = (a<allSlides.length-1) ? allSlides[a+1] : allSlides[0] ;
											}
										}
										// change the classes
										activeSlide.className = activeSlide.className.replace(' active','').replace('active','');
										nextSlide.className += ' active';
										// fade between the active and next slide
										classBehaviour.fader.crossFade(nextSlide.id, activeSlide.id, 0, 10, 10, "classBehaviour.slideshowList.unlock()");
									}
								}
			this.previous	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									if(!classBehaviour.slideshowList.locked){
										classBehaviour.slideshowList.locked = true;
										// get all slides
										allSlides = objNode.parentNode.getElementsByTagName('li');
										// for all slides
										var activeSlide, nextSlide;
										for(var a=0; a<allSlides.length; a++){
											// if the slide doesn't have an id, make one
											allSlides[a].id = (allSlides[a].id) ? allSlides[a].id : 'slide' + a;
											// if this slide is marked active
											if(allSlides[a].className.indexOf('active')>-1){
												// store the active slide
												activeSlide = allSlides[a];
												// store the next slide
												nextSlide = (a>0) ? allSlides[a-1] : allSlides[allSlides.length-1] ;
											}
										}
										// change the classes
										activeSlide.className = activeSlide.className.replace(' active','').replace('active','');
										nextSlide.className += ' active';
										// fade between the active and next slide
										classBehaviour.fader.crossFade(nextSlide.id, activeSlide.id, 0, 10, 10, "classBehaviour.slideshowList.unlock()");
									}
								}
			this.unlock	=	function(){
									this.locked = false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.slideshowList = new SlideshowList;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.slideshowList;

	// Center landscape or portrait thumbnails in a defined area
		// define this class behaviour
		function CenteredThumbnails(){
			/* properties */
			this.name 		= 	'centeredThumbnails';
			/* methods */
			this.start		=	function(node){
									// get all links in this container
									allLinks = node.getElementsByTagName('a');
									// if this is a single item
									if(allLinks.length==0) allLinks = new Array(node);
									// for all containers
									for(var a=0; a<allLinks.length; a++){
										// get the dimensions of the container
										containerSize = new Array(allLinks[a].offsetWidth, allLinks[a].offsetHeight);
										// get the thumbnail
										thumbnail = allLinks[a].getElementsByTagName('img')[0];
										// get the dimensions of the thumbnail
										thumbnailSize = new Array(thumbnail.offsetWidth, thumbnail.offsetHeight);
										// set the position of the thumbnail
										offsetX = (containerSize[0] - thumbnailSize[0])/2;
										offsetY = (containerSize[1] - thumbnailSize[1])/2;
										thumbnail.style.margin = offsetY + "px " + offsetX + "px " + offsetY + "px " + offsetX + "px";
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.centeredThumbnails = new CenteredThumbnails;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.centeredThumbnails;
		
	// emulates a scrollbar
		// define this class behaviour
		function VirtualScrollbar(){
			/* properties */
			this.name 		= 	'virtualScrollbar';
			this.interval	=	null;
			this.controls	=	null;
			this.offset	=	50;
			/* methods */
			this.start		=	function(node){
									// get all the buttons of the controller
									allControls = node.getElementsByTagName('a');
									this.controls = allControls;
									// set the event handlers for scrolling up
									allControls[0].onmousedown = this.up;
									allControls[0].onmouseup = this.cancel;
									allControls[0].onmouseout = this.cancel;
									// set the event handlers for scrolling down
									allControls[2].onmousedown = this.down;
									allControls[2].onmouseup = this.cancel;
									allControls[2].onmouseout = this.cancel;
									// set the event handlers for the indicator bar
									allControls[1].onmousedown = this.pick;
									allControls[1].onmouseup = this.drop;
									allControls[1].onmousemove = this.drag;
									allControls[1].onmouseout = this.drop;
									document.onmousemove = this.nodrag;
									// set the scrollbar
									document.onmousewheel = this.onWheel;
									if(window.addEventListener) window.addEventListener('DOMMouseScroll', this.onWheel, false);
									// set the initial position
									pageId = classBehaviour.getClassParameter(node, 'id', 'scrollCanvas');
									this.scrollTo(pageId,0);
									// update regularly
									setInterval("classBehaviour.virtualScrollbar.scrollBy('"+pageId+"',0)",500);
								}
/* TODO: hide the scrollbar when it's not needed */
			this.scrollTo	=	function(id, position){
									var vsb = classBehaviour.virtualScrollbar;
									// normalize the position
									if(position>0) position = 0;
									// what is the scrollable page
									page = document.getElementById(id);
									// how high is the page
									pageHeight = page.offsetHeight;
									// how high is the container of the page
										// containerHeight = page.parentNode.offsetHeight;
									containerHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;
									// don't allow negative scrolling
									if(pageHeight<containerHeight){
										pageHeight = containerHeight;
										vsb.controls[1].parentNode.parentNode.style.visibility = 'hidden';
									}else{
										vsb.controls[1].parentNode.parentNode.style.visibility = 'visible';
									}
									// if there's still a distace left to scroll on the bottom shift the page up
									if(navigator.userAgent.indexOf('Safari')>-1){
										page.style.position = 'absolute';
										page.style.top = (position<containerHeight-pageHeight) ? (containerHeight-pageHeight) + 'px' : position + 'px' ;
									}else{
										page.style.marginTop = (position<containerHeight-pageHeight) ? (containerHeight-pageHeight) + 'px' : position + 'px' ;
									}
									// set the height of the scrollbar
									vsb.controls[1].parentNode.parentNode.style.height = containerHeight + 'px';
									// set the length of the indicator
									indicator = vsb.controls[1].getElementsByTagName('img')[0];
									indicator.width = indicator.offsetWidth;
									indicator.height = Math.round(containerHeight * containerHeight / pageHeight) - 45;
									// set the position of the indicator
									if(navigator.userAgent.indexOf('Safari')>-1){
										if(pageHeight>containerHeight) indicator.style.marginTop = Math.round((containerHeight - indicator.height - vsb.offset) * (parseInt(page.style.top) / (containerHeight - pageHeight))) + 'px';
									}else{
										if(pageHeight>containerHeight) indicator.style.marginTop = Math.round((containerHeight - indicator.height - vsb.offset) * (parseInt(page.style.marginTop) / (containerHeight - pageHeight))) + 'px';
									}
								}
			this.scrollBy	=	function(id, distance){
									// what is the scrollable page
									page = document.getElementById(id);
									// how far has the page scrolled up
									if(navigator.userAgent.indexOf('Safari')>-1){
										scrolledHeight = (page.style.top) ? parseInt(page.style.top) : 0 ;
									}else{
										scrolledHeight = (page.style.marginTop) ? parseInt(page.style.marginTop) : 0 ;
									}
									// calculate the new position
									position = scrolledHeight + distance;
									// set the position
									this.scrollTo(id, position);
								}
			/* events */
			this.down		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// get the id for the scrollable page
									pageId = classBehaviour.getClassParameter(objNode.parentNode.parentNode, 'id', 'scrollCanvas');
									// store this instance of the controls
									vsb.controls = objNode.parentNode.parentNode.getElementsByTagName('a');
									// start the scroll loop
									vsb.interval = setInterval("classBehaviour.virtualScrollbar.scrollBy('"+pageId+"', -5);",25);
									// cancel the click
									return false;
								}
			this.up		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// get the id for the scrollable page
									pageId = classBehaviour.getClassParameter(objNode.parentNode.parentNode, 'id', 'scrollCanvas');
									// store this instance of the controls
									vsb.controls = objNode.parentNode.parentNode.getElementsByTagName('a');
									// start the scroll loop
									vsb.interval = setInterval("classBehaviour.virtualScrollbar.scrollBy('"+pageId+"', 5);",25);
									// cancel the click
									return false;
								}
			this.cancel	=	function(){
									var vsb = classBehaviour.virtualScrollbar;
									// disable the scrolling
									clearInterval(vsb.interval);
									// cancel the click
									return false;
								}
			this.pick		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// mark the dragged item as being active
									objNode.className = 'active';
									// initial value
									vsb.drag(objNode);
									// cancel the click
									return false;
								}
			this.drag		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// if the scrollbar is marked as draggable
									if(objNode.className == 'active'){
										// get the click position
										mouseX = (typeof(event)!='undefined') ? event.x : that.layerX ;
										mouseY = (typeof(event)!='undefined') ? event.y : that.layerY ;
										// get the page dimensions
										id = classBehaviour.getClassParameter(objNode.parentNode.parentNode, 'id', 'scrollCanvas');
										page = document.getElementById(id);
										// how high is the page
										pageHeight = page.offsetHeight;
										// how high is the container of the page
										containerHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;
											// containerHeight = page.parentNode.offsetHeight;
										// corelate the mouse-position to the scroll-position
										position = Math.round(-1 * mouseY * pageHeight / containerHeight + 100);
										// pass the position on to the page
										vsb.controls = objNode.parentNode.parentNode.getElementsByTagName('a');
										vsb.scrollTo(id, position);
									}
									// cancel the click
									return false;
								}
			this.nodrag	=	function(){
									return false;
								}
			this.drop		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// mark the dragged item as being passive
									objNode.className = 'passive';
									// cancel the click
									return false;
								}
			this.onWheel	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// get the id for the scrollable page
									pageId = 'scrollCanvas';
									// get the scroll distance
									distance = (window.event) ? window.event.wheelDelta/120 : -objNode.detail/3 ; 
									// scroll the page
									vsb.scrollBy(pageId, 5*distance);
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.virtualScrollbar = new VirtualScrollbar;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.virtualScrollbar;
		
	// show specific content as a floating layer
		// define this class behaviour
		function FloatingDescription(){
			/* properties */
			this.name 		= 	'floatingDescription';
			this.display	=	document.getElementById('floatingDescription');
			/* methods */
			this.start		=	function(node){
									// set the mouse interaction
									node.onmouseover = this.show;
									node.onmouseout = this.hide;
									node.onmousemove = this.place;
									// extra for Safari
									node.onmousedown = this.place;
									document.onclick = this.hide;
								}
			/* events */
			this.show		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fdn = classBehaviour.floatingDescription;
									// don't bother if the node is invisible
									if(objNode.getElementsByTagName('A').length>0){
										if(objNode.getElementsByTagName('A')[0].style.visibility!='hidden'){
											// get the desired content from the active node
											likelyContainers = objNode.getElementsByTagName('div');
											for(var a=0; a<likelyContainers.length; a++)
												if(likelyContainers[a].className.indexOf('description')>-1)
													descriptionHtml = likelyContainers[a].innerHTML;
											// fill the floating description
											fdn.display.innerHTML = descriptionHtml;
											// show the floating display
											fdn.display.style.visibility = 'visible';
										}
									}else{
										// get the desired content from the active node
										likelyContainers = objNode.getElementsByTagName('span');
										for(var a=0; a<likelyContainers.length; a++)
											if(likelyContainers[a].className.indexOf('description')>-1)
												descriptionHtml = likelyContainers[a].innerHTML;
										// fill the floating description
										fdn.display.innerHTML = descriptionHtml;
										// show the floating display
										fdn.display.style.visibility = 'visible';
									}
								}
			this.hide		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fdn = classBehaviour.floatingDescription;
									// hide the floating display
									fdn.display.style.visibility = 'hidden';
								}
			this.place		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fdn = classBehaviour.floatingDescription;
									// get an optional width
									width = parseInt(classBehaviour.getClassParameter(objNode, 'width', '-1'));
									fdn.display.style.width = (width>0) ? width + 'px' : 'auto' ;
									// get the position
									screenXpos = (typeof(event)!='undefined') ? (event.clientX) : (that.pageX);
									screenYpos = (typeof(event)!='undefined') ? (event.clientY) : (that.pageY);
									// if the position is too close to the edge
									screenWidth = (window.innerWidth) ? window.innerWidth : (document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.clientWidth ;
									if(screenXpos>screenWidth-fdn.display.offsetWidth) screenXpos -= fdn.display.offsetWidth;
									// if the position is too close to the bottom
									screenHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;
									labelHeight = document.getElementById('floatingDescription').offsetHeight;
									if(screenYpos+labelHeight+10>screenHeight) screenYpos -= labelHeight;
									// reposition the floating display
									fdn.display.style.position = 'absolute';
									fdn.display.style.left = screenXpos + 'px' ;
									fdn.display.style.top = screenYpos + 'px' ;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.floatingDescription = new FloatingDescription;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.floatingDescription;
		
	// Use SwfObject to replace a title with a flash version
		// define this class behaviour
		function FlashTitle(){
			/* properties */
			this.name 		= 	'flashTitle';
			this.index		=	0;
			/* methods */
			this.start		=	function(node){
									// give the node an id of it doesn't have one
									if(!node.id){
										node.id = 'flashTitle' + this.index;
										this.index += 1;
									}
									// set the default values for all parameters
									flashMovie		= "../flash/title.swf";
									flashWidth		= node.offsetWidth;
									flashHeight		= node.offsetHeight;
									flashVersion	= "7";
									flashBuild		= "0";
									flashWmode		= "Transparent";
									flashVariables	= "lorem=ipsum&dolor=sit amet";
									// for all childnodes of node which may contain configuration variables
									for(var a=0; a<node.childNodes.length; a++){
										if(node.childNodes[a].className == "movie") flashMovie = node.childNodes[a].value;
										if(node.childNodes[a].className == "width") flashWidth = node.childNodes[a].value;
										if(node.childNodes[a].className == "height") flashHeight = node.childNodes[a].value;
										if(node.childNodes[a].className == "majorversion") flashVersion = node.childNodes[a].value;
										if(node.childNodes[a].className == "build") flashBuild = node.childNodes[a].value;
										if(node.childNodes[a].className == "wmode") flashWmode = node.childNodes[a].value;
										if(node.childNodes[a].className == "flashvars") flashVariables = node.childNodes[a].value;
									}
									// get the alternative to the flash content and filter a title from it
									flashVariables = "inputText=" + node.innerHTML.replace(/<(.|\n)*?>/gi,"").replace(" ","") + "&" + flashVariables;
									// load the flash plugin for "UFO"
									if(UFO){
										var FO = { 
											movie			: flashMovie,
											width			: flashWidth, 
											height			: flashHeight,
											majorversion	: flashVersion, 
											build			: flashBuild, 
											wmode			: flashWmode,
											flashvars		: flashVariables
										}
										UFO.create(FO, node.id);
									}
								}
			/* events */
		}
		// add this function to the classbehaviour object
		classBehaviour.flashTitle = new FlashTitle;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.flashTitle;
		
	// foolishly replace a perfectly functional form element with an inaccessible graphic abbomination
		// define this class behaviour
		function FauxRadio(){
			/* properties */
			this.name 		= 	'fauxRadio';
			/* methods */
			this.start		=	function(node){
									// make the image look like a button
									node.style.cursor = 'pointer';
									// set the button event
									node.onclick = this.click;
									classBehaviour.nextNode(node).onchange = this.sync;
								}
			/* events */
			this.click		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the target object
									target = classBehaviour.nextNode(objNode);
									// toggle it's state
									target.checked = true;
									// synchronize the form element and it's fake image
									target.onchange();
								}
			this.sync		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the fake element's image
									imageNode = classBehaviour.previousNode(objNode);
									// make it look like the state of the form element
									imageNode.src = (objNode.checked) ? imageNode.src.replace('_link','_active') : imageNode.src.replace('_active','_link') ;
									// get the rest of the input elements from the same parent
									allSiblings = objNode.parentNode.getElementsByTagName('input');
									for(var a=0; a<allSiblings.length; a++){
										if(allSiblings[a].name == objNode.name && allSiblings[a].id != objNode.id){
											allSiblings[a].checked = false;
											imageSibling = classBehaviour.previousNode(allSiblings[a]);
											imageSibling.src = imageSibling.src.replace('_active','_link') ;
										}
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fauxRadio = new FauxRadio;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fauxRadio;
		
	// foolishly replace a perfectly functional form element with an inaccessible graphic abbomination
		// define this class behaviour
		function FauxCheckBox(){
			/* properties */
			this.name 		= 	'fauxCheckBox';
			/* methods */
			this.start		=	function(node){
									// make the image look like a button
									node.style.cursor = 'pointer';
									// set the button event
									node.onclick = this.click;
									classBehaviour.nextNode(node).onchange = this.sync;
								}
			/* events */
			this.click		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the target object
									target = classBehaviour.nextNode(objNode);
									// toggle it's state
									target.checked = !target.checked;
									// synchronize the form element and it's fake image
									target.onchange();
								}
			this.sync		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the fake element's image
									imageNode = classBehaviour.previousNode(objNode);
									// make it look like the state of the form element
									imageNode.src = (objNode.checked) ? imageNode.src.replace('_link','_active') : imageNode.src.replace('_active','_link') ;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fauxCheckBox = new FauxCheckBox;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fauxCheckBox;
		
/* /TODO */

	// STARTUP-SEQUENCE
	// start the user interface script
	if(document.getElementById('parallax')) userInterface.startUp();
	if(document.body.className.indexOf('iframe')>-1) transFrameLinks.startUp();
	
	// start the parsing of classes
	classBehaviour.parseDocument();
	
	if(navigator.userAgent.indexOf('Safari/4')>-1) document.writeln('<style>#scrollCanvas fieldset textarea {background-color:#ffffff;}</style>')
	
	
