/*name			: Class Behaviour - Seperate Modular Behavioursupdate			: 20070705author			: Maurice van Creijdependencies	: classbehaviours.jsinfo			: http://www.woollymittens.nl/*/
	// 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;
		
	// runs through a sequence of class names		// define this class behaviour		function AnimatedClassName(){			// properties			this.name 		= 	'animatedClassName';
			this.index		=	0;
			this.interval	=	null;			// methods			this.start		=	function(node){									// give an id if the item has none
									node.id = (node.id) ? node.id : this.name + this.index++ ;
									// get the animation properties
									animationDelay = parseInt(classBehaviour.utilities.getClassParameter(node, 'delay', '500'));
									// see if mouse interaction is required
									onlyOnFocus = (classBehaviour.utilities.getClassParameter(node, 'focus', 'no') == 'yes');
									if(onlyOnFocus){
										// set a classname for keeping track of the focus
										node.className += ' interaction_no';
										// set the event handlers
										node.onmouseover = this.play;
										node.onmouseout = this.stop;
										node.onfocus = this.play;
										node.onblur = this.stop;
									}else{
										// start its animation sequence
										this.interval = setInterval('classBehaviour.animatedClassName.loop("'+node.id+'")', animationDelay);
									}								}			// events
			this.play		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// add the interaction marker
									objNode.className = objNode.className.replace('interaction_no', 'interaction_yes');
									// start the animation
									classBehaviour.animatedClassName.loop(objNode.id);
								}
			this.stop		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// remove the interaction marker
									objNode.className = objNode.className.replace('interaction_yes', 'interaction_no');
								}			this.loop		=	function(animId){
									animNode = document.getElementById(animId);
									// get the animation properties
									animationStep = parseInt(classBehaviour.utilities.getClassParameter(animNode, 'step', '0'));
									animationLoop = parseInt(classBehaviour.utilities.getClassParameter(animNode, 'loop', '4'));
									// get the next animation step
									nextAnimationStep = (animationStep<animationLoop) ? animationStep+1 : 0 ;
									// set the next animation step
									animNode.className = animNode.className.replace('step_' + animationStep + ' ', 'step_' + nextAnimationStep + ' ');
									// if this node has the focus, do the animation again, or reset it
									interaction = classBehaviour.utilities.getClassParameter(animNode, 'interaction', null);
									animationDelay = parseInt(classBehaviour.utilities.getClassParameter(animNode, 'delay', '500'));
									if(interaction=='yes'){
										setTimeout('classBehaviour.animatedClassName.loop("'+animId+'")', animationDelay);
									}else if(interaction=='no'){
										classBehaviour.utilities.setClassParameter(animNode, 'step', '0');
									}								}		}		// add this function to the classbehaviour object		classBehaviour.animatedClassName = new AnimatedClassName;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.animatedClassName;			// 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';
			this.index		=	0;
			this.timeout	=	null;			// methods			this.start		=	function(node){
									//for the childnodes of the navigation
									allItems = node.getElementsByTagName('LI');
									for(var a=0; a<allItems.length; a++){
										if(allItems[a].nodeName == 'LI'){
											// add starting properties
											allItems[a].className += (allItems[a].className.indexOf('link')<0) ? ' link' : '' ;
											// add the mouse events
											allItems[a].onmouseover = this.hoverOver;
											allItems[a].onmouseout = this.hoverOff;
										}
									}								}
			// events
			this.hoverOver	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var psh = classBehaviour.pseudoHover;
									// cancel the reset time-out
									clearTimeout(psh.timeout);
									// set the clipping to reveal the content graduately
									panelNode = objNode.getElementsByTagName('UL');
									if(panelNode.length>0){
										panelNode[0].id = (panelNode[0].id) ? panelNode[0].id : psh.name + psh.index++;
										classBehaviour.fader.reveal(panelNode[0].id, panelNode[0].offsetWidth, panelNode[0].offsetHeight, 100, 25);
									}
									// change the classname to show the item in MSIE 6
									objNode.className = objNode.className.replace('link', 'hover');
								}
			this.hoverOff	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var psh = classBehaviour.pseudoHover;
									// cancel the reset time-out
									clearTimeout(psh.timeout);
									// set the clipping to vanish the content gradualy
									panelNode = objNode.getElementsByTagName('UL');
									if(panelNode.length>0){
										psh.timeout = setTimeout('classBehaviour.fader.vanish("'+panelNode[0].id+'")', 250);
									}
									// vanish the peers
									peersAndChildPanels = objNode.parentNode.getElementsByTagName('UL');
									for(var a=0; a<peersAndChildPanels.length; a++){
										if(peersAndChildPanels[a].id && peersAndChildPanels[a]!=panelNode[0] && peersAndChildPanels[a].parentNode.parentNode!=panelNode[0])
											classBehaviour.fader.vanish(peersAndChildPanels[a].id);
									}
									// change the classname to show the item in MSIE 6
									objNode.className = objNode.className.replace('hover', 'link');
								}		}		// 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.index			= 0;
			this.timeOut		= null;			// methods			this.start			=	function(node){										this.setUpFader(node);									}			this.setUpFader		=	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// set the properties of this node
										objNode.id = (objNode.id) ? objNode.id : this.name + this.index++ ;
										objNode.className = objNode.className.replace(this.name, '');										// clone the image
										clonedNode = objNode.cloneNode(true);
										// set the properties of the clone
										clonedNode.style.position = 'absolute';
										clonedNode.className = clonedNode.className.replace(this.name, 'hover');
										if(clonedNode.src) clonedNode.src = clonedNode.src.replace('_link.','_hover.');
										clonedNode.id = (clonedNode.id) ? clonedNode.id : this.name + this.index++ ;
										// place it before the original icon
										objNode.parentNode.insertBefore(clonedNode, objNode);
										// get the new node as an object
										newNode = classBehaviour.utilities.previousNode(objNode);										// set the default fade										classBehaviour.fader.setFade(newNode, 0);										// set up the events										newNode.onmouseover = this.addHover;										newNode.onmouseout = this.remHover;									}			// events			this.addHover 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var fmh = classBehaviour.fadeMouseHover;									// if there's no fade active at the moment 									if(classBehaviour.fader.getFade(objNode)%100==0){
										// fade out the image										classBehaviour.fader.fadeIn(objNode.id, 20, 50, '');									// else try again in a bit									}else{
										fmh.timeOut = setTimeout('classBehaviour.fadeMouseHover.addHover(document.getElementById("' + objNode.id + '"))',50);									}								}			this.remHover 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var fmh = classBehaviour.fadeMouseHover;									// if there's no fade active at the moment 									if(classBehaviour.fader.getFade(objNode)%100==0){
										// fade out the image										classBehaviour.fader.fadeOut(objNode.id, 20, 50, '');									// else try again in a bit									}else{										fmh.timeOut = setTimeout('classBehaviour.fadeMouseHover.remHover(document.getElementById("' + objNode.id + '"))',100);									}								}		}		// 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.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;										// give this node an id if it doesn't have one yet										node.id = (node.id) ? node.id : this.name + this.index++ ;										// 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) ;
										// get all nodes of this class
										allNodes = classBehaviour.utilities.getElementsByClassName(t2n.name);										// for every node in the node-list										for(var a=0; a<allNodes.length; a++){											// get its family											peerLabel = allNodes[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 lists without this node
									allLists = node.getElementsByTagName('ul');									// get all tabs from the first list									allTabs = allLists[0].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 list, it'd better be the last one									pager = (allLists[allLists.length-1].className.indexOf('contentPager')>-1) ? allLists[allLists.length-1] : null;
									if(pager!=null){										// assign the events for the buttons										pager.getElementsByTagName('button')[0].onclick = this.previous;										pager.getElementsByTagName('button')[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 = objNode.parentNode.parentNode.parentNode.getElementsByTagName('ul')[0];									// 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 = objNode.parentNode.parentNode.parentNode.getElementsByTagName('ul')[0];									// 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 = objNode.parentNode.parentNode.parentNode.getElementsByTagName('ul')[objNode.parentNode.parentNode.parentNode.getElementsByTagName('ul').length-1];										pager.getElementsByTagName('span')[0].firstChild.nodeValue = (pageNumber+1) + '/' + allTabs.length ;									}									// cancel the jump to the anchor
									objNode.blur();									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		// 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>img.pngAlpha {visibility:hidden;}</style>");		// 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 ;									// for the downlevel browser MSIE and the image has not been processed before									if(
										typeof(objNode.style.filter)!='undefined'
										&& (navigator.userAgent.indexOf('MSIE 6.0')>-1 || navigator.userAgent.indexOf('MSIE 5')>-1)										&& navigator.userAgent.indexOf('Opera')<0
										&& objNode.src.indexOf('.png')>-1
									){										// change the image styles									//	objNode.style.width		= objNode.width + 'px';									//	objNode.style.height	= objNode.height + 'px';									//	objNode.style.filter	= "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + objNode.src + "', sizingMethod='crop')";										// replace the original with the alpha variant										objNode.src = objNode.src.replace('.png', '.gif');
										objNode.style.visibility = 'visible';									}								}		}		// add this function to the classbehaviour object		classBehaviour.pngAlpha = new PngAlpha;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.pngAlpha;			// Open an overlay as a popup window		// define this class behaviour		function OpenLayerPopUp(){			// properties			this.name 		= 	'openLayerPopUp';
			this.popUpClass	=	'layerPopUp';			this.step		=	10;			this.begin		=	0;			this.end		=	50;
			this.index		=	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
									node.id = (node.id) ? node.id : this.name + 'Link' + this.index++ ;									if(classBehaviour.utilities.getClassParameter(node, 'auto', 'no')=='yes')
										setTimeout('classBehaviour.openLayerPopUp.load(document.getElementById("'+node.id+'"))', 250);								}			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, but show the outside
										node.style.visibility = 'visible';										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);
									popUpWidth = classBehaviour.utilities.getClassParameter(referNode, 'width', '470');
									popUpHeight = classBehaviour.utilities.getClassParameter(referNode, 'height', '300');
									// 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');
									lastDiv = allDivs[allDivs.length-1];
									importedText = (importedText.indexOf('<body>')>-1) ? importedText.split('<body>')[1].split('</body>')[0] : importedText.replace('<?xml version="1.0"?>', '') ;
									importedText = importedText.replace(/{id}/gi, popUpId);
									importedText = importedText.replace(/{title}/gi, referNode.title);
									importedText = importedText.replace(/{url}/gi, referNode.href.split('?url=')[1]);
									importedText = importedText.replace(/{width}/gi, popUpWidth);
									importedText = importedText.replace(/{height}/gi, popUpHeight);
									lastDiv.innerHTML = importedText;
									//alert(lastDiv.innerHTML);
									// apply any classbehaviours
									//debug(lastDiv.getElementsByTagName('div').length);
									classBehaviour.parseDocument(lastDiv.getElementsByTagName('div')[0]);
									// show the pop-up
									olp.show(referNode, popUpId);
								}
			this.center		=	function(popUpObj){
									if(popUpObj){
										// the dimensions can not be measured with "display:none;"										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 = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight ;										// center the popup										popupContent.style.marginTop = (screenHeight>popupHeight) ? Math.round((screenHeight-popupHeight)/2) + 'px' : '30px' ;	
									}
								}			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									popUpObj = document.getElementById(popUpId);
									// hide the popup for now
									popUpObj.style.visibility = 'hidden';
									// center the popup
									this.center(popUpObj);
									// 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('fullHeightzPopUp')<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';									}
									// if there is a popup open already
									if(olp.opened!=null){
										// instantly hide the old one
										document.getElementById(olp.opened).style.display = 'none';
										// instantly show the new one
										document.getElementById(popUpId).style.display = 'block';
										document.getElementById(popUpId).style.visibility = 'visible';
									}else{
										// fade the popup in, but give the contents a little head start										setTimeout('classBehaviour.openLayerPopUp.fadeIn("'+popUpId+'", '+olp.begin+')', 1000);
									}									// remember the open popup
									olp.opened = popUpId;									// 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;
									while(popUp.className.indexOf(olp.popUpClass)<0){
										popUp = popUp.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('fullHeightzPopUp')<0) document.body.parentNode.style.overflow = "";										// show the selects
										allSelects = document.getElementsByTagName('select');										for(var a=0; a<allSelects.length; a++) allSelects[a].style.visibility = 'visible';									}
									// clear the iframe contents
									popUpIframes = popUp.getElementsByTagName('iframe');									if(popUpIframes.length>0){
										popUpIframes[0].src = "";
									}
									// note that nothing is opened
									olp.opened = null;									// cancel the click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.openLayerPopUp = new OpenLayerPopUp;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openLayerPopUp;
		
	// replace the contents of the popup		// define this class behaviour		function ReplaceLayerPopUp(){			// properties			this.name 		= 	'replaceLayerPopUp';			// methods			this.start		=	function(node){									// set the event handler for the link
									node.onclick = this.clicked;								}
			this.wait		=	function(progress, referer){
									// No indicator was designed
								//	debug(progress);
								}
			this.insert		=	function(xmlObj, referer, xmlText){
									// get the root of this popup
									rootNode = classBehaviour.utilities.rootNode(referer, null, null, 'layerPopUp');
									// clean the incoming content
									popUpText = xmlText.split('<!-- cut here -->')[1];
									// insert the new content
									rootNode.innerHTML = popUpText;
									// re-apply the classbehaviour
									classBehaviour.parseDocument(rootNode);
									// recenter
									classBehaviour.openLayerPopUp.center(rootNode);									// find the close gadget									popUpClosers = rootNode.getElementsByTagName('a');
									if(popUpClosers.length>0){										popUpClosers[0].onclick = classBehaviour.openLayerPopUp.hide;
									}
								}
			// events			this.clicked 	= 	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var rlp = classBehaviour.replaceLayerPopUp;									// get the new content from the url
									importUrl = objNode.href;
									classBehaviour.xmlDoc.addRequest(importUrl, rlp.insert, rlp.wait, null, objNode);									// cancel browser mouse click									return false;								}		}		// add this function to the classbehaviour object		classBehaviour.replaceLayerPopUp = new ReplaceLayerPopUp;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.replaceLayerPopUp;
		
	// move the node to the bottom of the document		// define this class behaviour		function LayerPopUp(){			// properties			this.name 		= 	'layerPopUp';			// methods			this.start		=	function(node){
									// if this node wasn't moved									if(node.className.indexOf('doNotMove')<0) this.process(node);								}			this.process 	= 	function(objNode){									// take this node
								 	removedChild = objNode.parentNode.removeChild(objNode);
								 	removedChild.className += ' doNotMove';
									// and put it at the end of the document
									document.body.appendChild(removedChild);								}		}		// add this function to the classbehaviour object		classBehaviour.layerPopUp = new LayerPopUp;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.layerPopUp;
		
	// use a button to hide the popup layer		// define this class behaviour		function CloseLayerPopUp(){			// properties			this.name 			= 	'closeLayerPopUp';			// methods			this.start			=	function(node){
										node.onclick = this.closePopUp;									}			this.closePopUp 	= 	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;										// get the root of this popup
										rootNode = classBehaviour.utilities.rootNode(objNode, null, null, 'layerPopUp');
										// close the layer
										classBehaviour.openLayerPopUp.hide(rootNode);										return false;									}		}		// add this function to the classbehaviour object		classBehaviour.closeLayerPopUp = new CloseLayerPopUp;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.closeLayerPopUp;
							// 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 SortByColumn(){			// properties			this.name 		= 	'sortByColumn';			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.sortByColumn;									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.sortByColumn;									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.sortByColumn;									// 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									classBehaviour.zebraTable.process(fullTable);								}		}		// add this function to the classbehaviour object		classBehaviour.sortByColumn = new SortByColumn;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.sortByColumn;			// 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;			// 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;
			this.lastFocus		=	null;
			this.customChecks	=	new CustomChecks;			// 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].onmousedown = this.clear;												nodes[a].onblur = this.input;												nodes[a].onchange = this.input;												// 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;
										// Show the input warning if this is a suitable form element
										if(objNode.className.indexOf('noWarning')<0)
											objNode.className = (status) ? objNode.className.replace(' validationWarning', '') : objNode.className + ' validationWarning' ;										// 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) ? allLabels[a].className.replace(' validationWarning', '') : allLabels[a].className + ' validationWarning' ;												}											}										}									}			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' || objNode.nodeName=='BUTTON');									}
			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.ajaxWait		=	function(submitProgress, submitReferer, submitError){
										// inform the user on the progress in the reply area
										submitReferer.innerHTML = (submitProgress<0) ? 'error: ' + submitError : 'sending: ' + Math.round(submitProgress*100) + '%' ;
									}
			this.ajaxReply		=	function(replyObj, replyReferer, replyText){
										// strip and write the reply to the form reply area
										replyReferer.innerHTML = (replyText.indexOf('</body>')>-1) ? replyText.split('<body>')[1].split('</body>')[0] : replyText.split('<root>')[1].split('</root>')[0] ;
										// activate any classbehaviours
										classBehaviour.parseDocument(replyReferer);
									}
			// events
			this.clear	=	function(objNode){								var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
								var vi = classBehaviour.validateInput;
								// remember the focus point
								vi.lastFocus = objNode;								// 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;
								// if there was a focus point stored use it
								if(vi.lastFocus!=null) objNode = vi.lastFocus;
								// find the form's root
								if(objNode!=null) rootNode = classBehaviour.utilities.rootNode(objNode, null, null, 'validateAllInput');								// get all subnodes in the form
								var objSubNodes = rootNode.getElementsByTagName("*");								// for all nodes
								var queryString = '';								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);
									// Note the name and value
									if(objSubNodes[intA].nodeName=='INPUT' || objSubNodes[intA].nodeName=='SELECT' || objSubNodes[intA].nodeName=='TEXTAREA')
										queryString += (objSubNodes[intA].checked || (objSubNodes[intA].type!='radio' && objSubNodes[intA].type!='checkbox')) ? objSubNodes[intA].name + '=' + objSubNodes[intA].value + '&' : '' ;								}
								// if an ajax submit is required
								replyId = classBehaviour.utilities.getClassParameter(rootNode, 'ajaxReplyId', null);
								submitId = classBehaviour.utilities.getClassParameter(rootNode, 'ajaxReplyUrl', null);
								if(replyId!=null && submitId!=null && booPassed){
									// get the submitted properties
									replyTarget = document.getElementById(replyId);
									submitUrl = (document.getElementById(submitId).nodeName=='FORM') ? document.getElementById(submitId).getAttribute('action') : document.getElementById(submitId).getAttribute('value') ;
									// submit the form using ajax
									classBehaviour.xmlDoc.addRequest(submitUrl + '?' + queryString, vi.ajaxReply, vi.ajaxWait, queryString, replyTarget);
									// cancel the actual submit
									return false;
								// else
								}else{									// let the form submit or not									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 '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;												}
			}		// 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){
									// find the form
									formNode = classBehaviour.utilities.rootNode(node, 'FORM', null, null);									// set the form validation eventhandler									formNode.onsubmit = classBehaviour.validateInput.all;								}		}		// add this function to the classbehaviour object		classBehaviour.validateAllInput = new ValidateAllInput;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateAllInput;	// Triggers all validateInput class behaviours within a node to submit an AJAX form,		// define this class behaviour		function ValidateAllNow(){			// properties			this.name 		= 	'validateAllNow';			// methods			this.start		=	function(node){									// validate all inputs manualy									node.onclick = classBehaviour.validateInput.all;								}		}		// add this function to the classbehaviour object		classBehaviour.validateAllNow = new ValidateAllNow;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.validateAllNow;
			// 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 handlers of 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	=	'default';				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;
		
	// 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 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('a');									// if this is a single item									if(allLinks.length==0) allLinks = new Array(node);									// for all containers									for(var a=0; a<allLinks.length; a++){										// get the dimensions of the container										containerSize = new Array(allLinks[a].offsetWidth, allLinks[a].offsetHeight);										// get the thumbnail										thumbnail = allLinks[a].getElementsByTagName('img')[0];										// get the dimensions of the thumbnail										thumbnailSize = new Array(thumbnail.offsetWidth, thumbnail.offsetHeight);										// set the position of the thumbnail										offsetX = (containerSize[0] - thumbnailSize[0])/2;										offsetY = (containerSize[1] - thumbnailSize[1])/2;										thumbnail.style.margin = offsetY + "px " + offsetX + "px " + offsetY + "px " + offsetX + "px";									}
								}		}		// add this function to the classbehaviour object		classBehaviour.centeredThumbnails = new CenteredThumbnails;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.centeredThumbnails;			// 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(that)!='undefined') ? (that.layerX) + 'px' : (event.x) + 'px' ;									targetNode.style.top = (typeof(that)!='undefined') ? (that.layerY) + 'px' : (event.y) + 'px' ;								}		}		// add this function to the classbehaviour object		classBehaviour.hoverNextNode = new HoverNextNode;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.hoverNextNode;			// 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
										if (node.getElementsByTagName('input')[0] != null)
										{
										    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;
			// Update a slide based on clicks on thumbnails		// define this class behaviour		function ThumbnailToPhoto(){			// properties			this.name 		= 	'thumbnailToPhoto';
			this.thumbnails	=	new Array();
			this.stackTop	=	1;			// methods			this.start		=	function(node){
									// add the thumbnail to the index
									this.thumbnails[this.thumbnails.length] = node;									// set the click event
									node.onclick = this.loadPhoto;								}			// events			this.loadPhoto	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var ttp = classBehaviour.thumbnailToPhoto;
									// if this is not an active thumbnail
									if(objNode.className.indexOf('active')<0){
										// get the target of this thumbnail
										targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', 'thumbnailTarget');
										// for all thumbnails
										allThumbnails = ttp.thumbnails;
										for(var a=0; a<allThumbnails.length; a++){
											// deactivate the thumbnails with the same target
											thumbnailTargetId = classBehaviour.utilities.getClassParameter(allThumbnails[a], 'id', 'thumbnailTarget')
											if(thumbnailTargetId==targetId) allThumbnails[a].className = allThumbnails[a].className.replace(' active','');
										}
										// activate this thumbnail
										objNode.className += ' active';
										// find the image in the existing target stack
										targetStack = document.getElementById(targetId);
										targetImages = targetStack.getElementsByTagName('img');
										targetImage = null;
										for(var a=0; a<targetImages.length; a++) if(targetImages[a].src==objNode.href) targetImage = targetImages[a];
										// if the image isn't in the stack allready
										if(targetImage==null){
											// create a new image
											clonedImage = targetImages[0].cloneNode(true);
											// place it at the bottom of the stack
											targetStack.insertBefore(clonedImage, targetStack.firstChild);
											// set the properties of the new image
											clonedImage = classBehaviour.utilities.previousNode(targetImages[0]);
											clonedImage.id = null;
											clonedImage.onload = ttp.showPhoto;
											clonedImage.src = objNode.href;
											clonedImage.title = objNode.getElementsByTagName('img')[0].title;
											clonedImage.alt = objNode.getElementsByTagName('img')[0].alt;
										// else
										}else{
											// if this isn't the same slide as the last one, skip to the show function
											ttp.showPhoto(targetImage);
										}
									}
									// cancel the click									return false;								}
			this.showPhoto	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									var ttp = classBehaviour.thumbnailToPhoto;
									// fade it out
									classBehaviour.fader.setFade(objNode, 0);
									// put it at the top of the stack
									ttp.stackTop += 1;
									objNode.style.zIndex = ttp.stackTop;
									// fade it in
									objNode.id = (objNode.id==null) ? objNode.id : ttp.name + ttp.stackTop ;
									classBehaviour.fader.fadeIn(objNode.id, 10, 50, null);								}		}		// 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;
			this.bookmark		=	null;
			// 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();
										// store the selection when the mouse lifts
										if(editor.selection) editor.onmouseup = this.storeSelect;
									}
			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.storeSelect	=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var ecs = classBehaviour.richTextEditor;
										// store the selection
										editor = objNode;
										if(editor.selection){
											ecs.bookmark = editor.selection.createRange().getBookmark();
										}
									}
			this.restoreSelect	=	function(editor){
										var ecs = classBehaviour.richTextEditor;
										// restore the selection
										if(editor.selection){
											if(ecs.bookmark){
												range = editor.documentElement.firstChild.nextSibling.createTextRange();
												range.moveToBookmark(ecs.bookmark);
												range.select();
											}
										}
									}
			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);
											// restore the selection if it was lost
											ecs.restoreSelect(editor);
											// 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;
	// 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		=	"";			// 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
											if(typeof(newEntry)=='string')												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, onlyChanges){
											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 && onlyChanges) ? 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, onlyChanges){
											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)){
														if(typeof(objChildNodes[intA].id)=='string'){
															// 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, onlyChanges)) 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 = 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, onlyChanges)){
															// 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, onlyChanges)){
														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, onlyChanges);
												}
											}
										}
			this.showNodeClasses	=	function(that){
											var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
											var mss = classBehaviour.makeStylesheet;
											// position it out of the way
											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';
											// are only the changes to the existing stylesheets required?
											onlyChanges = (classBehaviour.utilities.getClassParameter(objNode, 'changesOnly', 'yes')=='yes');
											// generate the stylesheet code
											mss.getNodeClasses(document.body, 0 , '', onlyChanges);
											// replace the page with the stylesheet prototype
											document.body.innerHTML = (navigator.userAgent.indexOf('MSIE 6')>-1) ? '<textarea style="width:720px;height:480px;border:solid 1px #000000;">' + mss.styleSheet + '</textarea>' : '<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", "2"));
									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;
									// set the cursor
									targetNode.style.cursor = 'pointer';								}
			// 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		=	null;
			this.url 		= 	null;
			this.input 		= 	null;
			this.output 	= 	null;
			this.startIndex	=	0;
			this.endIndex	=	8;
			/* objects */
			this.search		=	new Search;
			this.source		=	new Source;
			// methods
			this.start		=	function(node){
									node.onsubmit = this.doSubmit;
									// get the default values
									this.form		=	document.getElementById('searchform');
									this.url 		= 	document.getElementById('searchsource');
									this.input 		= 	document.getElementById('searchstring');
									this.output 	= 	document.getElementById('searchresults');
								}
			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;
		
	// displays and updates the nodes of a chat window		// define this class behaviour		function RssChat(){			// properties			this.name 		= 	'rssChat';
			this.index		=	0;
			this.timeout	=	null;
			this.delay		=	4096;			// methods			this.start		=	function(node){
									// give the node an id if it doesn't have one
									node.id = (node.id) ? node.id : this.name + this.index++ ;
									// set the button event
									node.getElementsByTagName('button')[0].onclick = this.send;
									// load the feed
									rssUrl = node.getElementsByTagName('input')[0].value;
									rssRnd = '&upd=' + '?upd=' + new Date().getTime();
									classBehaviour.xmlDoc.addRequest(rssUrl+rssRnd, this.update, this.wait, null, node.id);								}
			this.wait		=	function(progress, nodeId, error){
									var node = document.getElementById(nodeId);
									progressNode = node.getElementsByTagName('div')[0];
									progressNode.style.backgroundPosition = (progress<0) ? '0% 100%' : (100-progress*100) +'% 0%' ;
									progressNode.innerHTML = (progress<0) ? 'error: ' + error : Math.round(progress*100) + '% updated' ;
								}
			this.update		=	function(xml, nodeId, txt){
									var node = document.getElementById(nodeId);
									// clear any pending timeout
									clearTimeout(classBehaviour.rssChat.timeout);
									// update the chat title
									rssHeader = node.getElementsByTagName('h3');
									if(rssHeader.length>0) rssHeader[0].innerHTML = xml.getElementsByTagName('title')[0].firstChild.nodeValue;
									// clear all previous items except the protoype
									previousDts = node.getElementsByTagName('dt');
									previousDds = node.getElementsByTagName('dd');
									for(var a=previousDts.length-1; a>0; a--){
										removedDd = previousDds[a].parentNode.removeChild(previousDds[a]);
										removedDt = previousDts[a].parentNode.removeChild(previousDts[a]);
									}
									// for all chat items
									allItems = xml.getElementsByTagName('item');
									listNode = node.getElementsByTagName('dl')[0];
									for(var a=0; a<allItems.length; a++){
										// get the item properties
										itemAuthor = (allItems[a].getElementsByTagName('author')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('author')[0].firstChild.nodeValue : '' ;
										itemPubDate = (allItems[a].getElementsByTagName('pubDate')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('pubDate')[0].firstChild.nodeValue : '' ;
										itemCategory = (allItems[a].getElementsByTagName('category')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('category')[0].firstChild.nodeValue : '' ;
										itemLink = (allItems[a].getElementsByTagName('link')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('link')[0].firstChild.nodeValue : '' ;
										itemTitle = (allItems[a].getElementsByTagName('title')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('title')[0].firstChild.nodeValue : '' ;
										itemDescription = (allItems[a].getElementsByTagName('description')[0].childNodes.length>0) ? allItems[a].getElementsByTagName('description')[0].firstChild.nodeValue : '' ;
										// format the date
										itemPubDate = (new Date(itemPubDate)).toLocaleString();
										// clone the prototype node
										clonedDt = node.getElementsByTagName('dt')[0].cloneNode(true);
										clonedDd = node.getElementsByTagName('dd')[0].cloneNode(true);
										// modify its contents
										clonedDt.className = clonedDt.className.replace('prototype', '');
										clonedDt.innerHTML = clonedDt.innerHTML.replace(/{author}/gi, itemAuthor).replace(/{pubDate}/gi, itemPubDate).replace(/{category}/gi, itemCategory).replace(/{link}/gi, itemLink).replace(/{title}/gi, itemTitle);
										clonedDd.className = clonedDd.className.replace('prototype', '');
										clonedDd.firstChild.nodeValue = itemDescription;
										// insert it at the top
										listNode.appendChild(clonedDt);
										listNode.appendChild(clonedDd);
									}
									// set the scroll position to the bottom
									listNode.scrollTop = listNode.scrollHeight + 1000;
									// order another update
									rssUrl = node.getElementsByTagName('input')[0].value;
									rssRnd = '&upd=' + '?upd=' + new Date().getTime();
									classBehaviour.rssChat.timeout = setTimeout('classBehaviour.xmlDoc.addRequest("'+rssUrl+rssRnd+'", classBehaviour.rssChat.update, classBehaviour.rssChat.wait, null, "'+nodeId+'")', classBehaviour.rssChat.delay);
								}
			// events
			this.send		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var rsc = classBehaviour.rssChat
									// find the root node
									rootNode = classBehaviour.utilities.rootNode(objNode, null, null, rsc.name);
									// get the submitted values
									itemAuthor = rootNode.getElementsByTagName('input')[1].value.replace(';', ':');
									itemPubDate = (new Date()).toUTCString();
									itemCategory = "replies";
									itemLink = document.location.href;
									itemTitle = document.title;
									itemDescription = rootNode.getElementsByTagName('textarea')[0].value;
									// construct the post
									rssPost = "&root=channel&parent=item&indexa=-1&valuesa=author;" + itemAuthor + ";pubDate;" + itemPubDate + ";category;" + itemCategory + ";title;" + itemTitle + ";description;" + itemDescription;
									// make the http request
									rssUrl = rootNode.getElementsByTagName('input')[0].value;
									rssRnd = '&upd=' + '?upd=' + new Date().getTime();
									classBehaviour.xmlDoc.addRequest(rssUrl+rssRnd+rssPost, rsc.update, rsc.wait, null, rootNode.id);
									// clear the textarea
									rootNode.getElementsByTagName('textarea')[0].value = '';
								}		}		// add this function to the classbehaviour object		classBehaviour.rssChat = new RssChat;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.rssChat;
		
	// 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;
				
	// 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;
		
	// Resize an iframe to accomodate the contents
		// define this class behaviour		function AutoSizeIframe(){			// properties			this.name 			= 	'autoSizeIframe';
			// methods			this.start			=	function(node){
										// set the onload event of the frame
										node.onload = this.resize;
										this.resize();
									}
			// events
			this.resize			=	function(){
										var asi = classBehaviour.autoSizeIframe;
										// if the frame is loaded, resize all iframes of this class
										allIframes = document.getElementsByTagName('iframe');
										for(var a=0; a<allIframes.length; a++)
											if(allIframes[a].className.indexOf(asi.name)>-1)
												if(window.frames[allIframes[a].name].document.getElementsByTagName('body').length>0)
													if(window.frames[allIframes[a].name].document.getElementsByTagName('body')[0].offsetHeight>0)
														document.getElementById(allIframes[0].id).style.height = (window.frames[allIframes[a].name].document.getElementsByTagName('body')[0].offsetHeight) + 'px';
									}		}		// add this function to the classbehaviour object		classBehaviour.autoSizeIframe = new AutoSizeIframe;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.autoSizeIframe;
		
	// Fetch the links from a list of portfolio templates
		// define this class behaviour		function PortfolioList(){			// properties			this.name 			= 	'portfolioList';
			// methods			this.start			=	function(node){
										// set the onclick event of the button
										allLinks = node.getElementsByTagName('a');
										for(var a=0; a<allLinks.length; a++) allLinks[a].onclick = this.clickItem;
									}
			this.waitForList	=	function(loadStatus, referedNode){
										// update the progress indicator
										referedNode.getElementsByTagName('div')[0].innerHTML = (loadStatus<0) ? '<h1>loading: failed</h1><p>Please try another.</p>' : '<h1>loading: ' + (loadStatus*100) + '%</h1>';

									}
			this.insertTheList	=	function(xmlObj, referedNode, xmlText){
										// if this page is an index list
										sourceUrl = classBehaviour.utilities.previousNode(referedNode).href;
										if(xmlText.indexOf('templates index')>-1 && xmlText.indexOf('<body>')>-1){
											// process the html to add a window opener
											sourceBaseUrl = sourceUrl.replace('/index.html', '');
											importedHtml = xmlText.split('<body>')[1].split('</body>')[0].replace(/href="./gi, 'href="' + sourceBaseUrl);
											// paste the html in place of the progress indicator
											referedNode.getElementsByTagName('div')[0].innerHTML = importedHtml;
										// else open the link normally
										}else{
											document.location.href = classBehaviour.utilities.previousNode(referedNode).href;
										}
									}
			// events
			this.clickItem		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var pfl = classBehaviour.portfolioList;
										// if the list has not been filled earlier
										if(classBehaviour.utilities.nextNode(objNode)==objNode){
											// construct the list holder
											newDiv = document.createElement('div');
											newDiv.className = 'popUp hideThisNode';
											newBorder = document.createElement('div');
											newBorder.className = 'popUpBorder';
											newTitle = document.createElement('h1');
											newText = document.createTextNode('loading...');
											// show the list holder with a progress indicator
											newTitle.appendChild(newText);
											newBorder.appendChild(newTitle);
											newDiv.appendChild(newBorder);
											objNode.parentNode.appendChild(newDiv);
											// start the loading
											classBehaviour.xmlDoc.addRequest(objNode.href, pfl.insertTheList, pfl.waitForList, null, classBehaviour.utilities.nextNode(objNode));
											// prepare the item for toggleNextNode
											objNode.className += ' family_portfolio0';
											classBehaviour.toggleNextNode.start(objNode);
											classBehaviour.toggleNextNode.toggle(objNode);
										// else
										}else{
											// toggle the list item
											classBehaviour.toggleNextNode.toggle(objNode);
										}
										// cancel the click
										return false;
									}		}		// add this function to the classbehaviour object		classBehaviour.portfolioList = new PortfolioList;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.portfolioList;
		
	// Manages an artificial scroll bar
		// define this class behaviour		function ArtificialScrollBar(){			// properties			this.name 			= 	'artificialScrollBar';
			this.interaction	=	false;
			this.interactor		=	null;
			this.scrollInterval	=	null;
			this.index			=	0;
			// methods			this.start			=	function(node){
										// give the scrollbar an id if it doesn't have one
										node.id = (node.id) ? node.id : this.name + this.index++ ;
										// get the objects inside
										allDivs = node.getElementsByTagName('DIV');
										// disable the normal scrollbar
										node.style.overflow = 'hidden';
										// show the artificial scrollbar
										allDivs[allDivs.length-5].style.display = 'block';
										// set the canvas event handlers
										node.onmouseover = this.overCanvas;
										node.onmouseout = this.offCanvas;
										// set the detector events
										allDivs[allDivs.length-1].onmousedown = this.onDown;
										allDivs[allDivs.length-1].onmousemove = this.onDrag;
										allDivs[allDivs.length-1].ondrag = this.onDrag;
										document.onmouseup = this.onUp;
										node.onmousewheel = this.onWheel;
										if(window.addEventListener) window.addEventListener('DOMMouseScroll', this.onWheel, false);
										// set the button event handlers
										allDivs[allDivs.length-3].onmousedown = this.buttonDown;
										allDivs[allDivs.length-3].onmouseup = this.buttonOff;
										allDivs[allDivs.length-3].onmouseout = this.buttonOff;
										allDivs[allDivs.length-4].onmousedown = this.buttonUp;
										allDivs[allDivs.length-4].onmouseup = this.buttonOff;
										allDivs[allDivs.length-4].onmouseout = this.buttonOff;
										// start position
										setTimeout('classBehaviour.artificialScrollBar.moveTo(document.getElementById("'+node.id+'"), 0)', 100);
									}
			this.resize			=	function(rootNode){
										// get the required objects
										allDivs = rootNode.getElementsByTagName('DIV');
										contentNode = allDivs[0];
										indicatorNode = allDivs[allDivs.length-2];
									}
			this.moveTo			=	function(rootNode, position){
										// get the required objects
										allDivs = rootNode.getElementsByTagName('DIV');
										contentNode = allDivs[0];
										indicatorNode = allDivs[allDivs.length-2];
										// size the indicator
										contentToWindowRatio = contentNode.parentNode.offsetHeight / contentNode.offsetHeight;
										scrollBarHeight = indicatorNode.parentNode.offsetHeight;
										indicatorSize = contentToWindowRatio * scrollBarHeight;
										if(!isNaN(indicatorSize)) indicatorNode.style.height = Math.round(indicatorSize) + 'px';
										// if the page is longer than the canvas
										if(contentToWindowRatio<1){
											// set the indicator position
											indicatorSurplus = indicatorSize / 2;
											indicatorPosition = position - indicatorSurplus;
											if(position < indicatorSurplus) indicatorPosition = 0;
											if(indicatorPosition > scrollBarHeight-indicatorSize) indicatorPosition = scrollBarHeight-indicatorSize;
											if(!isNaN(indicatorPosition)) indicatorNode.style.top = Math.round(indicatorPosition) + 'px';
											// set the content position
											scrollBarFraction = (position - indicatorSurplus) / (scrollBarHeight - indicatorSurplus * 2);
											contentOverlap = contentNode.offsetHeight - contentNode.parentNode.offsetHeight;
											contentPosition = scrollBarFraction * contentOverlap;
											if(contentPosition<0) contentPosition = 0;
											if(contentPosition>contentOverlap) contentPosition = contentOverlap;
											if(!isNaN(contentPosition)) contentNode.style.top = Math.round(0 - contentPosition) + "px";
										}
									}
			this.moveBy			=	function(rootNode, distance){
										if(rootNode){
											// get the required objects
											allDivs = rootNode.getElementsByTagName('DIV');
											contentNode = allDivs[0];
											indicatorNode = allDivs[allDivs.length-2];
											// get the current scroll position
											indicatorPosition = (indicatorNode.style.top) ? parseInt(indicatorNode.style.top) : 0 ;
											indicatorSize = (indicatorNode.style.height) ? parseInt(indicatorNode.style.height) : 0 ;
											// set the new scroll position
											this.moveTo(rootNode, indicatorPosition+indicatorSize/2+distance);
										}
									}
			// events
			this.onDown			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// activate the controls
										asb.interaction = true;
										// get the interaction location
										mouseY = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.y : that.layerY ;
										// send the coordinates to the indicator
										asb.moveTo(objNode.parentNode.parentNode, mouseY);
										// cancel the click
										return false;
									}
			this.onDrag			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// if the controls are active
										if(asb.interaction){
											// get the interaction location
											mouseY = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.y : that.layerY ;
											// send the coordinates to the indicator
											asb.moveTo(objNode.parentNode.parentNode, mouseY);
											// cancel the click
											return false;
										}
									}
			this.onUp			=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// de-activate the controls
										asb.interaction = false;
										// cancel the click
										return false;
									}
			this.buttonUp		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// move the scroller 1 step up
										asb.moveBy(asb.interactor, -5);
										// set an interval
										asb.scrollInterval = setInterval("classBehaviour.artificialScrollBar.moveBy(classBehaviour.artificialScrollBar.interactor, -5)", 50);
										// cancel the click
										return false;
									}
			this.buttonDown		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// move the scroller 1 step down
										asb.moveBy(asb.interactor, 5);
										// set an interval
										asb.scrollInterval = setInterval("classBehaviour.artificialScrollBar.moveBy(classBehaviour.artificialScrollBar.interactor, 5)", 50);
										// cancel the click
										return false;
									}
			this.buttonOff		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// clear the scrolling interval
										clearInterval(asb.scrollInterval);
										// cancel the click
										return false;
									}
			this.onWheel		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// get the scroll distance
										distance = (window.event) ? window.event.wheelDelta/120 : -objNode.detail/3 ; 
										// scroll the page
										asb.moveBy(asb.interactor, -5*distance);
										// cancel the click
										return false;
									}
			this.overCanvas		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// store the object hovered over
										asb.interactor = objNode;
									}
			this.offCanvas		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var asb = classBehaviour.artificialScrollBar;
										// store the object hovered over
										asb.interactor = null;
									}		}		// add this function to the classbehaviour object		classBehaviour.artificialScrollBar = new ArtificialScrollBar;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.artificialScrollBar;
		
	// Use the longdesc url to display a tooltip
		// define this class behaviour		function LongdescToolTip(){			// properties			this.name 			= 	'longdescToolTip';
			// methods			this.start			=	function(node){
										// set the event handlers of the image
										node.onmouseover = this.overImage;
										node.onmouseout = this.offImage;
						//				node.onmousemove = this.moveImage;
									}
			this.waitForDesc	=	function(importProgress, referedNode){
										targetNode = classBehaviour.utilities.previousNode(referedNode);
										targetNode.innerHTML = 'loading: ' + Math.round(importProgress*100) + '%';
									}
			this.insertDesc		=	function(importedObj, referedNode, importedText){
										targetNode = classBehaviour.utilities.previousNode(referedNode);
										targetNode.innerHTML = importedText.split('<body>')[1].split('</body>')[0];;
									}
			// events
			this.overImage		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var ltt = classBehaviour.longdescToolTip;										// get the taget node
										targetNode = classBehaviour.utilities.previousNode(objNode);
										// if this node is an existing tooltip
										if(targetNode.nodeName=='DIV' && targetNode.className.indexOf(ltt.name)>-1){
											// show it											targetNode.style.visibility = 'visible';
										}else{
											// make a new one
											newToolTip = document.createElement('DIV');
											newToolTip.className = ltt.name;
											objNode.parentNode.insertBefore(newToolTip, objNode);
											// order it to be filled
											classBehaviour.xmlDoc.addRequest(objNode.getAttribute('longdesc'), ltt.insertDesc, ltt.waitForDesc, null, objNode);
										}
									}
			this.offImage		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var ltt = classBehaviour.longdescToolTip;										// get the next node										targetNode = classBehaviour.utilities.previousNode(objNode);
										// if this node is an existing tooltip
										if(targetNode.nodeName=='DIV' && targetNode.className.indexOf(ltt.name)>-1){											// hide it
											targetNode.style.visibility = 'hidden';
										}
									}
			this.moveImage		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var ltt = classBehaviour.longdescToolTip;										// get the next node										targetNode = classBehaviour.utilities.previousNode(objNode);
										// if this node is an existing tooltip
										if(targetNode.nodeName=='DIV' && targetNode.className.indexOf(ltt.name)>-1){											targetNode.style.position = 'absolute';											targetNode.style.left = (typeof(that)!='undefined') ? (that.layerX) + 'px' : (event.x) + 'px' ;											targetNode.style.top = (typeof(that)!='undefined') ?  (that.layerY) + 'px' : (event.y) + 'px' ;
										}
									}		}		// add this function to the classbehaviour object		classBehaviour.longdescToolTip = new LongdescToolTip;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.longdescToolTip;
		
	// Replace a link to external content with the actual content
		// define this class behaviour		function InsertFromFile(){			// properties			this.name 			= 	'insertFromFile';
			// methods			this.start			=	function(node){
										// start loading
										classBehaviour.xmlDoc.addRequest(node.getAttribute('href'), this.insert, this.wait, null, node);
									}
			this.wait			=	function(importProgress, referedNode){
										referedNode.innerHTML = 'loading: ' + Math.round(importProgress*100) + '%';
									}
			this.insert			=	function(importedObj, referedNode, importedText){
										// insert the content before the link
										newDiv = document.createElement('div');
										referedNode.parentNode.insertBefore(newDiv, referedNode);
										insertedNode = classBehaviour.utilities.previousNode(referedNode);
										insertedNode.innerHTML = importedText.split('<body>')[1].split('</body>')[0];
										// activate any classbehaviours in there
										classBehaviour.parseDocument(insertedNode);
										// remove the link
										removedNode = referedNode.parentNode.removeChild(referedNode);
									}		}		// add this function to the classbehaviour object		classBehaviour.insertFromFile = new InsertFromFile;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.insertFromFile;
		
	// this keeps a screen element fixed to the scrolling
		// define this class behaviour		function ScrollLock(){			// properties			this.name 		= 	'scrollLock';
			this.index		=	0;
			this.timeout	=	null;
			this.objects	=	new Array();			// methods			this.start		=	function(node){
									// give this node and id if there isn't any
									node.id = (node.id) ? node.id : this.name + this.index ;
									// store this scrolling object and its offset
									this.objects[this.objects.length] = node;
									// set the scolling event
									window.onscroll = this.scrolled;								}
			// events
			this.scrolled	=	function(that, noOffset){
									var slc = classBehaviour.scrollLock;
									// clear the timeout on this function
									clearTimeout(classBehaviour.scrollLock.timeout);
									// for all scrolling objects
									for(var a=0; a<slc.objects.length; a++){
										// get the scrolling object
										scrollingObject = slc.objects[a];
										// get the scrolling offset
										offset = Math.round(classBehaviour.utilities.getClassParameter(scrollingObject, 'offset', '0'));
										// get the scrolling position
										scrollPos = document.documentElement.scrollTop;
										// reposition the scrolling object
										availableHeight = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight ;
										if(scrollPos>=offset && scrollingObject.offsetHeight<availableHeight){
											scrollingObject.style.position = (navigator.appVersion.indexOf('MSIE 6')<0) ? 'fixed' : 'absolute' ;
											scrollingObject.style.marginTop = (navigator.appVersion.indexOf('MSIE 6')<0) ? (-1*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.scrollLock.timeout = setTimeout('classBehaviour.scrollLock.scrolled(null, true);', 128);
								}		}		// add this function to the classbehaviour object		classBehaviour.scrollLock = new ScrollLock;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.scrollLock;

	// 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', 'forward')=='backward') ? this.startBackward : this.startForward ;									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.startBackward	=	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.scrollBackward(id);								}			this.startForward	=	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.scrollForward(id);								}			// methods			this.idle			=	function(id){										classBehaviour.scrollList.speed = 1;										classBehaviour.scrollList.scrollForward(id);									}			this.prepareList	=	function(id) {										scroller = document.getElementById(id);										// if this list has not been prepared before										if(scroller.className.indexOf('trippled')<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 += ' trippled';											// 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');										// 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;										// wait for a while, then start idle scrolling										id = classBehaviour.utilities.getClassParameter(objNode, 'id', 'scrollList0');										sl.idleTimer = setTimeout('classBehaviour.scrollList.idle("'+id+'")',2000);									}			this.scrollBackward	=	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.scrollBackward("' + id + '")', 40);								}			this.scrollForward	=	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.scrollForward("' + id + '")', 40);								}		}		// add this function to the classbehaviour object		classBehaviour.scrollList = new ScrollList;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.scrollList;

	// 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){
									/*									var strStyles, arrStyles;									// retrieve styles string									strStyles = classBehaviour.cookies.getCookie('dragAndDrop');														// 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){
									/*									// store styles									classBehaviour.cookies.setCookie('dragAndDrop', 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;

	// handle the mouseclicks of a slider
		// define this class behaviour		function ValueSlider(){			// properties			this.name 		= 	'valueSlider';
			this.active		=	false;			// methods			this.start		=	function(node){
									// get the cover layer
									sliderCover = node.getElementsByTagName('div')[1];
									sliderCover.onmousedown = this.onDown;
									sliderCover.onmouseup = this.onUp;
									sliderCover.onmousemove = this.onMove;
									sliderCover.onmouseout = this.onUp;
									// get the form element
									sliderInput = classBehaviour.utilities.nextNode(node);
									sliderInput.onchange = this.onTyped;								}
			this.setSlider	=	function(rootNode, sliderSize, inputValue){
									// get the minimum value
									minimumValue = parseInt(classBehaviour.utilities.getClassParameter(rootNode, 'min', 0));
									// get the maximum value
									maximumValue = parseInt(classBehaviour.utilities.getClassParameter(rootNode, 'max', 100));
									// get the maximum size of the slider
									maximumSize = rootNode.offsetWidth - 5;
									// calculate the missing size or value
									if(sliderSize==null) sliderSize = Math.round((inputValue - minimumValue) / maximumValue * maximumSize) ;
									if(inputValue==null) inputValue = Math.round(sliderSize / maximumSize * (maximumValue - minimumValue)) + minimumValue ;
									// normalize the values
									if(sliderSize<1) sliderSize = 1;
									if(sliderSize>maximumSize) sliderSize = maximumSize;
									if(inputValue<minimumValue) inputValue = minimumValue;
									if(inputValue>maximumValue) inputValue = maximumValue;
									// set the size of the slider
									rootNode.getElementsByTagName('div')[0].style.width = (sliderSize + 5) + 'px';
									// set the value of the input
									classBehaviour.utilities.nextNode(rootNode).value = inputValue;
									rootNode.getElementsByTagName('span')[0].innerHTML = inputValue;
								}
			// events
			this.onDown		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsl = classBehaviour.valueSlider;
									// get the mouse position
									mouseX = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.x : that.layerX ;
									// set the value
									vsl.setSlider(objNode.parentNode, mouseX, null);
									// mark the function active
									vsl.active = true;
									// cancel the mouse dragging the layer off
									return false;
								}
			this.onUp		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsl = classBehaviour.valueSlider;
									// mark the function inactive
									vsl.active = false;
									// cancel the mouse dragging the layer off
									return false;
								}
			this.onMove		=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsl = classBehaviour.valueSlider;
									// if the function is marked active
									if(vsl.active){
										// get the mouse position
										mouseX = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.x : that.layerX ;
										// set the value
										vsl.setSlider(objNode.parentNode, mouseX, null);
									}
									// cancel the mouse dragging the layer off
									return false;
								}
			this.onTyped	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var vsl = classBehaviour.valueSlider;
									// get the value
									sliderNode = classBehaviour.utilities.previousNode(objNode);
									inputValue = parseInt(objNode.value);
									// set the slider
									vsl.setSlider(sliderNode, null, inputValue);
								}		}		// add this function to the classbehaviour object		classBehaviour.valueSlider = new ValueSlider;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.valueSlider;

	// copy text to the clipboard
		// define this class behaviour		function CopyToClipboard(){			// properties			this.name 			= 	'copyToClipboard';
			// methods			this.start			=	function(node){
										node.onclick = this.copyContents;
									}
			// events			this.copyContents	=	function(that){									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;									// get the target content
									targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', null);
									if(targetId!=null){
										targetNode = document.getElementById(targetId);
										targetValue = (targetNode.value) ?  targetNode.value : targetNode.innerHTML ;
										if(window.clipboardData){
											window.clipboardData.setData('text', targetValue);
										}else{
											// this doesn't work :(
										//	targetValue = document.selection.createRange();
										//	targetValue.execCommand("Copy");
										}
									}								}		}		// add this function to the classbehaviour object		classBehaviour.copyToClipboard = new CopyToClipboard;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.copyToClipboard;

	// replace the content of a section based on a select
		// define this class behaviour		function SelectContent(){			// properties			this.name 			= 	'selectContent';
			// methods			this.start			=	function(node){
										node.onchange = this.loadNew;
										// load the initial content
										this.loadNew(node);
									}
			// events			this.loadNew		=	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var sct = classBehaviour.selectContent;
										// get the url from the select
										newUrl = objNode.value;
										// get the refered target
										targetId = classBehaviour.utilities.getClassParameter(objNode, 'id', null);
										// load it
										if(targetId!=null && newUrl!='') classBehaviour.xmlDoc.addRequest(newUrl, sct.insertNew, sct.waitForNew, null, document.getElementById(targetId));									}			this.waitForNew		=	function(loadStatus, loadReferer, loadError){										// post the status to the target area
										loadReferer.innerHTML = (loadStatus<0) ? 
																	'<dt class="selectContentProgress">Foutmelding: '+loadError+'%</dt>' : 
																	'<dt class="selectContentProgress">Bezig met inladen: '+Math.round(loadStatus*100)+'%</dt>';
																			}			this.insertNew		=	function(loadedXml, loadedReferer, loadedTxt){
										// make the content invisible
										classBehaviour.fader.setFade(loadedReferer, 0);										// replace the contents
										loadedReferer.innerHTML = loadedTxt.split('</root>')[0].split('<root>')[1]
										// apply their classbehaviours
										classBehaviour.parseDocument(loadedReferer);
										// reveal the contents
										classBehaviour.fader.fadeIn(loadedReferer.id, 10, 100);									}		}		// add this function to the classbehaviour object		classBehaviour.selectContent = new SelectContent;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.selectContent;
