var Accordion =
{
	frameRate: 100,
	duration: 0.3,
	
	init: function()
	{
		var accordions = $(".accordion");

		for (var i = 0, ii = accordions.length; i < ii; i++)
		{
			var folds = accordions[i].childNodes;
			for (var j = 0, jj = folds.length; j < jj; j++)
			{
				if (folds[j].nodeType == 1)
				{
					var accordionContent = document.createElement("div");
			        accordionContent.className = "accordionContent";

			        for (var k = 0; k < folds[j].childNodes.length; k++)
			        {
			        	if (folds[j].childNodes[k].nodeName.toLowerCase() !=
			        			"h2")
			        	{
			        		accordionContent.appendChild(folds[j].childNodes[k]);
			        		k--;
			        	}
			        }

			        folds[j].appendChild(accordionContent);
			        folds[j]._accordionContent = accordionContent;
					
					Accordion.collapse(folds[j]);
					var foldLinks = folds[j].getElementsByTagName("a");
					var foldTitleLink = foldLinks[0];
					$(foldTitleLink).bind("click", Accordion.clickListener);
					
					for (var k = 1, kk = foldLinks.length; k < kk; k++)
					{
						$(foldLinks[k]).bind("focus", Accordion.focusListener);
					}
				}
			}
			
			if (location.hash.length > 1)
			{
				var activeFold = document.getElementById(location.hash.substring(1));
				if (activeFold && activeFold.parentNode == accordions[i])
				{
					Accordion.expand(activeFold);
				}
			}
		}
	},

	collapse: function(fold)
	{
		var content = fold._accordionContent;
		content._height = parseInt(content.style.height, 10);
		content._increment = content._height /
				(Accordion.frameRate * Accordion.duration);
		
		if ($(fold).hasClass("expanded"))
		{
			clearTimeout(fold._accordionContent._timer);
			Accordion.collapseAnimate(fold._accordionContent);
		}
		else
		{
			$(fold).addClass("collapsed");
		}
	},
	
	collapseAnimate: function(content)
	{
		var newHeight = content._height - content._increment;
		
		if (newHeight < 0)
		{
			newHeight = 0;
			$(content.parentNode).removeClass("expanded");
			$(content.parentNode).addClass("collapsed");
		}
		else
		{
			var nextFrame = function()
			{
				Accordion.collapseAnimate(content);
			};
			
			content._timer = setTimeout(nextFrame, 1000 / Accordion.frameRate);
		}
		
		content._height = newHeight;
		content.style.height = Math.round(newHeight) + "px";
	},

	collapseAll: function(accordion)
	{
		var folds = accordion.childNodes;
		for (var i = 0, ii = folds.length; i < ii; i++)
		{
			if (folds[i].nodeType == 1)
			{
				Accordion.collapse(folds[i]);
			}
		}
	},

	expand: function(fold)
	{
		var content = fold._accordionContent;
		
		if (!$(fold).hasClass("expanded"))
		{
			Accordion.collapseAll(fold.parentNode);
			content.style.height = "0";
			content._height = 0;
			$(fold).removeClass("collapsed");
			$(fold).addClass("expanded");
			content._increment = content.scrollHeight /
					(Accordion.frameRate * Accordion.duration);
			Accordion.expandAnimate(content);
		}
	},
	
	expandAnimate: function(content)
	{
		var newHeight = content._height + content._increment;
		
		if (newHeight > content.scrollHeight)
		{
			newHeight = content.scrollHeight;
		}
		else
		{
			var nextFrame = function()
			{
				Accordion.expandAnimate(content);
			};
			
			content._timer = setTimeout(nextFrame, 1000 / Accordion.frameRate);
		}
		
		content._height = newHeight;
		content.style.height = Math.round(newHeight) + "px";
		content.scrollTop = 0;
	},
	
	clickListener: function(event)
	{
		var fold = this.parentNode.parentNode;
		if ($(fold).hasClass("collapsed"))
		{
			Accordion.expand(fold);
		}
		else
		{
			Accordion.collapse(fold);
		}
		event.preventDefault();
	},
	
	focusListener: function(event)
	{
		var element = this;
		while (element.parentNode)
		{
			if ($(element.parentNode).hasClass("accordion"))
			{
				Accordion.expand(element);
				return;
			}
			element = element.parentNode;
		}
	}
};

Accordion.init();

