function avMenuSlider(aMenuId, aSelectedTitle, aDefaultImagePath)
{
	this.animationDuration		= 200;
	this.panelHeight			= 0;
	this.collapseHeight			= 0;
	this.expanded 				= false;	
	
	this.mMenuId				= aMenuId;
	this.mSelectedTitle			= aSelectedTitle;
	this.mDefaultImagePath		= aDefaultImagePath;
	this.mRoot					= null;
	this.mImageContainer		= null;
	this.mMenuPanel				= null;
	this.mContentContainer		= null;
	this.mMenuBar				= null;
	this.mToggleButton			= null;
	this.mItems					= new Array();
	this.mDefaultImage			= null;
	
	avMenuSlider.prototype.selectByTitle = function(aTitle)
	{
		for (var theIndex = 0; theIndex < this.mItems.length; theIndex++) {
			var theItem = this.mItems[theIndex];
			var theTitle = null;
			if (document.all)
				theTitle = theItem.title.innerText;
			else
			    theTitle = theItem.title.textContent;

			if (theTitle == aTitle) {
				this.displayHeaderImage(theIndex, false);
				return;
			}
		}
		this.displayHeaderImage(-1, false);
	}
	
	avMenuSlider.prototype.reset = function()
	{
		this.displayPanel(false);
		this.displayMenuContent(false);
		this.selectByTitle(this.mSelectedTitle);
	}
	
	avMenuSlider.prototype.displayHeaderImage = function(aIndex, aDisplayPanel)
	{
		if (this.mImageContainer == null)
			return;

		if (this.mDefaultImage != null)
			this.mDefaultImage.style.display = aIndex == -1 ? "block" : "none";
		
		for (var i = 0; i < this.mItems.length; i++) {
			var theItem = this.mItems[i];
			if (i == aIndex) {
				theItem.title.className = "avMenuHighlight";
				theItem.content.style.display = "block";
				theItem.image.style.display = "block";
			} else {
				theItem.title.className = null;
				theItem.content.style.display = "none";
				theItem.image.style.display = "none";
			}
		}
		
		// Show/hide the menu bar.
		this.displayPanel(aDisplayPanel);
	}

	avMenuSlider.prototype.displayPanel = function(aShow)
	{
		if (this.mMenuPanel == null)
			return;

		this.mMenuPanel.style.top = (this.mImageContainer.offsetTop + this.mImageContainer.offsetHeight) + "px";
		this.mMenuPanel.style.display = aShow ? "block" : "none";
		if (!this.expanded)
			this.mMenuPanel.style.height = this.collapseHeight + "px"
		this.invalidateButtonState();
	}
	
	avMenuSlider.prototype.aggregateEvent = function(aEvent)
	{
		if (aEvent == null)
			aEvent = window.event;

		if (typeof(aEvent.relatedTarget) == "undefined")
			aEvent.relatedTarget = aEvent.toElement;
		if (typeof(aEvent.target) == "undefined")
			aEvent.target = aEvent.srcElement;
		return aEvent;
	}

	avMenuSlider.prototype.resetHeaderImage = function(aEvent)
	{
		if (this.expanded)
			return;
		
		var theEvent = this.aggregateEvent(aEvent);
		if (theEvent.relatedTarget == null)
			return;

		if (!this.isChild(theEvent.relatedTarget)) {
			this.reset();
		}
	}
	avMenuSlider.prototype.isChild = function(aNode)
	{
		if (aNode == null || this.mRoot == null)
			return false;
		
		var theParent = aNode;
		for (; theParent != null; theParent = theParent.parentNode) {
			if (theParent == this.mRoot)
				return true;
		}
		return false;
	}

	avMenuSlider.prototype.displayMenuContent = function(aShow)
	{
		if (this.mMenuBar != null) {
			this.expanded = aShow;

			if (aShow) {
				this.mContentContainer.style.height = (this.panelHeight - this.collapseHeight) + "px";
				var theEffect = new avs.effects.Resize();
				theEffect.duration = this.animationDuration;
				theEffect.fromHeight = 0;
				theEffect.toHeight = this.panelHeight;
				theEffect.play(this.mMenuPanel);
				this.mMenuPanel.className = "avMenuPanelExpanded";
			} else {
				this.mMenuPanel.className = "avMenuPanelCollapsed";
				this.mMenuPanel.style.height = this.collapseHeight + "px";
			}
		}
		this.invalidateButtonState();
	}
	avMenuSlider.prototype.invalidateButtonState = function(aShow)
	{
		if (this.mToggleButton != null && this.mContentContainer != null) {
			this.mToggleButton.className = this.expanded ? "avMenuButtonOpen" : "avMenuButtonClose";
		}
	}

	avMenuSlider.prototype.toggleContent = function()
	{
		this.displayMenuContent(!this.expanded);
		this.invalidateButtonState();
	}
	
	avMenuSlider.prototype.initialize = function()
	{
		var me = this;
		
		// Initialize
		if (this.mMenuId == null) {
			// nothing to do :(
		} else {
			var theCurrentDocumentHandler = document.onclick;
			document.onclick = function(aEvent) {
				var theEvent = me.aggregateEvent(aEvent);
				if (!me.isChild(theEvent.target)) {
					if (theCurrentDocumentHandler != null)
						theCurrentDocumentHandler(aEvent);
					me.reset();
				}
			}

			var theContainer = document.getElementById(this.mMenuId);
			if (theContainer.tagName != "UL")
				throw new Error("The Menu is supposed to be a \"Unnamed List (UL)\"");
			theContainer.style.display = "none";
			
			this.mRoot = document.createElement("div");
			this.mRoot.className = "avMenu";
			this.mRoot.style.position = "relative";
			theContainer.parentNode.insertBefore(this.mRoot, theContainer);
			
			var theListItems = new Array();
			var theChildren = theContainer.childNodes;
			for (var i = 0; i < theChildren.length; i++) {
				var theItem = theChildren[i];
				if (theItem.tagName != "LI")
					continue;
				
				theListItems.push(theItem);
			}

			// Parse the list
			var theTable = document.createElement("table");
			theTable.className = "avMenuTitles"
			theTable.style.width = "100%";
			theTable.style.borderCollapse = "collapse";
			var theRow = document.createElement("tr");
			var theBody = document.createElement("tbody");
			theTable.appendChild(theBody);
			theBody.appendChild(theRow);
			
			this.mImageContainer = document.createElement("div");
			this.mImageContainer.className = "avMenuHeaderImage";
			this.mImageContainer.style.position = "relative";
			if (this.mDefaultImagePath != null && this.mDefaultImagePath.length > 0 ) {
				this.mDefaultImage = document.createElement("img");
				this.mDefaultImage.src = this.mDefaultImagePath;
				this.mDefaultImage.style.overflow = "hidden";
				this.mImageContainer.appendChild(this.mDefaultImage);
			}
			
			this.mContentContainer = document.createElement("div");
			this.mContentContainer.className = "avMenuContent";
			this.mContentContainer.style.position = "absolute";
			this.mContentContainer.style.overflow = "hidden";
			this.mContentContainer.style.bottom = this.collapseHeight + "px";
			
			for (var i = 0; i < theListItems.length; i++) {
				var theChildren = theListItems[i].childNodes;
				var theTitle   = null;
				var theContent = null;
				var theImage   = null;
				var theCell    = null;
				
				for (var j = theChildren.length - 1; j >= 0; j--) {
					var theChild = theChildren[j];
					switch (theChild.tagName) {
						case "H6":
							if (theTitle != null)
								throw new Error("Only one \"H6\" element allowed.");
							theTitle = theChild;
							theCell = document.createElement("td");
							theCell.className = "avMenuTitle"
							theCell.appendChild(theTitle);
							break;
						case "DIV":
							if (theContent != null)
								throw new Error("Only one \"DIV\" element allowed.");
							theContent = theChild;
							theContent.style.display = "none";
							this.mContentContainer.appendChild(theContent);
							break;
						case "IMG":
							if (theImage != null)
								throw new Error("Only one \"IMG\" element allowed.");
							theImage = theChild;
							theImage.style.display = "none";
							this.mImageContainer.appendChild(theChild);
							break;
					}
				}
				if (theTitle != null && theImage != null && theContent != null) {
					theCell.onmouseover = function()
					{
						var theId = parseInt(this.getAttribute("avId"));
						me.displayHeaderImage(theId, true);
					}
					theRow.appendChild(theCell);
					var theItem = {title: theTitle, content: theContent, image: theImage}
					theCell.setAttribute("avId", this.mItems.length);
					this.mItems.push(theItem);
				}
			}
			
			this.mMenuPanel = document.createElement("div");
			this.mMenuPanel.className = "avMenuPanelCollapsed";
			this.mMenuPanel.style.position = "absolute";
			this.mMenuPanel.style.display = "none";
			this.mMenuPanel.style.width = "100%";
			
			this.mMenuBar = document.createElement("div");
			this.mMenuBar.className = "avMenuBar";
			this.mMenuBar.style.display = "block";
			this.mMenuBar.style.position = "absolute";
			this.mMenuBar.style.left 	= "0px";
			this.mMenuBar.style.bottom 	= "0px";
			this.mMenuBar.style.width 	= "100%";
			this.mMenuBar.style.height 	= this.collapseHeight + "px";
			
			this.mToggleButton = document.createElement("div");
			this.mToggleButton.className = "avMenuToggleButton";
			this.mToggleButton.onclick = function() { me.toggleContent(); }
			this.mMenuBar.appendChild(this.mToggleButton);
			
			this.mMenuPanel.appendChild(this.mContentContainer);
			this.mMenuPanel.appendChild(this.mMenuBar);
			
			this.mRoot.appendChild(theTable);
			this.mRoot.appendChild(this.mImageContainer);
			this.mRoot.appendChild(this.mMenuPanel);
			
			this.displayMenuContent(false);
			this.mRoot.onmouseout = function (aEvent) { me.resetHeaderImage(aEvent); }
			this.selectByTitle(this.mSelectedTitle);
		}
	}
	
	this.initialize();
}

avs = {}
avs.effects = {}
avs.effects.Effect = function() {

	// public properties
	this.duration = 1000;
	this.elapsed  = 0;
	this.target   = null;

	// private members
	this._mTimer	= null;
	this._mInterval	= 50;

	avs.effects.Effect.prototype.play = function(aTarget) {
		if (this._mTimer != null)
			return;
		
		var theTarget = aTarget;
		if (typeof(aTarget) == "string")
			theTarget = document.getElementById(aTarget);
		
		this.target = theTarget;
		this.elapsed = 0;
		this.onStart();
		this._onBeforeRender();
	}	
	avs.effects.Effect.prototype.onRender = function() {
		alert("U need to override the onRender function");
	}
	avs.effects.Effect.prototype.onStart = function() {
		alert("U need to override the onStart function");
	}
	avs.effects.Effect.prototype.onEnd = function() {
		alert("U need to override the onEnd function");
	}
	avs.effects.Effect.prototype._onBeforeRender = function() {
		this.elapsed += this._mInterval;
		this.onRender();
		if (this.elapsed < this.duration) {
			var me = this;
			this._mTimer = window.setTimeout(function() { me._onBeforeRender(); }, this._mInterval);
		} else {
			this._mTimer = null;
			this.onEnd();
		}
	}
}
avs.effects.Resize = function() {
	this.width 			= 0;
	this.height 		= 0;
	this.fromWidth		= undefined;
	this.toWidth		= undefined;
	this.fromHeight		= undefined;
	this.toHeight		= undefined;

	avs.effects.Resize.prototype.onStart = function() {
		this.width = this.target.offsetWidth;
		this.height = this.target.offsetHeight;
	}
	avs.effects.Resize.prototype.onEnd = function() {
		this.target.style.width = (this.toWidth == undefined ? this.width : this.toWidth) + "px";
		this.target.style.height = (this.toHeight == undefined ? this.height : this.toHeight) + "px";
	}
	avs.effects.Resize.prototype.onRender = function() {
		var theSteps = this.duration / this._mInterval;
		var theCurrentStep = (this.duration - this.elapsed) / this._mInterval;

		var theStartWidth = this.fromWidth == undefined ? this.width : this.fromWidth;
		var theEndWidth   = this.toWidth == undefined ? this.width : this.toWidth;
		var theDiffWidth = theEndWidth - theStartWidth;
		if (theDiffWidth != 0) {
			var theWidth = (theSteps - theCurrentStep) * (theDiffWidth / theSteps);
			this.target.style.width = theWidth + "px";
		}

		var theStartHeight = this.fromHeight == undefined ? this.height : this.fromHeight;
		var theEndHeight   = this.toHeight == undefined ? this.height : this.toHeight;
		
		var theDiffHeight = theEndHeight - theStartHeight;
		if (theDiffHeight != 0) {
			var theHeight  = (theSteps - theCurrentStep) * (theDiffHeight / theSteps);
			this.target.style.height = theHeight + "px";
		}
	}
}
avs.effects.Resize.prototype = new avs.effects.Effect();


function getStyle(aElement, aStyleProperty)
{
	var theNode = typeof(aElement) == "string" ? document.getElementById(aElement) : aElement;
	var theStyle = null;
	if (theNode.currentStyle)
		theStyle = theNode.currentStyle[aStyleProperty];
	else if (window.getComputedStyle)
		theStyle = document.defaultView.getComputedStyle(aElement, null).getPropertyValue(aStyleProperty);
	
	return theStyle;
}