/*name			: Class Behaviourupdate			: 20070705author			: 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		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){												// get 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]);												}											}										}									}		this.fader				=	new Fader;		this.utilities			=	new Utilities;
		this.xmlDoc				=	new XmlDoc;
		this.console			=	new Console;	}	// create the main class-behaviour object	var classBehaviour = new ClassBehaviour;	// UTILITIES
		// General purpose functions		function Utilities(){			this.screenHeight 		= 	function(){											return (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;										}			// 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 ;										}			// get the next node without worrying about text nodes			this.nextNode			=	function(node, count){
											testNode = node;
											if(count==null) count = 1;											// look for the next html node
											for(var a=0; a<count; a++){												do {													testNode = testNode.nextSibling;
													if(testNode==null) testNode = node;												}while(testNode.nodeName.indexOf('#text')>-1);
											}											// return it											return testNode;										}			// get the previous node without worrying about text nodes			this.previousNode		=	function(node, count){
											testNode = node;
											if(count==null) count = 1;											// look for the previous html node
											for(var a=0; a<count; a++){												do {													testNode = testNode.previousSibling;
													if(testNode==null) testNode = node;												}while(testNode.nodeName.indexOf('#text')>-1);
											}											// return it											return testNode;										}
			// get the first real child node without worrying about text nodes			this.firstNode			=	function(node, count){											return this.nextNode(node.firstChild, count);										}
			// find the parent node with the given classname
			this.rootNode			=	function(node, rootTag, rootId, rootClass){
											// try parent nodes until you find the one which meets the conditions
											rootFound = false;
											while(!rootFound && node.nodeName!='BODY'){
												rootFound = (rootTag && node.nodeName) ? (node.nodeName.indexOf(rootTag)>-1) : rootFound ;
												rootFound = (rootId && node.id) ? (node.id.indexOf(rootId)>-1) : rootFound ;
												rootFound = (rootClass && node.className) ? (node.className.indexOf(rootClass)>-1) : rootFound ;
												node = (!rootFound) ? node.parentNode : node;
											}
											// pass it back
											return node;
										}			// 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;										}
			// adds an event-handler the proper way
			this.addEvent			=	function(node, eventName, eventHandler){
											if(node.addEventListener) 	node.addEventListener(eventName, eventHandler, false)
											else if(node.attachEvent) 	node.attachEvent("on"+eventName, eventHandler)
											else 						node["on"+eventName] = eventHandler;
											return true;
										}		}		
		// Decorative fader animations		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!=""){											// unhide the new page											document.getElementById(idIn).style.display = 'block';											// set the fade amount											cf.setFade(document.getElementById(idIn), amount);										}										if(idOut && idOut!=""){											// unhide the new page											document.getElementById(idOut).style.display = 'block';											// set the fade amount											cf.setFade(document.getElementById(idOut), 100-amount);										}										// 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										if(idIn && idIn!=""){
											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);									}								}
			this.grow			=	function(id, width, height, step, delay, evalEvent){
										var cf = classBehaviour.fader;
										// validate the new size
										if(!width) width = -1;
										if(!height) height = -1;
										// get the object
										resizeObject = document.getElementById(id);
										// get the object's size
										objectWidth = parseInt(resizeObject.offsetWidth);
										objectHeight = parseInt(resizeObject.offsetHeight);
										// compare the sizes
										tooNarrow = objectWidth<width;
										tooShort = objectHeight<height;
										// if the height isn't big enough
										if(tooNarrow || tooShort){
											// increase it one increment
											if(tooNarrow) resizeObject.style.width = (objectWidth + step) + 'px';
											if(tooShort) resizeObject.style.height = (objectHeight + step) + 'px';
											// repeat
											setTimeout("classBehaviour.fader.grow('"+id+"', "+width+", "+height+", "+step+", "+delay+", '"+evalEvent+"');", delay);
										// else
										}else{
											// trigger the end event
											cf.onEnd(evalEvent);
										}
									}
			this.shrink		=	function(id, width, height, step, delay, evalEvent){
										var cf = classBehaviour.fader;
										// validate the new size
										if(!width) width = 99999;
										if(!height) height = 99999;
										// get the object
										resizeObject = document.getElementById(id);
										// get the object's size
										objectWidth = parseInt(resizeObject.offsetWidth);
										objectHeight = parseInt(resizeObject.offsetHeight);
										// compare the sizes
										tooWide = objectWidth>width;
										tooTall = objectHeight>height;
										// if the height isn't big enough
										if(tooWide || tooTall){
											// increase it one increment
											if(tooWide) resizeObject.style.width = (objectWidth - step) + 'px';
											if(tooTall) resizeObject.style.height = (objectHeight - step) + 'px';
											// repeat
											setTimeout("classBehaviour.fader.shrink('"+id+"', "+width+", "+height+", "+step+", "+delay+", '"+evalEvent+"');", delay);
										// else
										}else{
											// trigger the end event
											cf.onEnd(evalEvent);
										}
									}			// events			this.onEnd		=	function(evalEvent){									eval(evalEvent);								}		}
		
		// AJAX interface
		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, referingObject){
										// 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	=	referingObject;
										// 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;
			}
		
		// Debug console
		function Console(){
			// properties
			this.debugLog = new Array();
			this.dbg = null;
			this.tellerX = 0;
			this.interval = 0;
			this.maxLength = 128;
			this.strArr2Str= '';
			// methods
			this.debug 			= 	function(){
										// open the debug window if it isn't open yet
										if(this.dbg==null) this.dbg = window.open('','debugwindow','width=256,height=580,resizable=yes,scrollbars=yes');
										// add line count
										this.tellerX = this.tellerX + 1;
										// for all debugable arguments
										intDebugLine = this.debugLog.length;
										this.debugLog[intDebugLine] = '';
										for(var intA=0; intA<arguments.length; intA++){
											// recursive array splitter
											if(typeof(arguments[intA])=='object'){
												this. strArr2Str = '------Object-------<br />';
												this.plotArray(arguments[intA],0);
												this. strArr2Str += '-------end---------<br />';
												arguments[intA] = this. strArr2Str;
											}
											// add a debug line
											this.debugLog[intDebugLine] += arguments[intA] + '&nbsp;';
										}
										// blit all debug lines
										if(this.tellerX>this.interval){
											this.dbg.document.open();
											this.dbg.document.write('<html><head><title>debug info</title></head><body>');
											tellerY = this.debugLog.length - 1;
											if(this.debugLog.length>this.maxLength){maxLines=this.maxLength}else{maxLines=this.debugLog.length}
											for(tellerZ=0 ; tellerZ < maxLines ; tellerZ++){
												this.dbg.document.writeln(this.debugLog[tellerY]+"<br />");
												tellerY = tellerY-1;
											}
											this.dbg.document.write('</body></html>');
											this.dbg.document.close();
											this.tellerX = 0;
										}
									}
			this.plotArray 		= 	function(arrIn,intRecursion){
										// indentation
										var strSpacing = ''
										for(var intC=0; intC<intRecursion; intC++){
											strSpacing += '&nbsp;&nbsp;&nbsp;';
										}
										// plotting individual elements
										if(arrIn!=null){
											for(var intB=0; intB<arrIn.length; intB++){
												if(typeof(arrIn[intB])=='object'){
													plotArray(arrIn[intB],intRecursion+1)
												}else{
													this. strArr2Str += strSpacing + arrIn[intB] + '<br />'
												}
												// end of line
												if(intB==arrIn.length-1 && intRecursion==1){
													this. strArr2Str += '------------------<br />';
												}
											}
										}else{
											this. strArr2Str += 'NULL<br />';
										}
									}
			this.debugClear 	= 	function(){
										this.debugLog.length = 0;
									}
			this.debugHtml 		= 	function(string){
										string = '<xmp>' + string + '</xmp>'
										this.debug(string)
									}
		}
		
		// legacy wrapper functions
		function debug(){
			classBehaviour.console.debug(arguments);
		}
			// BEHAVIOURS	// blinks		// define this class behaviour		function Blink(){			// properties			this.name 		= 	'blink';			this.nodes 	= 	new Array();			// methods			this.start		=	function(node){									// set the starting class, if not present									if(node.className.indexOf('blinkon')<0) node.className += " blinkon";									// make new blink entry									this.nodes[this.nodes.length] = new Array(node,null,1024);									// start blink loop									this.loop(this.nodes.length-1);								}			// events			this.loop		=	function(blinkIndex){									// what object goes with this index									blinkObject = this.nodes[blinkIndex][0];									// toggle the blink class of this object									blinkObject.className = (blinkObject.className.indexOf('blinkoff')>-1) ? blinkObject.className.replace('blinkoff','blinkon') : blinkObject.className.replace('blinkon','blinkoff');									// set timeout till the next blink toggle									this.nodes[blinkIndex][1] = setTimeout('classBehaviour.blink.loop('+blinkIndex+')',this.nodes[blinkIndex][2]);								}		}		// add this function to the classbehaviour object		classBehaviour.blink = new Blink;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.blink;			// 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') ;									// if there is an image within, replace it with the hover state too									allImages = objNode.getElementsByTagName('IMG');									if(allImages.length>0) allImages[0].src = allImages[0].src.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') ;									// if there is an image within, replace it with the hover state too									allImages = objNode.getElementsByTagName('IMG');									if(allImages.length>0) allImages[0].src = allImages[0].src.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 by active									objNode.className = objNode.className.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;			// make all sub elements fake the :hover attribute with .hover		// define this class behaviour		function PseudoHover(){			// properties			this.name 		= 	'pseudoHover';			// methods			this.start		=	function(node){
									// if this is Internet Explorer 6
									if(navigator.appVersion.indexOf('MSIE 6')>-1){										// get all elements										allNodes = node.getElementsByTagName('LI');										// for all elements										for(var a=0; a<allNodes.length; a++){											// add the hover event											classBehaviour.classMouseHover.start(allNodes[a]);										}
									}								}		}		// add this function to the classbehaviour object		classBehaviour.pseudoHover = new PseudoHover;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.pseudoHover;			// 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			=	20;			this.delay			=	10;			this.index			=	0;			/* 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 ;										// is this node marked as "auto", order it to open on a timeout										autoDelay = classBehaviour.utilities.getClassParameter(node, 'auto', null);										if(autoDelay){											this.index++											node.id = (node.id) ? node.id : this.name + this.index ;											setTimeout('classBehaviour.toggleNextNode.toggle(document.getElementById("'+node.id+'"))', autoDelay);										}									}			this.shrink			=	function(label, container, finished){										var t2n = classBehaviour.toggleNextNode;										// deactivate the label										label.className = label.className.replace('active','link');										label.parentNode.className = label.parentNode.className.replace('active','link');										// if the container isn't shrunk completely										if(container.offsetHeight>t2n.step){											// height before											heightBefore = container.style.height;											// reduce its height by an amount											container.style.overflow = 'hidden';											container.style.visibility = 'visible';											container.style.height = (container.offsetHeight - t2n.step) + 'px';											// height after											heightAfter = container.style.height;											// the resizing isnt' working, skip straight to the end situation											finished = (heightBefore==heightAfter) ? classBehaviour.hideThisNode.start(container) : false ;										}else{											// close the container											classBehaviour.hideThisNode.start(container);										}										// return the state										return finished;									}			this.grow			=	function(label, container, finished){										var t2n = classBehaviour.toggleNextNode;										// activate the label										label.className = label.className.replace('link','active').replace('hover','active');										label.parentNode.className = label.parentNode.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(container.offsetHeight<totalHeight-t2n.step){											// height before											heightBefore = container.style.height;											// increase its height by an amount											container.style.overflow = 'hidden';											container.style.visibility = 'visible';											container.style.height = (container.offsetHeight + t2n.step) + 'px';											// height after											heightAfter = container.style.height;											// the resizing isnt' working, skip straight to the end situation
											finished = (heightBefore==heightAfter) ? classBehaviour.showThisNode.start(container) : finished = false;										}else{											// open the container
											classBehaviour.showThisNode.start(container);										}										// return the state										return finished;									}
			this.findContainer	=	function(targetLabel, targetRecursion){
										// if there was a target recursion, recurse parent nodes
										if(targetRecursion) for(var a=0; a<parseInt(targetRecursion); a++) targetLabel = targetLabel.parentNode;
										// get the next sibling of the label, which should be the container
										targetObject = classBehaviour.utilities.nextNode(targetLabel);
										// pass it back
										return targetObject;
									}			/* events */			this.toggle 		= 	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;										var t2n = classBehaviour.toggleNextNode;										// get all information on this node										targetLabel = objNode;										targetContainerId = classBehaviour.utilities.getClassParameter(targetLabel, 'id', null);
										targetRecursion = classBehaviour.utilities.getClassParameter(targetLabel, 'parent', null);										targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : t2n.findContainer(targetLabel, targetRecursion) ;
										// if the target container is not marked for hiding or showing, mark it now
										if(targetContainer.className.indexOf('hideThisNode')<0 && targetContainer.className.indexOf('showThisNode')<0) targetContainer.className += ' showThisNode' ;										// call for the node to grow or shrink										targetGrows = (targetContainer.className.indexOf('hideThisNode')>-1);										t2n.update(targetLabel.id, targetGrows);										// cancel the click										return false;									}			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.utilities.getClassParameter(targetLabel, 'id', null);										targetFamily = classBehaviour.utilities.getClassParameter(targetLabel, 'family', null);
										targetRecursion = classBehaviour.utilities.getClassParameter(targetLabel, 'parent', null);										targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : t2n.findContainer(targetLabel, targetRecursion) ;										// 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.utilities.getClassParameter(peerLabel, 'id', null);											peerFamily = classBehaviour.utilities.getClassParameter(peerLabel, 'family', null);
											peerRecursion = classBehaviour.utilities.getClassParameter(peerLabel, 'parent', null);											peerContainer = (peerContainerId) ? document.getElementById(peerContainerId) : t2n.findContainer(peerLabel, peerRecursion) ;											// 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 && peerContainer!=targetContainer){												// 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 && !grows){												// close the container one step												finished = this.shrink(targetLabel, targetContainer, finished);											// else 											}else if(peerLabel.id==targetLabel.id && grows){												// open the container one step												finished = this.grow(targetLabel, targetContainer, finished);											}										}										// if any step marked the function as unfinished										if(!finished){											// repeat it											setTimeout("classBehaviour.toggleNextNode.update('"+id+"',"+grows+")", t2n.delay);										}else{											// notify the iframe resizer to update its size if needed											if(document.body.className.indexOf('resizeIframe')>-1) classBehaviour.resizeIframe.delay();										}									}		}		// add this function to the classbehaviour object		classBehaviour.toggleNextNode = new ToggleNextNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleNextNode;
							// tabbed content		// define this class behaviour		function TabbedContent(){			// properties			this.name 		= 	'tabbedContent';			// methods			this.start		=	function(node){									// get all tabs									allTabs = node.getElementsByTagName('a');									// store the most likely opened tab									openedTab = allTabs[0];									// for all tabs									for(var a=0; a<allTabs.length; a++){										// get the id this tab refers to										tabId = allTabs[a].href.split('#')[1];										// apply onclick events to the referred tab										allTabs[a].onclick = this.open;										// apply the starting state of the tab if needed										if(allTabs[a].className.indexOf('closedTab')<0 && allTabs[a].className.indexOf('openedTab')<0) allTabs[a].className += ' closedTab';										// apply the starting state of the referred content if needed										document.getElementById(tabId).style.display = 'none';										// if this tab is referred to in the page url, remember it as active
										if(document.location.href.indexOf(allTabs[a].href)>-1) openedTab = allTabs[a];										// if this tab was manualy set
										if(allTabs[a].className.indexOf('openedTab')>-1) openedTab = allTabs[a];
									}									// if there is a pager									pager = document.getElementById(classBehaviour.utilities.getClassParameter(node, 'pagerId', 'none'));									if(pager){										// assign the events for the buttons										pager.getElementsByTagName('a')[0].onclick = this.previous;										pager.getElementsByTagName('a')[1].onclick = this.next;									}									// open the most likely first tab
									this.open(openedTab, true);								}			// events			this.next		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var tbd = classBehaviour.tabbedContent;									// get the pager information									pagerInfo = objNode.parentNode.parentNode.getElementsByTagName('span')[0].firstChild.nodeValue;									// what is the current pagenumber									currentPage = parseInt(pagerInfo.split('/')[0]);									// how many pages are there									totalPages = parseInt(pagerInfo.split('/')[1]);									// what is the next page									nextPage = (currentPage<totalPages) ? currentPage + 1 : 1 ;									// what is the tabs strip									tabStrip = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'tabsId', 'none'));									if(tabStrip){										// get the relevant page from the tab strip										targetTab = tabStrip.getElementsByTagName('a')[nextPage-1];										// activate it's click										tbd.open(targetTab);									}								}			this.previous	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var tbd = classBehaviour.tabbedContent;									// get the pager information									pagerInfo = objNode.parentNode.parentNode.getElementsByTagName('span')[0].firstChild.nodeValue;									// what is the current pagenumber									currentPage = parseInt(pagerInfo.split('/')[0]);									// how many pages are there									totalPages = parseInt(pagerInfo.split('/')[1]);									// what is the next page									previousPage = (currentPage>1) ? currentPage - 1 : totalPages ;									// what is the tabs strip									tabStrip = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'tabsId', 'none'));									if(tabStrip){										// get the relevant page from the tab strip										targetTab = tabStrip.getElementsByTagName('a')[previousPage-1];										// activate it's click										tbd.open(targetTab);									}								}			this.open		=	function(that, noAnimation){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var tbd = classBehaviour.tabbedContent;																				// INDEX THE TAB STATES									// get all tabs									var allTabs = objNode.parentNode.parentNode.getElementsByTagName('a');									var prevTab = null;									var pageNumber = 0;									// find the current tab									for(var a=0; a<allTabs.length; a++){										// rememeber the previous tab										if(allTabs[a].className.indexOf('openedTab')>-1) prevTab = allTabs[a];										// count the new pagenumber										if(allTabs[a]==objNode) pageNumber = a;									}									// if this is the current tab again									if(prevTab!=objNode || noAnimation){																			// PREVIOUS TAB										if(prevTab){											// mark the previous tab as passive											prevTab.className = prevTab.className.replace('openedTab', 'closedTab');											// if the tab has an image											tabImages = prevTab.getElementsByTagName('img');											if(tabImages.length>0) tabImages[0].src = tabImages[0].src.replace('_active','_link');											// id the previous tabbed content											prevContentId = prevTab.href.split('#')[1];										}																				// NEXT TAB										// mark the next tab as active										objNode.className = objNode.className.replace('closedTab', 'openedTab');										// if the tab has an image										tabImages = objNode.getElementsByTagName('img');										if(tabImages.length>0) tabImages[0].src = tabImages[0].src.replace('_link','_active').replace('_hover','_active');										// id the next tabbed content										nextContentId = objNode.href.split('#')[1];																				// FADE ANIMATION										isAnimated = (noAnimation) ? 'no' : classBehaviour.utilities.getClassParameter(objNode, 'animated', 'yes') ;										if(isAnimated=='yes'){											// make the previous tab float											document.getElementById(prevContentId).style.position = 'absolute';											document.getElementById(prevContentId).style.top = '0px';											// make the next tab no float											document.getElementById(nextContentId).style.position = 'relative';											// order the animation											classBehaviour.fader.crossFade(nextContentId, prevContentId, 0, 10, 50, null);										}else{
											if(prevTab) document.getElementById(prevContentId).style.display = 'none';											document.getElementById(nextContentId).style.display = 'block';										}																				// PAGE NUMBER										// update page-numbering										pager = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'pagerId', 'none'));										if(pager){											pager.getElementsByTagName('span')[0].firstChild.nodeValue = (pageNumber+1) + '/' + allTabs.length ;										}									}									// cancel the jump to the anchor									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.tabbedContent = new TabbedContent;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.tabbedContent;
					// replace image with transparent version, invoke activeX background loader		// define this class behaviour		function PngAlpha(){			// properties			this.name 		= 	'pngAlpha';			// methods			this.start		=	function(node){									/*event*/;									this.process(node);									node.onload = this.process;								}			// events			this.process 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// if the image has been processed before									if(objNode.src.indexOf('_alpha')<0){										// alpha image url										var strAlphaSrc = objNode.src.replace(/\.png|\.jpg|\.gif/gi,"_alpha.png");										// for the downlevel browser MSIE										if(typeof(objNode.style.filter)!='undefined'){											// change the image styles											objNode.style.width		= objNode.width + 'px';											objNode.style.height	= objNode.height + 'px';											objNode.style.filter	= "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + strAlphaSrc + "', sizingMethod='crop')";											// get the path to the image folder											var strPathSrc = '';											var arrPathSrc = objNode.src.split('/');											for(var intA=0; intA<arrPathSrc.length-1; intA++){strPathSrc += arrPathSrc[intA] + '/'};											// replace the original with the alpha variant											objNode.src = strPathSrc + '_alpha.png';										// for the rest of the world										}else{											// replace the image source with the alpha channel version											objNode.src = strAlphaSrc;										}									}								}		}		// add this function to the classbehaviour object		classBehaviour.pngAlpha = new PngAlpha;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.pngAlpha;			// 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, img.pngAlternative {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');
										// if there were no images in this tag, it probably IS the image
										if(allImages.length==0) allImages = new Array(objNode);										// 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;			// Open an overlay as a popup window		// define this class behaviour		function OpenLayerPopUp(){			// properties			this.name 		= 	'openLayerPopUp';			this.step		=	10;			this.begin		=	0;			this.end		=	50;
			this.instance	=	0;			// methods			this.start		=	function(node){									// find the target layer									targetPopUp = null;									// the node's open button									node.onclick = this.load;									// open the popup immediately if required									if(classBehaviour.utilities.getClassParameter(node, 'auto', 'no')=='yes') this.load(node);								}			this.fadeIn	=	function(id, amount){									var olp = classBehaviour.openLayerPopUp;									node = document.getElementById(id);									nodes = node.getElementsByTagName('div');									nodeShadow = nodes[0];									nodeContent = nodes[1];									// if the amount is not 50									if(amount<olp.end){										// hide the popup content										nodeContent.style.visibility = 'hidden';										// set the shadow's fade to the next step										nodeShadow.style.display = 'block';										if(typeof(nodeShadow.style.MozOpacity)!='undefined')	nodeShadow.style.MozOpacity = amount/100;										if(typeof(nodeShadow.style.filter)!='undefined')		nodeShadow.style.filter = "alpha(opacity=" + amount + ")";										if(typeof(nodeShadow.style.opacity)!='undefined')		nodeShadow.style.opacity = amount/100;										// show the popup collection										node.style.display = 'block';										// repeat the fade										setTimeout("classBehaviour.openLayerPopUp.fadeIn('" + id + "'," + (amount+olp.step) + ")",10);									}else{										// show the popup content										nodeContent.style.visibility = 'visible';									}								}			this.fadeOut	=	function(id, amount){									var olp = classBehaviour.openLayerPopUp;									node = document.getElementById(id);									nodes = node.getElementsByTagName('div');									nodeShadow = nodes[0];									nodeContent = nodes[1];									// if the amount is not 100									if(amount>olp.begin){										// hide the popup content										nodeContent.style.visibility = 'hidden';										// set the fade to the next step										if(typeof(nodeShadow.style.MozOpacity)!='undefined')	nodeShadow.style.MozOpacity = amount/100;										if(typeof(nodeShadow.style.filter)!='undefined')		nodeShadow.style.filter = "alpha(opacity=" + amount + ")";										if(typeof(nodeShadow.style.opacity)!='undefined')		nodeShadow.style.opacity = amount/100;										// repeat the fade										setTimeout("classBehaviour.openLayerPopUp.fadeOut('" + id + "'," + (amount-olp.step) + ")",10);									}else{										// hide the popup content										node.style.display = 'none';										// hide the popup's shadow										nodeShadow.style.display = 'none';									}								}			// events
			this.load		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var olp = classBehaviour.openLayerPopUp;
									// get the popup id
									popUpHref = (objNode.href) ? objNode.href : '' ;
									popUpId = (popUpHref.indexOf('#')>-1) ? popUpHref.split('#')[1] : classBehaviour.utilities.getClassParameter(objNode, 'id', 'popUpWithScrollBar') ;
									// if the popup is allready loaded
									popUpObj = document.getElementById(popUpId);
									if(popUpObj){
										olp.show(objNode, popUpId);
									}else{
										classBehaviour.xmlDoc.addRequest(popUpHref, olp.insert, olp.wait, null, objNode);
									}
									// cancel the click
									return false;
								}
			this.wait		=	function(progress, referNode){
									var olp = classBehaviour.openLayerPopUp;
									// it'd be fun to see a background image behind the link text be the progress-indicator
									referNode.parentNode.style.backgroundPosition = (100-progress*100) +'% 0px';
								}
			this.insert		=	function(importedObj, referNode, importedText){
									var olp = classBehaviour.openLayerPopUp;
									//  get the popup's id
									olp.instance += 1;
									popUpId = classBehaviour.utilities.getClassParameter(referNode, 'id', olp.name+olp.instance);
									// make a new node at the end of the page
									newNode = document.createElement('div');
									document.body.appendChild(newNode);
									// get the node and fill it with delicous html
									allDivs = document.getElementsByTagName('div');
									importedText = importedText.replace('<?xml version="1.0"?>', '');
									importedText = importedText.replace('{id}', popUpId);
									importedText = importedText.replace('{title}', referNode.title);
									importedText = importedText.replace('{url}', referNode.href.split('?url=')[1]);
									allDivs[allDivs.length-1].innerHTML = importedText;
									// show the pop-up
									olp.show(referNode, popUpId);
								}			this.show		=	function(openerObj, popUpId){									var olp = classBehaviour.openLayerPopUp;									var submit = false;									// adjust the fade parameters if it needs to open instantly
									if(openerObj){										olp.step = parseInt(classBehaviour.utilities.getClassParameter(openerObj, 'step', 10));										olp.begin = parseInt(classBehaviour.utilities.getClassParameter(openerObj, 'begin', 0));										olp.end = parseInt(classBehaviour.utilities.getClassParameter(openerObj, 'end', 50));
									}									// get the popup and position it									popUpObj = document.getElementById(popUpId);
									if(popUpObj){										// the dimensions can not be measured with "display:none;"										popUpObj.style.visibility = 'hidden';										popUpObj.style.display = 'block';										// get the content segment										popupContent = popUpObj.getElementsByTagName('DIV')[2];										// how high is the content										popupHeight = popupContent.offsetHeight;										// how high is the screen										screenHeight = popupContent.parentNode.offsetHeight;										// center the popup										popupContent.style.marginTop = Math.round((screenHeight-popupHeight)/2) + 'px' ;										// the dimensions can not be measured with "display:none;"										popUpObj.style.visibility = 'visible';										popUpObj.style.display = 'block';
									}
									// if the link had a title and if the popup has a title. put the link title in the popup									popUpTitles = popUpObj.getElementsByTagName('h1');									if(openerObj) if(openerObj.title && popUpTitles.length>0) popUpTitles[0].innerHTML = openerObj.title;									// load a given url in the iframe it it's not there allready									popUpIframes = popUpObj.getElementsByTagName('iframe');									if(popUpIframes.length>0 && openerObj.href.indexOf('?url=')>-1){
										if(popUpIframes[0].src!=openerObj.href.split('?url=')[1]) popUpIframes[0].src = openerObj.href.split('?url=')[1];
									}									// find the close gadget									popUpClosers = popUpObj.getElementsByTagName('a');
									if(popUpClosers.length>0){										popUpClosers[0].onclick = olp.hide;
									}									// remove the scroll bars									if(navigator.appVersion.indexOf('MSIE 6')>-1 || navigator.appVersion.indexOf('MSIE 5')>-1){
										// manage the scroll positions										if(popUpObj.className.indexOf('fullHeightPopUp')<0){
											// reset the scroll position
											document.documentElement.scrollLeft = 0;
											document.documentElement.scrollTop = 0;
											// hide the scrollbars if needed
											document.body.parentNode.style.overflow = "hidden";
											// reposition the popup according to the scroll position
											popUpObj.getElementsByTagName('DIV')[2].style.marginTop = Math.round(document.documentElement.scrollTop + (screenHeight-popupHeight)/2) + 'px' ;
										}
										// size the shadow under the popup										popUpObj.getElementsByTagName('DIV')[0].style.height = document.body.offsetHeight + 'px';
										// hide the selects										allSelects = document.getElementsByTagName('select');										for(var a=0; a<allSelects.length; a++) allSelects[a].style.visibility = 'hidden';									}									// fade the popup in									olp.fadeIn(popUpId, olp.begin);									// mark the body with a class									document.body.className += " hasLayerPopUp";									// cancel the click									return submit;								}			this.hide		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var olp = classBehaviour.openLayerPopUp;									// the popup object									popUp = objNode.parentNode.parentNode.parentNode;									// fade the popup out									olp.fadeOut(popUp.id, olp.end);									// restore the scroll bars									if(navigator.appVersion.indexOf('MSIE 6')>-1 || navigator.appVersion.indexOf('MSIE 5')>-1){
										// show the scrollbars										if(popUp.className.indexOf('fullHeightPopUp')<0) document.body.parentNode.style.overflow = "auto";										// show the selects
										allSelects = document.getElementsByTagName('select');										for(var a=0; a<allSelects.length; a++) allSelects[a].style.visibility = 'visible';									}									// unmark the body class									document.body.className = document.body.className.replace(" hasLayerPopUp", "");
									// clear the iframe contents
									popUpIframes = popUp.getElementsByTagName('iframe');									if(popUpIframes.length>0){
										popUpIframes[0].src = "";
									}									// cancel the click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.openLayerPopUp = new OpenLayerPopUp;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openLayerPopUp;
			// 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.utilities.getClassParameter(node, 'gridX', null));									this.grid.y	=	parseInt(classBehaviour.utilities.getClassParameter(node, 'gridY', null));									this.minPos.x	=	parseInt(classBehaviour.utilities.getClassParameter(node, 'limitLeft', null));									this.minPos.y	=	parseInt(classBehaviour.utilities.getClassParameter(node, 'limitTop', null));									this.maxPos.x	=	parseInt(classBehaviour.utilities.getClassParameter(node, 'limitRight', null));									this.maxPos.y	=	parseInt(classBehaviour.utilities.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.utilities.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.utilities.getClassParameter(sliderTarget, 'valueFromId', null);										sliderButton = document.getElementById(sliderButtonId);										// get the limit values from the slider										curValue	=	parseFloat(sliderTarget.value);										minValue	=	parseFloat(classBehaviour.utilities.getClassParameter(sliderButton, 'minValue', null));										maxValue	=	parseFloat(classBehaviour.utilities.getClassParameter(sliderButton, 'maxValue', null));										minPos		=	parseInt(classBehaviour.utilities.getClassParameter(sliderButton, 'limitLeft', null));										maxPos		=	parseInt(classBehaviour.utilities.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.utilities.getClassParameter(sliderButton, 'valueToId', null);										sliderTarget	=	document.getElementById(sliderTargetId);										// get the limit values from the slider										curValue	=	parseFloat(sliderTarget.value);										minValue	=	parseFloat(classBehaviour.utilities.getClassParameter(sliderButton, 'minValue', null));										maxValue	=	parseFloat(classBehaviour.utilities.getClassParameter(sliderButton, 'maxValue', null));										minPos		=	parseInt(classBehaviour.utilities.getClassParameter(sliderButton, 'limitLeft', null));										maxPos		=	parseInt(classBehaviour.utilities.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.utilities.getClassParameter(sliderButton, 'valueToId', null);											sliderTarget	=	document.getElementById(sliderTargetId);											// slider limits											minPos			=	parseInt(classBehaviour.utilities.getClassParameter(sliderButton, 'limitLeft', null));											maxPos			=	parseInt(classBehaviour.utilities.getClassParameter(sliderButton, 'limitRight', null));											minValue		=	parseFloat(classBehaviour.utilities.getClassParameter(sliderButton, 'minValue', null));											maxValue		=	parseFloat(classBehaviour.utilities.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;			// show contents as code		// define this class behaviour		function ShowAsCode(){			// properties			this.name 		= 	'showAsCode';			// methods			this.start		=	function(node){									/* event */									this.process(node);								}			this.process 	= 	function(objNode){									// replace html tags									objNode.innerHTML = objNode.innerHTML.replace(/</gi,"&lt;").replace(/>/gi,"&gt;\n").replace(/ /gi,"&nbsp;").replace(/\t/gi,"&nbsp;&nbsp;&nbsp;").replace(/\n/gi,"<br />");								}		}		// add this function to the classbehaviour object		classBehaviour.showAsCode = new ShowAsCode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.showAsCode;			// Add a className to a tag using the query parameter "class"',		// define this class behaviour		function AddQueryToClassName(){			// properties			this.name 		= 	'addQueryToClassName';			// methods			this.start		=	function(node){									this.process(node);								}			this.process	= 	function(objNode){									// get the query parameter									var strQueryParameter = classBehaviour.utilities.getQueryParameter("class");									// add to front of classNames									if(strQueryParameter!=null) objNode.className = strQueryParameter + ' ' + objNode.className;								}		}		// add this function to the classbehaviour object		classBehaviour.addQueryToClassName = new AddQueryToClassName;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.addQueryToClassName;			// Add a suffix to an image source using the query parameter "src"',		// define this class behaviour		function AddQueryToSrc(){			// properties			this.name 		= 	'addQueryToSrc';			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									// get the query parameter									var strQueryParameter = classBehaviour.utilities.getQueryParameter("src")									// add to front of classNames									if(strQueryParameter!=null) objNode.src = objNode.src.replace('.','_'+strQueryParameter+'.');								}		}		// add this function to the classbehaviour object		classBehaviour.addQueryToSrc = new AddQueryToSrc;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.addQueryToSrc;			// Resizes the window to avoid a scrollbar		// define this class behaviour		function ResizeToFit(){			// properties			this.name 		= 	'resizeToFit';			// methods			this.start		=	function(node){									node.onload = this.process;									this.process(node);								}			// events			this.process 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// measure the content									containerWidth = (window.innerWidth) ? window.innerWidth : (document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.clientWidth ;									requiredWidth = document.body.offsetWidth;									containerHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;									requiredHeight = document.body.offsetHeight;									// max dimensions									requiredWidth = (requiredWidth<screen.availWidth) ? requiredWidth : screen.availWidth;									requiredHeight = (requiredHeight<screen.availHeight) ? requiredHeight : screen.availHeight;									// resize the window									window.resizeTo(requiredWidth,requiredHeight);								}		}		// add this function to the classbehaviour object		classBehaviour.resizeToFit = new ResizeToFit;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.resizeToFit;			// Resizes the iframe to avoid a scrollbar		// define this class behaviour		function ResizeIframe(){			// properties			this.name 		= 	'resizeIframe';			// methods			this.start		=	function(node){									onload = this.delay;																	}			this.process 	= 	function(){									// fetch the iframe									var iframes = window.parent.document.getElementsByTagName('iframe');									var iframe = (iframes.length>0) ? iframes[iframes.length-1] : null;									// if there was an iframe									if(iframe){										// measure content										containerHeight = (window.innerHeight) ? window.innerHeight : (document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight ;										requiredHeight = document.body.offsetHeight;										// resize the iframe										iframe.style.height = requiredHeight + 'px';									}								}			// events			this.delay		=	function(){									setTimeout('classBehaviour.resizeIframe.process()',500);								}		}		// add this function to the classbehaviour object		classBehaviour.resizeIframe = new ResizeIframe;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.resizeIframe;			// Resizes the window to avoid a scrollbar		// define this class behaviour		function FitToWindow(){			// properties			this.name 		= 	'fitToWindow';			// methods			this.start		=	function(node){									node.onresize = this.process;									this.process(node);								}			// events			this.process 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// while the scroll position is not 0									var intWhileCount = 0;									do{										// scroll the document by 1 pixel										window.scrollTo(1,1);										// measure the scroll position													intScrollX = (typeof(document.body.scrollLeft)!='undefined') ?  document.body.scrollLeft : window.pageXOffset ;										intScrollY = (typeof(document.body.scrollTop)!='undefined') ? document.body.scrollTop : window.pageYOffset ;										// if the scroll position is not 0										if(intScrollX==0){											// was a height specified											if(objNode.style.width=='') objNode.style.width = '100px';											// make the container larger											objNode.style.width = (parseInt(objNode.style.width) + 32) + 'px';										}										if(intScrollY==0){											// was a height specified											if(objNode.style.height=='') objNode.style.height = '100px';											// make the container larger											objNode.style.height = (parseInt(objNode.style.height) + 32) + 'px';										}										// count the steps										intWhileCount += 1;									}while((intScrollX==0 || intScrollY==0) && intWhileCount<32);									}		}		// add this function to the classbehaviour object		classBehaviour.fitToWindow = new FitToWindow;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fitToWindow;			// Alternates the classes of a table's rows and columns		// define this class behaviour		function ZebraTable(){			// properties			this.name 		= 	'zebraTable';			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									var objRows, objCols, intCellNumber;									// get all table rows									objRows = objNode.getElementsByTagName('TR');									// for all table rows									for(var intRow=0; intRow<objRows.length; intRow++){										// undo any previous classing										objRows[intRow].className = objRows[intRow].className.replace('odd','');										objRows[intRow].className = objRows[intRow].className.replace('even','');										// add oddrow or evenrow class to the row										objRows[intRow].className += (intRow%2==0) ? ' odd' : ' even' ;										// and row and col counters if they're not allready present										if(objRows[intRow].className.indexOf('row_')<0) objRows[intRow].className += ' row_' + intRow;										// get all nodes in this row										objCols = objRows[intRow].childNodes;										// for every node in the row										intCellNumber = 0;										for(var intCol=0; intCol<objCols.length; intCol++){											// is this a cell or a header											if(objCols[intCol].nodeName.indexOf('text')<0){												// undo any previous classing												objCols[intCol].className = objCols[intCol].className.replace('odd','');												objCols[intCol].className = objCols[intCol].className.replace('even','');												// add oddcol or evencol class												objCols[intCol].className += (intCellNumber%2==0) ? ' odd' : ' even' ;												// and row and col counters if they're not allready present												if( objCols[intCol].className.indexOf('col_')<0) objCols[intCol].className += ' col_' + intCellNumber;												// keep cell numbers												intCellNumber += 1;											}										}									}								}		}		// add this function to the classbehaviour object		classBehaviour.zebraTable = new ZebraTable;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.zebraTable;			// Makes the headers of a table click/sortable		// define this class behaviour		function SortColumn(){			// properties			this.name 		= 	'sortColumn';			this.column	=	0;			// methods			this.start		=	function(node){									node.onclick = this.sort;									// apply the default sort direction style									if(node.className.indexOf('sorted')<0) node.className += ' unSorted';								}			this.forward 	= 	function(rowA,rowB){									var st = classBehaviour.sortColumn;									var regTags = new RegExp('<(.|\n)+?>','gi');									// get the string values from the node									strA = (rowA.childNodes[st.column].childNodes.length == 0) ? ' ' : rowA.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');									strB = (rowB.childNodes[st.column].childNodes.length == 0) ? ' ' : rowB.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');									// get the numeric values from the node									intA = parseInt(strA.replace(',',''));									intB = parseInt(strB.replace(',',''));									// compare the values for the sort funtion									if(strA==strB || (navigator.appVersion.indexOf('MSIE 5.0')>-1)){										// equal										return 0;									}else if(isNaN(intA) || isNaN(intB)){										// compare the textual values										return (strA<strB) ? 1 : -1 ;									}else{										// compare the numeric values										return intB - intA;									}								}			this.reverse 	= 	function(rowA,rowB){									var st = classBehaviour.sortColumn;									var regTags = new RegExp('<(.|\n)+?>','gi');									// get the string values from the node									strA = (rowA.childNodes[st.column].childNodes.length == 0) ? ' ' : rowA.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');									strB = (rowB.childNodes[st.column].childNodes.length == 0) ? ' ' : rowB.childNodes[st.column].innerHTML.replace('---','0,00').replace(regTags,'');									// get the numeric values from the node									intA = parseInt(strA.replace(',',''));									intB = parseInt(strB.replace(',',''));									// compare the values for the sort funtion									if(strA==strB || (navigator.appVersion.indexOf('MSIE 5.0')>-1)){										// equal										return 0;									}else if(isNaN(intA) || isNaN(intB)){										// compare the textual values										return (strA>strB) ? 1 : -1 ;									}else{										// compare the numeric values										return intA - intB;									}								}			// events			this.sort 		= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var st = classBehaviour.sortColumn;									// defaults									sortDirection	= 'sortedForward';									// find column number									var objSiblings	= objNode.parentNode.childNodes;									for(var intA=0; intA<objSiblings.length; intA++){										// is this a cell of a text-node										if(objSiblings[intA].nodeName=="TD" || objSiblings[intA].nodeName=="TH"){											// test if this is the clicked node											if(objSiblings[intA] == objNode){												// remember the clicked column												st.column = intA;												// toggle the sort direction												sortDirection = (objSiblings[intA].className.indexOf('sortedForward')>-1) ? 'sortedReverse' : 'sortedForward' ;												// adjust the sorting direction classname												objSiblings[intA].className = objSiblings[intA].className.replace('sortedReverse', sortDirection);												objSiblings[intA].className = objSiblings[intA].className.replace('sortedForward', sortDirection);												objSiblings[intA].className = objSiblings[intA].className.replace('unSorted', sortDirection);											}else{												// unmark any previously sorted column												objSiblings[intA].className = objSiblings[intA].className.replace('sortedReverse', 'unSorted');												objSiblings[intA].className = objSiblings[intA].className.replace('sortedForward', 'unSorted');											}										}									}									// make a nodelist									var fullTable		= objNode.parentNode.parentNode.parentNode;									var sortParent		= fullTable.getElementsByTagName('TBODY')[0];									var nodeList		= sortParent.childNodes;									var nodeArray		= new Array();									// for all table rows									for(var intA=0; intA<nodeList.length; intA++){										if(nodeList[intA].nodeName.indexOf('TR')>-1){											// store it in an array											nodeArray[nodeArray.length] = nodeList[intA];										}									}									// sort the collection using a helper function									nodeArray = (sortDirection=='sortedForward') ? nodeArray.sort(st.forward) : nodeArray.sort(st.reverse);									// clear the unsorted nodelist									for(var intA=0; intA<nodeList.length; intA++){										if(nodeList[intA].nodeName.indexOf('TR')>-1){											sortParent.removeChild(nodeList[intA]);										}									}									// append the sorted nodelist									for(var intA=0; intA<nodeArray.length; intA++){										sortParent.appendChild(nodeArray[intA]);									}									// reapply the zebra effect									if(fullTable.className.indexOf('zebraTable')>-1) classBehaviour.zebraTable.process(fullTable);								}		}		// add this function to the classbehaviour object		classBehaviour.sortColumn = new SortColumn;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.sortColumn;			// 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;			// Close the window (it's cold)		// define this class behaviour		function CloseThisWindow(){			// properties			this.name 		= 	'closeThisWindow';			// methods			this.start		=	function(node){									node.onclick = this.process;								}			this.process 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									window.close();								}		}		// add this function to the classbehaviour object		classBehaviour.closeThisWindow = new CloseThisWindow;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.closeThisWindow;		      // Jump back to the previous page            // define this class behaviour            function GoToPrevious(){                  // properties                  this.name         =     'goToPrevious';                  // methods                  this.start        =     function(node){                                                      node.onclick = this.process;                                                }                  this.process      =     function(that){                                                      var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;                                                      // open the print dialog                                                      window.history.go(-1);                                                }            }            // add this function to the classbehaviour object            classBehaviour.goToPrevious = new GoToPrevious;            classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.goToPrevious;			// Make dropdown menu		// define this class behaviour		function DropDownMenu(){			// properties			this.name 		= 	'dropDownMenu';			// methods			this.start		=	function(node){									this.process(node);								}			this.recurse 	= 	function(objParentNode){									var cmh = classBehaviour.classMouseHover;									var tnn = classBehaviour.toggleNextNode;									// mark the node as active									cmh.addActive(objParentNode);									// add active class to the anchor									if(objParentNode.getElementsByTagName('A').length>0) cmh.addActive(objParentNode.getElementsByTagName('A')[0]);									// replace image source for active version									if(objParentNode.getElementsByTagName('IMG').length>0)  tnn.toggleNext(objParentNode.getElementsByTagName('IMG')[0]);									// next recursion to same node type									if(objParentNode.nodeName == objParentNode.parentNode.parentNode.nodeName) this.recurse(objParentNode.parentNode.parentNode);								}			this.process 	= 	function(objNode){									var mau = classBehaviour.matchActiveUrl;									var objNodes, objMatch, objNextNode;									// apply default settings to all LIs									objNodes = objNode.getElementsByTagName('LI');									for(var intNode=0; intNode<objNodes.length; intNode++){										// hideThisNode										if(objNodes[intNode].className.indexOf('link')<0 && objNodes[intNode].className.indexOf('active')<0) objNodes[intNode].className += ' link';									}									// apply default settings to all IMGs									objNodes = objNode.getElementsByTagName('IMG');									for(var intNode=0; intNode<objNodes.length; intNode++){										// if this node has children										if(objNodes[intNode].parentNode.getElementsByTagName('UL').length>0){											// set a starting value for the open and closed toggle											objNodes[intNode].parentNode.getElementsByTagName('UL')[0].style.display  = 'none';											// rename the image to indicate it's subnodes.											objNodes[intNode].src = objNodes[intNode].src.replace('_child', '_parent');										}										// toggleNextNode										objNodes[intNode].onclick = this.togglePeers;									}									// apply default settings to all As									objNodes = objNode.getElementsByTagName('A');									for(var intNode=0; intNode<objNodes.length; intNode++){										// if the item has no valid link										if(objNodes[intNode].href.indexOf("#")==objNodes[intNode].href.length-1){											// make it the link of it's first child											objNodes[intNode].href = objNodes[intNode+1].href										}										// use matchActiveUrl to find active items OR use the ones marked manualy										objMatch = (mau.process(objNodes[intNode]) || objNodes[intNode].className.indexOf('active')>-1) ? objNodes[intNode] : objMatch ;									}									// recurse back the last matching node									if(objMatch!=null) this.recurse(objMatch.parentNode);								}			this.togglePeers=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var tnn = classBehaviour.toggleNextNode;									// get all the peers of this node									allPeers = objNode.parentNode.parentNode.childNodes;									// for all peers									for(var a=0; a<allPeers.length; a++){										// if the peer is no textnode and not the target node										if(allPeers[a].nodeName.toLowerCase().indexOf('li')>-1 && objNode.parentNode!=allPeers[a]){											// if the peer has a submenu toggle											subToggles = allPeers[a].getElementsByTagName('img');											if(subToggles.length>0){												// if the node is opened												if(subToggles[0].src.indexOf('active')>-1){													// close it													tnn.toggleNext(subToggles[0]);												}											}										}									}									// toggle the current noce									tnn.toggleNext(objNode);								}		}		// add this function to the classbehaviour object		classBehaviour.dropDownMenu = new DropDownMenu;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.dropDownMenu;			// Make foldout menu		// define this class behaviour		function FoldOutMenu(){			// properties			this.name 		= 	'foldOutMenu';			this.timeout	=	null;			this.delay		=	1024;			this.foldIns 	= 	new Array();			this.activeNode =	null;			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									var objNodes, objMatch;									var mau = classBehaviour.matchActiveUrl;									// apply events to all LIs									objNodes = objNode.getElementsByTagName('LI');									for(var intNode=0; intNode<objNodes.length; intNode++){										// mouseover events										objNodes[intNode].onmouseover	= this.addHover;										objNodes[intNode].onmouseout	= this.remHover;									}									// apply default settings to all As									objNodes = objNode.getElementsByTagName('A');									for(var intNode=0; intNode<objNodes.length; intNode++){										// if the item has no valid link										if(objNodes[intNode].href.indexOf("#")==objNodes[intNode].href.length-1){											// make it the link of it's first child											objNodes[intNode].href = objNodes[intNode+1].href										}										// use matchActiveUrl to find active items OR use the ones marked manualy										objMatch = (mau.process(objNodes[intNode]) || objNodes[intNode].className.indexOf('active')>-1) ? objNodes[intNode] : objMatch ;									}									// recurse back the last matching node									if(objMatch!=null){										this.recurse(objMatch.parentNode);									}								}			this.recurse 	= 	function(objParentNode){									var cmh = classBehaviour.classMouseHover;									// add active class to the anchor									if(objParentNode.getElementsByTagName('A').length>0) cmh.addActive(objParentNode.getElementsByTagName('A')[0]);									// store the active node									this.activeNode = objParentNode;									// add the active src to any image in the node									imgNodes = objParentNode.getElementsByTagName('img');									if(imgNodes.length>0) imgNodes[0].src = imgNodes[0].src.replace('_link','_active');									// next recursion to same node type									if(objParentNode.nodeName == objParentNode.parentNode.parentNode.nodeName) this.recurse(objParentNode.parentNode.parentNode);								}			// events			this.addHover 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var cmh = classBehaviour.classMouseHover;									var fom = classBehaviour.foldOutMenu;									// if a delay is required									if(fom.delay>0){										// cancel the timeout on the delayed mouseevents										clearTimeout(fom.timeout);										// handle the delayed mouseouts										while(fom.foldIns.length>0){											// change the stored active node to "active"											if(fom.activeNode!=null) if(fom.activeNode.getElementsByTagName('IMG').length>0) fom.activeNode.getElementsByTagName('IMG')[0].src = fom.activeNode.getElementsByTagName('IMG')[0].src.replace('_link','_active');											// change the src of a child image											imgNodes = fom.foldIns[fom.foldIns.length-1].getElementsByTagName('img');											if(imgNodes.length>0) imgNodes[0].src = imgNodes[0].src.replace('_active','_link');											// remove the active classes from every item to be folded in											cmh.remHover(fom.foldIns[fom.foldIns.length-1]);											fom.foldIns.length = fom.foldIns.length - 1;										}										// restore all select form elements										allSelects = document.getElementsByTagName('SELECT');										if(document.all){											for(var a=0; a<allSelects.length; a++){												allSelects[a].style.visibility = 'visible';											}										}									}									// is the node exists									if(objNode!=null){										// emulate the parent node's mouseout event										cmh.addHover(objNode);										// change the stored active node to "link"										if(fom.activeNode!=null) if(fom.activeNode.getElementsByTagName('IMG').length>0) fom.activeNode.getElementsByTagName('IMG')[0].src = fom.activeNode.getElementsByTagName('IMG')[0].src.replace('_active','_link');										// change the src of a child image										imgNodes = objNode.getElementsByTagName('img');										if(imgNodes.length>0) imgNodes[0].src = imgNodes[0].src.replace('_link','_active');										// hide all select form elements										allSelects = document.getElementsByTagName('SELECT');										if(document.all){											for(var a=0; a<allSelects.length; a++){												allSelects[a].style.visibility = 'hidden';											}										}									}								}			this.remHover 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var cmh = classBehaviour.classMouseHover;									var fom = classBehaviour.foldOutMenu;									// if no delay is required									if(fom.delay==0){										// emulate the parent node's mouseout event										cmh.remHover(objNode);										// change the stored active node to "active"										if(fom.activeNode!=null){}										// change the src of a child image										imgNodes = objNode.getElementsByTagName('img');										if(imgNodes.length>0) imgNodes[0].src = imgNodes[0].src.replace('_active','_link');										// restore all select form elements										allSelects = document.getElementsByTagName('SELECT');										if(document.all){											for(var a=0; a<allSelects.length; a++){												allSelects[a].style.visibility = 'visible';											}										}									}else{										// cancel the timeout on the delayed mouseevents										clearTimeout(fom.timeout);										// store the mouseout for delayed closing										fom.foldIns[fom.foldIns.length] = objNode;										// order a delayed handling of the saved up mouseouts										fom.timeout = setTimeout('classBehaviour.foldOutMenu.addHover()',fom.delay);									}								}		}		// add this function to the classbehaviour object		classBehaviour.foldOutMenu = new FoldOutMenu;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.foldOutMenu;			// Remove this tag if it's found to be empty		// define this class behaviour		function RemoveIfEmpty(){			// properties			this.name 		= 	'removeIfEmpty';			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									// doesn't this node have child nodes?									if(objNode.childNodes.length==0){										// remove the node										objNode.parentNode.removeChild(objNode);									}								}		}		// add this function to the classbehaviour object		classBehaviour.removeIfEmpty = new RemoveIfEmpty;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.removeIfEmpty;			// Fixes the position of an element		// define this class behaviour		function FixedPosition(){			// properties			this.name 		= 	'fixedPosition';			this.nodes 		= 	new Array();			// methods			this.start		=	function(node){									this.nodes[this.nodes.length] = node;									if(document.all){										window.onscroll = this.process;									}else{										node.style.position = 'fixed';									}								}			// events			this.process 	= 	function(){									var fp = classBehaviour.fixedPosition;									// this is only needed in internet explorer									for(var a=0; a<fp.nodes.length; a++){										fp.nodes[a].style.marginTop = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px';										fp.nodes[a].style.marginLeft = (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + 'px';									}								}		}		// add this function to the classbehaviour object		classBehaviour.fixedPosition = new FixedPosition;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fixedPosition;			// 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.utilities.getClassParameter(objNode, 'width', '630');									var strHeight 		= ',height=' + classBehaviour.utilities.getClassParameter(objNode, 'height', '385');									var strLeft			= ',left=' + classBehaviour.utilities.getClassParameter(objNode, 'left', '');									var strTop			= ',top=' + classBehaviour.utilities.getClassParameter(objNode, 'top', '');									var strToolbars 	= ',toolbar=' + classBehaviour.utilities.getClassParameter(objNode, 'toolbar', 'no');									var strScrolling 	= ',scrollbars=' + classBehaviour.utilities.getClassParameter(objNode, 'scrollbars', 'no');									var strStatus 		= ',status=' + classBehaviour.utilities.getClassParameter(objNode, 'status', 'no');									var strResize 		= ',resizable=' + classBehaviour.utilities.getClassParameter(objNode, 'resizable', 'yes');									var strLocation 	= ',location=' + classBehaviour.utilities.getClassParameter(objNode, 'location', 'no');									var strMenu 		= ',menu=' + classBehaviour.utilities.getClassParameter(objNode, 'menu', 'no');									var strName 		= classBehaviour.utilities.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;			// Open links in the opener of this window		// define this class behaviour		function OpenInOpener(){			// properties			this.name 		= 	'openInOpener';			// methods			this.start		=	function(node){									node.onclick = this.process;								}			// events			this.process 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// open the href in the opener of this window									window.opener.location.href = objNode.href;									// optionaly close the window									if(classBehaviour.utilities.getClassParameter(objNode, 'closeParent', 'false')=='true') window.close();									// cancel the link									return false;																	}		}		// add this function to the classbehaviour object		classBehaviour.openInOpener = new OpenInOpener;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openInOpener;			// Open links in a new window		// define this class behaviour		function OpenAsWindow(){			// properties			this.name 		= 	'openAsWindow';			// methods			this.start		=	function(node){									node.target = "_blank"								}		}		// add this function to the classbehaviour object		classBehaviour.openAsWindow = new OpenAsWindow;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openAsWindow;			// Chooses a random increment of an image source		// define this class behaviour		function SetRandomSrc(){			// properties			this.name 		= 	'setRandomSrc';			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									// get min parameter									var intMin = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'min', '0'));									// get max parameter									var intMax = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'max', '1'));									// generate random number									var intRandom = Math.round(Math.random()*(intMax-intMin))+intMin;									// replace default increment by random number									if(objNode.src!=null) objNode.src = objNode.src.replace('_0','_'+intRandom);									objNode.className = objNode.className.replace('_0','_'+intRandom);								}		}		// add this function to the classbehaviour object		classBehaviour.setRandomSrc = new SetRandomSrc;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.setRandomSrc;			// Chooses a random increment of an image source		// define this class behaviour		function SetRandomClassName(){			// properties			this.name 		= 	'setRandomClassName';			// methods			this.start		=	function(node){									this.process(node);								}			this.process 	= 	function(objNode){									// get min parameter									var intMin = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'min', '0'));									// get max parameter									var intMax = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'max', '1'));									// generate random number									var intRandom = Math.round(Math.random()*(intMax-intMin))+intMin;									// replace default increment by random number									if(objNode.className!=null) objNode.className = objNode.className.replace('_0','_'+intRandom);									objNode.className = objNode.className.replace('_0','_'+intRandom);								}		}		// add this function to the classbehaviour object		classBehaviour.setRandomClassName = new SetRandomClassName;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.setRandomClassName;			// Class a link matching the document's url		// define this class behaviour		function MatchActiveUrl(){			// properties			this.name 		= 	'matchActiveUrl';			// methods			this.start		=	function(node){									this.process(node);								}			this.convertAbsToRelUrls 	= 	function(strUrl){												// is the url a relative path												if(strUrl.indexOf('/')<0 || strUrl.substr(0,1)=='.' || strUrl.substr(0,1)=='/'){													// the current absolute path													strAbs = document.location.href;													// remove the filename from the end													strAbs = strAbs.substring(0, strAbs.lastIndexOf('/'));													// while there are parent markers in the url													while(strUrl.indexOf('../')==0){														// remove one level from the absolute path														strUrl = strUrl.replace('../','');														// remove one parent marker from the relative path														strAbs = strAbs.substring(0, strAbs.lastIndexOf('/'));													}													// remove all current dir markers from the relative url													strUrl = strUrl.replace(/\.\//gi,'');													// add the url to the absolute path													strUrl = strAbs + '/' + strUrl;												}												return strUrl;											}			this.compareUrls 	= 	function(strUrlA,strUrlB){										var intCurScore = 0;										var intPotScore = 0;										var intMaxScore = 0;										var intA,intB;										// replace most common illegal characters										strUrlA = strUrlA.replace(/ /gi,"%20");										strUrlB = strUrlB.replace(/ /gi,"%20");										// remove anchors										strUrlA = strUrlA.split('#')[0];										strUrlB = strUrlB.split('#')[0];										// make sure both paths are absolute										strUrlA = this.convertAbsToRelUrls(strUrlA);										strUrlB = this.convertAbsToRelUrls(strUrlB);										// split the urls into manageable strings										var arrUrlA = strUrlA.split(/[?&#\/]/i);										var arrUrlB = strUrlB.split(/[?&#\/]/i);										// for every string of UrlA										for(intA=0; intA<arrUrlA.length; intA++){											// is the string in the substrings of UrlB											intB = 0; while(intB<arrUrlB.length && arrUrlA[intA]!=arrUrlB[intB]) intB += 1;											// if a match was found, add length of string A to current score											if(intB<arrUrlB.length) intCurScore += arrUrlA[intA].length;											// add length of string A to potential score											intPotScore += arrUrlA[intA].length;										}										// calcultate maximum score possible										intMaxScore = strUrlB.length - arrUrlB.length + 1;										// return the compare-score										return intCurScore/intPotScore;									}			this.process 	= 	function(objNode){									var cmh = classBehaviour.classMouseHover;									var smh = classBehaviour.srcMouseHover;									// get parent recursion									var intToParent	= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'toParent', '0'));									// get parent href									var intFromParent = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'fromParent', '0'));									// get the url and clean it up									var strUrl = this.convertAbsToRelUrls(document.location.href);									// get the href and clean it up									var strHref = (intFromParent>0) ? this.convertAbsToRelUrls(objNode.parentNode.getAttribute('href')) : this.convertAbsToRelUrls(objNode.getAttribute('href')) ;									// was the data bad									if(strHref!=null){										// compare score										var ftlCompareScore = this.compareUrls(strUrl, strHref) * this.compareUrls(strHref, strUrl);										// if the href matches the url 										if(ftlCompareScore==1){											// add the active class to the target item											cmh.addActive(objNode);											if(objNode.nodeName=='IMG') smh.addActive(objNode);											// if a parent node also needs to be marked											if(intToParent>0){												// get the relevant parent node												for(var intA=0; intA<intToParent; intA++) objNode = objNode.parentNode;												// if the href matches the url												if(ftlCompareScore==1){													// add the active class to the parent item													cmh.addActive(objNode);												}											}											// report a match											return true;										}									}									// report no match									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.matchActiveUrl = new MatchActiveUrl;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.matchActiveUrl;			// 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.utilities.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 explanation										hasExplanation = classBehaviour.utilities.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.warning 		=	function(objNode, status){										var vi = classBehaviour.validateInput;										// highlight he input field										objNode.className = (status) ? objNode.className.replace(' warning', '') : objNode.className + ' warning' ;										// 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.utilities.getClassParameter(objNode, 'warningId', null);											// check if the next node is for summaries
											nextNode 			= classBehaviour.utilities.nextNode(objNode);											// 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.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');										}									}			this.isFormElement	=	function(objNode){										return (objNode.nodeName=='INPUT' || objNode.nodeName=='SELECT' || objNode.nodeName=='TEXTAREA');									}
			this.summary 		= 	function(objNode){
										var vi = classBehaviour.validateInput;
										// find the root of the form
										rootNode = classBehaviour.utilities.rootNode(objNode, null, null, 'validateAllInput');
										// is a summary required
										vi.summaryId = classBehaviour.utilities.getClassParameter(rootNode, 'summaryId', null);										if(vi.summaryId){											summaryObj = document.getElementById(vi.summaryId);											summaryTxt = '';											// for all nodes
											var objSubNodes = rootNode.getElementsByTagName("*");											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=='block'){													// copy it's contents to the summary text													summaryTxt += '<li>' + objSubNodes[a].innerHTML + '</li>';												}											}											// add the summary text to the summary
											summaryObj.style.display = (summaryTxt.length>0) ? 'block' : 'none' ;											summaryObj.innerHTML = (summaryTxt.length>0) ? '<ul>' + summaryTxt + '</ul>' : '' ;										}
									}
			this.customChecks	=	new CustomChecks;
			// events
			this.clear	=	function(objNode){								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;								// if there was an explanation provides as a value								hasExplanation = classBehaviour.utilities.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.all 	= 	function(that){								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;								var vi = classBehaviour.validateInput;								var booPassed = true;
								// find the form's root
								rootNode = classBehaviour.utilities.rootNode(objNode, 'FORM', null, null);								// get all subnodes in the form
								var objSubNodes = rootNode.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 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.utilities.getClassParameter(objNode, 'type', '');								allowEmpty			= classBehaviour.utilities.getClassParameter(objNode, 'allowEmpty', 'no');								ifCheckedId			= classBehaviour.utilities.getClassParameter(objNode, 'ifCheckedId', null);								hasExplanation 		= classBehaviour.utilities.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.customChecks.bankAccount(objNode);										break;									case 'isradiochecked' :										booValueValidator = vi.customChecks.isRadioChecked(objNode);										break;									case 'anyofthesechecked' : 										booValueValidator = vi.customChecks.anyOfTheseChecked(objNode);										break;									case 'text' :										booValueValidator = (objNode.value!="");										break;
									case 'repeat' :
										booValueValidator = vi.customChecks.isRepeated(objNode);
									case 'regexp' : 
										customRegId = classBehaviour.utilities.getClassParameter(objNode,'regxid','myRegExp');
										customRegString = document.getElementById(customRegId).value;
										customRegExp = new RegExp(customRegString);										booValueValidator = (objNode.value.match(customRegExp)!=null);										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);
								// is a summary required?
								vi.summary(objNode);								// return a pass of fail boolean to whoever may want to know the results of the test								return (override!=null) ? validates : override;							}		}
			function CustomChecks(){
				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;												}
					this.isRepeated		=	function(objNode){
													// default validatie
													wasRepeated = false;
													// get the target field to compare
													repeatedId = classBehaviour.utilities.getClassParameter(objNode, 'id', null);
													// if the id is valid
													if(repeatedId!=null){
														repeatedValue = document.getElementById(repeatedId).value;
														wasRepeated = (repeatedValue==objNode.value);
													}
													// report back
													return wasRepeated;
												}
			}		// add this function to the classbehaviour object		classBehaviour.validateInput = new ValidateInput;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateInput;
			// 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;								}		}		// add this function to the classbehaviour object		classBehaviour.validateAllInput = new ValidateAllInput;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateAllInput;			// 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;			// Enforces minimal height of a container		// define this class behaviour		function MinHeight(){			// properties			this.name 		= 	'minHeight';			this.adjusts 	= 	new Array();			this.timeout 	= 	null;			// methods			this.start		=	function(node){									// immediate event									this.process(node);									// store object for later resize									this.adjusts[this.adjusts.length] = node;									window.onresize = this.delay;								}			this.adjust	 	= 	function(){									for(var intA=0; intA<this.adjusts.length; intA++){										this.adjusts[intA].style.height = 'auto';										this.process(this.adjusts[intA]);									}								}			// events			this.delay 		= 	function(){									clearTimeout(classBehaviour.minHeight.timeout);									// maxWidth might want to re-adjusted too									classBehaviour.minHeight.timeout = setTimeout('classBehaviour.minHeight.adjust();classBehaviour.maxWidth.adjust();',  256);								}			this.process 	= 	function(objNode){									// get the height parameters									var strMinHeight, strOffSet;											strMinHeight	= classBehaviour.utilities.getClassParameter(objNode, 'height', '100pct');									strOffSet		= classBehaviour.utilities.getClassParameter(objNode, 'heightOffset', '0px');									// get the current document and window dimensions									var intDocHeight, intCanvasHeight;									intDocHeight	= document.body.scrollHeight;									intCanvasHeight	= (typeof(window.innerHeight)!='undefined') ? window.innerHeight : document.body.offsetHeight ;									// adjust target container to fill the difference in dimensions									var intMinHeight= (strMinHeight.indexOf('pct')>-1) ? Math.round(intCanvasHeight * parseInt(strMinHeight) / 100) : parseInt(strMinHeight) ;									var intOffSet	= (strOffSet.indexOf('pct')>-1) ? Math.round(intCanvasHeight * parseInt(strOffSet) / 100) : parseInt(strOffSet) ;									// set the page's minimum height									if(document.all){										intOffSet -= 1;										objNode.style.height = (intMinHeight - intOffSet) + 'px';									}else{										objNode.style.minHeight = (intMinHeight - intOffSet) + 'px';									}								}		}		// add this function to the classbehaviour object		classBehaviour.minHeight = new MinHeight;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.minHeight;			// Enforces maximal width of a container		// define this class behaviour		function MaxWidth(){			// properties			this.name 		= 	'maxWidth';			this.adjusts 	= 	new Array();			// methods			this.start		=	function(node){									// immediate event									this.process(node);									// store object for later resize									this.adjusts[this.adjusts.length] = node;									window.onresize = this.delay;								}			this.adjust	 	= 	function(){									for(var intA=0; intA<this.adjusts.length; intA++){										this.adjusts[intA].style.width = 'auto';										this.process(this.adjusts[intA]);									}								}			// events			this.delay 		= 	function(){									clearTimeout(classBehaviour.maxWidth.timeout);									// minHeight might want to re-adjusted too									classBehaviour.minHeight.timeout = setTimeout('classBehaviour.minHeight.adjust();classBehaviour.maxWidth.adjust();',  256);								}			this.process 	= 	function(objNode){									// get the width parameters									var strMaxWidth, strOffSet;									strMaxWidth		= classBehaviour.utilities.getClassParameter(objNode, 'width', '100pct');									strOffSet		= classBehaviour.utilities.getClassParameter(objNode, 'widthOffset', '0px');									// get the current document and window dimensions									var intDocWidth, intCanvasWidth;									intDocWidth		= document.body.scrollWidth;									intCanvasWidth	= (typeof(window.innerWidth)!='undefined') ? window.innerWidth : document.body.offsetWidth ;									// adjust target container to fill the difference in dimensions									var intMaxWidth	= (strMaxWidth.indexOf('pct')>-1) ? Math.round(intCanvasWidth * parseInt(strMaxWidth) / 100) : parseInt(strMaxWidth) ;									var intOffSet	= (strOffSet.indexOf('pct')>-1) ? Math.round(intCanvasWidth * parseInt(strOffSet) / 100) : parseInt(strOffSet) ;									objNode.style.width = (intDocWidth>intMaxWidth) ? (intMaxWidth - intOffSet) + 'px' : 'auto' ;								}		}		// add this function to the classbehaviour object		classBehaviour.maxWidth = new MaxWidth;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.maxWidth;			// Scroll the list items of a container		// define this class behaviour		function ListScroller(){			// properties			this.name 		= 	'listScroller';			this.object	=	null;			this.dimensions =	new Coordinates();			this.limits	=	new Coordinates();			this.speed		=	new Coordinates();			this.distance	=	new Coordinates();			this.delay		=	null;			this.interval	=	null;			// methods			this.start		=	function(node){									// make a new instance of the scroller object									this.object			= node;									this.dimensions.x	= parseInt(classBehaviour.utilities.getClassParameter(node, 'width', '112'));									this.dimensions.y	= parseInt(classBehaviour.utilities.getClassParameter(node, 'height', '120'));									this.speed.x		= -1 * parseInt(classBehaviour.utilities.getClassParameter(node, 'left', '2'));									this.speed.y		= -1 * parseInt(classBehaviour.utilities.getClassParameter(node, 'top', '0'));									this.delay			= parseInt(classBehaviour.utilities.getClassParameter(node, 'delay', '64'));									this.distance.x		= 0;									this.distance.y		= 0;									// clone the list items for double buffering									var scrollList		= this.object.getElementsByTagName('UL')[0];									var scrollItems		= scrollList.getElementsByTagName('LI');									var itemsMax		= scrollItems.length;									for(var a=0; a<itemsMax; a++){										var new_node = scrollItems[a].cloneNode(true);										scrollList.appendChild(new_node); 									}									// note the scrolling limits									this.limits.x	= this.dimensions.x * itemsMax;									this.limits.y	= this.dimensions.y * itemsMax;									// set prerequisite styles										//	UL settings										scrollList.style.width	= (this.dimensions.x * 2 * itemsMax) + 'px';										scrollList.style.height	= (this.dimensions.y * 2 * itemsMax) + 'px';										// LI settings										for(var a=0; a<scrollItems.length; a++){											scrollItems[a].style.width	= this.dimensions.x + 'px';											scrollItems[a].style.height	= this.dimensions.y + 'px';										}									// set the mouseover events									this.object.onmouseout	= this.scroll;									this.object.onmouseover = this.pause;									// if there are direction controls give them events									if(document.getElementById('prevControl')) document.getElementById('prevControl').onclick = this.goLeft;									if(document.getElementById('nextControl')) document.getElementById('nextControl').onclick = this.goRight;									// initiate the scroll interval									this.scroll();								}			this.step		=	function(){									var scrollCanvas =	this.object.getElementsByTagName('UL')[0];									// calculate the new positions - loop on the right									if(this.speed.x<=0) newLeftPos	=	(this.distance.x <= -1*this.limits.x) ? '0px' : (this.distance.x + this.speed.x) + 'px';									if(this.speed.y<=0) newTopPos		=	(this.distance.y <= -1*this.limits.y) ? '0px' : (this.distance.y + this.speed.y) + 'px';									// loop on the right									if(this.speed.x>0) newLeftPos		=	(this.distance.x > 0) ? (-1*this.limits.x + this.speed.x) + 'px' : (this.distance.x + this.speed.x) + 'px';									if(this.speed.y>0) newTopPos		=	(this.distance.y > 0) ? (-1*this.limits.y + this.speed.y) + 'px' : (this.distance.y + this.speed.y) + 'px';									// update styles									scrollCanvas.style.left	= newLeftPos;									scrollCanvas.style.top	= newTopPos;									// update stored positions									this.distance.x			=	parseInt(newLeftPos);									this.distance.y			=	parseInt(newTopPos);									// cancel something									return 0;								}			// events			this.goLeft	=	function(){									var lsc = classBehaviour.listScroller;									// set the scrolling									lsc.speed.x = Math.abs(lsc.speed.x);									// cancel the click									return false;								}			this.goRight	=	function(){									var lsc = classBehaviour.listScroller;									// set the scrolling									lsc.speed.x = -1 * Math.abs(lsc.speed.x);									// cancel the click									return false;								}			this.scroll		=	function(){									classBehaviour.listScroller.interval = setInterval('classBehaviour.listScroller.step()', classBehaviour.listScroller.delay);									return 0;								}			this.pause		=	function(){									clearInterval(classBehaviour.listScroller.interval);									return 0;								}		}		/* allready defined elsewhere			function Coordinates(x,y,z){				this.x = x;				this.y = y;				this.z = z;			}		*/		// add this function to the classbehaviour object		classBehaviour.listScroller = new ListScroller;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.listScroller;		/* TODO: controls for the scroller	<li><a href="?3" id="prevControl"><img alt="Vorige" src="../images/movieGallery_previous_link.gif"/></a></li>	<li><a href="?4" id="nextControl"><img alt="Volgende" src="../images/movieGallery_next_link.gif"/></a></li>*/					// Toggle hidden siblings when clicking this node		// define this class behaviour		function ToggleHiddenSiblings(){			// properties			this.name 		= 	'toggleHiddenSiblings';			this.lastNode	=	null;			this.lastNext	=	null;			// methods			this.start		=	function(node){									node.onclick = this.process;								}			// events			this.process	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// If this node is a real check box									var prefState = null;									if(objNode.getAttribute('type')=='checkbox'){										// take it's state for hiding or showing										prefState = objNode.checked;									}									// from this node upwards, find the tbody or the table									var testNode = objNode.parentNode;									while(										testNode.nodeName.toLowerCase()!='tbody' && 										testNode.nodeName.toLowerCase()!='table' && 										testNode.nodeName.toLowerCase()!='div' && 										testNode.nodeName.toLowerCase()!='fieldset' && 										testNode.nodeName.toLowerCase()!='body'									){										testNode = testNode.parentNode;									}									var allNodes = testNode.getElementsByTagName('*');									// for the nodes within									for(var a=0; a<allNodes.length; a++){										// check if it is part of the hiding/showing action										if(allNodes[a].className.indexOf('hideThisNode')>-1){											// take the prefered state from the current state if the original node wasn't a checkbox											if(prefState==null) prefState = (allNodes[a].style.display=='none') ? true : false ;												// show of hide the sibling												if(prefState){													// show thenode using the correct visible state													node.style.display = classBehaviour.utilities.getVisibleState(node);												}else{													allNodes[a].style.display = 'none';												}										}									}								}		}		// add this function to the classbehaviour object		classBehaviour.toggleHiddenSiblings = new ToggleHiddenSiblings;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleHiddenSiblings;			// 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.utilities.getClassParameter(node, 'limitRight', '9999'));											this.limitLeft = parseInt(classBehaviour.utilities.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;			// Add or remove display:none; onclick		// define this class behaviour		function AdjustSize(){			// properties			this.name 		= 	'adjustSize';			// methods 			this.start		=	function(){									window.onresize = this.resize;									this.resize();								}			// events			this.delay		=	function(){											}			this.resize	= 	function(){									// measure window size									winWidth = (document.all) ? document.body.offsetWidth : window.innerWidth ;									winHeight = (document.all) ? document.body.offsetHeight : window.innerHeight ;									// adjust the classname according to the size									if(winWidth>1024){										document.body.className = document.body.className.replace('small','large').replace('medium','large');									}else if(winWidth<800){										document.body.className = document.body.className.replace('medium','small').replace('large','small');									}else{										document.body.className = document.body.className.replace('small','medium').replace('large','medium');									}								}		}		// add this function to the classbehaviour object		classBehaviour.adjustSize = new AdjustSize;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.adjustSize;			// Allows a file upload element to recieve fake markup		// define this class behaviour		function FileBrowser(){			// properties			this.name 		= 	'fileBrowser';			this.fileElement	=	null;			this.textElement	=	null;			this.buttonElement	=	null;			// methods 			this.start			=	function(node){										allInputs = node.getElementsByTagName('input');										// get the form elements										this.fileElement = allInputs[0];										this.textElement = allInputs[1];										this.buttonElement = allInputs[2];										// when the file is entered										this.fileElement.onchange = this.transfer;										this.fileElement.onmouseover = this.addHover;										this.fileElement.onmouseout = this.remHover;									}			// events			this.addHover		=	function(){										fb = classBehaviour.fileBrowser;										fb.buttonElement.onmouseover();									}			this.remHover		=	function(){										fb = classBehaviour.fileBrowser;										fb.buttonElement.onmouseout();									}			this.transfer		=	function(){										fb = classBehaviour.fileBrowser;										fb.textElement.value = fb.fileElement.value;									}		}		// add this function to the classbehaviour object		classBehaviour.fileBrowser = new FileBrowser;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fileBrowser;			// sizes an element according to a value		// define this class behaviour		function ChartValue(){			// properties 			this.name 			= 	'chartValue';			// methods 			this.start			=	function(node){										widthValue = parseInt(classBehaviour.utilities.getClassParameter(node, 'value', '0'));										widthValue -= 1;										if(widthValue<1) widthValue = 1;										node.style.width = (widthValue-1) + '%';									}		}		// add this function to the classbehaviour object		classBehaviour.chartValue = new ChartValue;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.chartValue;			// Copies selected text to a target container		// define this class behaviour		function TextSelection(){			// properties 			this.name 			= 	'textSelection';			// methods 			this.start			=	function(node){										node.onmouseup = this.process;									}			// events			this.process		=	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;										// get the target field										var target = document.getElementById(classBehaviour.utilities.getClassParameter(objNode, 'id', 'selectedText'));										// get the text selection										var selected;										if(window.getSelection){											selected = window.getSelection();										}else if(document.selection){											selected = document.selection.createRange().text;										}										// copy the text to the target field										if(target) target.value = selected;																			}		}		// add this function to the classbehaviour object		classBehaviour.textSelection = new TextSelection;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.textSelection;			// Shows elements based on the state of a related radio button or checkbox		// define this class behaviour		function DisplayIfChecked(){			// properties			this.name 		= 	'displayIfChecked';			this.timeout	= 	null;			// methods 			this.start		=	function(node){									node.onclick = this.delay;									node.onchange = this.delay;									this.delay(node);								}			// events			this.delay  	=   function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var hsic = classBehaviour.displayIfChecked;									// cancel the previous timeout								//	clearTimeout(hsic.timeout);									// wait a little while for MSIE									hsic.timeout = setTimeout("classBehaviour.displayIfChecked.toggle('" + objNode.id + "')", 100);								}			this.toggle		= 	function(id){									// source object									var objNode = document.getElementById(id);									// get all inputs									var allInputs = document.getElementsByTagName('input');									// for all inputs									for(var a=0; a<allInputs.length; a++){										// if this is a radio and it belong to the same named group										if(allInputs[a].name==objNode.name){											// get the target id											targetId = classBehaviour.utilities.getClassParameter(allInputs[a], 'id', 'displayThisIdIfChecked');											targetObj = document.getElementById(targetId);											// hide the targetnode if checked											if(targetObj){												targetObj.style.display = (allInputs[a].checked) ? classBehaviour.utilities.getVisibleState(targetObj) : 'none' ;											}										}									}								}		}		// add this function to the classbehaviour object		classBehaviour.displayIfChecked = new DisplayIfChecked;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.displayIfChecked;			// fade the element in		// define this class behaviour		function FadeElement(){			// properties			this.name 		= 	'fadeElement';			// methods			this.start		=	function(node){									this.process(node);								}			this.set		=	function(id, amount){									var node = document.getElementById(id);									// 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.get		=	function(id){									var fadeValue = null;									var node = document.getElementById(id);									// 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;								}			// events			this.process	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// the node need an id									if(objNode.id==''){										objNode.id = 'fader' + Math.round(Math.random()*10000);									}									// fade parameters									id		= objNode.id;									wait	= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'wait', '1024'));									start	= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'start', '0'));									// start value									this.set(objNode.id, start);									// start the fade									setTimeout("classBehaviour.fadeElement.loop('"+ id +"')", wait);								}			this.loop		=	function(id){									var fe = classBehaviour.fadeElement;									var objNode = document.getElementById(id);									// fade parameters									end			= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'end', '100'));									step		= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'step', '10'));									increment	= parseInt(classBehaviour.utilities.getClassParameter(objNode, 'increment', '5'));									next		= fe.get(id) + increment;									// set next fade status									fe.set(id, next);									// order a new step if needed									if(next<end) setTimeout("classBehaviour.fadeElement.loop('" + id + "')", step);								}			this.crossFade	=	function(idOut, idIn, amount){									var fe = classBehaviour.fadeElement;									// if the amount is not 50									if(amount<=100){										// set the fade amounts										fe.set(idIn, amount);										fe.set(idOut, 100-amount);										// unhide the new page										document.getElementById(idIn).style.display = 'block';										// repeat the fade										setTimeout("classBehaviour.fadeElement.crossFade('" + idOut + "','" + idIn + "'," + (amount+10) + ")",50);									}else{									// else										// hide the old page										document.getElementById(idOut).style.display = 'none';										// unlock the controls										classBehaviour.fadeElement.locked = false;									}								}		}		// add this function to the classbehaviour object		classBehaviour.fadeElement = new FadeElement;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fadeElement;			// make a decorative popup from a longdesc		// define this class behaviour		function ShowLongDesc(){			// properties			this.name 		= 	'showLongDesc';			// methods			this.start		=	function(node){									// apply the event handler to the link									classBehaviour.xmlDoc.addRequest(node.getAttribute('longdesc') + '?rnd='+Math.round(Math.random()*10000), this.load, this.wait, false, node);									node.onmouseover = this.show;									node.onmouseout = this.hide;								}			// events			this.over		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var sld = classBehaviour.showLongDesc;									// if this node doesn't have a display-node									if(objNode.previousSibling.className != 'longDesc'){										// make an AJAX call using the longdesc from the link											classBehaviour.xmlDoc.addRequest(objNode.getAttribute('longdesc') + '?rnd='+Math.round(Math.random()*10000), sld.load, sld.wait, false, objNode);									}else{										// just show the link										sld.show(objNode)										// cancel click on the link										return false;									}								}			this.wait		=	function(status, targetObject){									/* debug(status, targetObject.nodeName); */								}			this.load		=	function(xmlReply, targetObject){									var sld = classBehaviour.showLongDesc;									var objNode = targetObject;									// create a display-node right after the link-node									var displayNode = document.createElement('span');									// add the replied xml content to the new node									displayNode.innerHTML = xmlReply.getElementsByTagName('body')[0].firstChild.nodeValue;									// apply a markup class to the new node									displayNode.className = 'longDesc';									// give the original link a special markup									objNode.className += ' longDesc';									objNode.parentNode.insertBefore(displayNode, objNode);								}			this.show		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// show the displaynode									if(objNode.previousSibling.className=='longDesc') objNode.previousSibling.style.display = 'block';								}			this.hide		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// hide the node									if(objNode.previousSibling.className=='longDesc') objNode.previousSibling.style.display = 'none';								}		}		// add this function to the classbehaviour object		classBehaviour.showLongDesc = new ShowLongDesc;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.showLongDesc;		/* TODO: document this */	// Toggle nodes of a certain class		// define this class behaviour		function ToggleMarkedNodes(){			// properties			this.name 		= 	'toggleMarkedNodes';			this.lastNode	=	null;			this.lastNext	=	null;			// methods			this.start		=	function(node){									node.onclick = this.process;								}			// events			this.process	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// toggleMarkedNodes id_myNodeList openText_Open_the_list closeText_Close_the_list																		listId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'myNodeList');									openText = classBehaviour.utilities.getClassParameter(objNode, 'openText', 'Show more...').replace(/_/gi,' ');									closeText = classBehaviour.utilities.getClassParameter(objNode, 'closeText', 'Show less...').replace(/_/gi,' ');																		// get all nodes from the list									allNodes = document.getElementById(listId).childNodes;									// for every node in the list									for(var a=0; a<allNodes.length; a++){										// is it marked for hiding, show it if hidden, hide it if visible										if(allNodes[a].className) 											if(allNodes[a].className.indexOf('markedNode')>-1) 												allNodes[a].style.display = (allNodes[a].style.display!='none') ? 'none' : 'block' ;									}									// if the button is set to open, set is to close, else, set it to open									if(objNode.nodeName=='A'){										objNode.firstChild.nodeValue = (objNode.firstChild.nodeValue==openText) ? closeText : openText;									}else if(objNode.nodeName=='INPUT'){										objNode.value = (objNode.value==openText) ? closeText : openText;									}																	}		}		// add this function to the classbehaviour object		classBehaviour.toggleMarkedNodes = new ToggleMarkedNodes;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleMarkedNodes;			// Update a slide based on clicks on thumbnails		// define this class behaviour		function ThumbnailToPhoto(){			// properties			this.name 		= 	'thumbnailToPhoto';			this.busy		=	false;			// methods			this.start		=	function(node){									// set the event for this thumbnail									node.onclick = this.showPhoto;									// set the doublebuffer initial state									var targetId = classBehaviour.utilities.getClassParameter(node, 'id', 'photoTarget');									document.getElementById(targetId).getElementsByTagName('img')[0].style.display = 'block';									document.getElementById(targetId).getElementsByTagName('img')[1].style.display = 'none';								}			// events			this.showPhoto	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var ttp = classBehaviour.thumbnailToPhoto;									// get the display buffers									var targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'photoTarget');									bufferA = document.getElementById(targetId).getElementsByTagName('img')[0];									bufferB = document.getElementById(targetId).getElementsByTagName('img')[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.getElementsByTagName('img')[0].alt;									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){										// lock this function										ttp.busy = true;										// set the new source for the image from the clicked thumbnail										bufferIn.alt = targetAlt;										bufferIn.src = targetSrc;										// call the fader after the image has loaded										bufferIn.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;
			// Update a slide based on clicks on radio-buttons		// define this class behaviour		function RadioToPhoto(){			// properties			this.name 		= 	'radioToPhoto';			// methods			this.start		=	function(node){									node.onclick = this.setImage;								}			// events			this.setImage	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// where is the target
									targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'photoTarget');
									// set the source
									document.getElementById(targetId).src = objNode.value;								}		}		// add this function to the classbehaviour object		classBehaviour.radioToPhoto = new RadioToPhoto;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.radioToPhoto;
		
	// 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;			this.index		=	0;			// 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 has a link and submenus evident by their links											objLinks = objNodes[a].getElementsByTagName('A');											if(objLinks.length>0){												// default classname
												objLinks[0].className += (objLinks[0].className.indexOf('link')<0 || objLinks[0].className.indexOf('active')<0) ? ' link' : '' ;
												// mouseover events												objLinks[0].onmousemove	= this.open;												// 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, 											objLists = objNodes[a].getElementsByTagName('UL');											if(objLists.length>0){												// give it a random id												this.index++;												objLists[0].id = 'sub_' + this.index;												// delay the closing of the menu when over subitems												objLinks = objLists[0].getElementsByTagName('A');												for(var b=0; b<objLinks.length; b++) objLinks[b].onmouseover = this.cancel;											}										}									}									// global close event									objNode.onmouseout	= this.delay;									// 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
											fm.current.className = fm.current.className.replace('hover','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											objNode.className = objNode.className.replace('link','hover');
											// 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(fadeOpenId!='') document.getElementById(fadeOpenId).style.display = 'block';											if(fadeCloseId!='') document.getElementById(fadeCloseId).style.display = 'none';										}else{											fm.locked = true;											classBehaviour.fader.crossFade(fadeOpenId, fadeCloseId, 0, 10, 20, 'classBehaviour.fadingMenu.locked=false;');										}									}								}			this.cancel	=	function(){									var fm = classBehaviour.fadingMenu;									// clear the previous delay									clearTimeout(fm.timeout);								}			this.delay		=	function(){									var fm = classBehaviour.fadingMenu;									// clear the previous delay									clearTimeout(fm.timeout);									// delay the closing									fm.timeout = setTimeout('classBehaviour.fadingMenu.close()', 512);								}			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 every element into view		// starting style		document.writeln('<style>.scrollIn {visibility : hidden;}</style>')		// define this class behaviour		function ScrollIn(){			// properties			this.name 		= 	'scrollIn';			// methods			this.start		=	function(node){									// for all nodes in the list									var allNodes = node.getElementsByTagName('li');									for(var a=0; a<allNodes.length; a++){										// move the node it's length back and an additional factor										allNodes[a].style.marginLeft = ((a - allNodes.length) * 60 - 240) + 'px';									}									// make the list visible									node.style.visibility = 'visible';									// start the animation loop									this.loop(node.id);								}			// events			this.loop		=	function(id){									var repeat = false;									var offset = 0;									// for all nodes in the list									var allNodes = document.getElementById(id).getElementsByTagName('li');									for(var a=0; a<allNodes.length; a++){										offSet = parseInt(allNodes[a].style.marginLeft);										// if the offset isn't 0										if(offSet<0){											// reduce the offset											allNodes[a].style.marginLeft = (offSet + 5) + 'px';											// order a next step											repeat = true;										}									}									// repeat the loop									setTimeout('classBehaviour.scrollIn.loop("'+id+'")',10);								}		}		// add this function to the classbehaviour object		classBehaviour.scrollIn = new ScrollIn;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.scrollIn;			// 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.utilities.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.utilities.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.utilities.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.utilities.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;			// manage the customization budget		// define this class behaviour		function CustomizeList(){			// properties			this.name 		= 	'customizeList';			this.list		=	null;			// methods			this.start		=	function(node){									// store the list									this.list = node;									// get all the form elements in the list									allInputs = node.getElementsByTagName('input');									// for all for elements									for(var a=0; a<allInputs.length; a++){										// if this elements is a radiobutton										if(allInputs[a].getAttribute('type')=='radio'){											// add the event handler											allInputs[a].onchange = this.redraw;										}									}									// calculate the total price									this.redraw();								}			// events			this.redraw		=	function(){									var czl = classBehaviour.customizeList;									// get the default price									var totalPrice = parseInt(document.getElementById('customizeBase').value);									var optionsList = '';									// get all lists									allLists = czl.list.getElementsByTagName('ul');									// for all lists									for(var a=0; a<allLists.length; a++){										// get all list items										allItems = allLists[a].getElementsByTagName('input');										// for all list items										for(var b=0; b<allItems.length; b++){											// if the list item is checked											if(allItems[b].checked){												// highlight the item												allItems[b].parentNode.parentNode.className = allItems[b].parentNode.parentNode.className.replace('passive', 'active');												// add the price difference												totalPrice += parseInt(allItems[b].parentNode.getElementsByTagName('input')[1].value);												// add the option to the options list												optionsList += '<li><span>' + allItems[b].parentNode.getElementsByTagName('label')[0].innerHTML + '</span></li>'											// else											}else{												// remove the highlight												allItems[b].parentNode.parentNode.className = allItems[b].parentNode.parentNode.className.replace('active', 'passive');											}										}									}									// post the total price										document.getElementById('customizePrice').innerHTML = totalPrice.toFixed(2);										// document.getElementById('customizePrice').innerHTML = totalPrice.toLocaleString();									// post the options list									document.getElementById('customizeList').innerHTML = optionsList;								}		}		// add this function to the classbehaviour object		classBehaviour.customizeList = new CustomizeList;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.customizeList;			// 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									allButtons = node.getElementsByTagName('button');									// set the event handlers									if(allButtons.length>0) allButtons[allButtons.length-1].onclick = this.next;									if(allButtons.length>1) allButtons[allButtons.length-2].onclick = this.previous;									// set the default states of the slides									allSlides = node.getElementsByTagName('li');									allSlides[0].className += (allSlides[0].className.indexOf('active')<0) ? ' active' : '' ;									for(var a=0; a<allSlides.length; a++) 										allSlides[a].style.display = (allSlides[a].className.indexOf('active')>-1) ? 'block' : 'none' ;								}			// 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');										// default starting position										var activeSlide = allSlides[0];										var nextSlide = allSlides[1];										// look for the active node										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] ;											}										}										// set the display state										activeSlide.style.position = 'absolute';										nextSlide.style.position = 'relative';										// 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, 5, 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');										// default starting position										var activeSlide = allSlides[0];										var nextSlide = allSlides[allSlides.length-1];										// look for the active node										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] ;											}										}										// set the display state										activeSlide.style.position = 'absolute';										nextSlide.style.position = 'relative';										// 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, 5, 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;
		
	// Enrich a calendar control
		// define this class behaviour
		function DatePicker(){
			/* properties */
			this.name 		= 	'datePicker';
			this.dateHtml	=	'';
			this.index		=	0;
			/* methods */
			this.start		=	function(node, nodeId){
									if(node==null) node = document.getElementById(nodeId); 									// give this node an id if it doesn't have one yet
									this.index += 1;									node.id = (node.id) ? node.id : this.name + this.index ;
									// start the toggle event
									classBehaviour.toggleNextNode.start(node);
									// find the calendar container node
									calendarContainer = classBehaviour.utilities.nextNode(node);
									// import the calendar xml or use the one allready loaded
									if(this.dateHtml==''){
										// report the loading-in-progress of the calender
										this.dateHtml='loading...';
										// find the path to the xml source
										this.dateHtmlSrc = classBehaviour.utilities.nextNode(node).getElementsByTagName('input')[0].value;
										// import it
										classBehaviour.xmlDoc.addRequest(this.dateHtmlSrc, classBehaviour.datePicker.build, null, null, calendarContainer);
									}else if(this.dateHtml=='loading...'){
										// wait until the loading of the html is finished
										setTimeout('classBehaviour.datePicker.start(null, "' + node.id + '")', 512);
									}else{
										// continue, using the cached html
										this.build(null, calendarContainer, this.dateHtml);
									}
									// set the event handlers for this node
									node.onclick = this.open;
								}
			this.set		=	function(calendarNode, date){
									dpr = classBehaviour.datePicker;
									// get the next and previous buttons
									calendarNode.getElementsByTagName('button')[0].onclick = dpr.previous;
									calendarNode.getElementsByTagName('button')[1].onclick = dpr.next;
									// set the month dropdown
									monthNode = calendarNode.getElementsByTagName('select')[0];
									monthNode.selectedIndex = date.getMonth();
									monthNode.onchange = dpr.update;
									// set the year dropdown
									yearSelect = calendarNode.getElementsByTagName('select')[1];
									yearOptions = yearSelect.getElementsByTagName('option');
									currentYear = date.getFullYear();
									if(yearOptions.length==1){
										yearOption = yearOptions[0].cloneNode(true);
										for(var a=currentYear-100; a<currentYear+10; a++ ){
											yearOption = yearSelect.getElementsByTagName('option')[0].cloneNode(true);
											yearOption.value = a;
											yearOption.selected = (a==currentYear) ? 'selected' : '' ;
											yearOption.text = a;
											yearSelect.appendChild(yearOption);
										}
										yearSelect.removeChild(yearSelect.getElementsByTagName('option')[0]);
										yearSelect.onchange = dpr.update;
									}else{
										for(var a=0; a<yearOptions.length; a++) yearOptions[a].selected = (yearOptions[a].value==currentYear) ? 'selected' : '' ;
									}
									// clear out the previous month
									daySlots = calendarNode.getElementsByTagName('td');
									for(var a=0; a<daySlots.length; a++){
										daySlots[a].className = "empty";
										daySlots[a].innerHTML = "";
										daySlots[a].onclick = null;
									}
									// fill the new month
									currentDay = new Date(date.getFullYear(), date.getMonth(), 0);
									nextDay = new Date(date.getFullYear(), date.getMonth(), 1);
									startWeekDay = currentDay.getDay();
									do{
										// next date
										currentDay = new Date(currentDay.getFullYear(), currentDay.getMonth(), currentDay.getDate()+1);
										nextDay = new Date(nextDay.getFullYear(), nextDay.getMonth(), nextDay.getDate()+1);
										// put the date on the weekday cell
										daySlots[currentDay.getDate()+startWeekDay].innerHTML = currentDay.getDate();
										daySlots[currentDay.getDate()+startWeekDay].className = "";
										daySlots[currentDay.getDate()+startWeekDay].onclick = dpr.pick;
									}while(currentDay.getDate() < nextDay.getDate())
								}
			this.build		=	function(xmlDoc, calendarContainer, txtDoc){
									// store the html
									classBehaviour.datePicker.dateHtml = txtDoc;
									// clean the imported xhtml
									calendarContainer.innerHTML = txtDoc.replace('<?xml version="1.0"?>', '').replace('<root>', '').replace('</root>', '');
									// apply the events
									classBehaviour.parseDocument(calendarContainer);
								}
			/* events */
			this.open		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dpr = classBehaviour.datePicker;
									// close all other calendars
									dpr.close();
									// OBJECTS
									calendar = classBehaviour.utilities.nextNode(objNode);
									// STARTING DATE
									// get the input from the field
									// turn it into a date
									// if the result is a date
										// use it as a start date
									// else
										// take the current date
										theDate = new Date();
									// CONSTRUCT THE CALENDAR AT THE GIVEN DATE
									dpr.set(calendar, theDate);
									// POSITION THE CALENDAR
									// get the position
									screenXpos = (typeof(event)!='undefined') ? event.x : that.layerX;
									screenYpos = (typeof(event)!='undefined') ? event.y : that.layerY;
									// if the position is too close to the edge
									calendarWidth = calendar.firstChild.offsetWidth;
									screenWidth = (window.innerWidth) ? window.innerWidth : document.documentElement.clientWidth ;
									scrolledWidth = (typeof(document.documentElement.scrollLeft)!='undefined') ? document.documentElement.scrollLeft : window.pageXOffset ;
									if(screenXpos+calendarWidth > screenWidth+window.pageXOffset) screenXpos -= calendarWidth;
									// if the position is too close to the bottom
									calendarHeight = calendar.firstChild.offsetHeight;
									screenHeight = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight ;
									scrolledHeight = (typeof(document.documentElement.scrollTop)!='undefined') ? document.documentElement.scrollTop : window.pageYOffset ;
									if(screenYpos+calendarHeight+10 > screenHeight+scrolledHeight) screenYpos -= calendarHeight;
									// set the position
									calendar.style.left = screenXpos + 'px';
									calendar.style.top = screenYpos + 'px';
									// SHOW THE CALENDAR
									classBehaviour.toggleNextNode.toggle(objNode);
									// prepare to close the calendar
									calendar.onmouseover = dpr.cancel;
									calendar.onmouseout	= dpr.wait;
									return false;
								}
			this.wait		=	function(){
									closeCalendarTimeout = setTimeout('classBehaviour.datePicker.close()',1024);
								}
			this.cancel		=	function(){
									if(typeof(closeCalendarTimeout)!='undefined') clearTimeout(closeCalendarTimeout);
								}
			this.close		=	function(){
									// get all buttons that might have open calendars
									allButtons = document.getElementsByTagName('button');
									for(var a=0; a<allButtons.length; a++){
										if(allButtons[a].className.indexOf('datePicker')>-1) 
											if(classBehaviour.utilities.nextNode(allButtons[a]).className.indexOf('showThisNode')>-1)
												classBehaviour.toggleNextNode.toggle(allButtons[a]);
									}
								}
			this.update		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dpr = classBehaviour.datePicker;
									// get both selectors from the parent node
									selectors = objNode.parentNode.getElementsByTagName('select');
									// get the month
									month = parseInt(selectors[0].value);
									// get the year
									year = parseInt(selectors[1].value);
									// make a date out of it
									theDate = new Date(year, month, 1);
									// update the calendar
									dpr.set(objNode.parentNode.parentNode.parentNode.parentNode,theDate);
								}
			this.next		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dpr = classBehaviour.datePicker;
									// get the calendar
									calendar = objNode.parentNode.parentNode.parentNode.parentNode;
									// get the displayed date
									month = parseInt(objNode.parentNode.parentNode.parentNode.getElementsByTagName('select')[0].value);
									year = parseInt(objNode.parentNode.parentNode.parentNode.getElementsByTagName('select')[1].value);
									// add a month
									theDate = new Date(year,month+1,1);
									// build the calendar
									dpr.set(calendar, theDate);
									return false;
								}
			this.previous	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var dpr = classBehaviour.datePicker;
									// get the calendar
									calendar = objNode.parentNode.parentNode.parentNode.parentNode;
									// get the displayed date
									month = parseInt(objNode.parentNode.parentNode.parentNode.getElementsByTagName('select')[0].value);
									year = parseInt(objNode.parentNode.parentNode.parentNode.getElementsByTagName('select')[1].value);
									// subsctract a month
									theDate = new Date(year,month-1,1);
									// build the calendar
									dpr.set(calendar,theDate);
									return false;
								}
			this.pick		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// get the selected day
									dayValue = objNode.innerHTML;
									// get the selected month
									calendarTitle = objNode.parentNode.parentNode.parentNode.getElementsByTagName('caption')[0];
									month = calendarTitle.getElementsByTagName('select')[0];
										// monthValue = month[month.selectedIndex].innerHTML;
									monthValue = parseInt(month.value) + 1;
									// get the selected year
									year = calendarTitle.getElementsByTagName('select')[1];
									yearValue = year[year.selectedIndex].innerHTML;
									// put it in the input field
									targetFields = objNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName('input');
									targetFields[0].value = ((dayValue+'').length==1) ? '0' + dayValue  : dayValue;
									targetFields[1].value = ((monthValue+'').length==1) ? '0' + monthValue : monthValue;
									targetFields[2].value = yearValue;
									// close the calendar
									calendarButton = objNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName('button')[0];
									classBehaviour.toggleNextNode.toggle(calendarButton);
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.datePicker = new DatePicker;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.datePicker;
			// Center landscape or portrait thumbnails in a defined area		// define this class behaviour		function CenteredThumbnails(){			/* properties */			this.name 		= 	'centeredThumbnails';
			this.index		=	0;			/* methods */			this.start		=	function(node){
									// count the instance
									this.index += 1;
									// give this node an id if it doesn't have one
									if(node.id != null) node.id = this.name + this.index;
									// center the thumbnail in a short while									setTimeout('classBehaviour.centeredThumbnails.process("'+node.id+'")', 10);								}
			this.process	=	function(nodeId){
									// get the node
									node = document.getElementById(nodeId);
									// get all links in this container									allLinks = node.getElementsByTagName('div');									// 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;			// hover the next node near the mouse pointer		// define this class behaviour		function HoverNextNode(){			// properties			this.name 		= 	'hoverNextNode';			// methods			this.start		=	function(node){									// mouse handlers									node.onmouseover = this.show;									node.onmouseout = this.hide;									node.onmousemove = this.place;								}			// events			this.show		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									targetNode = classBehaviour.utilities.nextNode(objNode);									targetNode.style.visibility = 'visible';								}			this.hide		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									targetNode = classBehaviour.utilities.nextNode(objNode);									targetNode.style.visibility = 'hidden';								}			this.place		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									targetNode = classBehaviour.utilities.nextNode(objNode);									targetNode.style.position = 'absolute';									targetNode.style.left = (typeof(event)!='undefined') ? (event.x) + 'px' : (that.layerX) + 'px' ;									targetNode.style.top = (typeof(event)!='undefined') ? (event.y) + 'px' : (that.layerY) + 'px' ;								}		}		// add this function to the classbehaviour object		classBehaviour.hoverNextNode = new HoverNextNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.hoverNextNode;			// 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;									// 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';								}			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		// hide the alternative beforehand		document.writeln("<style>.flashTitle .flashAlternative{visibility : hidden;}</style>");		// define this class behaviour		function FlashTitle(){			// properties			this.name 			= 	'flashTitle';			this.index			=	0;
			this.cachedXml		=	'';			// methods			this.start			=	function(node){										// give the node an id of it doesn't have one										if(!node.id){											node.id = this.name + this.index;											this.index += 1;										}
										// check if there is flash
										requiredVersion = parseInt(classBehaviour.utilities.getClassParameter(node, 'version', '7'));
										if(this.checkForFlash(requiredVersion)){
											// load the source file
											if(this.cachedXml=='') this.loadXml(node)
											else if(this.cachedXml=='loading...') this.retryLater(node)
											else this.processXml(null, node, this.cachedXml);
										}else{
											// make the alternative content visible, just in case it didn't work
											classBehaviour.flashTitle.showAlt(node);
										}									}
			this.checkForFlash	=	function(requiredVersion){
										// check if Adobe's flash checking script is available
										return (typeof(DetectFlashVer)!='undefined') ? DetectFlashVer(requiredVersion, 0, 0) : true ;
									}
			this.loadXml		=	function(node){
										classBehaviour.flashTitle.cachedXml = 'loading...';
										// load the xml file
										loadUrl = node.getElementsByTagName('input')[0].value;
										classBehaviour.xmlDoc.addRequest(loadUrl, this.processXml, this.loadProgress, null, node);
									}
			this.retryLater		=	function(node){
										// wait while loading
										setTimeout('classBehaviour.flashTitle.start(document.getElementById("' + node.id + '"))', 100);
									}
			this.loadProgress	=	function(progress, referer){
										// if loading fails show the alternative
										if(progress<0) classBehaviour.flashTitle.showAlt(referer);
									}			this.processXml		=	function(sourceDoc, node, sourceText){
										// store the xml for re-use
										classBehaviour.flashTitle.cachedXml = sourceText;
										// set the default values for all parameters										flashMovie		= "../flash/flashTitle.swf";										flashWidth		= node.offsetWidth;										flashHeight		= node.offsetHeight;										flashWmode		= "Transparent";										flashScale		= "noScale";										flashSalign		= "l";										flashName		= "_" + node.id;										flashVariables	= "inputText=" + node.innerHTML.replace(/<(.|\n)*?>/gi,"").replace(/^\s+/gi,"").replace(/&amp;/gi,"&");										// for all childnodes of node which may contain configuration variables
										allInputs = node.getElementsByTagName('input');										for(var a=0; a<allInputs.length; a++){
											switch(allInputs[a].name){
												case 'movie' 			: flashMovie = allInputs[a].value; break;												case 'width' 			: flashWidth = allInputs[a].value; break;												case 'height' 			: flashHeight = allInputs[a].value; break;												case 'wmode' 			: flashWmode = allInputs[a].value; break;												case 'scale' 			: flashScale = allInputs[a].value; break;												case 'salign' 			: flashSalign = allInputs[a].value; break;												case 'name' 			: flashName = allInputs[a].value; break;												case 'flashvars' 		: flashVariables += '&' + allInputs[a].value; break;												default 				: break;											}										}										// if the dimensions are in %, be sure to tell the container										if(flashWidth.toString().indexOf('%')>-1) node.style.width = flashWidth;										if(flashHeight.toString().indexOf('%')>-1) node.style.height = flashHeight;										// load the flash plugin
										sourceText = sourceText.replace('<?xml version="1.0"?>', '');
										sourceText = sourceText.replace(/{movie}/gi, flashMovie);
										sourceText = sourceText.replace(/{width}/gi, flashWidth);
										sourceText = sourceText.replace(/{height}/gi, flashHeight);
										sourceText = sourceText.replace(/{wmode}/gi, flashWmode);
										sourceText = sourceText.replace(/{scale}/gi, flashScale);
										sourceText = sourceText.replace(/{salign}/gi, flashSalign);
										sourceText = sourceText.replace(/{name}/gi, flashName);
										sourceText = sourceText.replace(/{flashvars}/gi, flashVariables);
										node.innerHTML = sourceText;									}
			this.setFlashVar	=	function(nodeId, varName, varValue){
										// find the proper buried ID
										node = 	(document.getElementById('__'+nodeId)) ? 
													document.getElementById('__'+nodeId) : 
														(document.getElementById('_'+nodeId)) ? 
															document.getElementById('_'+nodeId) : 
																document.getElementById(nodeId) ;
										// send the parameter to the flash object
										if(typeof(node.SetVariable)!='undefined') node.SetVariable(varName, varValue);
									}			// events
			this.showAlt		=	function(node){
										allContents = node.getElementsByTagName('*');
										if(allContents.length>0) 
											for(var a=0; a<allContents.length; a++) 
												if(allContents[a].className.indexOf('flashAlternative')>-1) 
													allContents[a].style.visibility = 'visible';
									}		}		// add this function to the classbehaviour object		classBehaviour.flashTitle = new FlashTitle;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.flashTitle;
		/* 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 id									var targetId = classBehaviour.utilities.getClassParameter(node, 'id', 'photoTarget');									var target = document.getElementById(targetId);									// double the display buffer if there's only one									var buffers = target.getElementsByTagName('div');									if(buffers.length==1){										var newBuffer = buffers[0].cloneNode(true);										target.appendChild(newBuffer);										buffers = target.getElementsByTagName('div');									}									// give the buffers default id if they haven't got any									if(!buffers[0].id || buffers[1].id){										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									allowCache = (classBehaviour.utilities.getClassParameter(node, 'cache', 'yes')=='yes') ? true : false ;									if(allowCache){										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 thumbnails' links to passive									thumblinks = objNode.parentNode.parentNode.getElementsByTagName('a');									for(var a=0; a<thumblinks.length; a++) thumblinks[a].className = thumblinks[a].className.replace('active','link');									// set the active thumbnail									thumbnail = objNode.getElementsByTagName('img')[0];									thumbnail.src = thumbnail.src.replace('_link','_active').replace('_hover','_active');									// set the active thumbnails' linl									thumblink = objNode;									thumblink.className = thumblink.className.replace('link','active').replace('hover','active');									// get the display buffers									var targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'photoTarget');									bufferA = document.getElementById(targetId).getElementsByTagName('div')[0];									bufferB = document.getElementById(targetId).getElementsByTagName('div')[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 = thumbnail.alt;									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.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;
			// Turn an element into an HTML-editor
		// define this class behaviour
		function RichTextEditor(){
			/* properties */
			this.name 			= 	'richTextEditor';
			this.containerType	=	'FIELDSET';
			this.buttonType		=	'BUTTON';
			this.stylesheet		=	'';
			this.editorHtml		=	'';
			this.index			=	0;
			this.instances		= 	new Array();
			this.interval		=	null;
			this.resizing		=	false;
			/* methods */
			this.start			=	function(node){ 										// give this node an id if it doesn't have one yet
										if(node.id==null){
											this.index += 1;											node.id = this.name + this.index ;
										}
										// import the editor if it has not been preloaded
										if(this.editorHtml==''){
											this.editorHtml = 'loading...';
											pathNode = node.getElementsByTagName('INPUT')[0];
											classBehaviour.xmlDoc.addRequest(pathNode.value, this.importXml, this.awaitXml, null, node);
										// if another instance of the editor is loading
										}else if(this.editorHtml=='loading...'){
											setTimeout('classBehaviour.richTextEditor.start(document.getElementById("'+node.id+'"))', 512);
										// if the editor is allready there
										}else{
											classBehaviour.richTextEditor.process(node);
										}
									}
			this.awaitXml		=	function(loadStatus, rootNode){
										// debug(loadStatus);
									}
			this.importXml		=	function(toolsXml, rootNode, toolsText){
										var edc = classBehaviour.richTextEditor;
										// extract the html from the imported xml
										edc.stylesheet = toolsText.split('<stylesheet>')[1].split('</stylesheet>')[0];
										edc.editorHtml = toolsText.split('<editorHtml>')[1].split('</editorHtml>')[0];
										// process the nodes
										edc.process(rootNode);
									}
			this.process		=	function(rootNode){
										var edc = classBehaviour.richTextEditor;
										// insert the editor html before the textarea
										rootNode.innerHTML = edc.editorHtml + rootNode.innerHTML;
										// prepare the editor
										edc.setCanvas(rootNode);
										edc.setControls(rootNode);
										// add this editor to the instances of editors
										edc.instances[edc.instances.length] = rootNode;
										// sync loop between the textarea and the iframe
										clearInterval(edc.interval);
										edc.interval = setInterval("classBehaviour.richTextEditor.sync()", 256);
									}
			this.setCanvas		=	function(rootNode){
										var edc = classBehaviour.richTextEditor;
										// store the container type
										this.containerType = rootNode.nodeName;
										// hide the textarea
										textArea = rootNode.getElementsByTagName('TEXTAREA')[0];
										textArea.id = (textArea.id) ? textArea.id : edc.name + 'Textarea' + this.index;
										textArea.style.display = 'none';
										// show the iframe
										iframe = rootNode.getElementsByTagName('IFRAME')[0];
										iframe.id = (iframe.id) ? iframe.id : edc.name + 'Iframe' + this.index;
										iframe.style.display = 'block';
										// transform the iframe into an editor
										editor = edc.getEditor(iframe.id);
										editor.designMode = 'on';
										// set the initial content
										editor.open();
										editor.write(textArea.value + this.stylesheet);
										editor.close();
									}
			this.setControls	=	function(rootNode){
										// if there's no button bars yet
										toolBars = rootNode.getElementsByTagName('UL');
										if(toolBars.length==2){
											// HTML BUTTON BAR
											// apply the classbehaviours of the button bar
											classBehaviour.parseDocument(toolBars[0]);
											// get the buttons
											buttons = toolBars[0].getElementsByTagName('*');
											// for each button in the button bar
											for(var a=0; a<buttons.length; a++){
												// set the event handlers for the edit buttons
												if(buttons[a].className.indexOf('cmd_')>-1){
													if(buttons[a].nodeName=='SELECT') buttons[a].onchange = this.editCommand;
													if(buttons[a].nodeName=='BUTTON') buttons[a].onclick = this.editCommand;
												}
											}
											// show the button bar
											toolBars[0].style.display = 'block';
											
											// TEXT BUTTON BAR
											// apply the classbehaviours of the button bar
											classBehaviour.parseDocument(toolBars[1]);
											// get the buttons
											buttons = toolBars[1].getElementsByTagName(this.buttonType);
											// for each button in the button bar and set the event handlers for the edit buttons
											for(var a=0; a<buttons.length; a++)
												if(buttons[a].nodeName=='BUTTON') if(buttons[a].className.indexOf('cmd_')>-1) buttons[a].onclick = this.editCommand;
											// hide the button bar
											toolBars[1].style.display = 'none';
										}
									}
			this.getEditor		=	function(id){
										return (document.getElementById(id).contentDocument) ? 
													document.getElementById(id).contentDocument : 
														document.frames[id].document ;
									}
			this.sync			=	function(){
										var edc = classBehaviour.richTextEditor;
										// for all instances of this class
										for(var a=0; a<edc.instances.length; a++){
											// get the iframe that may be associated with the editor
											allIframes = edc.instances[a].getElementsByTagName('iframe');
											allTextareas = edc.instances[a].getElementsByTagName('textarea');
											if(allIframes.length>0 && allTextareas.length>0){
												// get the editor from the iframe
												editor = classBehaviour.richTextEditor.getEditor(allIframes[0].id);
												// if the iframe is replacing the textarea
												if(allTextareas[0].style.display=='none'){
													allTextareas[0].value = editor.documentElement.firstChild.nextSibling.innerHTML.split('<LINK')[0].split('<link')[0];
												// else the textarea will replace the iframe
												}else{
													editor.documentElement.firstChild.nextSibling.innerHTML = allTextareas[0].value + classBehaviour.richTextEditor.stylesheet;
												}
											}
										}
									}
			this.resize			=	function(container){
											if(!this.resizing){
												// get the editor
												iFrame = container.getElementsByTagName('iframe')[0];
												textArea = container.getElementsByTagName('textarea')[0];
												// what is the mode of the editor
												editor = (textArea.style.display=='none') ? iFrame : textArea;
												// if the editor wasn't marked big
												if(editor.className.indexOf('biggerEditor')<0){
													// mark is as big
													editor.className = 'biggerEditor ' + editor.className;
													// and lock this function
													classBehaviour.richTextEditor.resizing = true;
													// make the editor twice as big
														// editor.style.height = (editor.offsetHeight * 3) + 'px';
													classBehaviour.fader.grow(editor.id, null, editor.offsetHeight*3, 20, 10, 'classBehaviour.richTextEditor.resizing=false;');
												//else
												}else{
													// remove it mark
													editor.className = editor.className.replace('biggerEditor', '');
													// and lock this function
													classBehaviour.richTextEditor.resizing = true;
													// make the editor half as big
														//editor.style.height = Math.round(editor.offsetHeight / 3) + 'px';
													classBehaviour.fader.shrink(editor.id, null, editor.offsetHeight/3, 20, 10, 'classBehaviour.richTextEditor.resizing=false;');
												}
											}
											// cancel the click
											return false;
										}
			this.closeOption 	=	function(objNode){
										var ecs = classBehaviour.richTextEditor;
										// find the toggle button
										rootNode = classBehaviour.utilities.rootNode(objNode, 'LI', null, null);
										buttonNode = rootNode.getElementsByTagName(ecs.buttonType)[0];
										// and press it
										if(buttonNode.className.indexOf('toggleNextNode')>-1) buttonNode.onclick(buttonNode);
									}
			/* events */
			this.toggle			=	function(container){
											// get the elements from this editor
											iframes = container.getElementsByTagName('iframe');
											buttonBars = container.getElementsByTagName('ul');
											textareas = container.getElementsByTagName('textarea');
											// if the textearea is invisible
											if(textareas[0].style.display=='none'){
												// hide the button bar
												buttonBars[0].style.display = 'none';
												buttonBars[1].style.display = 'block';
												// hide the iframe
												iframes[0].style.display = 'none';
												// show the textarea
												textareas[0].style.display = 'block';
											}else{
												// show the button bar
												buttonBars[0].style.display = 'block';
												buttonBars[1].style.display = 'none';
												// show the iframe
												iframes[0].style.display = 'block';
												// hide the textarea
												textareas[0].style.display = 'none';
											}
											// cancel the click
											return false;
										}
			this.editCommand		=	function(that){
											var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
											var ecs = classBehaviour.richTextEditor;
											// get the editor canvas
											container = objNode;
											while(container.nodeName.indexOf(classBehaviour.richTextEditor.containerType)<0) container = container.parentNode;
											editorId = container.getElementsByTagName('iframe')[0].id;
											editor = ecs.getEditor(editorId);
											// get the selected section
											selection = 	(editor.selection) ? editor.selection.createRange().text : 
																(editor.getSelection) ? editor.getSelection() : 
																	(editor.createRange) ? editor.createRange() : 
																		null ;
											// gather the command parameters
											commandName = classBehaviour.utilities.getClassParameter(objNode, 'cmd', '');
											commandArgument = classBehaviour.utilities.getClassParameter(objNode, 'arg', objNode.value);
											// exceptions
											command = true;
											switch(commandName){
												case 'insertimage' :
													commandArgument = classBehaviour.utilities.previousNode(objNode).value;
													ecs.closeOption(objNode);
													break;
												case 'createlink' :
													commandArgument = classBehaviour.utilities.previousNode(objNode).value;
													ecs.closeOption(objNode);
													break;
												case 'forecolor' :
													ecs.closeOption(objNode);
													break;
												case 'forecolor2' :
													commandArgument = classBehaviour.utilities.previousNode(objNode).value;
													commandName='forecolor';
													ecs.closeOption(objNode);
													break;
												case 'fontname' :
													ecs.closeOption(objNode);
													break;
												case 'fontname2' :
													commandArgument = classBehaviour.utilities.previousNode(objNode).value;
													commandName='fontname';
													ecs.closeOption(objNode);
													break;
												case 'fontsize' :
													ecs.closeOption(objNode);
													break;
												case 'fontsize2' :
													commandArgument = classBehaviour.utilities.previousNode(objNode).value;
													commandName='fontsize';
													ecs.closeOption(objNode);
													break;
												case 'toggle' :
													command = ecs.toggle(container);
													break;
												case 'bigger' :
													command = ecs.resize(container);
													break;
												default : 
													break;
											}
											// execute the command
											if(selection && command) editor.execCommand(commandName, false, commandArgument);
											// cancel the click
											return false;
										}
		}
		// add this function to the classbehaviour object
		classBehaviour.richTextEditor = new RichTextEditor;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.richTextEditor;
	// Insert a node imported from an xml file		// define this class behaviour		function InsertParentNode(){			// properties			this.name 		= 	'insertParentNode';			// methods			this.start		=	function(node){									// set the event for this button									node.onclick = this.importNode;								}			// events			this.importNode	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// what xml doc needs to be imported
									xmlSourceId = classBehaviour.utilities.getClassParameter(objNode,'src','frmXmlSource');
									xmlUrl = document.getElementById(xmlSourceId).value;
									// place the http request
									classBehaviour.xmlDoc.addRequest(xmlUrl, classBehaviour.insertParentNode.inserNode, classBehaviour.insertParentNode.waiting, false, objNode);									// cancel the click									return false;								}
			this.waiting	=	function(loadStatus){
									// debug(loadStatus);
								}
			this.inserNode =	function(importedXml, referedNode, importedText){
									// how deep is the button in the moving node
									nodeDepth = parseInt(classBehaviour.utilities.getClassParameter(referedNode,'parent','1'));
									for(var a=0; a<nodeDepth; a++) referedNode = referedNode.parentNode;									// clone the contents									newNode = document.createElement('dl');
									newNode.className = 'interface';									// add the cached contents before this button									referedNode.parentNode.insertBefore(newNode, referedNode);
									// insert the imported html
									classBehaviour.utilities.previousNode(referedNode).innerHTML = importedText.replace('<?xml version="1.0"?>','').replace('<root>','').replace('<dl class="interface">','').replace('</dl>','').replace('</root>','');									// (maybe) execute the clasbehaviours again									classBehaviour.parseDocument(classBehaviour.utilities.previousNode(referedNode));
								}		}		// add this function to the classbehaviour object		classBehaviour.insertParentNode = new InsertParentNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.insertParentNode;	
		
	// Clone the previous node to after this one		// define this class behaviour		function CloneParentNode(){			// properties			this.name 		= 	'cloneParentNode';			// methods			this.start		=	function(node){									// set the event for this button									node.onclick = this.clone;								}			// events			this.clone	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// how deep is the button in the moving node
									nodeDepth = parseInt(classBehaviour.utilities.getClassParameter(objNode,'parent','1'));
									for(var a=0; a<nodeDepth; a++) objNode = objNode.parentNode;									// clone the contents									newNode = objNode.cloneNode(true);									// add the cached contents before this button									objNode.parentNode.insertBefore(newNode, objNode);									// (maybe) execute the clasbehaviours again									classBehaviour.parseDocument(classBehaviour.utilities.previousNode(objNode));									// cancel the click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.cloneParentNode = new CloneParentNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.cloneParentNode;				// Change the order of page elements		// define this class behaviour		function MoveParentNode(){			// properties			this.name 		= 	'moveParentNode';			// methods			this.start		=	function(node){									// set the event for this button									node.onclick = this.move;								}			// events			this.move	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// up or down?
									goingDown = (classBehaviour.utilities.getClassParameter(objNode,'move','down')=='down');
									// how deep is the button in the moving node
									nodeDepth = parseInt(classBehaviour.utilities.getClassParameter(objNode,'parent','1'));
									for(var a=0; a<nodeDepth; a++) objNode = objNode.parentNode;									// the node before which this one is to be inserted									targetNode = 	(goingDown) ? 														classBehaviour.utilities.nextNode(objNode).nextSibling : 															classBehaviour.utilities.previousNode(objNode);
									// what is the container node
									containerNode = objNode.parentNode;									// remove the parent node									cachedNode = containerNode.removeChild(objNode);									// insert the node in it's new location									containerNode.insertBefore(cachedNode, targetNode);									// re-init the classbehaviours within									classBehaviour.parseDocument(classBehaviour.utilities.previousNode(targetNode));									// cancel the click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.moveParentNode = new MoveParentNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.moveParentNode;

	// Clear a node from the document		// define this class behaviour		function RemoveParentNode(){			// properties			this.name 		= 	'removeParentNode';			// methods			this.start		=	function(node){									// set the event for this button									node.onclick = this.remove;								}			// events			this.remove	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// how deep is the button in the moving node
									nodeDepth = parseInt(classBehaviour.utilities.getClassParameter(objNode,'parent','1'));
									for(var a=0; a<nodeDepth; a++) objNode = objNode.parentNode;
									// what is the container node
									containerNode = objNode.parentNode;									// remove the parent node									cachedNode = containerNode.removeChild(objNode);									// cancel the click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.removeParentNode = new RemoveParentNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.removeParentNode;
			// change the focus to a table row		// define this class behaviour		function FocusRow(){			// properties			this.name 		= 	'focusRow';			// methods			this.start		=	function(node){									node.onclick = this.highlight;									// add events to all cells									for(var a=0; a<node.childNodes.length; a++) if(node.childNodes[a].nodeName!='#text') node.childNodes[a].onmousedown = this.highlight;									// add events to all form elements									inputs = node.getElementsByTagName('*');									for(var a=0; a<inputs.length; a++) if(inputs[a].nodeName!='#text') inputs[a].onfocus = this.highlight;									// add events to all iframes									iframes = node.getElementsByTagName('iframe');									for(var a=0; a<iframes.length; a++) iframes[a].onmousedown = this.highlight;								}			// events			this.highlight	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var frw = classBehaviour.focusRow;									// find the row									parentRow = objNode;									while(parentRow.nodeName!='TR') parentRow = parentRow.parentNode;									// find the previous node									peerRows = parentRow.parentNode.getElementsByTagName('TR');									previousRow = null;									for(var a=0; a<peerRows.length; a++){										// if the row is marked as active, take it as the previous row										if(peerRows[a].className.indexOf('active')>-1) previousRow = peerRows[a];									}									// deactivate the previous row									if(previousRow) if(parentRow!=previousRow) previousRow.className = previousRow.className.replace('active','link');									// add the active class									parentRow.className = parentRow.className.replace('link','active');								}		}		// add this function to the classbehaviour object		classBehaviour.focusRow = new FocusRow;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.focusRow;			// calculates a total of several input fields		// define this class behaviour		function TotalOfNumbers(){			// properties			this.name 		= 	'totalOfNumbers';			// methods			this.start		=	function(node){									// is this an input field									if(node.nodeName=="INPUT"){										// give it the onchange handler										node.onkeyup  = this.calculate;										node.onblur  = this.calculate;									}								}			// events			this.calculate = 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// what is the family group									totalFamily = classBehaviour.utilities.getClassParameter(objNode, 'family', 'default');									// for all inputs									total = 0;									allInputs = document.getElementsByTagName('INPUT');									for(var a=0; a<allInputs.length; a++){										// if this is the same family // add it to a total										added = parseFloat(allInputs[a].value);										if(classBehaviour.utilities.getClassParameter(allInputs[a], 'family', null)==totalFamily && !isNaN(added)) total += added;									}									// what is the target node									totalTarget = classBehaviour.utilities.getClassParameter(objNode, 'target', null);									// add the total to the target node									if(totalTarget) document.getElementById(totalTarget).innerHTML = total;								}		}		// add this function to the classbehaviour object		classBehaviour.totalOfNumbers = new TotalOfNumbers;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.totalOfNumbers;			// turns an unordered list into a tree menu		// define this class behaviour		function TreeMenu(){			// properties			this.name 		= 	'treeMenu';
			this.index		=	0;			// methods			this.start		=	function(node){									// number this list
									this.index += 1;
									c = this.index;
									// for all list items									var activeLink;									var allListParents = node.getElementsByTagName('ul');									for(var b=-1; b<allListParents.length; b++){										var allListItems = (b<0) ? node.getElementsByTagName('li') : allListParents[b].getElementsByTagName('li');										for(var a=0; a<allListItems.length; a++){											// LIST ITEM											allListItems[a].className += (allListItems[a].className.indexOf('link')<0 || allListItems[a].className.indexOf('active')<0) ? ' link' : '' ;											// TOGGLE											// if there is no toggle switch											itemTogglers = allListItems[a].getElementsByTagName('span');											if(itemTogglers.length==0){												// make a toggle switch												newToggle = document.createElement('span');												allListItems[a].insertBefore(newToggle, allListItems[a].firstChild);												// refresh the list												itemTogglers = allListItems[a].getElementsByTagName('span');											}											// if the node has child-nodes											childNodes = allListItems[a].getElementsByTagName('ul');											if(childNodes.length>0){												// give the childnodes an id												childNodes[0].id = this.name + c + b + a;
												// make it a toggle switch												itemTogglers[0].className = "link id_" + childNodes[0].id;												// should the previous branch close
												if(classBehaviour.utilities.getClassParameter(node, 'closePrevious', 'yes')=='yes')
													itemTogglers[0].className += " family_group" + c + b;
												// add the toggle event handler												itemTogglers[0].onclick = classBehaviour.toggleNextNode.toggle;												// hide the child nodes												childNodes[0].className = 'hideThisNode';												// prepare the toggler												classBehaviour.toggleNextNode.start(itemTogglers[0]);											// else											}else{												// make it a normal switch												itemTogglers[0].className = "passive";											}											// LINK											// get the link in this item											itemLinks = allListItems[a].getElementsByTagName('a');											// store the active link if it's the same as the document location											if(itemLinks.length>0){												isActive = classBehaviour.matchActiveUrl.process(itemLinks[0]);												// recurse simulated clicks up all of its parents												if(isActive) this.recurse(itemLinks[0].parentNode);											}										}									}								}			this.recurse	=	function(container){									var tmn = classBehaviour.treeMenu;									// get the toggle button									var itemTogglers = container.getElementsByTagName('span');									// toggle it									if(itemTogglers.length>0) if(itemTogglers[0].className.indexOf('link')>-1) classBehaviour.toggleNextNode.toggle(itemTogglers[0]);									// get parent of this container									var parentContainer = container.parentNode.parentNode;									// if it's another container									if(parentContainer.nodeName == "LI")										// recurse										tmn.recurse(parentContainer);								}		}		// add this function to the classbehaviour object		classBehaviour.treeMenu = new TreeMenu;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.treeMenu;
		
	// Matches the height of a group of elements
		// define this class behaviour		function MatchHeight(){			// properties			this.name 		= 	'matchHeight';			this.groups		=	new Array(
									// new Array('groupName', node, node, node);
								);			// methods			this.start		=	function(node){
									// what group does this node belong to
									nodeGroup = classBehaviour.utilities.getClassParameter(node, 'group', '0');
									// find this group in the list
									groupIndex = -1;
									for(var a=0; a<this.groups.length; a++) if(this.groups[a][0]==nodeGroup) groupIndex=a;
									// if it doesn't exist make it
									if(groupIndex<0){
										this.groups[this.groups.length] = new Array(nodeGroup, node);
									// else
									}else{
										// store the node in it's group
										this.groups[groupIndex][this.groups[groupIndex].length] = node;
									}
									// equalize the heights
									this.resize();								}			this.resize		=	function(){									// for all groups
									for(var a=0; a<this.groups.length; a++){
										// remember the heighest node in this group
										nodeHeight = 0;
										for(var b=1; b<this.groups[a].length; b++) 
											if(nodeHeight<this.groups[a][b].offsetHeight) 
												nodeHeight=this.groups[a][b].offsetHeight;
										// set all nodes to that height
										for(var b=1; b<this.groups[a].length; b++) 
											if(nodeHeight!=this.groups[a][b].offsetHeight)
												if(this.groups[a][b].style.minHeight){
													heightOffset = parseInt(classBehaviour.utilities.getClassParameter(this.groups[a][b], 'offset', '0'));
													this.groups[a][b].style.minHeight = (nodeHeight + heightOffset) + 'px'
												}else{
													heightOffset = parseInt(classBehaviour.utilities.getClassParameter(this.groups[a][b], 'offset', '0'));
													this.groups[a][b].style.height = (nodeHeight + heightOffset) + 'px'
												};
									}								}		}		// add this function to the classbehaviour object		classBehaviour.matchHeight = new MatchHeight;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.matchHeight;

	// Construct an empty stylesheet based on the hierarchy of tags
		// define this class behaviour		function MakeStylesheet(){			// properties			this.name 				=	'makeStylesheet';
			this.styleSheet			= 	"/* " + document.location.href.split('/')[document.location.href.split('/').length-1] + " */\n";
			this.referenceCss		=	"";
			this.rootObject			= 	document.body;			// methods			this.start				=	function(node){
											// make a reference stylesheet from the current stylesheets
											this.makeReferenceCss();
											// markup the stylesheet making button
											node.style.position = 'absolute';
											node.style.right = '0px';
											node.style.top = '0px';
											node.onclick = this.showNodeClasses;
											/* how to read stylesheet content
											debug(
												document.styleSheets[0].cssRules[1].selectorText,
												document.styleSheets[0].cssRules[1].cssText,
												document.styleSheets[0].cssRules[1].style.getPropertyValue('font-family')
											);
											*/										}
			this.makeReferenceCss	=	function(){
											for(var a=0; a<document.styleSheets.length; a++)
												if(document.styleSheets[a].cssRules)
													for(var b=0; b<document.styleSheets[a].cssRules.length; b++)
														this.referenceCss += document.styleSheets[a].cssRules[b].selectorText + ' {}\n\t';
										}
			this.isFormElement		=	function(node){
											return (('INPUT,SELECT,TEXTAREA,BUTTON').indexOf(node.nodeName)>-1);
										}
			this.isClassBehaviour	=	function(newEntry){
											foundHandler = false;
											// for all behaviours, if the behaviour's name exists in the class name, apply it's events											for(var b=0; b<classBehaviour.handlers.length; b++)												foundHandler = (newEntry.indexOf(classBehaviour.handlers[b].name)>-1) ? true : foundHandler;
											// report back
											return foundHandler;
										}
			this.isInStylesheet		=	function(newEntry){
											foundStyle = false;
											// clean the new entry
											newEntry = newEntry.replace(/\t/gi,'').replace(' {}\n','').replace(',','');
											// if the style allready exists in this constructed stylesheet
											foundStyle = (this.styleSheet.indexOf(newEntry)>-1);
											// if the style allready exists in any rule in another stylesheet
											foundStyle = (this.referenceCss.indexOf(newEntry)>-1) ? true : foundStyle ;
											// report back
											return foundStyle;
										}
			this.stripBehaviour		=	function(newEntry){
											foundHandler = false;
											// for all behaviours, if the behaviour's name exists in the class name, apply it's events											for(var b=0; b<classBehaviour.handlers.length; b++)												newEntry = newEntry.replace(classBehaviour.handlers[b].name+'.', '').replace(classBehaviour.handlers[b].name, '');
											// report back
											return newEntry;
										}
			this.getNodeClasses		=	function(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' && !this.isFormElement(objChildNodes[intA])){
													if(objChildNodes[intA].id!='' && !this.isClassBehaviour(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(!this.isInStylesheet(newEntry)) this.styleSheet += newEntry;
														// update the prefix
														idPrefix = '#' + objChildNodes[intA].id;
													}
												}
												// if it has a className
												if(typeof(objChildNodes[intA].className)!='undefined'){
													// strip the classnames
											//		allClasses = this.stripBehaviour(objChildNodes[intA].className.replace(/ /gi, '.'));
													allClasses = objChildNodes[intA].className.replace(/ /gi, '.');
													// if there's anything left
													if(objChildNodes[intA].className!=''){
														// add class to stylesheet prototype
														newEntry = strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses + ' {}\n';
														// add this style only if there's not double
														if(!this.isInStylesheet(newEntry)){
															// update the prefix
															this.styleSheet += newEntry;
															// if the last entry was a link
															if(objChildNodes[intA].nodeName=='A'){
																// repeat it four times with the mouseover states
																this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses + ':link,\n';
																this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses + ':visited {}\n';
																this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses + ':hover,\n';
																this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses + ':active {}\n';
																// and jump further in
																intRecursion += 1;
															}
														}
														// update the prefix
														classPrefix = objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses;
													}
												}
												// if it has neither
												if(
													objChildNodes[intA].className=='' && 
													(objChildNodes[intA].id=='' || this.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(!this.isInStylesheet(newEntry)){
														this.styleSheet += newEntry;
														// if the last entry was a link
														if(newEntry.indexOf(' a {}')>-1){
															// repeat it four times with the mouseover states
															this.styleSheet += '\t' + newEntry.replace('a {}','a:link,');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:visited {}');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:hover,');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:active {}');
															// and jump further in
															intRecursion += 1;
														}
													}
													// update the prefix
													tagPrefix = objChildNodes[intA].nodeName.toLowerCase();
												}
												// 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
													this.getNodeClasses(objChildNodes[intA], intRecursion+1, addPrefix);
												}
											}
										}
			this.showNodeClasses	=	function(){
											var mss = classBehaviour.makeStylesheet;
											document.body.style.textAlign = 'left';
											document.body.style.background = '#ffffff none';
											document.body.style.color = '#000000';
											document.body.style.fontFamily = 'Sans Serif';
											document.body.style.fontSize = '12pt';
											mss.getNodeClasses(mss.rootObject, 0 , '');
											document.body.innerHTML = '<textarea style="position:absolute;left:12.5%;top:12.5%;width:75%;height:75%;border:solid 1px #000000;">' + mss.styleSheet + '</textarea>';
										}		}		// add this function to the classbehaviour object		classBehaviour.makeStylesheet = new MakeStylesheet;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.makeStylesheet;
		
	// html encode the content of the document		// define this class behaviour		function HtmlEncode(){			// properties			this.name 		= 	'htmlEncode';			// methods			this.start		=	function(node){									// markup the stylesheet making button
									node.style.position = 'absolute';
									node.style.right = '0px';
									node.style.top = '25px';
									node.onclick = this.importDoc;								}
			// events
			this.importDoc	=	function(){
									// load the document
									classBehaviour.xmlDoc.addRequest(document.location.href, classBehaviour.htmlEncode.encode, classBehaviour.htmlEncode.wait, false, null);
								}
			this.wait		=	function(waitStatus){
									
								}
			this.encode		=	function(docXml, referedObj, docTxt){
									// present it back
									document.body.innerHTML = '<textarea id="htmlEncoded" style="position:absolute;left:12.5%;top:12.5%;width:75%;height:75%;border:solid 1px #000000;">' + docTxt + '</textarea>';
									// translate it to blog content
									document.getElementById('htmlEncoded').value = document.getElementById('htmlEncoded').value.replace(/>/gi, '&gt;').replace(/</gi, '&lt;'); // .replace(/\t/gi,'   ');
								}		}		// add this function to the classbehaviour object		classBehaviour.htmlEncode = new HtmlEncode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.htmlEncode;
		
	// move a link's click event to the parent node		// define this class behaviour		function ClickOnParent(){			// properties			this.name 		= 	'clickOnParent';			// methods			this.start		=	function(node){									// what node is the click supposed to go on?
									parentCount = parseInt(classBehaviour.utilities.getClassParameter(node, "parent", "1"));
									targetNode = node;
									for(var a=0; a<parentCount; a++) targetNode = targetNode.parentNode;
									// get the target of the link
									linkTarget = node.href;
									// set the click event
									targetNode.onclick = this.clicked;								}
			// events
			this.clicked	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// what is the link
									linkTargets = objNode.getElementsByTagName('A');
									for(var a=0; a<linkTargets.length; a++) if(linkTargets[a].className.indexOf('clickOnParent')>-1) linkTarget = linkTargets[a].href;
									// go to the link
									document.location.href = linkTarget;
								}		}		// add this function to the classbehaviour object		classBehaviour.clickOnParent = new ClickOnParent;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.clickOnParent;
		
	// emulates a scrollbar
		// define this class behaviour
		function VirtualScrollbar(){
			// properties
			this.name 		= 	'virtualScrollbar';
			this.interval	=	null;
			// methods
			this.start		=	function(node){
									// set the event handlers for the indicator bar
									node.onmousedown = this.pick;
									node.onmouseup = this.drop;
									node.onmousemove = this.drag;
									node.onmouseout = this.drop;
									document.onmousemove = this.nodrag;
									// set the initial position
									pageId = classBehaviour.utilities.getClassParameter(node, 'id', 'scrollCanvas');
									this.scrollTo(pageId, 0, node);
								}
			this.scrollTo	=	function(id, position, control){
									var vsb = classBehaviour.virtualScrollbar;
									// normalize the position
									if(position>0) position = 0;
									// what is the scrollable page
									page = document.getElementById(id).getElementsByTagName('div')[0];
									// how high is the page
									pageHeight = page.offsetHeight;
									// how high is the container of the page
									containerHeight = page.parentNode.offsetHeight;
									// don't allow negative scrolling
									if(pageHeight<containerHeight){
										pageHeight = containerHeight;
									}
									// 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 position of the indicator
									control.style.backgroundPosition = '0px ' + Math.round(-1.2 * containerHeight * position / pageHeight)  + 'px'
								}
			this.scrollBy	=	function(id, distance, control){
									// 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.pick		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsb = classBehaviour.virtualScrollbar;
									// mark the dragged item as being active
									objNode.className = objNode.className.replace('passive', '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.indexOf('active')>-1){
										// 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.utilities.getClassParameter(objNode, 'id', 'scrollCanvas');
										page = document.getElementById(id).getElementsByTagName('div')[0];
										// how high is the page
										pageHeight = page.offsetHeight;
										// how high is the container of the page
										containerHeight = page.parentNode.offsetHeight;
										// corelate the mouse-position to the scroll-position
										position = Math.round(-1 * mouseY * (pageHeight-containerHeight) / containerHeight);
										position = position * 1.2 + containerHeight * 0.2;
										// pass the position on to the page
										vsb.scrollTo(id, position, objNode);
									}
									// 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 = objNode.className.replace('active', 'passive');
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.virtualScrollbar = new VirtualScrollbar;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.virtualScrollbar;

	// constants/configuration
		function RssSearch(){
			// properties
			this.name 		= 	'rssSearch';
			this.form		=	document.getElementById('searchform');
			this.url 		= 	document.getElementById('searchsource');
			this.input 		= 	document.getElementById('searchstring');
			this.output 	= 	document.getElementById('searchresults');
			this.startIndex	=	0;
			this.endIndex	=	8;
			/* objects */
			this.search		=	new Search;
			this.source		=	new Source;
			// methods
			this.start		=	function(node){
									node.onsubmit = this.doSubmit;
								}
			this.find		=	function(start, end){
									// store paging preferences
									if(start!=null) this.startIndex = start;
									if(end!=null) 	this.endIndex = end;
									// lead the source to search
									if(this.source.document==null){
										this.source.load(this.url.value);
									}else{
										// search query
										var query					= this.search.query(this.input.value);
										// search process
										var results					= this.search.results(query, this.source.document);
										// search results
										var summary					= this.search.summary(results, this.startIndex, this.endIndex);
										// write the search summary
										this.output.innerHTML		= summary;
									}
									// cancel the submit
									return false;
								}
			// events
			this.doSubmit	=	function(){
									return classBehaviour.rssSearch.find();
								}
		}
			function Search(){
				this.sort		=	function(a, b){
										// sort by the first index of the object
										return (isNaN(a[0]) || isNaN(b[0])) ? 0 : b[0]-a[0] ;
									}
				this.query		=	function(searchString){
										// formulate the search string into a regular expression
										return new RegExp(searchString.replace(" ","|"),"gi");
									}
				this.results	=	function(query, doc, docText){
										var contents, titles, descs, text, matchText, matchScore;
										var results = new Array();
										// get all items in the rss feed
										contents = doc.getElementsByTagName('item');
										// for every item
										for(var a=0; a<contents.length; a++){
											// get the nodes
											titles	= contents[a].getElementsByTagName('title');
											descs	= contents[a].getElementsByTagName('description');
											// get the text from the nodes
											text = '';
											if(titles.length>0)		text += titles[0].firstChild.nodeValue;
											if(descs.length>0)		text += descs[0].firstChild.nodeValue;
											// match the query with the item's text
											matchText = text.match(query);
											// if there were hits
											if(matchText!=null){
												// calculate the score (the joined length of the matched array)
												matchScore = matchText.join(' ').length;
												// add the score and the node to the list of search results
												results[results.length] = new Array(matchScore,contents[a]);
											}
										}
										// sort the list of search results
										results = results.sort(this.sort);
										// pass the results back
										return results;
									}
				this.summary	=	function(results, startPage, resultsPerPage){
										var report = '<dl class="items">';
										var links, titles, summaries;
										var link, title, summary;
										// for the selected search results
										var a = startPage * resultsPerPage;
										while(a<results.length && (a+1)%resultsPerPage!=0){
											// link
											links			= results[a][1].getElementsByTagName('link')
											link			= (links.length==0) ? '' : links[0].firstChild.nodeValue;
											// title
											titles			= results[a][1].getElementsByTagName('title')
											title			= (titles.length==0) ? '' : titles[0].firstChild.nodeValue;
											// author
											authors			= results[a][1].getElementsByTagName('author')
											author			= (authors.length>0) ? authors[0].firstChild.nodeValue : '' ;
											// category
											categories		= results[a][1].getElementsByTagName('category')
											category		= (categories.length>0) ? categories[0].firstChild.nodeValue : '' ;
											// pubDate
											pubDates		= results[a][1].getElementsByTagName('pubDate')
											pubDate			= (pubDates.length>0) ? pubDates[0].firstChild.nodeValue.replace(':00 +0100', '') : '' ;
											// part of the description
											summaries		= results[a][1].getElementsByTagName('description')
											if(summaries.length>0){
												summary			= (summaries[0].xml) ? summaries[0].xml : summaries[0].firstChild.nodeValue;
												summary			= summary.replace(/&lt;/gi, '<').replace(/&gt;/gi, '>').replace(/<(.|\n)+?>/gi,'');
												summary			= (summaries[0].xml) ? summary.substr(0,64) + '...' : summary.substr(0,128) + '...';
											}else{
												summary			= '';
											}
											// construct report
											report			+= '<dt class="title"><a href="'+link+'">'+title+'</a></dt>\n';
											report			+= '<dd>\n';
											report			+= '	<ul class="information">\n';
											report			+= '		<li class="author">' + author + '</li>\n';
											report			+= '		<li class="category">' + category + '</li>\n';
											report			+= '		<li class="pubDate">' + pubDate + '</li>\n';
											report			+= '	</ul>\n';
											report			+= '	<div class="description"><p>'+summary+'</p></div>\n';
											report			+= '</dd>\n';
											// next item
											a += 1;
										}
										report += '</dl>';
										// if nothing was found
										if(results.length==0){
											// apologize
											report			+= '<p class="error">Sorry, no matches were found</p>';
										// else
										}else{
											var minPages	= 0;
											var maxPages	= Math.round(results.length/resultsPerPage+0.49);
											// page x of n
											report			+= '<ul class="pager">\n';
											report			+= (startPage>minPages) ? '<li class="previous"><a href="#" onclick="return classBehaviour.rssSearch.find('+(startPage-1)+','+resultsPerPage+')">Previous</a></li>' : '<li class="previous"></li>' ;
											report			+= (startPage<maxPages-1) ? '<li class="next"><a href="#" onclick="return classBehaviour.rssSearch.find('+(startPage+1)+','+resultsPerPage+')">Next</a></li>' : '<li class="next"></li>' ;
											report			+= '<li class="count">Page '+(startPage+1)+' of '+maxPages + '</li>';
											report			+= '</ul>\n';
										}
										// return the search results
										return report	;
									}
			}
			function Source(){
				this.document	=	null;
				this.load		=	function(url){
										classBehaviour.xmlDoc.addRequest(url, classBehaviour.rssSearch.source.onload, classBehaviour.rssSearch.source.wait);
									}
				this.wait		=	function(status){
										if(status<0){
											classBehaviour.rssSearch.output.innerHTML = '<hr /><p>Something went wrong.</p>'
										}else{
											classBehaviour.rssSearch.output.innerHTML = '<hr /><p>Searching: ' + Math.round(status * 100) + '%</p>';
										}
									}
				this.onload	=	function(root){
										classBehaviour.rssSearch.source.document = root;
										classBehaviour.rssSearch.find();
									}
			}
		// add this function to the classbehaviour object
		classBehaviour.rssSearch = new RssSearch;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.rssSearch;
		
	// applies the functionality of a specific spreadsheet type table		// define this class behaviour		function UltraTable(){			// properties			this.name 		= 	'ultraTable';			// methods			this.start		=	function(node){									scrollCanvas = node.getElementsByTagName('div')[3];
									scrollCanvas.onscroll = this.wasScrolled;								}
			// events
			this.wasScrolled	=	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// get the synched elements
										labelsScroller = objNode.parentNode.getElementsByTagName('table')[1];
										rowsScroller = objNode.parentNode.getElementsByTagName('table')[2];
										totalsScroller = objNode.parentNode.getElementsByTagName('table')[5];
										// scroll the synched elements
										labelsScroller.style.left = (-1 * objNode.scrollLeft) + 'px';
										rowsScroller.style.top = (-1 * objNode.scrollTop) + 'px';
										totalsScroller.style.left = (-1 * objNode.scrollLeft) + 'px';
									}		}		// add this function to the classbehaviour object		classBehaviour.ultraTable = new UltraTable;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.ultraTable;
		
	// applies the functionality of a specific spreadsheet type table		// define this class behaviour		function ToggleRowGroup(){			// properties			this.name 		= 	'toggleRowGroup';			// methods			this.start		=	function(node){									node.onclick = this.toggle;								}
			this.closeChild	=	function(a, allRows){
									// reset the row marker
									allRows[a].className = allRows[a].className.replace('activeRow','passiveRow');
									// what is the level of the last node
									lastLevel = parseInt(classBehaviour.utilities.getClassParameter(allRows[a], 'level', 0));
									// what is the level of the next node
									a += 1;
									nextLevel = parseInt(classBehaviour.utilities.getClassParameter(allRows[a], 'level', 0));
									// while the level is higher
									while(nextLevel>lastLevel){
										// reset the row marker
										allRows[a].className = allRows[a].className.replace('activeRow','passiveRow');
										// close that node
										allRows[a].className = allRows[a].className.replace('visibleRow','hiddenRow');
										// get a new next node
										a += 1;
										nextLevel = parseInt(classBehaviour.utilities.getClassParameter(allRows[a], 'level', 0));
									}
								}
			// events
			this.toggle		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var trg = classBehaviour.toggleRowGroup;
									// toggle the row marker
									objNode.className = (objNode.className.indexOf('passiveRow')>-1) ? objNode.className.replace('passiveRow','activeRow') : objNode.className.replace('activeRow','passiveRow') ;
									// what is the name of the targetted table rows
									targetName = classBehaviour.utilities.getClassParameter(objNode, 'openGroup', null);
									// get all the table rows
									allRows = objNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName('tr');
									// for every table row
									for(var a=0; a<allRows.length; a++){
										// is it part of the targetted group
										if(allRows[a].className.indexOf('rowGroup_'+targetName)>-1){
											// open it if it's closed or the other way around
											if(allRows[a].className.indexOf('hiddenRow')>-1){
												allRows[a].className = allRows[a].className.replace('hiddenRow','visibleRow');
											}else{
												allRows[a].className = allRows[a].className.replace('visibleRow','hiddenRow');
												// if the node has child nodes
												if(allRows[a].className.indexOf('openGroup_')>-1) trg.closeChild(a, allRows);
											}
										}
									}
								}		}		// add this function to the classbehaviour object		classBehaviour.toggleRowGroup = new ToggleRowGroup;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleRowGroup;
		
	// edit the order of items in select lists		// define this class behaviour		function ManyToMany(){			/* properties */			this.name 		= 	'manyToMany';			/* methods */			this.start		=	function(node){
									// was the click aimed at the select list
									if(node.nodeName=='SELECT'){
										node.className += ' from_' + node.id;
										node.ondblclick = this.clicked;
									}else{										node.onclick = this.clicked;
									}								}
			/* events */
			this.resetEdit   =	function(id){
			                        textArea = document.getElementById(id.replace('$', ''));
			                        if (textArea.type != 'textarea') return;
			                        selectArea = document.getElementById(id);
			                        textArea.value = '';
			                        for(i = 0; i < selectArea.length; i++)
			                            textArea.value += selectArea.options[i].value + '|' + selectArea.options[i].text + '\n';
			                    }
			this.clicked	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// button settings
									moveSourceId = classBehaviour.utilities.getClassParameter(objNode, 'from', null);
									moveDestinationId = classBehaviour.utilities.getClassParameter(objNode, 'to', null);
									upSourceId = classBehaviour.utilities.getClassParameter(objNode, 'up', null);
									downSourceId = classBehaviour.utilities.getClassParameter(objNode, 'down', null);
									// get the parent nodes
									moveSource = document.getElementById(moveSourceId);
									upSource = document.getElementById(upSourceId);
									downSource = document.getElementById(downSourceId);
									moveDestination = document.getElementById(moveDestinationId);
									// if we're going to move a node
									if(moveSource && moveDestination){
										// get the source node
										sourceNode = (moveSource.selectedIndex>-1) ? moveSource.getElementsByTagName('option')[moveSource.selectedIndex] : null;
										// get the target node
										destinationNode = (moveDestination.selectedIndex>-1) ? moveDestination.getElementsByTagName('option')[moveDestination.selectedIndex] : null;
										// if there is a source node
										if(sourceNode){
											// remove the source node
											removedNode = moveSource.removeChild(sourceNode);
											// insert the source node before the desination node 
											if(destinationNode){
												moveDestination.insertBefore(removedNode, destinationNode.nextSibling);
											}else{
												moveDestination.appendChild(removedNode);
											}
										}
									}
									// if we're going to shift a node up
									if(upSource){
										// get the source node
										upNodes = upSource.getElementsByTagName('option');
										sourceNode = (upSource.selectedIndex>-1) ? upNodes[upSource.selectedIndex] : null;
										destinationNode = (upSource.selectedIndex>0) ? upNodes[upSource.selectedIndex-1] : null ;
										if(sourceNode && destinationNode){
											// remove the source node
											removedNode = upSource.removeChild(sourceNode);
											// insert it at its new place
											upSource.insertBefore(removedNode, destinationNode);
										}
										classBehaviour.manyToMany.resetEdit(upSource.id);
									}
									// if we're going to shift a node down
									if(downSource){
										// get the source node
										downNodes = downSource.getElementsByTagName('option');
										sourceNode = (downSource.selectedIndex>-1) ? downNodes[downSource.selectedIndex] : null;
										destinationNode = (downSource.selectedIndex<downNodes.length-2) ? downNodes[downSource.selectedIndex+2] : null ;
										if(sourceNode && destinationNode){
											// remove the source node
											removedNode = downSource.removeChild(sourceNode);
											// insert it at its new place
											downSource.insertBefore(removedNode, destinationNode);
										}else if(sourceNode){
											// remove the source node
											removedNode = downSource.removeChild(sourceNode);
											// insert it at its new place
											downSource.appendChild(removedNode);
										}
										classBehaviour.manyToMany.resetEdit(downSource.id);
									}
									return false;
								}		}		// add this function to the classbehaviour object		classBehaviour.manyToMany = new ManyToMany;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.manyToMany;
				
	// Keep track of the mouse position
		// define this class behaviour		function MousePosition(){			/* properties */			this.name 			= 	'mousePosition';
			this.xPos			=	0;
			this.yPos			=	0;
			/* methods */			this.start			=	function(node){
										// get the mouse position
										node.onmouseover = this.store;
									}
			/* events */
			this.store			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var smp = classBehaviour.mousePosition;
										// store the mouse positions
										smp.xPos = (typeof(event)!='undefined') ? event.clientX-document.body.scrollLeft : that.pageX ;
										smp.yPos = (typeof(event)!='undefined') ? event.clientY-document.body.scrollTop : that.pageY ;
									}		}		// add this function to the classbehaviour object		classBehaviour.mousePosition = new MousePosition;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.mousePosition;
	
	// Sort table rows by dragging and dropping
		// define this class behaviour		function DragToSort(){			/* properties */			this.name 			= 	'dragToSort';
			this.moving			=	null;
			this.over			=	null;
			this.offsetX		=	-50;
			this.offsetY		=	1;
			this.timeout		=	null;
			this.allowed		=	true;
			/* methods */			this.start			=	function(node){
										// set the offset
										this.offsetX = parseInt(classBehaviour.utilities.getClassParameter(node,'offx', this.offsetX));
										this.offsetY = parseInt(classBehaviour.utilities.getClassParameter(node,'offy', this.offsetY));
										// apply the event handlers to all table rows
										allRows = node.getElementsByTagName('tr');
										for(var a=0; a<allRows.length; a++){
											// drag event handler
											if(allRows[a].parentNode.nodeName=='TBODY') allRows[a].onmousedown = this.pickUp;
											allRows[a].onmouseover = this.trackOver;
											allRows[a].onmouseout = this.trackOut;
											// add the undragged classname
											allRows[a].className += ' notDragged';
										}
										// for all buttons and input  fields in the table
										allInputs = node.getElementsByTagName('input');
										allButtons = node.getElementsByTagName('button');
										allLinks = node.getElementsByTagName('a');
										allSelects = node.getElementsByTagName('selects');
										// set a mouseover that disbles the pickup events
										for(var a=0; a<allInputs.length; a++){	allInputs[a].onmouseover = this.disallow; 	allInputs[a].onmouseout = this.allow;}
										for(var a=0; a<allButtons.length; a++){	allButtons[a].onmouseover = this.disallow; 	allButtons[a].onmouseout = this.allow;}
										for(var a=0; a<allLinks.length; a++){	allLinks[a].onmouseover = this.disallow; 		allLinks[a].onmouseout = this.allow;}
										for(var a=0; a<allSelects.length; a++){	allSelects[a].onmouseover = this.disallow; 	allSelects[a].onmouseout = this.allow;}
										// apply the move events
										document.onmousemove = this.moveAround;
										document.onmouseup = this.dropDown;
										// when dragged off-canvas
										document.onmouseout = this.wait;
									}
			this.disallow		=	function(){
										var dts = classBehaviour.dragToSort;
										dts.allowed = false;
									}
			this.allow			=	function(){
										var dts = classBehaviour.dragToSort;
										dts.allowed = true;
									}
			this.dropDown		=	function(){
										var dts = classBehaviour.dragToSort;
										// if there is an element being dragged
										if(dts.moving){
											// clear the remembered node
											dts.moving.style.position = 'static';
											dts.moving.style.left = 'auto' ;
											dts.moving.style.top = 'auto' ;
											// swap the nodes
											if(dts.over && dts.moving!=dts.over){
												// remove the dragged row
												storedNode = dts.moving.parentNode.removeChild(dts.moving);
												// insert it before the target row
												dts.over.parentNode.insertBefore(storedNode, dts.over);
												// redo the odd and even classes
												dts.reZebra(dts.over);
												// re-apply the classbehaviours
												classBehaviour.parseDocument(classBehaviour.utilities.previousNode(dts.over));
											}
											// clear the sources
											dts.moving = null;
											dts.over = null;
										}
										// cancel the mouse event
										return false;
									}
			this.reZebra		=	function(tableRow){
										// get all the siblings to this row
										allRows = tableRow.parentNode.getElementsByTagName('TR');
										for(var a=0; a<allRows.length; a++){
											allRows[a].className = (a%2==0) ? allRows[a].className.replace('even', 'odd') : allRows[a].className.replace('odd', 'even');
										}
									}
			/* events */
			this.trackOver		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dts = classBehaviour.dragToSort;
										// if we are over the table
										if(objNode.parentNode.nodeName=='TBODY'){
											// store the last node the mouse went over
											if(objNode!=dts.moving) dts.over = objNode;
											// highlight the row something is dragged over
											if(dts.moving!=null) objNode.className = objNode.className.replace('notDragged', 'isDraggedOver');
										}
									}
			this.trackOut		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dts = classBehaviour.dragToSort;
										// highlight the row something is dragged over
										if(objNode!=dts.moving) objNode.className = objNode.className.replace('isDraggedOver', 'notDragged');
									}	
			this.pickUp			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dts = classBehaviour.dragToSort;
										// is the mechanism disabled
										if(dts.allowed){
											// store the picked up object
											dts.moving = objNode;
											// get the mouse position
											scrollX = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft;
											scrollY = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
											xPos = (typeof(event)!='undefined') ? event.clientX+scrollX : that.pageX ;
											yPos = (typeof(event)!='undefined') ? event.clientY+scrollY : that.pageY ;
											// pick up the table row
											dts.moving.style.position = 'absolute';
											dts.moving.style.left = (xPos+dts.offsetX) + 'px' ;
											dts.moving.style.top = (yPos+dts.offsetY) + 'px' ;
											// cancel the mouse event
											return false;
										}
									}
			this.moveAround		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var dts = classBehaviour.dragToSort;
										// cancel the close timeout
										clearTimeout(dts.timeout);
										// if there is an object being dragged
										if(dts.moving){
											// get the mouse position
											scrollX = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft;
											scrollY = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
											xPos = (typeof(event)!='undefined') ? event.clientX+scrollX : that.pageX ;
											yPos = (typeof(event)!='undefined') ? event.clientY+scrollY : that.pageY ;
											// move the stored node around with the mouse
											dts.moving.style.position = 'absolute';
											dts.moving.style.left = (xPos+dts.offsetX) + 'px' ;
											dts.moving.style.top = (yPos+dts.offsetY) + 'px' ;
										}
										// cancel the mouse event
										return false;
									}
			this.wait			=	function(){
										var dts = classBehaviour.dragToSort;
										// set a timeout for resetting the system
										clearTimeout(dts.timeout);
										dts.timeout = setTimeout('classBehaviour.dragToSort.dropDown()', 250);
									}		}		// add this function to the classbehaviour object		classBehaviour.dragToSort = new DragToSort;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.dragToSort;
		
	// Sort table rows by clicking and dropping
		// define this class behaviour		function ClickToSort(){			/* properties */			this.name 			= 	'clickToSort';
			/* methods */			this.start			=	function(node){
										// get the prototype of the arrows
										indicatorArrows = node.getElementsByTagName('span')[0];
										// get the tbody
										theTbody = node.getElementsByTagName('tbody')[0];
										theTbody.className += ' hideIndicators';
										// for all table rows
										allRows = theTbody.getElementsByTagName('tr');
										for(var a=0; a<allRows.length; a++){
											// add a default class
											allRows[a].className += ' link';
											// set its event handlers
											if(navigator.appVersion.indexOf('MSIE 6')>-1){
												allRows[a].onmouseover = this.hoverOver;
												allRows[a].onmouseout = this.hoverOut;
											}
											allRows[a].onclick = this.selectRow;
											// get the first cell you can find
											firstCell = allRows[a].getElementsByTagName('td')[0];
											// clone in the prototype into the cell
											clonedArrows = indicatorArrows.cloneNode(true);
											firstCell.insertBefore(clonedArrows, firstCell.firstChild);
										}
									}
			this.reZebra		=	function(tableRow){
										// get all the siblings to this row
										allRows = tableRow.parentNode.getElementsByTagName('tr');
										for(var a=0; a<allRows.length; a++){
											allRows[a].className = (a%2==0) ? allRows[a].className.replace('even', 'odd') : allRows[a].className.replace('odd', 'even');
										}
									}
			/* events */
			this.hoverOver		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										objNode.className = objNode.className.replace('link', 'hover');
									}
			this.hoverOut		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										objNode.className = objNode.className.replace('hover', 'link');
									}
			this.selectRow		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var cts = classBehaviour.clickToSort;
										// get the tbody
										theTbody = objNode.parentNode;
										// if the tbody in hideIndicators mode
										if(theTbody.className.indexOf('hideIndicators')>-1){
											// mark the row as selected
											objNode.className = objNode.className.replace('link', 'active').replace('hover', 'active');
											// activate the indicator arrows
											theTbody.className = theTbody.className.replace('hideIndicators', 'showIndicators');
										// else
										}else{
											// de-activate the indicator arrows
											theTbody.className = theTbody.className.replace('showIndicators', 'hideIndicators');
											// for all rows in there
											theActiveRow = null;
											allRows = theTbody.getElementsByTagName('tr');
											for(var a=0; a<allRows.length; a++){
												// if the row is active
												if(allRows[a].className.indexOf('active')>-1){
													// store it as the source row 
													theActiveRow = allRows[a];
													// remove the active mark
													allRows[a].className = allRows[a].className.replace('active', 'link');
												}
											}
											// switch the source with the target node
											if(theActiveRow!=objNode){
												removedNode = theTbody.removeChild(theActiveRow);
												theTbody.insertBefore(removedNode, objNode);
											}
											// re-zebra
											cts.reZebra(objNode);
										}
									}
		}		// add this function to the classbehaviour object		classBehaviour.clickToSort = new ClickToSort;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.clickToSort;
		
	// Link two select lists
		// define this class behaviour		function LinkedSelects(){			/* properties */			this.name 			= 	'linkedSelects';
			/* methods */			this.start			=	function(node){
										// get the mouse position
										node.onchange = this.updateLinked;
										// sync the starting selection
										setTimeout('classBehaviour.linkedSelects.updateLinked(document.getElementById("' + node.id + '"))',100);
									}
			/* events */
			this.updateLinked	=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var lsl = classBehaviour.linkedSelects;
										// if there was a selected value
										if(objNode.value!=''){
											// get the target id
											linkedId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'myLinkedSelect');
											// get the target object
											linkedObj = document.getElementById(linkedId);
											// start loading
											classBehaviour.xmlDoc.addRequest(objNode.value, lsl.updateLoaded, lsl.updateProgress, null, linkedObj);
										}
									}
			this.updateProgress	=	function(progressStatus, referingObj){
										// get the first option in the select
										firstOption = referingObj.getElementsByTagName('option')[0];
										firstOption.selected = true;
										// use it as a progress indicator
										firstOption.firstChild.nodeValue = '--- loading: ' + parseInt(progressStatus*100) + '% ---';
									}
			this.updateLoaded	=	function(docXml, refererObj, docTxt){
										// for all the current options
										currentOptions = refererObj.getElementsByTagName('option');
										for(var a=currentOptions.length-1; a>=0; a--){
											removedNode = refererObj.removeChild(currentOptions[a]);
										}
										// for all the imported options
										importedOptions = docXml.getElementsByTagName('option');
										for(var a=0; a<importedOptions.length; a++){
											// replace the option contents
											newOption = document.createElement('option');
											newOptionText = document.createTextNode(importedOptions[a].firstChild.nodeValue);
											newOption.appendChild(newOptionText);
											newOption.value = importedOptions[a].getAttribute("value");
											refererObj.appendChild(newOption);
										}
									}		}		// add this function to the classbehaviour object		classBehaviour.linkedSelects = new LinkedSelects;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.linkedSelects;
		
/* TODO: make this using objects for multiple scrolling nodes
	// this keeps a screen element fixed to the scrolling
		// define this class behaviour		function StalkingNavigation(){			// properties			this.name 		= 	'stalkingNavigation';
			this.timeout	=	null;
			this.offset		=	200;
			this.objects	=	new Array();			// methods			this.start		=	function(node){
									// store this scrolling object and its offset
									// set the scolling event
									window.onscroll = this.scrolled;								}
			// events
			this.scrolled	=	function(that, noOffset){
									// clear the timeout on this function
									clearTimeout(classBehaviour.shoppingBasket.timeout);
									// for all scrolling objects
										// get the scrolling object
										scrollingObject = document.getElementById(classBehaviour.stalkingNavigation.name);
										// get the scrolling offset
										offset = classBehaviour.stalkingNavigation.offset;
										// get the scrolling position
										scrollPos = document.documentElement.scrollTop;
										// reposition the shopping basket
										availableHeight = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight ;
										if(scrollPos>=offset && basketList.offsetHeight<availableHeight){
											scrollingObject.style.position = 'fixed';
											scrollingObject.style.marginTop = (navigator.appVersion.indexOf('MSIE 6')<0) ? '-'+offset+'px' : (scrollPos-offset) + 'px' ;
										}else{
											scrollingObject.style.position = 'relative';
											scrollingObject.style.marginTop = '0px';
										}
									// order this function to run one last time after scrolling stops
									if(!noOffset) classBehaviour.stalkingNavigation.timeout = setTimeout('classBehaviour.stalkingNavigation.scrolled(null, true);', 128);
								}		}		// add this function to the classbehaviour object		classBehaviour.stalkingNavigation = new StalkingNavigation;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.stalkingNavigation;
*/
	// STARTUP-SEQUENCE	// start the parsing of classes	classBehaviour.parseDocument();