/* Menu.class.js 

This script will provide dropdown menus
Requires prototype.js
Written by Jeff Fohl for Godengo. jeff@godengo.com
Copyright, Godengo, Inc. 2010

*/

// this class defines the menu and all of its items
var Menu = Class.create({
						
	initialize:	function(menuContainerID, options) {
		// detect for the hated IE6
		Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6;
		Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 7;
		// debugger
		//this.console = new Element('div', { 'style': 'padding:10px; background:#fff; border:solid 1px #333; margin-bottom:10px; text-align:left;' });
		//var bodyEl = $$('body')[0];
		//bodyEl.insert({'top':this.console});
		this.options = Object.extend({
			dropshadow : true, // render a Javascript dropshadow?
			dropShadowOpacity : 50, // the opacity of the dropshadow (1-100)
			dropShadowSize : 0,
			offset : 0, // the offset of each element.
			delay : 100 // delay, in milliseconds for menus to go away after rolling off of them
				}, options || {});
		this.name = menuContainerID;
		this.menuObjects = [];
		this.flyOuts = [];
		this.menuContainer = $(menuContainerID);
		this.menuButtons = this.menuContainer.select("a.dropdown");
		this.flies = this.menuContainer.select("div.flyout");
		// we need to briefly make all elements visible, so we can measure them upon class instantiation.
		for (var x=0; x < this.flies.length; x++) {
				this.flies[x].style.display = "block";
		}
		for (var y=0; y < this.menuButtons.length; y++) {
			var submenu = this.menuButtons[y].siblings();
			this.menuObjects[y] = new MenuItem(this,this.menuButtons[y],submenu[0]);
			this.menuObjects[y].id = y;
		}
		// and now we make them invisible again
		for (var z=0; z < this.flies.length; z++) {
				this.flies[z].style.display = "none";
		}
	}
});

// This is the base class for the menu items, and controls the children of each top-level menu item.
// These menu items will be positioned just below their parent.

var MenuItem = Class.create({
	
	//initialization actions
	initialize: function(masterObject,button,menu) {
		this.button = button;
		this.button.savedClass = this.button.className;
		this.menu = menu;
		this.masterObject = masterObject;
		var thisMenu = this;
		thisMenu.button.onmouseover = function () {
			thisMenu.showMenu();
		};
		thisMenu.button.onmouseout = function () {
			thisMenu.rollOff();
		};
		if (this.menu !== null) {
			thisMenu.menu.onmouseover = function () {
				thisMenu.cancelTimer();
			};
			thisMenu.menu.onmouseout = function () {
				thisMenu.rollOff();
			};
		}
		this.ul = this.menu.firstDescendant();
		this.getDimensions();
		
		this.menuContainerHeight = (this.dimensions.height+this.masterObject.options.dropShadowSize)+'px';
		this.menuContainerWidth = (this.dimensions.width+this.masterObject.options.dropShadowSize)+'px';
		this.menu.setStyle({height:this.menuContainerHeight,width:this.menuContainerWidth});
		this.ul.setStyle({position:'absolute',zIndex:this.masterObject.options.dropShadowSize});
		
		if (this.masterObject.options.dropshadow === true) {
			this.addShadow();
		}
		this.menuItems = this.ul.childElements();
		
		for (var x=0;x<this.menuItems.length;x++) {
			// if IE6, set the width of the anchor elements in the list
			
			if (Prototype.Browser.IE6 || Prototype.Browser.IE7) {
				var a = this.menuItems[x].firstDescendant();
				var paddingRight = a.getStyle('paddingRight');
				var paddingLeft = a.getStyle('paddingLeft');
				var padding = parseInt(paddingRight) + parseInt(paddingLeft);
				a.style.width = this.dimensions.width - padding;
				// this.masterObject.console.insert({'bottom':this.dimensions.width+", "});
			}
			
			var submenus = this.menuItems[x].getElementsByTagName("div");
			if (submenus.length > 0) {
				var submenu = submenus[0];
				var newButton = this.menuItems[x].getElementsByTagName("a")[0];
				var newSub = new SubMenu(this.masterObject,newButton,submenu);
				newSub.childInit();
			}
		}
	},
	
	// clear the timer
	cancelTimer: function () {
		clearTimeout(this.timer);
	},
	// set the timer to hide the menu when you roll off of it
	rollOff: function () {
		var closeMenu = this.masterObject.name+".menuObjects["+this.id+"].hideMenu()";
		this.timer = setTimeout(closeMenu,this.masterObject.options.delay);
	},
	// show the menu
	showMenu: function () {
		for (var i=0;i<this.masterObject.menuObjects.length;i++) {
			this.masterObject.menuObjects[i].hideMenu();
			this.masterObject.menuObjects[i].cancelTimer();
		}
		if (this.menu !== null) {
		this.menu.style.display = "block";
		this.button.className += " hover";
		}
	},
	
	// hide the menu
	hideMenu: function () {
		if (this.menu !== null) {
		this.menu.style.display = "none";
		this.button.className = this.button.savedClass;
		}
	},
	
	// add a dropshadow to the menu
	addShadow: function () {
		this.dropShadow = [];
		for (var i=0; i < this.masterObject.options.dropShadowSize; i++) {
			this.dropShadow[i] = new Element('div');
			var zeeIndex = ((this.masterObject.options.dropShadowSize)-1)-i;
			var offsetY = i+'px';
			var offsetX = i+'px';
			// dropshadow algorithm
			var opacity = ((this.masterObject.options.dropShadowOpacity/2)/(this.masterObject.options.dropShadowSize/i))*0.01; 
			var shadowHeight = ((this.dimensions.height+this.masterObject.options.dropShadowSize)-(i*2))+'px';
			var shadowWidth = ((this.dimensions.width+this.masterObject.options.dropShadowSize)-(i*2))+'px';
			var rounded = Math.round(this.masterObject.options.dropShadowSize/2)+'px';
			this.dropShadow[i].setOpacity(opacity);
			this.dropShadow[i].setStyle({position:'absolute',backgroundColor:'#000000',height:shadowHeight,width:shadowWidth,top:offsetY,left:offsetX,zIndex:zeeIndex,MozBorderRadius:rounded,WebkitBorderRadius:rounded});
			this.menu.insert({'bottom':this.dropShadow[i]});
		}
	},
	
	// Here we add a border to the bottom element (in case one was not set in the CSS)
	// Then, we measure the size of the menu, and remove the bottom border (for aesthetics)
	getDimensions: function () {
		var liElements = this.ul.childElements();
		var lastLi = liElements[liElements.length-1];
		lastLi.setStyle({"border-bottom":"solid 1px #fff"});
		this.dimensions = this.menu.getDimensions();
		this.dimensions.height -= 1;
		lastLi.setStyle({borderBottom:'none'});
	}
});

// SubMenu class inherits from Menu class. This class handles menu items below the second tier of items, if they exist.
// These menu items will be positioned to the right of their parent.

var SubMenu = Class.create(MenuItem, {
	
	childInit: function () {
		this.flyoutID = (this.masterObject.flyOuts.push(this))-1;
		this.parentLi = this.menu.parentNode;
		this.parentLiWidth = this.parentLi.getWidth();
		this.menuOffset = this.parentLiWidth+this.masterObject.options.offset+"px";
		this.menu.setStyle({height:this.menuContainerHeight,width:this.menuContainerWidth,left:this.menuOffset,top:"0px"});
	},
	
	rollOff: function () {
		var closeMenu = this.masterObject.name+".flyOuts["+this.flyoutID+"].hideMenu()";
		this.timer = setTimeout(closeMenu,this.masterObject.options.delay);
	},
	
	showMenu: function () {
		if (this.menu !== null) {
		this.menu.style.display = "block";
		}
	},
	
	hideMenu: function () {
		if (this.menu !== null) {
			this.menu.style.display = "none";
		}
	}
});