/*
name			: Class Behaviour
update			: 20051129
author			: Xander Bindt, Frank van Rooijen, Maurice van Creij
dependencies		: lib_classbehaviour.js
info				: http://www.woollymittens.nl/content/details.asp?id=20040805133501
*/

	// main class-behaviour object
	function ClassBehaviour(){
		/* properties */
			this.handlers			=	new Array();
		/* methods */
			// return a parameter from the url's query strings
			this.getQueryParameter 	= 	function(paramName, defaultValue){
											// split the query string at the parameter name
											var queryParameters = document.location.search.split(paramName+"=");
											// split the parameter value from the rest of the string
											var queryParameter = (queryParameters.length>1) ? queryParameters[1].split("&")[0] : null ;
											// return the value
											return (queryParameter!=null) ? queryParameter : defaultValue ;
										}
			// returns a string of parameters found in the classname which can be [eval]uated
			this.getClassParameter	=	function(targetNode, paramName, defaultValue){
											// get the class parameter from the classname
											var classParameter = targetNode.className;
											// split the classname between the parameter name
											classParameter = classParameter.split(paramName + '_');
											// split the second piece between spaces and take the first part,  if there are two pieces
											classParameter = (classParameter.length>1) ? classParameter[1].split(' ')[0] : null ;
											// return the value
											return (classParameter!=null) ? classParameter : defaultValue ;
										}
			// parse the document for classnames
			this.parseDocument		=	function(){
											// get all document nodes
											var allNodes = (document.all) ? document.all : document.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]);
													}
												}
											}
										}
			// 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;
										}
	}
	// create the main class-behaviour object
	var classBehaviour = new ClassBehaviour;

	// replace in class
		// define this class behaviour
		function ClassMouseHover(){
			/* properties */
			this.name 		= 	'classMouseHover';
			/* methods */
			this.start		=	function(node){
									node.onmouseover = this.addHover;
									node.onmouseout = this.remHover;
								}
			this.hasNoStateClass 	= 	function(objNode){
											return (objNode.className.indexOf('link')<0 && objNode.className.indexOf('hover')<0 && objNode.className.indexOf('active')<0);
										}
			/* events */
			this.addHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace link by hover
									objNode.className = (cmh.hasNoStateClass(objNode)) ? 'hover ' + objNode.className : objNode.className.replace('link','hover') ;
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace hover by link
									objNode.className = (cmh.hasNoStateClass(objNode)) ? 'link ' + objNode.className : objNode.className.replace('hover','link') ;
								}
			this.addActive 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var cmh = classBehaviour.classMouseHover;
									// replace link by active
									objNode.className = objNode.className.replace('link','active') ;
									// replace hover 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 ;
										// 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 ;
									// 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 ;
									// replace link by hover
									objNode.src = objNode.src.replace('_link','_hover');
								}
			this.remHover 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// 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;
	
	// add display='none'; on parse
		// define this class behaviour
		function HideThisNode(){
			/* properties */
			this.name 		= 	'hideThisNode';
			/* methods */
			this.start		=	function(node){
									node.style.display = 'none';
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.hideThisNode = new HideThisNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.hideThisNode;
		
	// affirms the visibility status in regard to toggles
		// define this class behaviour
		function ShowThisNode(){
			/* properties */
			this.name 		= 	'showThisNode';
			/* methods */
			this.start		=	function(node){
									// apply the visible state
									node.style.display = classBehaviour.getVisibleState(node);
									// fill the "previous node" parameters of a related object
									classBehaviour.toggleNextNode.lastNode = node;
// TODO: untested test for childnodes
									// if this isn't the first node
									if(node.parentNode.childNodes[0] != node){
										// pick the previousnode
										objPreviousNode = (node.previousSibling.nodeName.indexOf("text")<0) ? node.previousSibling : node.previousSibling.previousSibling ;
										// store it as the 'previous' toggle
										if(objPreviousNode!=null) classBehaviour.toggleNextNode.lastNext = objPreviousNode;
									}
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.showThisNode = new ShowThisNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.showThisNode;
	
	// Open print dialog
		// define this class behaviour
		function OpenAsPrintable(){
			/* properties */
			this.name 		= 	'openAsPrintable';
			/* methods */
			this.start		=	function(node){
									node.onclick = this.process;
								}
			this.process 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// If there is a demo popup
									if(document.getElementById('tgtPopTitle')){
										// copy the title to the print popup title
										document.getElementById('tgtPopTitle').innerHTML = document.getElementById('content').getElementsByTagName('h1')[0].innerHTML;
										// copy the content tot the print popup content
										document.getElementById('tgtPopText').innerHTML = (document.getElementById('content').innerHTML.indexOf('</h1>')>-1) ? document.getElementById('content').innerHTML.split('</h1>')[1] : document.getElementById('content').innerHTML.split('</H1>')[1];
										// show the print popup
										classBehaviour.openLayerPopUp.show(document.getElementById('popup0'));
										// open the print dialog
										setTimeout("window.print();",2048);
									}else{
										window.print();
									}
									// cancel the click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.openAsPrintable = new OpenAsPrintable;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openAsPrintable;
	
	// Open links in a popup
		// define this class behaviour
		function OpenAsPopUp(){
			/* properties */
			this.name 		= 	'openAsPopUp';
			this.window		=	null;
			/* methods */
			this.start		=	function(node){
									node.onclick = this.process;
								}
			/* events */
			this.process 	= 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var oap = classBehaviour.openAsPopUp;
									// get the parameters from the classname
									var strWidth 		= 'width=' + classBehaviour.getClassParameter(objNode, 'width', '630');
									var strHeight 		= ',height=' + classBehaviour.getClassParameter(objNode, 'height', '385');
									var strLeft			= ',left=' + classBehaviour.getClassParameter(objNode, 'left', '');
									var strTop			= ',top=' + classBehaviour.getClassParameter(objNode, 'top', '');
									var strToolbars 	= ',toolbar=' + classBehaviour.getClassParameter(objNode, 'toolbar', 'no');
									var strScrolling 	= ',scrollbars=' + classBehaviour.getClassParameter(objNode, 'scrollbars', 'no');
									var strStatus 		= ',status=' + classBehaviour.getClassParameter(objNode, 'status', 'no');
									var strResize 		= ',resizable=' + classBehaviour.getClassParameter(objNode, 'resizable', 'yes');
									var strLocation 	= ',location=' + classBehaviour.getClassParameter(objNode, 'location', 'no');
									var strMenu 		= ',menu=' + classBehaviour.getClassParameter(objNode, 'menu', 'no');
									var strName 		= classBehaviour.getClassParameter(objNode, 'name', 'popup');
									// open requested window
									oap.window = window.open(objNode.getAttribute('href'), strName, strWidth+strHeight+strScrolling+strToolbars+strStatus+strResize+strLocation+strMenu+strLeft+strTop);
									oap.window.focus();
									// cancel click
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.openAsPopUp = new OpenAsPopUp;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.openAsPopUp;
	
	// 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;
	
	// Add or remove display:none; onclick
		// define this class behaviour
		function ToggleNextNode(){
			/* properties */
			this.name 		= 	'toggleNextNode';
			this.lastNode	=	null;
			this.lastNext	=	null;
			/* methods */
			this.start		=	function(node){
									node.onclick = this.toggleNext;
								}
			/* events */
			this.toggleThis = 	function(that, strClosePrevious){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var tnn = classBehaviour.toggleNextNode;
									// restore previous node
									if(tnn.lastNode!=null && tnn.lastNode!=objNode && strClosePrevious=='yes') tnn.lastNode.style.display = 'none';
									// toggle node's visibility
									objNode.style.display = (objNode.style.display=='none') ? classBehaviour.getVisibleState(objNode) : 'none' ;
									// remember last node
									tnn.lastNode = objNode;	
								}
			this.toggleNext = 	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var tnn = classBehaviour.toggleNextNode;
									// get parent recursion
									var intParentRecursion = parseInt(classBehaviour.getClassParameter(objNode,'useParent','0'));
									var objParentNode = objNode;
									for(var a=0; a<intParentRecursion; a++) objParentNode = objParentNode.parentNode;
									// check if a previousnode needs closing
									var strClosePrevious = classBehaviour.getClassParameter(objNode,'closePrevious','no');
									// get optional id
									var strCloseId = classBehaviour.getClassParameter(objNode, 'id', null);
									// determine the next node
									var objNextNode;
									if(strCloseId!=null){
										objNextNode = document.getElementById(strCloseId);
									}else if(objParentNode.nextSibling){
										objNextNode = (objParentNode.nextSibling.nodeName.indexOf("text")<0) ? objParentNode.nextSibling : objParentNode.nextSibling.nextSibling ;
									}
									// if there is a next node
									if(objNextNode!=null){
										// toggle it's visibility
										tnn.toggleThis(objNextNode, strClosePrevious);
										// If the next node has been hidden
										if(objNextNode.style.display=='none'){
											// restore current node's click state
											objNode.className = objNode.className.replace('active','link');
											if(objNode.src!=null) objNode.src = objNode.src.replace('active','link');
											// do the same to the parent node
//											objNode.parentNode.className = objNode.parentNode.className.replace('active','link');
										}else{
											// mark current node as active
											objNode.className = objNode.className.replace('link','active');
											objNode.className = objNode.className.replace('hover','active');
											if(objNode.src!=null) objNode.src = objNode.src.replace('link','active');
											if(objNode.src!=null) objNode.src = objNode.src.replace('hover','active');
											// do the same to the parent node
//											objNode.parentNode.className = objNode.parentNode.className.replace('link','active');
//											objNode.parentNode.className = objNode.parentNode.className.replace('hover','active');
											// restore previous node's click state
											if(tnn.lastNext!=null && tnn.lastNext!=objNode && strClosePrevious=='yes'){
												tnn.lastNext.className = tnn.lastNext.className.replace('active','link');
												if(objNode.src!=null) tnn.lastNext.src = tnn.lastNext.src.replace('active','link');
												// do the same to the parent node
//												tnn.lastNext.parentNode.className = tnn.lastNext.parentNode.className.replace('active','link');
											}
										}
										// remember last node
										tnn.lastNext = objNode;
									}
									// cancel onclick event
									return false;
								}
		}
		// add this function to the classbehaviour object
		classBehaviour.toggleNextNode = new ToggleNextNode;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.toggleNextNode;

	// present pages as fading slides
		// define this class behaviour
		function VoteQuiz(){
			/* properties */
			this.name 		= 	'voteQuiz';
			this.page		=	0;
			this.pages		=	0;
			this.highest	=	0;
			this.locked	= 	false;
			/* methods */
			this.start		=	function(node){
									// process the node
									this.process(node);
								}
			this.crossFade	=	function(idOut, idIn, amount){
									var pcf = classBehaviour.voteQuiz;
									// get the fade objects
									nodeOut = document.getElementById(idOut);
									nodeIn = document.getElementById(idIn);
									// if the amount is not 50
									if(amount<=100){
										// set the fade amounts
										if(typeof(nodeIn.style.MozOpacity)!='undefined'){
											nodeIn.style.MozOpacity = amount/100;
											nodeOut.style.MozOpacity = (100-amount)/100;
										}else if(typeof(nodeIn.style.filter)!='undefined'){
											nodeIn.style.filter = "alpha(opacity=" + (amount) + ")"
											nodeOut.style.filter = "alpha(opacity=" + (100-amount) + ")"
											// alternative for fadeout/in
											//nodeIn.style.filter = (amount>50) ? "alpha(opacity=" + (amount*2-100) + ")" : "alpha(opacity=0)" ;
											//nodeOut.style.filter = (amount<=50) ? "alpha(opacity=" + (100-amount*2) + ")" : "alpha(opacity=0)" ;
										}else if(typeof(nodeShadow.style.opacity)!='undefined'){
											nodeIn.style.opacity = amount/100;
											nodeOut.style.opacity = (100-amount)/100;
										}
										// unhide the new page
										nodeIn.style.display = 'block';
										// repeat the fade
										setTimeout("classBehaviour.voteQuiz.crossFade('" + idOut + "','" + idIn + "'," + (amount+20) + ")",50);
									}else{
									// else
										// hide the old page
										nodeOut.style.display = 'none';
										// unlock the controls
										classBehaviour.voteQuiz.locked = false;
									}
								}
			this.update	=	function(page){
									var pcf = classBehaviour.voteQuiz;
									// store the new page number
									if(page!=null) pcf.page = page;
									// remember the highest page voted on
									if(pcf.page>pcf.highest) pcf.highest = pcf.page;
									// make all page counters passive
									allPagerButtons = document.getElementById('pager').getElementsByTagName('a');
									for(var a=2; a<allPagerButtons.length; a++){
										allPagerButtons[a].className = (a>pcf.highest+2) ? 'passive' : 'link';
									}
									// make the new page counter active
									allPagerButtons[page+2].className = 'active';
									// hide the previous page button if this is the first page, or show it
									allPagerButtons[0].className = (pcf.page>0) ? 'link' : 'passive' ;
									// hide the next page button if this is the last page, or show it
									allPagerButtons[1].className = (pcf.page<pcf.pages-1 && pcf.page<pcf.highest) ? 'link' : 'passive' ;
								}
			/* events */
			this.process	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									// add the event handlers to the pager buttons
									allPagerButtons = document.getElementById('pager').getElementsByTagName('a');
									allPagerButtons[0].onclick = this.setPrev;
									allPagerButtons[1].onclick = this.setNext;
									for(var a=0; a<allPagerButtons.length; a++){
										// show the pager controls
										allPagerButtons[a].parentNode.style.display = 'inline';
										// add the event to the page number
										if(a>1) allPagerButtons[a].onclick = this.setPage;
										// hide the page refered to by the page number, except the first one)
										if(a>2) document.getElementById(allPagerButtons[a].href.split('#')[1]).style.display = 'none';
									}
									// all vote buttons
									allVoteButtons = document.getElementById('questions').getElementsByTagName('a');
									for(var a=0; a<allVoteButtons.length; a++){
										allVoteButtons[a].onclick = this.setVote;
									}
									// the in between button
									document.getElementById('tweenButton').onclick = this.setResults;
									// count the pages and store it
									this.pages = allPagerButtons.length - 2;
									// make the first page counter active
									this.update(0);
								}
			this.setNext	=	function(that, force){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var pcf = classBehaviour.voteQuiz;
									// if the conrols are not locked
									if(!pcf.locked && objNode.className.indexOf('passive')<0 || force){
										// lock the controls
										pcf.locked = true;
										// what is the current page number
										pageOut = pcf.page;
										// what is the next page number
										pageIn = ((pcf.page+1)<pcf.pages) ? pcf.page+1 : 0;
										// find the current page's id from the page number list
										idOut = objNode.parentNode.parentNode.getElementsByTagName('a')[pageOut+2].href.split('#')[1];
										// find the next page's id from the page number list
										idIn = objNode.parentNode.parentNode.getElementsByTagName('a')[pageIn+2].href.split('#')[1];
										// fade out the page
										pcf.crossFade(idOut, idIn, 0);
										// update the pager
										pcf.update(pageIn);
									}
									// cancel the click
									return false;
								}
			this.setPrev	=	function(that, force){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var pcf = classBehaviour.voteQuiz;
									// if the conrols are not locked
									if(!pcf.locked && objNode.className.indexOf('passive')<0 || force){
										// lock the controls
										pcf.locked = true;
										// what is the current page number
										pageOut = pcf.page;
										// what is the next page number
										pageIn = ((pcf.page)>0) ? pcf.page-1 : pcf.pages-1;
										// find the current page's id from the page number list
										idOut = objNode.parentNode.parentNode.getElementsByTagName('a')[pageOut+2].href.split('#')[1];
										// find the next page's id from the page number list
										idIn = objNode.parentNode.parentNode.getElementsByTagName('a')[pageIn+2].href.split('#')[1];
										// fade out the page
										pcf.crossFade(idOut, idIn, 0);
										// update the pager
										pcf.update(pageIn);
									}
									// cancel the click
									return false;
								}
			this.setPage	=	function(that, force){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var pcf = classBehaviour.voteQuiz;
									// if the conrols are not locked
									if((!pcf.locked && objNode.className.indexOf('active')<0 && objNode.className.indexOf('passive')<0) || force){
										// lock the controls
										pcf.locked = true;
										// what is the current page number
										pageOut = pcf.page;
										// find the current page's id from the page number list
										idOut = objNode.parentNode.parentNode.getElementsByTagName('a')[pageOut+2].href.split('#')[1];
										// find the next page's id from the page number list
										idIn = objNode.href.split('#')[1];
										// fade out the page
										pcf.crossFade(idOut, idIn, 0);
										// update the pager (this hack will to for now)
										pcf.update(parseInt(objNode.firstChild.nodeValue)-1);
									}
									// cancel the click
									return false;
								}
			this.setVote	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var pcf = classBehaviour.voteQuiz;
									// get all votes' images in this parent
									allVoteImgs = objNode.parentNode.parentNode.getElementsByTagName('img');
									// set all votes' images to passive
									for(var a=0; a<allVoteImgs.length; a++) allVoteImgs[a].src = allVoteImgs[a].src.replace('_active','_link');
									// get this vote's image
									voteImg = objNode.getElementsByTagName('img')[0];
									// set this vote's image to active
									voteImg.src = voteImg.src.replace('_hover','_active').replace('_link','_active');
									// if this is not the last question
									if(pcf.page<pcf.pages-1){
										// trigger the next question
										setTimeout("classBehaviour.voteQuiz.setNext(document.getElementById('nextControl').firstChild, true)", 512);
									// else
									}else{
										// go to the tween question
										setTimeout("classBehaviour.voteQuiz.setTween()", 512);
									}
									// cancel the click
									return false;
								}
			this.setTween	=	function(that){
									var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
									var pcf = classBehaviour.voteQuiz;
									// get rid of the pager
									document.getElementById('pager').style.display = 'none';
									// hide the questions and show the tween page
									pcf.crossFade('questions', 'tween', 0);
									// cancel the click
									return false;
								}
			this.setResults	=	function(that){
										var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
										var pcf = classBehaviour.voteQuiz;
										// get the results in the results page
										allResults = document.getElementById('results').getElementsByTagName('li');
										// hide all results
										for(var a=0; a<allResults.length; a++)  allResults[0].style.display = 'none';
										// pick a random result
										randomResult = Math.round(Math.random()*(allResults.length-1));
										// unhide the result
										allResults[randomResult].style.display = 'block';
										// hide the tween page and show the results page
										pcf.crossFade('tween', 'results', 0);
										// cancel the click
										return false;
									}
		}
		// add this function to the classbehaviour object
		classBehaviour.voteQuiz = new VoteQuiz;
		classBehaviour.handlers[classBehaviour.handlers.length] = classBehaviour.voteQuiz;
		
	// start the parsing of classes
	classBehaviour.parseDocument();
