/*
	Source: classbehaviours.handlers.togglenextnode.js
	ClassBehaviours is a javascript framework based on class-name parsing.
	Copyright 2011 by Maurice van Creij and published on http://www.woollymittens.nl/
	This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
*/

	// CLASSBEHAVIOURS CLASS
	// create the root classbehaviours object if it doesn't already exist
	if(typeof(classBehaviours)=='undefined') classBehaviours = {};

		// CLASSNAME BEHAVIOUR FUNCTIONS
		// create the handlers child object if it doesn't already exist
		if(typeof(classBehaviours.handlers)=='undefined') classBehaviours.handlers = {}

			// open or close a container object
			document.writeln("<style>.toggleNextNode{cursor:pointer;}</style>");
			classBehaviours.handlers.toggleNextNode = {
				// properties
				name: 'toggleNextNode',
				step: 10,
				acceleration: 10,
				extra: 0,
				delay: 50,
				index: 0,
				// methods
				start: function(node){
					var t2n = classBehaviours.handlers.toggleNextNode;
					var cu = classBehaviours.utilities;
					// set the event handlers for the source node
					if(node.nodeName=='INPUT' || node.nodeName=='TEXTAREA' || node.nodeName=='SELECT'){
						cu.addEvent(node, 'focus', function(event){t2n.toggle(node, event)});
						cu.addEvent(node, 'blur', function(event){t2n.toggle(node, event)});
					}else{
						cu.addEvent(node, 'click', function(event){t2n.toggle(node, event)});
					}
					// give this node an id if it doesn't have one yet
					node.id = (node.id) ? node.id : t2n.name + t2n.index++ ;
					// is this node marked as "auto", order it to open on a timeout
					autoDelay = cu.getClassParameter(node, 'auto', null);
					if(autoDelay){
						t2n.index++
						node.id = (node.id) ? node.id : t2n.name + t2n.index ;
						setTimeout(function(){
							classBehaviours.handlers.toggleNextNode.toggle(node);
						}, autoDelay);
					}
				},
				findContainer: function(targetLabel, targetRecursion){
					var t2n = classBehaviours.handlers.toggleNextNode;
					var cu = classBehaviours.utilities;
					// if there was a target recursion, recurse parent nodes
					if(targetRecursion) for(var a=0; a<parseInt(targetRecursion); a++) targetLabel = targetLabel.parentNode;
					// get the next sibling of the label, which should be the container
					targetObject = cu.nextNode(targetLabel);
					// give it an ID for reference
					targetObject.id = (targetObject.id) ? targetObject.id : t2n.name + 'Target' + t2n.index++;
					// pass it back
					return targetObject;
				},
				positionContainer: function(targetContainer, screenXpos, screenYpos){
					if(targetContainer.firstChild!=null){
						// if the position is too close to the edge
						targetContainerWidth = targetContainer.firstChild.offsetWidth;
						screenWidth = (window.innerWidth) ? window.innerWidth : document.documentElement.clientWidth ;
						scrolledWidth = (typeof(document.documentElement.scrollLeft)!='undefined') ? document.documentElement.scrollLeft : window.pageXOffset ;
						if(screenXpos+targetContainerWidth > screenWidth+window.pageXOffset) screenXpos -= targetContainerWidth;
						// if the position is too close to the bottom
						targetContainerHeight = targetContainer.firstChild.offsetHeight;
						screenHeight = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight ;
						scrolledHeight = (typeof(document.documentElement.scrollTop)!='undefined') ? document.documentElement.scrollTop : window.pageYOffset ;
						if(screenYpos+targetContainerHeight+10 > screenHeight+scrolledHeight) screenYpos -= targetContainerHeight;
						// set the position
						targetContainer.style.left = screenXpos + 'px';
						targetContainer.style.top = screenYpos + 'px';
					}
				},
				// events
				toggle: function(node, event){
					var objNode = node;
					var t2n = classBehaviours.handlers.toggleNextNode;
					var cu = classBehaviours.utilities;
					// get all information on this node
					targetLabel = objNode;
					targetAnchor = (targetLabel.getAttribute('href')!=null) ? (targetLabel.getAttribute('href').indexOf('#')>-1) ? targetLabel.getAttribute('href').split('#')[1] : null : null ;
					targetContainerId = cu.getClassParameter(targetLabel, 'id', targetAnchor);
					targetRecursion = cu.getClassParameter(targetLabel, 'parent', null);
					targetClosable = (cu.getClassParameter(targetLabel, 'closable', 'yes') == 'yes');
					targetAtMouse = (cu.getClassParameter(targetLabel, 'atmouse', 'no') == 'yes');
					targetContainer = (targetContainerId!=null) ? document.getElementById(targetContainerId) : t2n.findContainer(targetLabel, targetRecursion) ;
					// if the target container is not marked for hiding or showing, mark it now
					if(targetContainer.className.indexOf('hideThisNode')<0 && targetContainer.className.indexOf('showThisNode')<0) targetContainer.className += ' showThisNode' ;
					// call for the node to grow or shrink
					targetGrows = (targetContainer.className.indexOf('hideThisNode')>-1);
					if(!targetGrows && targetClosable || targetGrows) t2n.update(targetLabel.id, targetGrows);
					// position the node at the mouse' position if needed
					if(targetAtMouse && targetGrows){
						// get the position
						screenXpos = (typeof(event)!='undefined' && document.all) ? event.x : that.layerX ;
						screenYpos = (typeof(event)!='undefined' && document.all) ? event.y : that.layerY ;
						// set the position
						t2n.positionContainer(targetContainer, screenXpos, screenYpos);
					}
					// cancel the click
					if(event!=null) event.preventDefault ? event.preventDefault() : event.returnValue = false;
				},
				update: function(id, grows){
					var t2n = classBehaviours.handlers.toggleNextNode;
					var cu = classBehaviours.utilities;
					// get all information on this node
					var targetLabel = document.getElementById(id);
					var targetAnchor = (targetLabel.getAttribute('href')!=null) ? (targetLabel.getAttribute('href').indexOf('#')>-1) ? targetLabel.getAttribute('href').split('#')[1] : null : null ;
					var targetContainerId = cu.getClassParameter(targetLabel, 'id', targetAnchor);
					var targetFamily = cu.getClassParameter(targetLabel, 'family', null);
					var targetRecursion = cu.getClassParameter(targetLabel, 'parent', null);
					var targetContainer = (targetContainerId!=null) ? document.getElementById(targetContainerId) : t2n.findContainer(targetLabel, targetRecursion) ;
					// TARGET NODE
					// prepare the container
					targetContainer.style.overflow = 'hidden';
					targetContainer.style.visibility = 'visible';
					// open or close the container
					if(!grows){
						classBehaviours.fader.size(targetContainer, null, 1, t2n.step, t2n.delay, t2n.acceleration, function(){classBehaviours.handlers.hideThisNode.start(targetContainer)});
					}else{
						classBehaviours.fader.size(targetContainer, 1, null, t2n.step, t2n.delay, t2n.acceleration, function(){classBehaviours.handlers.showThisNode.start(targetContainer)});
					}
					// activate the link
					targetLabel.className = (!grows) ? targetLabel.className.replace('active', 'link') : targetLabel.className.replace('link', 'active');
					// PEER NODES
					// get all nodes of this class
					var allNodes = cu.getElementsByClassName(t2n.name);
					// for every node in the node-list
					for(var a=0; a<allNodes.length; a++){
						// get its properties
						var peerLabel = allNodes[a];
						var peerAnchor = (peerLabel.getAttribute('href')!=null) ? (peerLabel.getAttribute('href').indexOf('#')>-1) ? peerLabel.getAttribute('href').split('#')[1] : null : null ;
						var peerContainerId = cu.getClassParameter(peerLabel, 'id', peerAnchor);
						var peerFamily = cu.getClassParameter(peerLabel, 'family', null);
						var peerRecursion = cu.getClassParameter(peerLabel, 'parent', null);
						var peerContainer = (peerContainerId!=null) ? document.getElementById(peerContainerId) : t2n.findContainer(peerLabel, peerRecursion) ;
						// if this node belongs to the same family and is open but has a different id
						if(peerFamily==targetFamily && peerFamily!=null && peerContainer.className.indexOf('hideThisNode')<0 && peerContainer!=targetContainer){
							// prepare the container
							peerContainer.style.overflow = 'hidden';
							peerContainer.style.visibility = 'visible';
							var peerTarget = peerContainer;
							// close the container
							classBehaviours.fader.size(peerContainer, null, 1, t2n.step ,t2n.delay, t2n.acceleration, function(){classBehaviours.handlers.hideThisNode.start(peerTarget)});
							// de-activate the link
							peerLabel.className = peerLabel.className.replace('active', 'link');
						}
					}
				}
			}

			// hide the "hideThisNode" class behaviour by default
			document.writeln("<style>.hideThisNode{overflow:hidden; visibility:hidden; height:1px;}</style>");
			classBehaviours.handlers.hideThisNode = {
				// properties
				name: 'hideThisNode',
				// methods
				start: function(node){
					node.style.overflow = 'hidden';
					node.style.visibility = 'hidden';
					node.style.height = '1px';
					node.className = node.className.replace('showThisNode', 'hideThisNode');
				}
			}

			// explicit opposite of a hidden node
			document.writeln("<style>.ShowThisNode{overflow:visible; visibility:visible; height:auto;}</style>");
			classBehaviours.handlers.showThisNode = {
				// properties
				name: 'showThisNode',
				// methods
				start: function(node){
					node.style.overflow = 'visible';
					node.style.visibility = 'visible';
					node.style.height = 'auto';
					node.className = node.className.replace('hideThisNode', 'showThisNode');
				}
			}

	// JQUERY WRAPPER
	if(typeof(jQuery)!='undefined'){
		(function($){
			var methods = {
				init : function(options) {
					return this.each(function(){
						classBehaviours.handlers.toggleNextNode.start($(this).context);
					});
				},
				hideThisNode : function(){
					return this.each(function(){
						classBehaviours.handlers.hideThisNode.start($(this).context);
					});
				},
				showThisNode : function(){
					return this.each(function(){
						classBehaviours.handlers.showThisNode.start($(this).context);
					});
				}
			};
			$.fn.toggleNextNode = function(method){
				if(methods[method]) {
					return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
				}else if(typeof method === 'object' || !method){
					return methods.init.apply(this, arguments);
				}else{
					$.error('Method ' +  method + ' does not exist on jQuery.togglenextnode');
				}
			};
		})(jQuery);

		// JQUERY EVENTS
		$(document).ready(function() {
			$(".toggleNextNode").toggleNextNode();
			$(".hideThisNode").toggleNextNode('hideThisNode');
			$(".showThisNode").toggleNextNode('showThisNode');
		});
	}

