/*	name			: ClassBehaviours, the javascript framework based on class-name parsing	update			: 9.3.17	author			: Maurice van Creij, Marc Molenwijk	dependencies	: jquery.classbehaviours.js	info			: http://www.classbehaviours.com/    This file is part of jQuery.classBehaviours.    ClassBehaviours is a javascript framework based on class-name parsing.    Copyright (C) 2008  Maurice van Creij    ClassBehaviours is free software: you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation, either version 3 of the License, or    (at your option) any later version.    ClassBehaviours is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with ClassBehaviours. If not, see http://www.gnu.org/licenses/gpl.html.*/	// create the jQuery object if it doesn't already exist	if(typeof(jQuery)=='undefined') jQuery = function(){};	// create the root classbehaviours object if it doesn't already exist	if(typeof(jQuery.classBehaviours)=='undefined') jQuery.classBehaviours = function(){};	// create the handlers child object if it doesn't already exist	if(typeof(jQuery.classBehaviours.handlers)=='undefined') jQuery.classBehaviours.handlers = function(){}	// AJAX interface	jQuery.classBehaviours.ajax = {		// properties		queue: new Array(),		// utilities		getNodeValue: function(objNode){			strValue = (objNode.childNodes.length>0) ? objNode.firstChild.nodeValue : null ;			return (isNaN(strValue) || strValue==null) ? strValue : parseInt(strValue);		},		setNodeValue: function(objNode,strValue){			if(objNode.childNodes.length>0){				objNode.firstChild.nodeValue = strValue;			}else{				var objNewNode = ajax.createTextNode(strValue);				objNode.appendChild(objNewNode);			}		},		getChildNumber: function(objNode){			var objNodes = objNode.parentNode.childNodes;			var intTextNodes = 0;			for(var intA=0; intA<objNodes.length; intA++){				if(objNodes[intA].nodeName == '#text') intTextNodes += 1;				if(objNode==objNodes[intA]) return intA - intTextNodes;			}			return null;		},		serialize: function serialize(ajax){			ser = new XMLSerializer();			str = ser.serializeToString(ajax);			return(str);		},		defaultProgress: function(progressStatus, progressNode, progressError){			progressNode.innerHTML = (progressStatus>-1) ? 'Loading: ' + Math.round(progressStatus * 100) + '%' : 'Error: ' + progressError ;		},		defaultLoad: function(loadXml, loadNode, loadText){			loadNode.innerHTML = loadText.split('<body>')[1].split('</body>')[0];		},		getPostValues: function(node, nodeId){			// use the id if needed			if(nodeId!=null) node = document.getElementById(nodeId);			// get all elements of this form			formNode = jQuery.classBehaviours.utilities.rootNode(node, 'FORM');			rootNode = jQuery.classBehaviours.utilities.rootNode(node, 'FIELDSET');			allNodes = rootNode.getElementsByTagName('*');			// for all elements			postValues = '';			for(var a=0; a<allNodes.length; a++){				// build the query string from the name and value pairs				if(					allNodes[a].nodeName=='INPUT' ||					allNodes[a].nodeName=='SELECT' ||					allNodes[a].nodeName=='TEXTAREA'				)					if(						allNodes[a].getAttribute('type')!='submit' &&						allNodes[a].getAttribute('type')!='image' &&						allNodes[a].getAttribute('type')!='button' &&						allNodes[a].getAttribute('type')!='reset'					)						postValues += (allNodes[a].checked || (allNodes[a].type!='radio' && allNodes[a].type!='checkbox')) ?							allNodes[a].name + '=' + escape(allNodes[a].value) + '&' :							'' ;			}			// add the value of the pressed button			if(node.getAttribute('type')=='submit' || node.getAttribute('type')=='button') postValues += node.id + '=' + node.value + '&';			// add the cookie value too			if(document.cookie!=null) postValues += document.cookie.replace(/; /gi, "&")  + '&';			// return the values			return postValues;		},		// methods		addSubmit: function(node, loadHandler, progressHandler, post, referingObject){			// default values			loadHandler = (loadHandler==null) ? this.defaultLoad : loadHandler ;			progressHandler = (progressHandler==null) ? this.defaultProgress : progressHandler ;			// get all the post values			post = (post==null) ? '' : post + '&' ;			post += this.getPostValues(node);			// get the id's of the hidden fields			replyActionId = jQuery.classBehaviours.utilities.getClassParameter(rootNode, 'action', null);			replyMethodId = jQuery.classBehaviours.utilities.getClassParameter(rootNode, 'method', null);			// get the AJAX settings from the FORM tag or hidden fields			ajaxAction = (replyActionId==null) ? formNode.getAttribute('action') : document.getElementById(replyActionId).value ;			ajaxMethod = (replyMethodId==null) ? formNode.getAttribute('method') : document.getElementById(replyMethodId).value ;			ajaxQuery = (ajaxAction.indexOf('?')<0) ? '?' + post : '&' + post ;			// POST or GET the form			if(ajaxMethod=='post') 	jQuery.classBehaviours.ajax.addRequest(ajaxAction, loadHandler, progressHandler, post, referingObject)			else 					jQuery.classBehaviours.ajax.addRequest(ajaxAction + ajaxQuery, loadHandler, progressHandler, null, referingObject);			// return false			return false;		},		addRequest: function(url, loadHandler, progressHandler, post, referingObject){			// get the first free slot in the que			index = this.queue.length;			// add new request to the end of the que			this.queue[index] = new this.HttpRequest();			// set request constants			this.queue[index].idx			=	index;			this.queue[index].url			=	url;			this.queue[index].post			=	post;			this.queue[index].method		=	(post!=null) ? 'POST' : 'GET' ;			// request events			this.queue[index].doOnLoad		=	loadHandler;			this.queue[index].doOnProgress	=	progressHandler;			this.queue[index].referObject	=	referingObject;			// ask the queue handler to handle the next queued item			this.handleQueue();			// return false			return false;		},		makeRequest: function(queued){			// branch for native XMLHttpRequest object			if(window.XMLHttpRequest){				queued.request = new XMLHttpRequest();				queued.request.onreadystatechange = this.progress;				queued.request.open(queued.method, queued.url, true);				if(queued.method == 'POST'){					queued.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");					queued.request.setRequestHeader("Content-length", queued.post.length);					queued.request.setRequestHeader("Connection", "close");				}				queued.request.send(queued.post);			// branch for IE/Windows ActiveX version			}else if(window.ActiveXObject){				queued.request = new ActiveXObject("Microsoft.XMLHTTP");				queued.request.onreadystatechange = this.progress;				queued.request.open(queued.method, queued.url, true);				if(queued.method == 'POST'){					queued.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");					queued.request.setRequestHeader("Content-length", queued.post.length);					queued.request.setRequestHeader("Connection", "close");				}				queued.request.send(queued.post);			// if all else fails: load the document in an iFrame			}else if(window.frames){				// create an iframe to read the document in					objIframe = document.createElement("IFRAME");					objIframe.src = queued.url;					objIframe.id = "feedimport0";					objIframe.name = "feedimport0";					objIframe.style = "visibility : invisible;position : absolute;left : -1600px; top : -1600px;";					//objIframe.onload = ajax_load; // Doesn't work in Opera				// append the iframe to the document					document.body.appendChild(objIframe);				// wait for the iframe to load				this.wait();			}		},		handleQueue: function(){			queue = jQuery.classBehaviours.ajax.queue;			// if the first item in the queue is a completed request			if(queue.length>0){				if(queue[0].ready==4 /*&& ajax.queue[0].status==200*/){					// remove the completed request					queue.reverse();					queue.length = queue.length - 1;					queue.reverse();				}			}			// if the first item in the queue isn't allready in progress			if(queue.length>0){				if(!(queue[0].ready<4 && queue[0].ready!=null)){					this.makeRequest(queue[0]);				}			}		},		// events		progress: function(){			queued = jQuery.classBehaviours.ajax.queue[0];			// remember the readyState			queued.ready = queued.request.readyState;			// only if req shows "complete"			if(queued.request.readyState == 4){				// remember the status				queued.status = queued.request.status;				// only if "OK"				if(queued.request.status == 200 || queued.request.status == 304){					// update optional progress indicator code					if(queued.doOnProgress) queued.doOnProgress(1, queued.referObject, queued.request.status);					// prepare the document					queued.document = queued.request.responseXML;					queued.text = queued.request.responseText;					// trigger the load event					if(queued.doOnLoad) queued.doOnLoad(queued.document, queued.referObject, queued.text);					// request the next item in the queue to be handled					jQuery.classBehaviours.ajax.handleQueue();				}else{					// update optional progress indicator code					if(queued.doOnProgress) queued.doOnProgress(-1, queued.referObject, queued.request.status);				}			}else{				// update optional progress indicator code				if(queued.doOnProgress) queued.doOnProgress(queued.request.readyState, queued.referObject, 200);			}			// return the status if desired			return queued.request.readyState;		},		wait: function(){			queued = jQuery.classBehaviours.ajax.queue[0];			// if the xml document has loaded in the iframe			if(window.frames["feedimport0"]){				// define the xml document object				queued.document = window.frames["feedimport0"].document;				queued.text = window.frames["feedimport0"].document.body.innerHTML;				// what to do after the xml document loads				queued.doOnLoad(queued.document, queued.referObject, queued.text);			// else try again in a while			}else{				setTimeout("ajax.wait()",256);			}		}	}		// prototype http request object		jQuery.classBehaviours.ajax.HttpRequest = function(){			// request constants			this.idx			=	null;			this.url			=	null;			this.post			=	null;			this.method			=	'GET';			// request events			this.doOnLoad		=	null;			this.doOnProgress	=	null;			this.referObject	=	null;			// request properties			this.request		=	null;			this.document		=	null;			this.text			=	null;			this.ready			=	null;			this.status			=	null;		}	// debug console	jQuery.classBehaviours.console = {		// porperties		id: 'debugConsole0',		limit: 32,		// methods		debug: function(){			// create the debug console if it doesn't exist yet			debugConsole = document.getElementById(jQuery.classBehaviours.console.id);			if(debugConsole==null){				// create a new console node				newConsole = document.createElement('div');				newConsole.id = jQuery.classBehaviours.console.id;				newText = document.createTextNode('-- newest at top --');				newConsole.appendChild(newText);				document.body.appendChild(newConsole);				debugConsole = document.getElementById(jQuery.classBehaviours.console.id);			}			// set the console's properties			if(debugConsole.style.background=='') 	debugConsole.style.background = '#ffffff url(../images/button_passive.png) no-repeat 0px 0px';			if(debugConsole.style.border=='') 		debugConsole.style.border = 'solid 1px #000000';			if(debugConsole.style.bottom=='') 		debugConsole.style.bottom = 'auto';			if(debugConsole.style.height=='') 		debugConsole.style.height = (navigator.userAgent.indexOf('MSIE 6')>-1) ? '580px' : '98%' ;			if(debugConsole.style.left=='') 		debugConsole.style.left = 'auto';			if(debugConsole.style.overflow=='') 	debugConsole.style.overflow = 'auto';			if(debugConsole.style.padding=='') 		debugConsole.style.padding = '1% 1% 1% 1%';			if(debugConsole.style.position=='') 	debugConsole.style.position = (navigator.userAgent.indexOf('MSIE 6')>-1) ? 'absolute' : 'fixed' ;			if(debugConsole.style.right=='') 		debugConsole.style.right = '-1px';			if(debugConsole.style.top=='') 			debugConsole.style.top = '-1px';			if(debugConsole.style.width=='') 		debugConsole.style.width = '128px';			debugConsole.onclick = jQuery.classBehaviours.console.move;			jQuery.classBehaviours.fader.setFade(debugConsole, 75);			// send all the incoming arguments to the debug console			newList = document.createElement('ul');			for(var a=0; a<arguments.length; a++){				// create a list item for each argument				newListItem = document.createElement('li');				newListText = document.createTextNode(arguments[a]);				newListItem.appendChild(newListText);				newList.appendChild(newListItem);			}			debugConsole.insertBefore(newList, debugConsole.firstChild);			// if there are too many enties, remove a few			allLists = debugConsole.getElementsByTagName('ul');			if(allLists.length>jQuery.classBehaviours.console.limit)				for(var a=allLists.length-1; a>jQuery.classBehaviours.console.limit; a--)					removedChild = debugConsole.removeChild(allLists[allLists.length-1]);		},		clear: function(){			// clear the entries			debugConsole = document.getElementById(jQuery.classBehaviours.console.id);			if(debugConsole!=null){				allLists = debugConsole.getElementsByTagName('ul');				for(var a=allLists.length-1; a>=0; a--)					removedChild = debugConsole.removeChild(allLists[allLists.length-1]);			}		},		html: function(string){			string = '<xmp>' + string + '</xmp>'			this.debug(string)		},		// events		move: function(that){			var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;			// get the console			debugConsole = document.getElementById(jQuery.classBehaviours.console.id);			// toggle through several console positions			if(debugConsole.style.right == '-1px' && debugConsole.style.width == '128px'){				debugConsole.style.bottom = 'auto';				debugConsole.style.height = (navigator.userAgent.indexOf('MSIE 6')>-1) ? '580px' : '98%' ;				debugConsole.style.left = '-1px';				debugConsole.style.right = 'auto';				debugConsole.style.top = '-1px';				debugConsole.style.width = '128px';				debugConsole.style.zIndex = '100000';			}else if(debugConsole.style.left == '-1px' && debugConsole.style.width == '128px'){				debugConsole.style.bottom = '-1px';				debugConsole.style.height = '128px';				debugConsole.style.left = '-1px';				debugConsole.style.right = 'auto';				debugConsole.style.top = 'auto';				debugConsole.style.width = '98%';				debugConsole.style.zIndex = '100000';			}else if(debugConsole.style.bottom == '-1px' && debugConsole.style.width == '98%'){				debugConsole.style.bottom = 'auto';				debugConsole.style.height = (navigator.userAgent.indexOf('MSIE 6')>-1) ? '580px' : '98%' ;				debugConsole.style.left = 'auto';				debugConsole.style.right = '-1px';				debugConsole.style.top = '-1px';				debugConsole.style.width = '128px';				debugConsole.style.zIndex = '100000';			}		}	}	// short-cut wrapper functions	debug = jQuery.classBehaviours.console.debug;	// cookies Library	jQuery.classBehaviours.cookies = {		// methods		getDaysFromNow: function(intDays){			var dateCurrent = new Date();			var intCurrent = Date.parse(dateCurrent);			var intPeriod = intDays*24*60*60*1000;			var datePeriodInFuture = new Date(intCurrent+intPeriod);			return datePeriodInFuture;		},		setCookie: function(name, value, expires, path, domain, secure) {			var curCookie = name + "=" + escape(value) +				((expires) ? "; expires=" + expires.toGMTString() : "") +				((path) ? "; path=" + path : "") +				((domain) ? "; domain=" + domain : "") +				((secure) ? "; secure" : "");			document.cookie = curCookie;		},		getCookie: function(name) {			var dc = document.cookie;			var prefix = name + "=";			var begin = dc.indexOf("; " + prefix);			if (begin == -1) {				begin = dc.indexOf(prefix);				if (begin != 0) return null;			}else{				begin += 2;			}			var end = document.cookie.indexOf(";", begin);			if (end == -1)				end = dc.length;			return unescape(dc.substring(begin + prefix.length, end));		},		deleteCookie: function(name, path, domain) {			if (getCookie(name)) {				document.cookie = name + "=" +				((path) ? "; path=" + path : "") +				((domain) ? "; domain=" + domain : "") +				"; expires=Thu, 01-Jan-70 00:00:01 GMT";			}		},		fixDate: function(date) {			var base = new Date(0);			var skew = base.getTime();			if (skew > 0)				date.setTime(date.getTime() - skew);		},		makeBoolean: function(strIn){			if(strIn=='true'){				booOut = true;			}else{				booOut = false;			}			return booOut;		},		csv2array: function(csvIn){			return csvIn.split(',');		},		array2csv: function(arrIn){			return ''+arrIn;		}	}	// decorative fader animations	jQuery.classBehaviours.fader = {		// properties		getFade: function(node){			var fadeValue = null;			if(node!=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;		},		setFade: function(node, amount){			if(node!=null){				// 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;			*/		},		getSize: function(node){			// measure the height of the container			var nodeWidth = node.offsetWidth;			var nodeHeight = node.offsetHeight;			// measure the height of all the childnodes of the container			var totalWidth = 0;			var totalHeight = 0;			var contents = node.childNodes;			for(var a=0; a<contents.length; a++){				totalWidth += (contents[a].offsetWidth) ? contents[a].offsetWidth : 0 ;				totalHeight += (contents[a].offsetHeight) ? contents[a].offsetHeight : 0 ;			}			// pass back the largest number			return new Array(nodeWidth, nodeHeight, totalWidth, totalHeight);		},		setSize: function(node, xAmount, yAmount){			if(xAmount!=null) node.style.width = xAmount + 'px';			if(yAmount!=null) node.style.height = yAmount + 'px';		},		// methods		fade: function(id, start, end, step, delay, acceleration, evalOnEnd){			var cf = jQuery.classBehaviours.fader;			// get the target node			target = document.getElementById(id);			// get the start value if missing			if(start==null) 		start = cf.getFade(target);			if(end==null) 			end = 100;			if(step==null) 			step = 1;			if(delay==null) 		delay = 10;			if(acceleration==null) 	acceleration = 1;			if(evalOnEnd==null) 	evalOnEnd = '';			// calculate the new value			if(start<end)		{value = (start+step>end) ? end : start+step ;}			else if(start>end)	{value = (start-step<end) ? end : start-step ;}			// set the fade			cf.setFade(target, value);			// order the next step			if(value!=end) 		{setTimeout("jQuery.classBehaviours.fader.fade('"+id+"',"+value+","+end+","+(step+acceleration)+","+delay+","+acceleration+",'"+evalOnEnd+"')", delay);}			else 				{eval(evalOnEnd);}		},		size: function(id, start, end, step, delay, acceleration, evalOnEnd){			var cf = jQuery.classBehaviours.fader;			// get the target node			target = document.getElementById(id);			// get the start value if missing			if(start==null) 		start = cf.getSize(target)[1];			if(end==null) 			end = cf.getSize(target)[3];			if(step==null) 			step = 10;			if(delay==null) 		delay = 10;			if(acceleration==null) 	acceleration = 10;			if(evalOnEnd==null) 	evalOnEnd = '';			// calculate the new value			if(start<end)		{value = (start+step>end) ? end : start+step ;}			else if(start>end)	{value = (start-step<end) ? end : start-step ;}			// set the fade			cf.setSize(target, null, value);			// order the next step			if(value!=end) 		{setTimeout("jQuery.classBehaviours.fader.size('"+id+"',"+value+","+end+","+(step+acceleration)+","+delay+","+acceleration+",'"+evalOnEnd+"')", delay);}			else 				{eval(evalOnEnd);}		},		/* START: legacy functions */		fadeIn: function(id, step, delay, evalOnEnd, acceleration){			jQuery.classBehaviours.fader.fade(id, 0, 100, step, delay, acceleration, evalOnEnd);		},		fadeOut: function(id, step, delay, evalOnEnd, acceleration){			jQuery.classBehaviours.fader.fade(id, 100, 0, step, delay, acceleration, evalOnEnd);		},		crossFade: function(idIn, idOut, amount, step, delay, evalOnEnd, acceleration){			jQuery.classBehaviours.fader.fade(idIn, 0, 100, step, delay, acceleration, evalOnEnd);			jQuery.classBehaviours.fader.fade(idOut, 100, 0, step, delay, acceleration, '');		},		grow: function(id, step, delay, evalOnEnd, acceleration){			jQuery.classBehaviours.fader.size(id, 1, null, step, delay, acceleration, evalOnEnd);		},		shrink: function(id, step, delay, evalOnEnd, acceleration){			jQuery.classBehaviours.fader.size(id, null, 1, step, delay, acceleration, evalOnEnd);		}		/* END: legacy functions */	}	// general purpose functions	jQuery.classBehaviours.utilities = {		// returns all nodes of the same class		getElementsByClassName: function(className, node){			// use the whole body if no target was provided			target = (node!=null) ? node : document ;			// make an empty array for the results			var foundNodes = new Array();			// for all elements in the parent node			var allNodes = (target.all) ? target.all : target.getElementsByTagName("*");			for(var a=0; a<allNodes.length; a++){				// if the item has a className				if(allNodes[a].className){					// process the classname					nodeClass = allNodes[a].className + ' ';					// add it to the results if the classname was found					if(nodeClass.indexOf(className+' ')>-1) foundNodes[foundNodes.length] = allNodes[a];				}			}			// return the list			return foundNodes;		},		// places a sibling node after a given node		insertAfter: function(parentNode, siblingNode, newNode){			nextNode = jQuery.classBehaviours.utilities.nextNode(siblingNode);			if(nextNode==siblingNode) parentNode.appendChild(newNode)			else parentNode.insertBefore(newNode, nextNode);		},		// detaries the available room on the screen		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		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 ;		},		// gets the value of a parameter from a className		getClassParameter: function(targetNode, paramName, defaultValue){			if(targetNode!=null){				// get the class parameter from the classname				var classParameter = targetNode.className;				// split the classname between the parameter name				classParameter = (classParameter!=null) ? classParameter.split(paramName + '_') : new Array();				// 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 ;			}		},		// sets the value of a parameter from a className		setClassParameter: function(targetNode, paramName, newValue){			if(targetNode!=null){				// create a default value, if there isn't one				if(targetNode.className.indexOf(' ' + paramName + '_')<0) targetNode.className += ' ' + paramName + '_0';				// get the old value				oldValue = this.getClassParameter(targetNode, paramName, null);				// replace the old value				if(oldValue!=null) targetNode.className = targetNode.className.replace(paramName+'_'+oldValue, paramName+'_'+newValue);			}		},		// get the next node without worrying about text nodes		nextNode: function(node, count){			testNode = node;			if(count==null) count = 1;			// look for the next html node			for(var a=0; a<count; a++){				do {					testNode = testNode.nextSibling;					if(testNode==null) testNode = node;				}while(testNode.nodeName.indexOf('#text')>-1);			}			// return it			return testNode;		},		// get the previous node without worrying about text nodes		previousNode: function(node, count){			testNode = node;			if(count==null) count = 1;			// look for the previous html node			for(var a=0; a<count; a++){				do {					testNode = testNode.previousSibling;					if(testNode==null) testNode = node;				}while(testNode.nodeName.indexOf('#text')>-1);			}			// return it			return testNode;		},		// get the first real child node without worrying about text nodes		firstNode: function(node, count){			return this.nextNode(node.firstChild, count);		},		// find the parent node with the given classname		rootNode: function(node, rootTag, rootId, rootClass){			// try parent nodes until you find the one which meets the conditions			rootFound = false;			while(!rootFound && node.nodeName!='BODY'){				rootFound = (rootTag && node.nodeName) ? (node.nodeName.indexOf(rootTag)>-1) : rootFound ;				rootFound = (rootId && node.id) ? (node.id.indexOf(rootId)>-1) : rootFound ;				rootFound = (rootClass && node.className) ? (node.className.indexOf(rootClass)>-1) : rootFound ;				node = (!rootFound) ? node.parentNode : node;			}			// pass it back			return node;		},		// returns the visible display state needed for this element		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;		},		// hide select form elements for graphic glitches in certain browsers		hideSelects: function(node){			if(				navigator.userAgent.indexOf('MSIE 6')>-1 ||				(navigator.userAgent.indexOf('Firefox/2')>-1 && navigator.userAgent.indexOf('Mac')>-1)			){				allSelects = (node) ? node.getElementsByTagName('SELECT') : document.getElementsByTagName('SELECT') ;				for(var a=0; a<allSelects.length; a++){					allSelects[a].style.visibility = 'hidden';				}			}		},		showSelects: function(node){			if(				navigator.userAgent.indexOf('MSIE 6')>-1 ||				(navigator.userAgent.indexOf('Firefox/2')>-1 && navigator.userAgent.indexOf('Mac')>-1)			){				allSelects = (node) ? node.getElementsByTagName('SELECT') : document.getElementsByTagName('SELECT') ;				for(var a=0; a<allSelects.length; a++){					allSelects[a].style.visibility = 'visible';				}			}		},		// adds an event-handler the proper way		addEvent: function(node, eventName, eventHandler){			if(node.addEventListener) 	node.addEventListener(eventName, eventHandler, false)			else if(node.attachEvent) 	node.attachEvent("on"+eventName, eventHandler)			else 						node["on"+eventName] = eventHandler;			return true;		}	}	// Parser functions	jQuery.classBehaviours.parser = {		// status of the parser		waiting: false,		// verify the state of the object		start: function(){			// if the document is complete enough start the behaviours, else wait until everything is loaded			var handlersCount = 0;			for (b in jQuery.classBehaviours.handlers) handlersCount++;			this.waiting = (handlersCount>0 && document.body) ? this.parseDocument() : jQuery.classBehaviours.utilities.addEvent(window, 'load', this.parseDocument) ;		},		// scan the whole document		parseDocument: function(){			// pass the document object to the parser			jQuery.classBehaviours.parser.parseNode(document);			// return the status			return false;		},		// scan the document object model for target classNames		parseNode: function(node){			// for all childnodes of the given node			var allNodes = node.getElementsByTagName("*");			for(var a=0; a<allNodes.length; a++){				// process the classnames of the node				this.processNode(allNodes[a]);			}			// do the same for the parent node			this.processNode(node);		},		// process the classnames of the node		processNode: function(node){			// get its className			nodeClass = ' ' + node.className + ' ';			// if this node has a className			if(nodeClass!=null && nodeClass!=' undefined '){				// for all class behaviours				for(b in jQuery.classBehaviours.handlers){					// if the behaviour name is in the className tested node					if(nodeClass.indexOf(' ' + jQuery.classBehaviours.handlers[b].name + ' ')>-1){						// apply its respective behaviour						jQuery.classBehaviours.handlers[b].start(node);					}				}			}		}	}	// add this addon to the jQuery object	if(typeof(jQuery.fn)!='undefined'){		// set the event handler for this jQuery method		$(document).ready(			function(){// TODO: at the moment this is handled by the individual classbehaviours modules, until this proves too slow//				$.classBehaviours.parser.parseDocument()			}		);	}else{		// start the (backup) parsing of classes if the main jQuery library is not available		jQuery.classBehaviours.parser.start()	}
