if(typeof Array.prototype.push=="undefined"){
	Array.prototype.push=function(stuff){
		this[this.length]=stuff;
	}
}
if(typeof Function.prototype.call=="undefined"){
	Function.prototype.call = function () {
		var oObject = arguments[0];
		oObject._this_func = this;
		var aArgs = new Array();
		for (var i=1; i < arguments.length; i++) {
			aArgs[aArgs.length] = "arguments[" + i + "]";
		}
		eval("oObject._this_func(" + aArgs.join(",") + ")");
		oObject._this_func = null;
	};
}
// Constructor
// Turns a list into an accordion
function Accordion(htmlList, openItemNumber){
	this.basicAnimation=true;
	if(document.body && document.body.style.opacity!=null){
		// supports alpha fading
		this.basicAnimation=false;
	}
	this.list=htmlList;
	this.listHeadings=new Array();
	this.listItems=new Array();
	this.listItemHeights=new Array();
	this.currentItem=openItemNumber;
	this.animSpeed=0.3;
	// set up arrays and attach event listeners to headings
	if(this.list){
		for(var i=0; i<this.list.childNodes.length; i++){
			var node=this.list.childNodes[i];
			if(node.nodeType!=3){
				this.listHeadings.push(node);
				YAHOO.util.Event.addListener(this.list.childNodes[i], "click", this.clickListener, this);
				var itemNode=this.getFirstRealChild(node, "UL");
				if(itemNode){
					this.listItems.push(itemNode);
					var region=YAHOO.util.Dom.getRegion(itemNode);
					var realHeight=region.bottom-region.top;
					this.listItemHeights.push(realHeight);
				}else{
					this.listItems.push(null);
					this.listItemHeights.push(0);
				}
			}
		}
		this.closeAll();
	}
	if(this.currentItem>=0 && this.list){
		this.open(this.currentItem);
	}
}

Accordion.prototype.getFirstRealChild=function(node, type){
	var result=null;
	for(var i=0; i<node.childNodes.length && !result; i++){
		if(node.childNodes[i].nodeType!=3 && node.childNodes[i].nodeName==type){
			result=node.childNodes[i];
		}
	}
	return result;
}

Accordion.prototype.removeClass=function(target, className){
	var currentClasses=target.className.split(" ");
	var newClasses="";
	for(var i=0; i<currentClasses.length; i++){
		if(currentClasses[i]!=className){
			newClasses+=" "+currentClasses[i];
		}
	}
	target.className=newClasses;
}

Accordion.prototype.closeAll=function(){
	for(var i=0; i<this.listItems.length; i++){
		if(this.listItems[i]){
			this.listItems[i].style.display="none";
			this.listItems[i].style.height="0px";
			if(!this.basicAnimation){
				this.listItems[i].style.opacity=0;
			}
			this.removeClass(this.listHeadings[i], "expanded");
		}
	}
}

Accordion.prototype.open=function(itemNo){
	this.listItems[itemNo].style.display="";
	this.listItems[itemNo].style.height=this.listItemHeights[itemNo];
	this.listHeadings[itemNo].className+=" expanded";
	if(!this.basicAnimation){
		this.listItems[itemNo].style.opacity=1;
	}
}

Accordion.prototype.expand=function(itemNo){
	var expandNode=this.listItems[itemNo];
	if(!expandNode){
		return;
	}
	var headingNode=this.listHeadings[itemNo];
	var removeClass=this.removeClass;
	// change the active class
	if(this.currentItem>=0){
		this.removeClass(this.listHeadings[this.currentItem], "expanded");
	}
	headingNode.className+=" expanded";
	var attributes={
		height: {to: this.listItemHeights[itemNo]}
	}
	if(!this.basicAnimation){
		attributes.opacity={to: 1};
	}
	var anim = new YAHOO.util.Anim(expandNode, attributes, this.animSpeed, YAHOO.util.Easing.easeOut);
	if(!this.basicAnimation){
		anim.onStart.subscribe(
			function(){
				this.getEl().style.opacity=0;
				this.getEl().style.height="0px";
				this.getEl().style.display="";
			}
		);
	}else{
		anim.onStart.subscribe(
			function(){
				this.getEl().style.height=1;
				this.getEl().style.display="";
			}	
		);
	}
	anim.onComplete.subscribe(
		function(){
			this.getEl().style.display="";
		}
	);
	anim.animate();
}

Accordion.prototype.contract=function(itemNo){
	var contractNode=this.listItems[itemNo];
	if(!contractNode){
		return;
	}
	var headingNode=this.listHeadings[itemNo];
	var removeClass=this.removeClass;
	var attributes={
		height: {to: 2}
	}
	if(!this.basicAnimation){
		attributes.height.to=0;
		attributes.opacity={to: 0};
	}
	var anim = new YAHOO.util.Anim(contractNode, attributes, this.animSpeed, YAHOO.util.Easing.easeOut);
	var startHeight=this.listItemHeights[itemNo];
	if(!this.basicAnimation){
		anim.onStart.subscribe(
			function(){
				this.getEl().style.opacity=1;
				this.getEl().style.height=startHeight;
				this.getEl().style.display="";
			}
		);
	}else{
		anim.onStart.subscribe(
			function(){
				this.getEl().style.height=startHeight;
				this.getEl().style.display="";
				this.getEl().style.visibility="hidden";
			}
		);
	}
	anim.onComplete.subscribe(
		function(){
			this.getEl().style.display="none";
			this.getEl().style.visibility="";
		}
	);
	anim.animate();
}

Accordion.prototype.clickListener=function(ev, accordion){
	// the "this" scope is the heading node the event was registered on
	// the "accordion" parameter is what you'd expect to be the "this" scope
	// restore some semblance of normality by delegating to a rescoped function
	accordion.handleClick.call(accordion, this);
	YAHOO.util.Event.stopEvent(ev);
}

Accordion.prototype.handleClick=function(headingNode){
	var headingNumber;
	for(var i=0; i<this.listHeadings.length && !headingNumber; i++){
		if(this.listHeadings[i]==headingNode){
			headingNumber=i;
		}
	}
	if(headingNumber!=this.currentItem){
		// something has actually changed
		this.contract(this.currentItem);
		this.expand(headingNumber);
		this.currentItem=headingNumber;
	}
}
