/*
name			: Class Behaviour
update			: 20070705
author			: Maurice van Creij
dependencies		: lib_classbehaviour.js
info				: http://www.woollymittens.nl/content/details.asp?id=20040805133501
*/
	// MAIN
	// main class-behaviour object
	function ClassBehaviour(){
		/* properties */
			this.handlers			=	new Array();
		/* methods */
			// parse the document for classnames
			this.parseDocument		=	function(node){
											target = (node) ? node : document;
											// get all document nodes
											var allNodes = (target.all) ? target.all : target.getElementsByTagName("*");
											// for all tags
											for(var a=0; a<allNodes.length; a++){
												// if the item has a className
												if(allNodes[a].className){
													// get the classname
													nodeClass = allNodes[a].className;
													// for all behaviours
													for(var b=0; b<this.handlers.length; b++){
														// if the behaviour's name exists in the class name, apply it's events
														if(nodeClass.indexOf(this.handlers[b].name)>-1) this.handlers[b].start(allNodes[a]);
													}
												}
											}
										}
			// (cross)fader and pseudo event handler
			this.fader				=	new Fader;
			// helper functions
			this.utilities			=	new Utilities;
	}
	// create the main class-behaviour object
	var classBehaviour = new ClassBehaviour;
	
	// UTILITIES
		function Utilities(){
			this.screenHeight 		= 	function(){
											return (window.innerHeight) ? 
												window.innerHeight : (document.documentElement.clientHeight) ? 
																		document.documentElement.clientHeight : document.body.clientHeight ;
										}
			// return a parameter from the url's query strings
			this.getQueryParameter 	= 	function(paramName, defaultValue){
											// split the query string at the parameter name
											var queryParameters = document.location.search.split(paramName+"=");
											// split the parameter value from the rest of the string
											var queryParameter = (queryParameters.length>1) ? queryParameters[1].split("&")[0] : null ;
											// return the value
											return (queryParameter!=null) ? queryParameter : defaultValue ;
										}
			// returns a string of parameters found in the classname which can be [eval]uated
			this.getClassParameter	=	function(targetNode, paramName, defaultValue){
											// get the class parameter from the classname
											var classParameter = targetNode.className;
											// split the classname between the parameter name
											classParameter = classParameter.split(paramName + '_');
											// split the second piece between spaces and take the first part,  if there are two pieces
											classParameter = (classParameter.length>1) ? classParameter[1].split(' ')[0] : null ;
											// return the value
											return (classParameter!=null) ? classParameter : defaultValue ;
										}
			// get the previous node without worrying about text nodes
			this.nextNode			=	function(node){
											// look for the next html node
											do {
												node = node.nextSibling;
											} while(node.nodeName.indexOf('#text')>-1);
											// return it
											return node;
										}
			// get the next node without worrying about text nodes
			this.previousNode		=	function(node){
											// look for the previous html node
											do {
												node = node.previousSibling;
											} while(node.nodeName.indexOf('#text')>-1);
											// return it
											return node;
										}
			// returns the visible display state needed for this element
			this.getVisibleState	=	function(node){
											// what kind of node is this
											switch(node.nodeName.toLowerCase()){
												case 'table' : visibleState='table' ; break;
												case 'thead' : visibleState='table-header-group' ; break;
												case 'tfoot' : visibleState='table-footer-group' ; break;
												case 'tbody' : visibleState='table-row-group' ; break;
												case 'tr' : visibleState='table-row' ; break;
												case 'td' : visibleState='table-cell' ; break;
												case 'th' : visibleState='table-cell' ; break;
												default : visibleState='block';
											}
											// apply the state
											return (document.all && navigator.userAgent.indexOf('Opera')<0) ? 'block' : visibleState;
										}
		}
		
		function Fader(){
			/* properties */
			/* methods */
			this.getFade	=	function(node){
									var fadeValue = null;
									// get the fade value using the proper method
									if(typeof(node.style.MozOpacity)!='undefined')	fadeValue = Math.round(parseFloat(node.style.MozOpacity)*100);
									if(typeof(node.style.filter)!='undefined')		fadeValue = parseInt(node.filters.alpha.opacity);
									if(typeof(node.style.opacity)!='undefined')		fadeValue = Math.round(parseFloat(node.style.opacity)*100);
									// return the value
									return fadeValue;
								}
			this.setFade	=	function(node, amount){
									// set the fade value using the proper method
									if(typeof(node.style.MozOpacity)!='undefined')	node.style.MozOpacity = amount/100;
									if(typeof(node.style.filter)!='undefined')		node.style.filter = "alpha(opacity=" + amount + ")";
									if(typeof(node.style.opacity)!='undefined')		node.style.opacity = amount/100;
										/*
										filter:alpha(opacity=50);	imageobject.filters.alpha.opacity=opacity
										-moz-opacity: 0.5;			imageobject.style.MozOpacity=opacity/100
										opacity: 0.5;
										-khtml-opacity: 0.5;
										*/
								}
			this.fadeIn		=	function(idIn, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// get the fading object
									node = document.getElementById(idIn);
									// get the current fade
									fade = cf.getFade(node) + step;
									// if not 100%
									if((fade)<100){
										// set the new fade
										cf.setFade(node, fade);
										// next step
										cf.timeOut = setTimeout("classBehaviour.fader.fadeIn('"+idIn+"',"+step+","+delay+",'"+evalEvent+"')", delay);
									// else
									}else{
										// set the fade to 100%
										cf.setFade(node, 100);
										// trigger the end event
										eval(evalEvent);
									}
								}
			this.fadeOut	=	function(idOut, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// get the fading object
									node = document.getElementById(idOut);
									// get the current fade
									fade = cf.getFade(node) - step;
									// if not 100%
									if(fade>0){
										// set the new fade
										cf.setFade(node, fade);
										// next step
										cf.timeOut = setTimeout("classBehaviour.fader.fadeOut('"+idOut+"',"+step+","+delay+",'"+evalEvent+"')", delay);
									// else
									}else{
										// set the fade to 100%
										cf.setFade(node, 0);
										// trigger the end event
										eval(evalEvent);
									}
								}
			this.crossFade	=	function(idIn, idOut, amount, step, delay, evalEvent){
									var cf = classBehaviour.fader;
									// if the amount is not the end value yet
									if(amount<=100){
										// set the fade amounts
										if(idIn && idIn!=""){
											// unhide the new page
											document.getElementById(idIn).style.display = 'block';
											// set the fade amount
											cf.setFade(document.getElementById(idIn), amount);
										}
										if(idOut && idOut!=""){
											// unhide the new page
											document.getElementById(idOut).style.display = 'block';
											// set the fade amount
											cf.setFade(document.getElementById(idOut), 100-amount);
										}
										// construct the fade function
										var evalLoop = "classBehaviour.fader.crossFade('"+idIn+"', '"+idOut+"', "+(amount+step)+", "+step+", "+delay+", '"+evalEvent+"')";
										// repeat the fade
										setTimeout(evalLoop, delay);
									}else{
									// else
										// cancel the opacity style
										if(idIn && idIn!=""){
											var node = document.getElementById(idIn);
											if(typeof(node.style.MozOpacity)!='undefined')	node.style.MozOpacity = 'auto';
											if(typeof(node.style.filter)!='undefined')		node.style.filter = 'none';
											if(typeof(node.style.opacity)!='undefined')		node.style.opacity = 'auto';
										}
										// hide the old page
										if(idOut && idOut!="") document.getElementById(idOut).style.display = 'none';
										// trigger the end event
										cf.onEnd(evalEvent);
									}
								}
			/* events */
			this.onEnd		=	function(evalEvent){
									eval(evalEvent);
								}
		}
		
	// BEHAVIOURS
	// replace in class
		// define this class behaviour
		function ClassMouseHover(){
			/* properties */
			this.name 		= 	'classMouseHover';
			/* methods */
			this.start		=	function(node){
									node.onmouseover = this.addHover;
									node.onmouseout = this.remHover;
								}
			this.hasNoStateClass 	= 	function(objNode){
											return (objNode.className.indexOf('link')<0 && objNode.className.indexOf('hover')<0 && objNode.className.indexOf('active')<0);
										}
			/* events */
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace link by hover
									objNode.className = (cmh.hasNoStateClass(objNode)) ? 'hover ' + objNode.className : objNode.className.replace('link','hover') ;
									// 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;

	// replace in src sub-string
		// define this class behaviour
		function SrcMouseHover(){
			/* properties */
			this.name 			= 	'srcMouseHover';
			this.cache 			= new Array();
			/* methods */
			this.start			=	function(node){
										this.cacheImages(node);
										node.onmouseover = this.addHover;
										node.onmouseout = this.remHover;
									}
			this.cacheImages	 = 	function(that) {
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if this is not the image, it must be the parent
										if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
										// replace link by hover
										var cacheIdx = this.cache.length;
										// hover version
										this.cache[cacheIdx] = new Image();
										this.cache[cacheIdx].src = objNode.src.replace('_link','_hover');
										// active version
										this.cache[cacheIdx+1] = new Image();
										this.cache[cacheIdx+1].src = objNode.src.replace('_link','_active');
									}
			/* events */
			this.addActive 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(objNode.nodeName!='IMG') objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by active
									objNode.src = objNode.src.replace('_link','_active');
									// replace hover by active
									objNode.src = objNode.src.replace('_hover','_active');
								}
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by hover
									objNode.src = objNode.src.replace('_link','_hover');
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// if this is not the image, it must be the parent
									if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
									// replace link by hover
									objNode.src = objNode.src.replace('_hover','_link');
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.srcMouseHover = new SrcMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.srcMouseHover;
		
	// replace in src sub-string
		// define this class behaviour
		function FadeMouseHover(){
			/* properties */
			this.name 			= 'fadeMouseHover';
			this.cache 			= new Array();
			this.count			= 0;
			this.timeOut		= null;
			/* methods */
			this.start			=	function(node){
										this.cacheImages(node);
										// node.onload = this.setUpFader;
										this.setUpFader(node);
									}
			this.setUpFader		=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var fmh = classBehaviour.fadeMouseHover;
										// give this image an id, if it doesn't have one
										if(!objNode.id) objNode.id = 'fadingImage' + fmh.count;
										fmh.count += 1;
										// set the active version of the image source as a background-image of the container
										objNode.parentNode.style.backgroundImage = 'url(' + objNode.src.replace('_link','_hover') + ')';
										// set the image as a block element
										objNode.parentNode.style.display = 'block';
										objNode.parentNode.style.width = objNode.width + 'px';
										objNode.parentNode.style.height = objNode.height + 'px';
										// set the default fade
										classBehaviour.fader.setFade(objNode, 100);
										// set up the events
										objNode.onmouseover = fmh.addHover;
										objNode.onmouseout = fmh.remHover;
									}
			this.cacheImages	 = 	function(that) {
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// if this is not the image, it must be the parent
										if(!objNode.src) objNode = objNode.getElementsByTagName('IMG')[0];
										// replace link by hover
										var cacheIdx = this.cache.length;
										// hover version
										this.cache[cacheIdx] = new Image();
										this.cache[cacheIdx].src = objNode.src.replace('_link','_hover');
									}
			/* events */
			this.addHover 	= 	function(that, id){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fmh = classBehaviour.fadeMouseHover;
									// if an id is passed. It overrides the event node
									if(id) objNode = document.getElementById(id);
									// if there's no fade active at the moment // fade out the image
									if(classBehaviour.fader.getFade(objNode)%100==0){
										classBehaviour.fader.fadeOut(objNode.id, 20, 50, '');
									// else try again in a bit
									}else{
										// fmh.timeOut = setTimeout("classBehaviour.fadeMouseHover.addHover(null, '" + objNode.id + "')",50);
									}
								}
			this.remHover 	= 	function(that, id){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fmh = classBehaviour.fadeMouseHover;
									// if an id is passed. It overrides the event node
									if(id) objNode = document.getElementById(id);
									// if there's no fade active at the moment // fade in the image
									if(classBehaviour.fader.getFade(objNode)%100==0){
										classBehaviour.fader.fadeIn(objNode.id, 20, 50, '');
									// else try again in a bit
									}else{
										fmh.timeOut = setTimeout("classBehaviour.fadeMouseHover.remHover(null, '" + objNode.id + "')",50);
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fadeMouseHover = new FadeMouseHover;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fadeMouseHover;
		
	// hides nodes
		// hide the "hideThisNode" class behaviour by default 
		document.writeln("<style>.hideThisNode{overflow:hidden; visibility:hidden; height:1px;}</style>");
		// define this class behaviour
		function HideThisNode(){
			/* properties */
			this.name 		= 	'hideThisNode';
			/* methods */
			this.start		=	function(node){
									node.style.overflow = 'hidden';
									node.style.visibility = 'hidden';
									node.style.height = '1px';
								}
		}
		// 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';
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.showThisNode = new ShowThisNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.showThisNode;
		
	// show or hide a node
		// define this class behaviour
		document.writeln("<style>.toggleNextNode{cursor:pointer;}</style>");
		function ToggleNextNode(){
			/* properties */
			this.name 		= 	'toggleNextNode';
			this.nodes		=	new Array();
			this.step		=	30;
			this.delay		=	10;
			this.index		=	0;
			/* methods */
			this.start		=	function(node){
									// set the event handlers for the source node
									node.onclick = this.toggle;
									// add this node to the node list
									this.nodes[this.nodes.length] = node;
									// give this node an id if it doesn't have one yet
									node.id = (node.id) ? node.id : this.name + this.nodes.length ;
									// is this node marked as "auto", order it to open on a timeout
									autoDelay = classBehaviour.utilities.getClassParameter(node, 'auto', null);
									if(autoDelay){
										this.index++
										node.id = (node.id) ? node.id : this.name + this.index ;
										setTimeout('classBehaviour.toggleNextNode.toggle(document.getElementById("'+node.id+'"))', autoDelay);
									}
								}
			this.shrink	=	function(label, container, finished){
									var t2n = classBehaviour.toggleNextNode;
									// deactivate the label
									label.className = label.className.replace('active','link');
									label.parentNode.className = label.parentNode.className.replace('active','link');
									// if the container isn't shrunk completely
									if(container.offsetHeight>t2n.step){
										// height before
										heightBefore = container.style.height;
										// reduce its height by an amount
										container.style.overflow = 'hidden';
										container.style.visibility = 'visible';
										container.style.height = (container.offsetHeight - t2n.step) + 'px';
										// height after
										heightAfter = container.style.height;
										// the resizing isnt' working
										if(heightBefore==heightAfter){
											// skip straight to the end situation
											container.style.overflow = 'hidden';
											container.style.visibility = 'hidden';
											container.style.height = '1px';
											container.className = container.className.replace('showThisNode','hideThisNode');
										// else
										}else{
											// mark the function as unfinished
											finished = false;
										}
									}else{
										// close the container
										container.style.overflow = 'hidden';
										container.style.visibility = 'hidden';
										container.style.height = '1px';
										container.className = container.className.replace('showThisNode','hideThisNode');
									}
									// return the state
									return finished;
								}
			this.grow		=	function(label, container, finished){
									var t2n = classBehaviour.toggleNextNode;
									// 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(targetContainer.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
										if(heightBefore==heightAfter){
											// skip straight to the end situation
											container.style.overflow = 'visible';
											container.style.visibility = 'visible';
											container.style.height = 'auto';
											container.className = container.className.replace('hideThisNode','showThisNode');
										// else
										}else{
											// mark the function as unfinished
											finished = false;
										}
									}else{
										// open the container
										container.style.overflow = 'visible';
										container.style.visibility = 'visible';
										container.style.height = 'auto';
										container.className = container.className.replace('hideThisNode','showThisNode');
									}
									// return the state
									return finished;
								}
			/* events */
			this.toggle = 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var t2n = classBehaviour.toggleNextNode;
									// get all information on this node
									targetLabel = objNode;
									targetContainerId = classBehaviour.utilities.getClassParameter(targetLabel, 'id', null);
									targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : classBehaviour.utilities.nextNode(targetLabel) ;
									targetGrows = (targetContainer.className.indexOf('hideThisNode')>-1);
									// call for the node to update
									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);
									targetContainer = (targetContainerId) ? document.getElementById(targetContainerId) : classBehaviour.utilities.nextNode(targetLabel) ;
									targetFamily = classBehaviour.utilities.getClassParameter(targetLabel, 'family', null);
									// for every node in the node-list
									for(var a=0; a<t2n.nodes.length; a++){
										// get its family
										peerLabel = t2n.nodes[a];
										peerContainerId = classBehaviour.utilities.getClassParameter(peerLabel, 'id', null);
										peerContainer = (peerContainerId) ? document.getElementById(peerContainerId) : classBehaviour.utilities.nextNode(peerLabel) ;
										peerFamily = classBehaviour.utilities.getClassParameter(peerLabel, 'family', null);
										// if this node belongs to the same family and is open but has a different id
										if(peerFamily==targetFamily && peerFamily!=null && peerContainer.className.indexOf('hideThisNode')<0 && 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;
		
	// Toggle by proxy
		// define this class behaviour
		function ToggleByProxy(){
			/* properties */
			this.name 		= 	'toggleByProxy';
			/* methods */
			this.start		=	function(node){
									node.onclick = this.clicked;
								}
			this.clicked	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// what id are we refering to
									targetLabelId = classBehaviour.utilities.getClassParameter(objNode, 'id', null);
									targetLabel = document.getElementById(targetLabelId);
									// toggle the label
									classBehaviour.toggleNextNode.toggle(targetLabel);
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.toggleByProxy = new ToggleByProxy;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleByProxy;
		
	// tabbed content
		// define this class behaviour
		function TabbedContent(){
			/* properties */
			this.name 		= 	'tabbedContent';
			/* methods */
			this.start		=	function(node){
									// get all tabs
									allTabs = node.getElementsByTagName('a');
									// store the most likely opened tab
									openedTab = allTabs[0];
									// for all tabs
									for(var a=0; a<allTabs.length; a++){
										// get the id this tab refers to
										tabId = allTabs[a].href.split('#')[1];
										// apply onclick events to the referred tab
										allTabs[a].onclick = this.open;
										// apply the starting state of the tab if needed
										if(allTabs[a].className.indexOf('closedTab')<0 && allTabs[a].className.indexOf('openedTab')<0) allTabs[a].className += ' closedTab';
										// apply the starting state of the referred content if needed
										document.getElementById(tabId).style.display = 'none';
										// if this tab is referred to in the page url, remember it as active
										if(document.location.href.indexOf(allTabs[a].href)>-1) openedTab = allTabs[a];
										// if this tab was manualy set
										if(allTabs[a].className.indexOf('openedTab')>-1) openedTab = allTabs[a];
									}
									// if there is a pager
									pager = document.getElementById(classBehaviour.utilities.getClassParameter(node, 'pagerId', 'none'));
									if(pager){
										// assign the events for the buttons
										pager.getElementsByTagName('a')[0].onclick = this.previous;
										pager.getElementsByTagName('a')[1].onclick = this.next;
									}
									// open the most likely first tab
									this.open(openedTab, true);
								}
			/* events */
			this.next		=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var tbd = classBehaviour.tabbedContent;
									// get the pager information
									pagerInfo = objNode.parentNode.parentNode.getElementsByTagName('span')[0].firstChild.nodeValue;
									// what is the current pagenumber
									currentPage = parseInt(pagerInfo.split('/')[0]);
									// how many pages are there
									totalPages = parseInt(pagerInfo.split('/')[1]);
									// what is the next page
									nextPage = (currentPage<totalPages) ? currentPage + 1 : 1 ;
									// what is the tabs strip
									tabStrip = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'tabsId', 'none'));
									if(tabStrip){
										// get the relevant page from the tab strip
										targetTab = tabStrip.getElementsByTagName('a')[nextPage-1];
										// activate it's click
										tbd.open(targetTab);
									}
								}
			this.previous	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var tbd = classBehaviour.tabbedContent;
									// get the pager information
									pagerInfo = objNode.parentNode.parentNode.getElementsByTagName('span')[0].firstChild.nodeValue;
									// what is the current pagenumber
									currentPage = parseInt(pagerInfo.split('/')[0]);
									// how many pages are there
									totalPages = parseInt(pagerInfo.split('/')[1]);
									// what is the next page
									previousPage = (currentPage>1) ? currentPage - 1 : totalPages ;
									// what is the tabs strip
									tabStrip = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'tabsId', 'none'));
									if(tabStrip){
										// get the relevant page from the tab strip
										targetTab = tabStrip.getElementsByTagName('a')[previousPage-1];
										// activate it's click
										tbd.open(targetTab);
									}
								}
			this.open		=	function(that, noAnimation){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var tbd = classBehaviour.tabbedContent;								
			
									// INDEX THE TAB STATES
									// get all tabs
									var allTabs = objNode.parentNode.parentNode.getElementsByTagName('a');
									var prevTab = null;
									var pageNumber = 0;
									// find the current tab
									for(var a=0; a<allTabs.length; a++){
										// rememeber the previous tab
										if(allTabs[a].className.indexOf('openedTab')>-1) prevTab = allTabs[a];
										// count the new pagenumber
										if(allTabs[a]==objNode) pageNumber = a;
									}

									// if this is the current tab again
									if(prevTab!=objNode || noAnimation){
									
										// PREVIOUS TAB
										if(prevTab){
											// mark the previous tab as passive
											prevTab.className = prevTab.className.replace('openedTab', 'closedTab');
											// if the tab has an image
											tabImages = prevTab.getElementsByTagName('img');
											if(tabImages.length>0) tabImages[0].src = tabImages[0].src.replace('_active','_link');
											// id the previous tabbed content
											prevContentId = prevTab.href.split('#')[1];
										}
										
										// NEXT TAB
										// mark the next tab as active
										objNode.className = objNode.className.replace('closedTab', 'openedTab');
										// if the tab has an image
										tabImages = objNode.getElementsByTagName('img');
										if(tabImages.length>0) tabImages[0].src = tabImages[0].src.replace('_link','_active').replace('_hover','_active');
										// id the next tabbed content
										nextContentId = objNode.href.split('#')[1];
										
										// FADE ANIMATION
										isAnimated = (noAnimation) ? 'no' : classBehaviour.utilities.getClassParameter(objNode, 'animated', 'yes') ;
										if(isAnimated=='yes'){
											// make the previous tab float
											document.getElementById(prevContentId).style.position = 'absolute';
											document.getElementById(prevContentId).style.top = '0px';
											// make the next tab no float
											document.getElementById(nextContentId).style.position = 'relative';
											// order the animation
											classBehaviour.fader.crossFade(nextContentId, prevContentId, 0, 20, 50, null);
										}else{
											if(prevTab) document.getElementById(prevContentId).style.display = 'none';
											document.getElementById(nextContentId).style.display = 'block';
										}
										
										// PAGE NUMBER
										// update page-numbering
										pager = document.getElementById(classBehaviour.utilities.getClassParameter(objNode.parentNode.parentNode, 'pagerId', 'none'));
										if(pager){
											pager.getElementsByTagName('span')[0].firstChild.nodeValue = (pageNumber+1) + '/' + allTabs.length ;
										}
										
									}
									// cancel the jump to the anchor
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.tabbedContent = new TabbedContent;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.tabbedContent;
				
	// Open an overlay as a popup window
		// define this class behaviour
		function OpenLayerPopUp(){
			/* properties */
			this.name 		= 	'openLayerPopUp';
			this.step		=	10;
			this.begin		=	0;
			this.end		=	50;
			/* methods */
			this.start		=	function(node){
									// find the target layer
									targetPopUp = null;
									// process the node
									this.process(node);
									// the node's open button
									node.onclick = this.show;
									// open the popup immediately if required
									if(classBehaviour.utilities.getClassParameter(node, 'auto', 'no')=='yes') this.show(node);
								}
			this.fadeIn	=	function(id, amount){
	
									var olp = classBehaviour.openLayerPopUp;
									node = document.getElementById(id);
									nodes = node.getElementsByTagName('div');
									nodeShadow = nodes[0];
									nodeContent = nodes[1];
									
									
									// if the amount is not 50
									if(amount<olp.end){
										// hide the popup content
										nodeContent.style.visibility = 'hidden';
										// set the shadow's fade to the next step
										nodeShadow.style.display = 'block';
										
										if(typeof(nodeShadow.style.MozOpacity)!='undefined')	nodeShadow.style.MozOpacity = amount/100;
										if(typeof(nodeShadow.style.filter)!='undefined')		nodeShadow.style.filter = "alpha(opacity=" + amount + ")";
										if(typeof(nodeShadow.style.opacity)!='undefined')		nodeShadow.style.opacity = amount/100;
										// show the popup collection
										node.style.display = 'block';
										// repeat the fade
										setTimeout("classBehaviour.openLayerPopUp.fadeIn('" + id + "'," + (amount+olp.step) + ")",10);
									}else{
										// show the popup content
										nodeContent.style.visibility = 'visible';
										//  Add to fix the flash button problem
										nodeContent.style.zIndex = 10001;
										nodeShadow.style.zIndex = 9999;
									}
								}
			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.process	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// prepare the popup's layout
								}
			this.show		=	function(that, id){
									
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var olp = classBehaviour.openLayerPopUp;
									var submit = false;
									// adjust the fade parameters if it needs to open instantly
									olp.step = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'step', 10));
									olp.begin = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'begin', 0));
									olp.end = parseInt(classBehaviour.utilities.getClassParameter(objNode, 'end', 50));
									// is this a link with an href
									popUpId = (id) ? id : classBehaviour.utilities.getClassParameter(objNode, 'id', 'popup0') ;
									// get the popup object
									popUp = (popUpId) ? document.getElementById(popUpId) : objNode;
									// position the popup
										// the dimensions can not be measured with "display:none;"
										popUp.style.visibility = 'hidden';
										popUp.style.display = 'block';
										// get the content segment
										popupContent = popUp.getElementsByTagName('DIV')[2];
										// how high is the content
										popupHeight = popupContent.offsetHeight;
										// how high is the screen
										screenHeight = popupContent.parentNode.offsetHeight;
										// center the popup
										popupContent.style.marginTop = Math.round((screenHeight-popupHeight)/2) + 'px' ;
										// the dimensions can not be measured with "display:none;"
										popUp.style.visibility = 'visible';
										popUp.style.display = 'block';
									// if there is an iframe in the popup load the url into it
									popUpIframes = popUp.getElementsByTagName('iframe');
									popUpTitles = popUp.getElementsByTagName('h1');
									if(popUpIframes.length>0){
										// is an href supplied
										if(objNode.href){
											// if the link had a title and if the popup has a title. put the link title in the popup
											if(objNode.title && popUpTitles.length>0) popUpTitles[0].innerHTML = objNode.title;
											// load the href in the iframe
											popUpIframes[0].src = objNode.href;
										// is this a form submit
										}else if(objNode.nodeName=="BUTTON" || objNode.nodeName=="INPUT"){
											// find the form this button belongs to
											formNode = objNode.parentNode;
											while(formNode.nodeName!='FORM') formNode = formNode.parentNode;
											// change the form to submit to the iframe
											formNode.target = popUpIframes[0].id;
											// then change it back for the other sumbit buttons
											setTimeout("document.getElementById('"+formNode.id+"').target='_self';",512);
											// allow the function to submit
											submit = true;
										}
									}
									// find the close gadget
									popUpCloser = popUp.getElementsByTagName('a')[0];
									popUpCloser.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(popUp.className.indexOf('fullHeightPopUp')<0){
											// reset the scroll position
											document.documentElement.scrollLeft = 0;
											document.documentElement.scrollTop = 0;
											// hide the scrollbars if needed
											document.body.parentNode.style.overflow = "hidden";
											// reposition the popup according to the scroll position
											popUp.getElementsByTagName('DIV')[2].style.marginTop = Math.round(document.documentElement.scrollTop + (screenHeight-popupHeight)/2) + 'px' ;
										}
										// size the shadow under the popup
										popUp.getElementsByTagName('DIV')[0].style.height = document.body.offsetHeight + 'px';
										// hide the selects
										allSelects = document.getElementsByTagName('select');
										for(var a=0; a<allSelects.length; a++) allSelects[a].style.visibility = 'hidden';
									}
									// fade the popup in
									olp.fadeIn(popUp.id, olp.begin);
									// mark the body with a class
									document.body.className += " hasLayerPopUp";
									// cancel the click
									return submit;
								}
			this.hide		=	function(that, id){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var olp = classBehaviour.openLayerPopUp;
									// the popup object
									if (id)
									{
									    popUp = document.getElementById(id);
									    }
									else
									{
									    popUp = objNode.parentNode.parentNode.parentNode;
									    }
									// fade the popup out
									olp.fadeOut(popUp.id, 50);
									// restore the scroll bars
									if(navigator.appVersion.indexOf('MSIE 6')>-1 || navigator.appVersion.indexOf('MSIE 5')>-1){
										// show the scrollbars
										if(popUp.className.indexOf('fullHeightPopUp')<0) document.body.parentNode.style.overflow = "auto";
										// show the selects
										allSelects = document.getElementsByTagName('select');
										for(var a=0; a<allSelects.length; a++) allSelects[a].style.visibility = 'visible';
									}
									// unmark the body class
									document.body.className = document.body.className.replace(" hasLayerPopUp", "");
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.openLayerPopUp = new OpenLayerPopUp;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openLayerPopUp;
		
	// Use SwfObject to replace a title with a flash version
		// hide the alternative beforehand
		document.writeln("<style>.flashTitle .alternative{visibility : hidden;}</style>");
		// define this class behaviour
		function FlashTitle(){
			/* properties */
			this.name 		= 	'flashTitle';
			this.index		=	0;
			/* methods */
			this.start		=	function(node){
									// give the node an id of it doesn't have one
									if(!node.id){
										node.id = 'flashTitle' + this.index;
										this.index += 1;
									}
									// load the flash
									this.process(node);
								}
			this.process	=	function(node){
									// set the default values for all parameters
									flashMovie		= "../flash/title.swf";
									flashWidth		= node.offsetWidth;
									flashHeight		= node.offsetHeight;
									flashVersion	= "7";
									flashBuild		= "0";
									flashWmode		= "Transparent";
									flashScale		= "noScale";
									flashSalign		= "l";
									flashName		= "_" + node.id;
									flashVariables	= "lorem=ipsum&dolor=sit amet";
									// 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].className){
											case 'movie' 			: flashMovie = allInputs[a].value; break;
											case 'width' 			: flashWidth = allInputs[a].value; break;
											case 'height' 			: flashHeight = allInputs[a].value; break;
											case 'majorversion' 	: flashVersion = allInputs[a].value; break;
											case 'build' 			: flashBuild = 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;
									// get the alternative to the flash content and filter a title from it
									flashVariables = "inputText=" + escape(node.innerHTML.replace(/<(.|\n)*?>/gi,"").replace(/^\s+/gi,"").replace(/&amp;/gi,"&")) + "&" + flashVariables;
									// load the flash plugin
									if(UFO){
										// load the flash plugin using: Unobtrusive Flash Objects (UFO) v3.22
										var FO = { 
											movie			: flashMovie,
											width			: flashWidth, 
											height			: flashHeight,
											majorversion	: flashVersion, 
											build			: flashBuild, 
											wmode			: flashWmode,
											scale			: flashScale,
											salign			: flashSalign,
											id				: flashName,
											name			: flashName,
											flashvars		: flashVariables
										}
										UFO.create(FO, node.id);
									}else if(AC_FL_RunContent){
										// load the flash plugin using: AC_RunActiveContent.js - Flash Player Version Detection - v1.7
										pluginHtml = 	AC_FL_RunContent(
															'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0',
															'width', flashWidth,
															'height', flashHeight,
															'src', flashMovie,
															'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
															'scale', flashScale,
															'wmode', flashWmode,
															'id', flashName,
															'name', flashName,
															'movie', 'title',
															'salign', flashSalign,
															'flashvars', flashVariables
														);
										node.innerHTML = pluginHtml;
									}
									// make the alternative content visible, just in case it didn't work
									setTimeout('classBehaviour.flashTitle.showAlternative("' + node.id + '")', 1000);
								}
			/* events */
			this.showAlternative	=	function(id){
											if (document.getElementById(id) != null)
											{
												allDivs = document.getElementById(id).getElementsByTagName('div');
												if(allDivs.length>0) if(allDivs[0].className.indexOf('alternative')>-1) allDivs[0].style.visibility = 'visible';
											}
										}
		}
		// add this function to the classbehaviour object
		classBehaviour.flashTitle = new FlashTitle;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.flashTitle;
		
	// Make fading menu
		// define this class behaviour
		function FadingMenu(){
			/* properties */
			this.name 		= 	'fadingMenu';
			this.current 	=	null;
			this.always		=	null;
			this.locked		=	false;
			this.timeout	=	null;
			this.index		=	0;
			/* methods */
			this.start		=	function(node){
									this.process(node);
								}
			this.process 	= 	function(objNode){
									var objNodes, objMatch;
									// apply events to all LIs
									objNodes = objNode.childNodes;
									for(var a=0; a<objNodes.length; a++){
										if(objNodes[a].nodeName=="LI"){
											// if this LI has a link and submenus evident by their links
											objLinks = objNodes[a].getElementsByTagName('A');
											if(objLinks.length>0){
												// default classname
												objLinks[0].className += (objLinks[0].className.indexOf('link')<0 || objLinks[0].className.indexOf('active')<0) ? ' link' : '' ;
												// mouseover events
												objLinks[0].onmousemove	= this.open;
												// store the last link marked active
				//								this.always = (objLinks[0].className.indexOf('active')>-1) ? objLinks[0] : this.always ;
											}
											// if this LI has a child UL, 
											objLists = objNodes[a].getElementsByTagName('UL');
											if(objLists.length>0){
												// give it a random id
												this.index++;
												objLists[0].id = 'sub_' + this.index;
												// delay the closing of the menu when over subitems
												objLinks = objLists[0].getElementsByTagName('A');
												for(var b=0; b<objLinks.length; b++) objLinks[b].onmouseover = this.cancel;
											}
										}
									}
									// global close event
									objNode.onmouseout	= this.delay;
									// open the starting node
									this.open(this.always, true);
								}
			/* events */
			this.open 		= 	function(that, noFade){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var fm = classBehaviour.fadingMenu;
									// cancel the closing timer
									clearTimeout(fm.timeout);
									// if not locked
									if(!fm.locked && objNode!=fm.current){
										// PREVIOUS MENU
										if(fm.current){
											// deactivate the link
// TODO: stylesheet link
											fm.current.className = fm.current.className.replace('hover','link');
											// deactivate the image
				//							linkImage = fm.current.getElementsByTagName('IMG')[0];
				//							linkImage.src = linkImage.src.replace('_hover','_link');
											// store the sub-menu
											linkMenu = fm.current.parentNode.getElementsByTagName('UL');
											fadeCloseId = (linkMenu.length>0) ? linkMenu[0].id : '' ;
										}else{
											fadeCloseId = '';
										}
										// OPEN NEW MENU
										if(objNode){
											// deactivate the link
// TODO: stylesheet link
											objNode.className = objNode.className.replace('link','hover');
											// activate the image
				//							linkImage = objNode.getElementsByTagName('IMG')[0];
				//							linkImage.src = linkImage.src.replace('_link','_hover');
											// store the sub-menu
											linkMenu = objNode.parentNode.getElementsByTagName('UL');
											fadeOpenId = (linkMenu.length>0) ? linkMenu[0].id : '' ;
										}
										// store the current link 
										fm.current = objNode;
										// SET THE FADE
										if(noFade || document.all){
											if(fadeOpenId!='') document.getElementById(fadeOpenId).style.display = 'block';
											if(fadeCloseId!='') document.getElementById(fadeCloseId).style.display = 'none';
										}else{
											fm.locked = true;
											classBehaviour.fader.crossFade(fadeOpenId, fadeCloseId, 0, 20, 20, 'classBehaviour.fadingMenu.locked=false;');
										}
									}
								}
			this.cancel	=	function(){
									var fm = classBehaviour.fadingMenu;
									// clear the previous delay
									clearTimeout(fm.timeout);
								}
			this.delay		=	function(){
									var fm = classBehaviour.fadingMenu;
									// clear the previous delay
									clearTimeout(fm.timeout);
									// delay the closing
									fm.timeout = setTimeout('classBehaviour.fadingMenu.close()', 512);
								}
			this.close 		= 	function(){
									var fm = classBehaviour.fadingMenu;
									// if not locked
									if(!fm.locked){
										fm.open(fm.always);
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.fadingMenu = new FadingMenu;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.fadingMenu;
		
	// 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;
		
	// Construct an empty stylesheet based on the hierarchy of tags
		//document.writeln('<button class="makeStylesheet" style="position : absolute; left : 0px; top : 0px; z-index : 10000;">Click to create stylesheet.</button>');
		// define this class behaviour
		function MakeStylesheet(){
			/* properties */
			this.name 				=	'makeStylesheet';
			this.styleSheet			= 	"/* " + document.location.href.split('/')[document.location.href.split('/').length-1] + " */\n";
			this.referenceCss		=	"";
			this.rootObject			= 	document.body;
			/* methods */
			this.start				=	function(node){
											// make a reference stylesheet from the current stylesheets
											this.makeReferenceCss();
											// set the click event of the button
											node.onclick = this.showNodeClasses;
											/*
											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++)
												for(var b=0; b<document.styleSheets[a].cssRules.length; b++)
													this.referenceCss += document.styleSheets[a].cssRules[b].selectorText + ' {}\n\t';
										}
			this.isFormElement		=	function(node){
											return (('INPUT,SELECT,TEXTAREA,BUTTON').indexOf(node.nodeName)>-1);
										}
			this.isClassBehaviour	=	function(newEntry){
											foundHandler = false;
											// for all behaviours, if the behaviour's name exists in the class name, apply it's events
											for(var b=0; b<classBehaviour.handlers.length; b++)
												foundHandler = (newEntry.indexOf(classBehaviour.handlers[b].name)>-1) ? true : foundHandler;
											// report back
											return foundHandler;
										}
			this.isInStylesheet		=	function(newEntry){
											foundStyle = false;
											// clean the new entry
											newEntry = newEntry.replace(/\t/gi,'').replace(' {}\n','').replace(',','');
											// if the style allready exists in this constructed stylesheet
											foundStyle = (this.styleSheet.indexOf(newEntry)>-1);
											// if the style allready exists in any rule in another stylesheet
											foundStyle = (this.referenceCss.indexOf(newEntry)>-1) ? true : foundStyle ;
											// report back
											return foundStyle;
										}
			this.getNodeClasses		=	function(objNode, intRecursion, prefix){
											var strTabs = '';
											var idPrefix, classPrefix, tagPrefix, addPrefix;
											var newEntry = '';
											// for every recursion add one tab
											for(var intB=0; intB<intRecursion; intB++) strTabs += '\t';
											// get the child nodes
											var objChildNodes = objNode.childNodes;
											// for every childnode
											for(var intA=0; intA<objChildNodes.length; intA++){
												// reset prefixes
												idPrefix = '';
												classPrefix = '';
												tagPrefix = '';
												addPrefix = '';
												// if it has an id, but is not a form element
												if(typeof(objChildNodes[intA].id)!='undefined' && !this.isFormElement(objChildNodes[intA])){
													if(objChildNodes[intA].id!=''){
														// add class to stylesheet prototype
														newEntry = strTabs + '#' + objChildNodes[intA].id + ' {}\n';
															// strStyleSheet += strTabs + prefix + '#' + objChildNodes[intA].id + ' {}\n'
														// add this style only if there's not double
														if(!this.isInStylesheet(newEntry)) this.styleSheet += newEntry;
														// update the prefix
														idPrefix = '#' + objChildNodes[intA].id;
													}
												}
												// if it has a className
												if(typeof(objChildNodes[intA].className)!='undefined'){
													if(objChildNodes[intA].className!=''){
														// split the classnames
														allClasses = objChildNodes[intA].className.split(' ');
														// for all classes
														for(var b=allClasses.length-1; b>=0; b--){
															// add class to stylesheet prototype
															newEntry = strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ' {}\n';
															// add this style only if there's not double
															if(!this.isInStylesheet(newEntry) && !this.isClassBehaviour(newEntry)){
																// update the prefix
																this.styleSheet += newEntry;
																// if the last entry was a link
																if(objChildNodes[intA].nodeName=='A'){
																	// repeat it four times with the mouseover states
																	this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ':link,\n';
																	this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ':visited {}\n';
																	this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ':hover,\n';
																	this.styleSheet += '\t' + strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b] + ':active {}\n';
																	// and jump further in
																	intRecursion += 1;
																}
															}
															// update the prefix
															classPrefix = objChildNodes[intA].nodeName.toLowerCase() + '.' + allClasses[b];
														}
													}
												}
												// if it has neither
												if(
													objChildNodes[intA].className=='' && 
													(objChildNodes[intA].id=='' || this.isFormElement(objChildNodes[intA])) && 
													objChildNodes[intA].nodeName.indexOf('text')<0 && 
													objChildNodes[intA].nodeName.indexOf('comment')<0
												){
													// add class to stylesheet prototype
													newEntry = strTabs + prefix + objChildNodes[intA].nodeName.toLowerCase() + ' {}\n';
													// add this style only if there's not double
													if(!this.isInStylesheet(newEntry)){
														this.styleSheet += newEntry;
														// if the last entry was a link
														if(newEntry.indexOf(' a {}')>-1){
															// repeat it four times with the mouseover states
															this.styleSheet += '\t' + newEntry.replace('a {}','a:link,');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:visited {}');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:hover,');
															this.styleSheet += '\t' + newEntry.replace('a {}','a:active {}');
															// and jump further in
															intRecursion += 1;
														}
													}
													// update the prefix
													tagPrefix = objChildNodes[intA].nodeName.toLowerCase();
												}
												// if it has childNodes
												if(objChildNodes[intA].childNodes.length>0){
													// update the prefix
													if(idPrefix){
														addPrefix = idPrefix + ' ';
													}else if(classPrefix){
														addPrefix = prefix + classPrefix + ' ';
													}else if(tagPrefix){
														addPrefix = prefix + tagPrefix + ' ';
													}
													// recurse
													this.getNodeClasses(objChildNodes[intA], intRecursion+1, addPrefix);
												}
											}
										}
			this.showNodeClasses	=	function(){
											var mss = classBehaviour.makeStylesheet;
											document.body.style.textAlign = 'left';
											document.body.style.background = '#ffffff none';
											document.body.style.color = '#000000';
											document.body.style.fontFamily = 'Sans Serif';
											document.body.style.fontSize = '12pt';
											mss.getNodeClasses(mss.rootObject, 0 , '');
											document.body.innerHTML = '<pre>' + mss.styleSheet + '</pre>';
										}
		}
		// add this function to the classbehaviour object
		classBehaviour.makeStylesheet = new MakeStylesheet;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.makeStylesheet;
		
	// Open print dialog
		// define this class behaviour
		function NumbersOnly(){
			/* properties */
			this.name 			= 	'numbersOnly';
			/* methods */
			this.start			=	function(node){
										node.onkeydown = this.keyPressed;
										node.onkeyup = this.fieldChanged;
										node.onchange = this.fieldChanged;
										// store the previous value
										node.className += " previous_" + node.value;
									}
			/* events */
			this.keyPressed		=	function(e){
										ascVal = (document.all) ? event.keyCode : e.which ;
										keyVal = String.fromCharCode(ascVal).toLowerCase();
										// numbers top keyboard
										if ( ascVal > 47 && ascVal < 58)
										    return true;
										// numbers numpad
										if ( ascVal > 95 && ascVal < 106)
										    return true;
										// arrow keys
										if (ascVal > 36 && ascVal < 41)
										return true;
										// tab, backspace, delete
										if ( ascVal == 9 || ascVal == 8 ||   ascVal == 46)
										    return true;
										
										return  false;
									}
			this.fieldChanged 	= 	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									
										// if the new value is not a number
										if(objNode.value.match(/^[0-9]+$/)==null && objNode.value!=""){
											// get the previous value
											previousValue = classBehaviour.utilities.getClassParameter(objNode,'previous','');
											objNode.value = previousValue;
										}else{
											// save the new value
											classNameFragments = objNode.className.split(" previous_");
											objNode.className = classNameFragments[0] + " previous_" + objNode.value;
										}
									}
		}
		// add this function to the classbehaviour object
		classBehaviour.numbersOnly = new NumbersOnly;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.numbersOnly;
		
	// Changes a template's skin
		// define this class behaviour		function SkipToNextField(){			/* properties */			this.name 			= 	'skipToNextField';
			/* methods */			this.start			=	function(node){
										// apply the counter event to the field
										node.onkeyup = this.count;
									}
			// event
			this.count			=	function(that){										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										// get the maximum count from the node
										maxCount = classBehaviour.utilities.getClassParameter(objNode, 'count', 2);
										nextId = classBehaviour.utilities.getClassParameter(objNode, 'id', null);
										// get the current count from the node
										curCount = objNode.value.length;
										// if the count is too high
										if(curCount>=maxCount){
											// is there id for the next node?
											if(nextId!=null){
												nextNode = document.getElementById(nextId);
												nextNode.focus();
											// else look for it yourself
											}else{
												// while the next form element has not been found
												notFound = true;
												while(notFound){
													// skip to the next node
													nextNode = classBehaviour.utilities.nextNode(objNode);
													// if this a form element
													if(nextNode.nodeName=='INPUT' || nextNode.nodeName=='TEXTAREA' || nextNode.nodeName=='BUTTON' || nextNode.nodeName=='SELECT'){
														// put the focus on it
														nextNode.focus();
														// break the loop
														notFound = false;
													}
													if(objNode==nextNode){
														// break the loop
														notFound = false;
													}
												}
											}
										}
									}		}		// add this function to the classbehaviour object		classBehaviour.skipToNextField = new SkipToNextField;		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.skipToNextField;
		
/* /TODO */
	// STARTUP-SEQUENCE
	// start the parsing of classes
	classBehaviour.parseDocument();
	
