/**
 * MooMenu 
 * @version 0.62 (beta)
 * @author Jason J. Jaeger | greengeckodesign.com
 * @copyright 2008 Jason John Jaeger
 * @license MIT-style License
 *			Permission is hereby granted, free of charge, to any person obtaining a copy
 *			of this software and associated documentation files (the "Software"), to deal
 *			in the Software without restriction, including without limitation the rights
 *			to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *			copies of the Software, and to permit persons to whom the Software is
 *			furnished to do so, subject to the following conditions:
 *	
 *			The above copyright notice and this permission notice shall be included in
 *			all copies or substantial portions of the Software.
 *	
 *			THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *			IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *			FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *			AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *			LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *			OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *			THE SOFTWARE.
 *	
 *  @changeLog_________________________________________________________________________________
 *  Feb 17th 2008:
 *  JJJ - Incremented version to 0.62
 *  	- Added mmbClassName and mmbFocusedClassName options to allow morphing of main menu btns
 *  
 *  Feb 16th 2008:
 *  JJJ - Incremented version to 0.61
 *  	- Made changes to options syntax. 
 *  	- Improved keyboard accessability to take into account a menu's orientation, and its x and y direction when using arrow keys
 *  	- Added matchWidthMode option.
 *  
 *  Feb 14th 2008:
 *  JJJ - Incremented version to 0.60
 *  	- Added menuWidth option to simulate a table based layout for the main menu when the orienation is horizontal
 **/

var MooMenu = new Class({
	options: {
        id: 'nav',//the id of the main menu (ul or ol)
		
		//subMenu behavior
		effect: 'slide & fade',// 'slide', 'fade', 'slide & fade', or  null
		duration: 600,//duration of the effect in milliseconds
		physics: Fx.Transitions.Quint.easeOut,//how the effect behaves
		hideDelay: 1000,//in milliseconds, how long you have after moving you mouse off of the submenus before they dissapear
		
		//layout
		menuWidth:null,//stretch main menu btn widths to fit within the width {set in the css} of the parent UL or OL
		matchWidthMode:false,//initial submenus match their parent button's width
		orientation: 'horizontal',//horizontal or vertical
		direction:{	x: 'right',	y: 'down' },//for submenus ( relative to the parent button )left or right, up or down
		
		//dynamic style
		opacity: 95,//of the submenus
		mmbFocusedClassName:null,//main menu button classname, used for morphing to focused state
		mmbClassName:null,//main menu button classname, used for morphing back to original state
		
		//tweak
		tweakInitial:{ x:0, y:0	},//if you need to tweak the placement of the initial submenus
		tweakSubsequent:{ x:0, y:0 },//if you need to tweak the placement of the subsequent submenus

		debug:false
    },
	
	classElHash: new Hash(),//index = childMenu element id, item = submenu class
	hideAllMenusTimeout:null,
	parentBtns: new Hash(),
	
	initialize: function(options){
        this.setOptions(options);
		this.options.opacity = this.options.opacity /100;
		var btnArray = $(this.options.id).getElements('a');
		var tempObjArray= [];
		
		//initialize directions
		this.options.direction.x = this.options.direction.x.toLowerCase();
		this.options.direction.y = this.options.direction.y.toLowerCase();
		if(this.options.direction.x === 'right'){
			this.options.direction.xInverse = 'left';
		}else if(this.options.direction.x === 'left'){
			this.options.direction.xInverse = 'right';
		}
		if(this.options.direction.y === 'up'){
			this.options.direction.yInverse = 'down';
		}else if(this.options.direction.y === 'down'){
			this.options.direction.yInverse = 'up';
		}
		
		//create temp objects
		btnArray.each(function(x){
			var tempObj = new Object();		   
		   	if ( $(x).getNext('ul')  || $(x).getNext('ol') ) {
				var theSubMenuType = 'subsequent';
				if($(x).parentNode.parentNode.id && $(x).parentNode.parentNode.id == this.options.id){theSubMenuType ='initial';	}
				tempObj.btn=$(x);
				this.parentBtns.set(this.getOrSetId(tempObj.btn), tempObj.btn);
				if(theSubMenuType === 'initial'){
					tempObj.btn.addClass('mainMenuParentBtn');
				}else{
					tempObj.btn.addClass('subMenuParentBtn');
				}
				tempObj.childMenu=$(x).getNext();
				tempObj.parentSubMenus= this.getParents($(x), this.options.id, 'ul,ol');
				tempObj.subMenuType=theSubMenuType;
				tempObjArray.push(tempObj);
			}
		}.bind(this));

		//rip the submenus apart into separate divs
		var subMenusContainer = new Element('div', { 'id': 'subMenusContainer'	}).inject( document.body ,'inside');
		tempObjArray.each(function(item,index){	
			var subMenuOuterWrapper = new Element('div', {	'class': 'smOW'	}).inject(subMenusContainer)
			item.childMenu.inject(subMenuOuterWrapper);
			item.childMenu = subMenuOuterWrapper;
			this.classElHash.set(this.getOrSetId(subMenuOuterWrapper), null);
		}.bind(this));
		
		//update the IDs in the parentSubMenus Arrays in the temp objects
		for (var index in tempObjArray) {
			if (tempObjArray.hasOwnProperty(index)) {
				var tempParentSubMenusHash = new Hash();
				for(var x in tempObjArray[index].parentSubMenus){
					if(tempObjArray[index].parentSubMenus.hasOwnProperty(x)){
						var currentParentId = $(tempObjArray[index].parentSubMenus[x]).getParent().id;
						tempParentSubMenusHash.set(currentParentId,null);
					}
				}
				tempObjArray[index].parentSubMenus = tempParentSubMenusHash;
			}
		}
		subMenusContainer.getElements('a').each(function(item,index){ item.set('tabindex','-1'); });
		
		//now create the MooSubMenu class instances from the temp objects
		for (var index in tempObjArray) {
			if (tempObjArray.hasOwnProperty(index)) {
				var aSubMenu = new MooSubMenu(this.options,{
					root:this,
					btn:tempObjArray[index].btn,
					childMenu:tempObjArray[index].childMenu,
					parentSubMenus: tempObjArray[index].parentSubMenus,
					subMenuType:tempObjArray[index].subMenuType
				});
				aSubMenu.setOptions(this.options);//so the submenus inherit the current option values instead of the default option values
				this.classElHash[tempObjArray[index].childMenu.id] = aSubMenu;
			}
		}

		//add class references to the parentSubMenus Hashes
		this.classElHash.each(function(item,index){	
			var parentArr =[];
			item.parentSubMenus.each(function(item2,index2){ 
				item.parentSubMenus[index2] = this.classElHash[index2]; 
				parentArr.push(this.classElHash[index2]);
			}.bind(this));
			item.parentSubMenu = parentArr[0];
		}.bind(this));
		
		//attach event handlers to non-parent main menu buttons
		var nonParentBtns = $(this.options.id).getElements('a').filter(function(item, index){ return !this.parentBtns.contains(item); }.bind(this));
		nonParentBtns.each(function(item, index){
			item.addEvents({
				'mouseenter': function(e){
					e = new Event(e).stop();
					item.focus();			
				}.bind(this),
				
				'focus': function(e){
					e = new Event(e).stop();
					this.hideAllSubMenusNow();	
					
					if(this.options.mmbClassName && this.options.mmbFocusedClassName){
						$(item).retrieve('btnMorph', new Fx.Morph(item, { 'duration':(this.options.duration/2), transition:this.options.physics, link:'cancel'})).start(this.options.mmbFocusedClassName); 
					}
				}.bind(this),
				
				'mouseleave':function(e){
					e = new Event(e).stop();
					item.blur();
				}.bind(this),
				
				'blur':function(e){
					e = new Event(e).stop();
					if (this.options.mmbClassName && this.options.mmbFocusedClassName) {
						$(item).retrieve('btnMorph', new Fx.Morph(item, {	'duration': (this.options.duration * 5),transition: this.options.physics,link: 'cancel'	})).start(this.options.mmbClassName);
					}
				}.bind(this),
				
				'keydown' : function(e){
				    var event = new Event(e);
					if (e.key === 'up' || e.key === 'down' || e.key === 'left' || e.key === 'right') {	e.stop();	}
					
					if( e.key === 'left' && this.options.orientation === 'horizontal' || 
						e.key === 'up' && this.options.orientation === 'vertical'){
						
						if(item.getParent('li').getPrevious('li')){
							item.getParent('li').getPrevious('li').getFirst('a').focus();
						}else{
							item.getParent('li').getParent().getLast('li').getFirst('a').focus();
						}
					}else if(e.key === 'right' && this.options.orientation === 'horizontal' || 
							 e.key === 'down' && this.options.orientation === 'vertical'){
						if(item.getParent('li').getNext('li')){
							item.getParent('li').getNext('li').getFirst('a').focus();
						}else{
							item.getParent('li').getParent().getFirst('li').getFirst('a').focus();
						}	
					}
				}.bind(this)
			});
		}, this);

		//stretch main menu btn widths to fit within the width of the parent UL or OL
		if(parseFloat(this.options.menuWidth) > 0 && this.options.orientation === 'horizontal'){
			var targetWidth = parseFloat(this.options.menuWidth) ;
			var totalBtnWidth = 0;
			var mainBtns = $(this.options.id).getElements('a');
			var tolerance = 0 + parseFloat($(mainBtns[0]).getStyle('border-left-width')) + parseFloat( $(mainBtns[mainBtns.length-1]).getStyle('border-right-width'));
			var limit = 1000;
			var currentIndex = 0;
			mainBtns.each(function(item,index){ item.setStyles({'padding-left':0,'padding-right':0}) }.bind(this));
			while((totalBtnWidth+tolerance) < targetWidth && limit >0 ){
				limit--;
				totalBtnWidth = 0;
				mainBtns[currentIndex].setStyle('width', mainBtns[currentIndex].getCoordinates().width + 1);
				mainBtns.each(function(item,index){ totalBtnWidth+= item.getCoordinates().width; }.bind(this));
				currentIndex++;
				if(currentIndex>mainBtns.length-1){currentIndex = 0;	}
			}
		}
    },

	getParents: function(obj, wrapperId, tagNames){
		var parents = [];
		if(tagNames){
			tagNames = tagNames.toString().split(",");
			tagNames.each(function(item, index){tagNames[index] = tagNames[index].toLowerCase();}); 
		}
		currentObj = obj;
		var limit = 200;
		var counter = 0;
		while(currentObj.parentNode && currentObj.parentNode.id != wrapperId){
			counter++;
			if(counter > limit){break;}
			if( !tagNames || tagNames.contains(currentObj.parentNode.tagName.toLowerCase())  ){
				parents.push(currentObj.parentNode);
			}
			currentObj = currentObj.parentNode;
		}
		return parents;
	},

	getOrSetId: function(obj){
		if(!obj.id){
			var d = new Date();
			var milli = d.getMilliseconds().toString();
			var randomNumber = Math.floor(Math.random()*1000);
			if(obj.nodeName){
				obj.id = obj.nodeName.toString() + '-' + milli + randomNumber.toString();
			}else{
				obj.id = "element" + milli + randomNumber.toString();	
			}
		}
		return obj.id;
	},
	
	hideAllSubMenusNow: function(){
		$clear(this.hideAllMenusTimeout);
		this.classElHash.each( function(item, index){	item.hideSubMenu();	}.bind(this));
	}  
});
MooMenu.implement(new Options);
MooMenu.implement(new Events);

var MooSubMenu = new Class({
	Extends: MooMenu,
    options: {},
	root:null,
	btn:null,
	childMenu:null,
	subMenuType:null,
	parentSubMenus:new Hash(),
	parentSubMenu: null,
	hidden:true,
	myEffect:null,
	width:false,
	height:null,
	widthMatched:false,
		
	initialize: function(options,uniqueVars){
	    this.setOptions(options);
		for(var x in uniqueVars){	if(uniqueVars.hasOwnProperty(x)){ this[x] = uniqueVars[x];	}	}
		
		if(this.options.effect){
			this.myEffect = new Fx.Morph(
				$(this.childMenu).getFirst(), {	duration: this.options.duration, transition: this.options.physics,  link: 'cancel' } 
			);
		}
		if(this.options.effect === 'slide' || this.options.effect === 'slide & fade'){
			if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' ) {
				this.childMenu.getFirst().setStyle('margin-top','0' );
			}else {
				this.childMenu.getFirst().setStyle('margin-left', '0');
			}
			
		}else if (this.options.effect === 'fade' || this.options.effect === 'slide & fade'){
			this.childMenu.getFirst().setStyle('opacity',0 );
		}
		
		if (this.options.effect != 'fade' && this.options.effect != 'slide & fade') {
			this.childMenu.getFirst().setStyle('opacity',this.options.opacity);
		}
		
		$(this.childMenu).addEvents({
			'mouseenter': function(e){		
			}.bind(this)
		});
		
		//attach event handlers to non-parent sub menu buttons
		var nonParentBtns = $(this.childMenu).getElements('a').filter(function(item, index){ return !this.parentBtns.contains(item); }.bind(this));
		nonParentBtns.each(function(item, index){
			$(item).addClass('subMenuBtn');
			
			item.addEvents({
				'mouseenter': function(e){
					e = new Event(e).stop();
					item.focus();				
				}.bind(this),
				
				'focus': function(e){
					e = new Event(e).stop();
					this.cancellHideAllSubMenus();
					this.hideOtherSubMenus();
				}.bind(this),
				
				'mouseleave': function(e){
					e = new Event(e).stop();
					item.blur();
				}.bind(this),
				
				'blur': function(e){
					e = new Event(e).stop();
					this.cancellHideAllSubMenus();
					this.hideAllSubMenus();
				}.bind(this),
				
				'keydown' : function(e){
				    var event = new Event(e);
					
					if (e.key === 'up' || e.key === 'down' || e.key === 'left' || e.key === 'right' || e.key === 'tab') {	e.stop();	}
					
					if(e.key === 'up'){
						if(item.getParent('li').getPrevious('li')){
							//move focus to the next link up if possible
							item.getParent('li').getPrevious('li').getFirst('a').focus();
						}else if(this.options.direction.y ==='down'){
							//move focus to the parent link
							this.btn.focus();
						}else if(this.options.direction.y ==='up'){
							//move focus to the last link in the subMenu
							item.getParent('li').getParent().getLast('li').getFirst('a').focus();
						}
					}else if(e.key === 'down'){
						if(item.getParent('li').getNext('li')){
							//move focus to the next link down if possible
							item.getParent('li').getNext('li').getFirst('a').focus();
						}else if(this.options.direction.y ==='down'){
							//move focus to the first link in the submenu
							item.getParent('li').getParent().getFirst('li').getFirst('a').focus();
						}else if(this.options.direction.y ==='up'){
							//move focus to the parent link
							this.btn.focus();
						}
					}else if(e.key === this.options.direction.xInverse){
						this.btn.focus();
					}
				}.bind(this)
			});
			
		}, this);
		
		$(this.btn).removeClass('subMenuBtn');
		
		if (this.subMenuType == 'initial') {
			this.btn.addClass('mainParentBtn');	
		}else{	
			this.btn.addClass('subParentBtn');	
		}
		
		$(this.btn).addEvents({
			'mouseenter' : function(e){
				e = new Event(e).stop();
				$(this.btn).focus();
			}.bind(this),
			
			'focus' : function(e){
				e = new Event(e).stop();
				this.cancellHideAllSubMenus();
				this.hideOtherSubMenus();
				this.showSubMenu();
				if(this.subMenuType === 'initial' && this.options.mmbClassName && this.options.mmbFocusedClassName){
					$(this.btn).retrieve('btnMorph', new Fx.Morph($(this.btn), { 'duration':(this.options.duration/2), transition:this.options.physics, link:'cancel' })).start(this.options.mmbFocusedClassName);
				}
				
			}.bind(this),
				
			'mouseleave': function(e){
				e = new Event(e).stop();
				$(this.btn).blur();
			}.bind(this),
			
			'blur': function(e){
				e = new Event(e).stop();
				this.cancellHideAllSubMenus();
				this.hideAllSubMenus();
			}.bind(this),
			
			'keydown' : function(e){
			    e = new Event(e)
				if (e.key === 'up' || e.key === 'down' || e.key === 'left' || e.key === 'right') {	e.stop();	}
				
				if(!this.parentSubMenu){
					//main menu parent buttons
					if(
						this.options.orientation === 'horizontal' && e.key === this.options.direction.y ||
						this.options.orientation === 'vertical' && e.key === this.options.direction.x
					){
						if(this.options.direction.y ==='down'){
							//move focus to the first link in the child menu
							this.childMenu.getFirst().getFirst('li').getFirst('a').focus();
						}else if(this.options.direction.y ==='up'){
							//move focus to the first link in the child menu
							this.childMenu.getFirst().getLast('li').getFirst('a').focus();
						}
					}else if(
						this.options.orientation === 'horizontal' && e.key === 'left' ||
						this.options.orientation === 'vertical' && e.key === this.options.direction.yInverse 
					){
						//move focus to the previous link if possible, if not, move focus to the last link in the menu
						if(this.btn.getParent().getPrevious()){
							this.btn.getParent().getPrevious().getFirst().focus();
						}else{
							this.btn.getParent().getParent().getLast().getFirst().focus();
						}
					}else if(
						this.options.orientation === 'horizontal' && e.key === 'right' ||
						this.options.orientation === 'vertical' && e.key === this.options.direction.y 
					){
						//move focus to the next link if possible, if not, move focus to the first link in the menu
						if (this.btn.getParent().getNext()) {
							this.btn.getParent().getNext().getFirst().focus();
						}else{
							this.btn.getParent().getParent().getFirst().getFirst().focus();
						}
					}
				}else{
					if(e.key === 'tab'){e.stop();}
					//submenu parent buttons
					if (e.key === 'up') {
						if (this.btn.getParent('li').getPrevious('li')) {
							//move focus to the next link up
							this.btn.getParent('li').getPrevious('li').getFirst('a').focus();
						}else if(this.options.direction.y === 'down'){
							//move focus to the parent link
							this.parentSubMenu.btn.focus();
						}else if(this.options.direction.y === 'up'){
							//move focus to the bottom link in this submenu
							this.btn.getParent('li').getParent().getLast('li').getFirst('a').focus();
						}
					}else if(e.key === 'down'){
						if(this.btn.getParent('li').getNext('li')){
							//move focus to the next link down
							this.btn.getParent('li').getNext('li').getFirst('a').focus();
						}else if(this.options.direction.y === 'down'){
							//move focus to the top link in this submenu
							this.btn.getParent('li').getParent().getFirst('li').getFirst('a').focus();
						}else if(this.options.direction.y === 'up'){
							//move focus to the parent link
							this.parentSubMenu.btn.focus();
						}
					}else if(e.key === this.options.direction.xInverse){
						this.parentSubMenu.btn.focus();
					}else if(e.key === this.options.direction.x){
						if(this.options.direction.y === 'down'){
							this.childMenu.getFirst().getFirst('li').getFirst('a').focus();
						}else if(this.options.direction.y === 'up'){
							this.childMenu.getFirst().getLast('li').getFirst('a').focus();
						}
					}
				}
			}.bind(this)	
		});
    },
	
	matchWidth:function(){
		if (this.widthMatched || !this.options.matchWidthMode || this.subMenuType === 'subsequent'){return;}
		var parentWidth = this.btn.getCoordinates().width;
		$(this.childMenu).getElements('a').each(function(item,index){
			var borderWidth = parseFloat($(this.childMenu).getFirst().getStyle('border-left-width')) + parseFloat($(this.childMenu).getFirst().getStyle('border-right-width'));
			var paddingWidth = parseFloat(item.getStyle('padding-left')) +	 parseFloat(item.getStyle('padding-right'));
			var offset = borderWidth + paddingWidth ;
			if(parentWidth > item.getCoordinates().width){
				item.setStyle('width',parentWidth - offset);
				item.setStyle('margin-right',-borderWidth);
			}
		}.bind(this));
		this.width = this.childMenu.getFirst().getCoordinates().width;
		this.widthMatched = true;
	},
	
	hideSubMenu: function() {
		if(this.hidden){return;}
		if (this.subMenuType == 'initial') {
			if(this.options.mmbClassName && this.options.mmbFocusedClassName){
				$(this.btn).retrieve('btnMorph', new Fx.Morph($(this.btn), { 'duration':(this.options.duration), transition:this.options.physics, link:'cancel' })).start(this.options.mmbClassName )
				.chain(function(){
					$(this.btn).removeClass('mainMenuParentBtnFocused');
					$(this.btn).addClass('mainMenuParentBtn');
				}.bind(this));
			}else{
				$(this.btn).removeClass('mainMenuParentBtnFocused');
				$(this.btn).addClass('mainMenuParentBtn');
			}
		}else{
			$(this.btn).removeClass('subMenuParentBtnFocused');
			$(this.btn).addClass('subMenuParentBtn');
		}
		
		if(this.options.effect && this.options.effect.toLowerCase() === 'slide'){
			if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' && this.options.direction.y === 'down') {
				this.myEffect.start({ 'margin-top': -this.height }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' && this.options.direction.y === 'up') {
				this.myEffect.start({ 'margin-top': this.height }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if(this.options.direction.x === 'right'){
				this.myEffect.start({ 'margin-left': -this.width }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if(this.options.direction.x === 'left'){
				this.myEffect.start({ 'margin-left': this.width }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}
		}else if(this.options.effect == 'fade'){
			this.myEffect.start({ 'opacity': 0 }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
		}else if(this.options.effect == 'slide & fade'){
			
			if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' && this.options.direction.y === 'down') {
				this.myEffect.start({ 'margin-top': -this.height,opacity:0 }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' && this.options.direction.y === 'up') {
				this.myEffect.start({ 'margin-top': this.height,opacity:0 }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if(this.options.direction.x === 'right'){
				this.myEffect.start({ 'margin-left': -this.width,opacity:0 }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}else if(this.options.direction.x === 'left'){
				this.myEffect.start({ 'margin-left': this.width, opacity:0 }).chain(function(){	this.childMenu.style.display = "none";	}.bind(this));
			}
		}else{
			this.childMenu.style.display = "none";
		}
		this.hidden = true;
	},
	
	hideOtherSubMenus: function() {
		var showArr = [];
		(this.root.classElHash).each(function(item,index){	
			if(!this.parentSubMenus.contains(item) && this.childMenu.id != index  ){
				item.hideSubMenu();
			}else{
				showArr.push(item);
			}
		}.bind(this));
		
		for(i = (showArr.length-1); i>=0 ;i--){
			
			if(showArr[i].options.direction.x != this.root.options.direction.x && showArr[i].options.direction.x != showArr[i-1].options.direction.x){
				//the sliding effects sometimes goof up at this point in FF, so the KLUDGE for now is to remove the effect on this submenu
				showArr[i].options.effect = null;		
			}
			showArr[i].showSubMenu();		
		}
	},
	
	hideAllSubMenus: function(){
		$clear(this.root.hideAllMenusTimeout);
		this.root.hideAllMenusTimeout = (function(){
			$clear(this.hideAllMenusTimeout);
			this.root.classElHash.each( function(item, index){	item.hideSubMenu();	}.bind(this));
		}).bind(this).delay(this.options.hideDelay);		
	},

	cancellHideAllSubMenus: function(){ 
		$clear(this.root.hideAllMenusTimeout);	
	},
	
	showSubMenu: function(now){
		if(!this.btn || !this.hidden){return;}
	
		if (this.subMenuType == 'initial') {
			$(this.btn).removeClass('mainMenuParentBtn');
			$(this.btn).addClass('mainMenuParentBtnFocused');	
		}else{
			$(this.btn).removeClass('subMenuParentBtn');
			$(this.btn).addClass('subMenuParentBtnFocused');
		}
		
		this.childMenu.setStyles({'display':'block','visibility':'hidden'});
		
		if(!this.width || !this.height ){
			this.width = this.childMenu.getFirst().getCoordinates().width;
			this.height = this.childMenu.getFirst().getCoordinates().height;
			this.childMenu.setStyle('height',this.height,'border');
			if(this.options.effect === 'slide' || this.options.effect === 'slide & fade'){
				if (this.subMenuType == 'initial' && this.options.orientation === 'horizontal' ) {
					this.childMenu.getFirst().setStyle('margin-top','0' );
					if(this.options.direction.y === 'down'){
						this.myEffect.set({ 'margin-top': - this.height });
					}else if(this.options.direction.y === 'up'){
						this.myEffect.set({ 'margin-top': this.height });
					}
				}else {
					if(this.options.direction.x === 'left'){
						this.myEffect.set({ 'margin-left': this.width });
					}else{
						this.myEffect.set({ 'margin-left': -this.width });
					}
				}
			}
		}
		this.matchWidth();
		this.positionSubMenu();
		
		if(this.options.effect === 'slide' ){
			this.childMenu.setStyles({'display':'block','visibility':'visible'});
			if (this.subMenuType === 'initial' && this.options.orientation === 'horizontal') {
				if(now){
					this.myEffect.set({ 'margin-top': 0 });
				}else{
					this.myEffect.start({ 'margin-top': 0 });
				}
			}else{
				if (now) {
					this.myEffect.set({ 'margin-left': 0 });
				}else{
					this.myEffect.start({ 'margin-left': 0 });
				}
			}
		}else if(this.options.effect === 'fade' ){
			if (now) {
				this.myEffect.set({'opacity': this.options.opacity});
			}else{
				this.myEffect.start({'opacity': this.options.opacity});
			}
		}else if(this.options.effect == 'slide & fade'){
			this.childMenu.setStyles({'display':'block','visibility':'visible'});
			this.childMenu.getFirst().setStyles({'left':0});
			if (this.subMenuType === 'initial' && this.options.orientation === 'horizontal') {
				if (now) {
					this.myEffect.set({ 'margin-top': 0, 'opacity': this.options.opacity });
				}else{
					this.myEffect.start({ 'margin-top': 0, 'opacity': this.options.opacity });
				}
			}else{
				if (now) {
					if (this.options.direction.x === 'right') {
						this.myEffect.set({ 'margin-left': 0, 'opacity': this.options.opacity });
					}else if (this.options.direction.x === 'left') {
						this.myEffect.set({ 'margin-left': 0, 'opacity': this.options.opacity });
					}	
				}else{
					if (this.options.direction.x === 'right') {
						this.myEffect.start({ 'margin-left': 0, 'opacity': this.options.opacity });
					}else if (this.options.direction.x === 'left') {
						this.myEffect.start({ 'margin-left': 0, 'opacity': this.options.opacity });
					}
				}
			}
		}else{
			this.childMenu.setStyles({'display':'block','visibility':'visible'});
		}
		this.hidden = false;
		
	},
	
	positionSubMenu: function(){
		
		this.childMenu.setStyle('width',this.width) ;
		this.childMenu.getFirst().setStyle('width',this.width) ;
				
		//if any parent has bounced off a viewport edge, inherit that new direction
		if (this.subMenuType === 'subsequent') {
			if(this.parentSubMenu && this.options.direction.x != this.parentSubMenu.options.direction.x){
				if(this.parentSubMenu.options.direction.x === 'left' && this.options.effect && this.options.effect.contains('slide')){
					this.myEffect.set({ 'margin-left': this.width });	
				}
			}
			this.options.direction.x = this.parentSubMenu.options.direction.x;
			this.options.direction.xInverse = this.parentSubMenu.options.direction.xInverse;
			this.options.direction.y = this.parentSubMenu.options.direction.y;
			this.options.direction.yInverse = this.parentSubMenu.options.direction.yInverse;
		}
		
		if(this.subMenuType == 'initial'){
			if(	this.options.direction.y === 'up'){
				if(this.options.orientation === 'vertical'){
					this.childMenu.style.top = this.btn.getCoordinates().bottom - this.height + this.options.tweakInitial.y + 'px';
				}else{			
					this.childMenu.style.top = this.btn.getCoordinates().top - this.height + this.options.tweakInitial.y + 'px';
				}
			}else if(this.options.orientation == 'horizontal'){
				this.childMenu.style.top = this.btn.getCoordinates().bottom + this.options.tweakInitial.y + 'px';
			}else if(this.options.orientation == 'vertical'){
				this.childMenu.style.top = this.btn.getPosition().y + this.options.tweakInitial.y + 'px';	
			}
			if(	this.options.orientation == 'horizontal'){
				this.childMenu.style.left = this.btn.getPosition().x + this.options.tweakInitial.x + 'px';
			}else if(this.options.direction.x == 'left'){
				this.childMenu.style.left = this.btn.getPosition().x - this.childMenu.getCoordinates().width + this.options.tweakInitial.x + 'px';
			}else if(this.options.direction.x == 'right'){
				this.childMenu.style.left = this.btn.getCoordinates().right + this.options.tweakInitial.x + 'px';
			}
		}else if(this.subMenuType == 'subsequent'){
			
			if(this.options.direction.y === 'down'){
				this.childMenu.style.top = this.btn.getCoordinates().top + this.options.tweakSubsequent.y + 'px';
			}else if(this.options.direction.y === 'up'){
				if((this.btn.getCoordinates().bottom - this.height + this.options.tweakSubsequent.y)< 1){
					this.options.direction.y = 'down';
					this.options.direction.yInverse = 'up';
					this.childMenu.style.top = this.btn.getCoordinates().top + this.options.tweakSubsequent.y + 'px';
				}else{
					this.childMenu.style.top = this.btn.getCoordinates().bottom - this.height + this.options.tweakSubsequent.y + 'px';
				}
			}
			if(this.options.direction.x == 'left'){
				this.childMenu.style.left = this.btn.getCoordinates().left - this.childMenu.getCoordinates().width + this.options.tweakSubsequent.x + 'px';
				
				if( this.childMenu.getPosition().x < 0){
					this.options.direction.x = 'right';
					this.options.direction.xInverse = 'left';
					this.childMenu.style.left = this.btn.getPosition().x + this.btn.getCoordinates().width + this.options.tweakSubsequent.x + 'px';
					
					if(this.options.effect === 'slide' || this.options.effect === 'slide & fade'){
						this.myEffect.set({ 'margin-left': -this.width, 'opacity': this.options.opacity });
					}
				}
			}else if(this.options.direction.x == 'right'){
				this.childMenu.style.left = this.btn.getCoordinates().right + this.options.tweakSubsequent.x + 'px';
				var smRight = this.childMenu.getCoordinates().right;

				if( smRight > document.getCoordinates().width ){
					this.options.direction.x = 'left';
					this.options.direction.xInverse = 'right';
					this.childMenu.style.left = this.btn.getCoordinates().left - this.childMenu.getCoordinates().width + this.options.tweakSubsequent.x + 'px'
					if (this.options.effect === 'slide' || this.options.effect === 'slide & fade') {
						this.myEffect.set({	'margin-left': this.width,	'opacity': this.options.opacity	});
						this.options.direction.x = "left";
						this.options.direction.xInverse = "right";
					}
				}
			}
		}
	}	
});

MooSubMenu.implement(new Options);
MooSubMenu.implement(new Events);