/**
 * Classe Menu - utilisée pour l'animation du menu principal du site. Menu à 1 seul niveau seulement.
 * 
 * @version 1.0
 * @author Sylvain LEPRETRE (sylvain.lepretre@gmail.com)
 */

var MenuTop = Class.create({
	/**
	 * constructeur - prend en paramètre l'ID (ou l'élément lui-même) de la liste du menu
	 * 
	 * @param string elementID - id de la liste du menu ( ou menu lui-même )
	 * @return Menu
	 * 
	 * @constructor
	 * @access public
	 */
	initialize:				function(elementID) {
								// initialisation des variables
								this.element = $(elementID);								
								this.init();
								// enregistrement des observateurs
								this.observe();
							},
	/**
	 * prépare le menu et ses sous-menus
	 * 
	 * @access private
	 */
	init:					function() {
								// parcours du menu principal
								for(var i=0; i<this.element.childNodes.length; i++) {
									var li = $(this.element.childNodes[i]);
									var subMenu = this._getSubMenu(li);	
									if(!subMenu) {
										continue;	
									}
										
									
									li.subMenu = new SubMenu(subMenu);			
									// récupération des dimensions & positions relatives
									
									var liDimensions = li.getDimensions();
									var viewportOffset = this.viewportOffset(li);	
									var offset = {
										'top': 	new String((parseInt(viewportOffset.top) + parseInt(liDimensions.height))+'px'),
										'left': new String((parseInt(viewportOffset.left) + 10)+'px')
									};
									li.subMenu.setOffset(offset);															
								}
							},
	/**
	 * vérifie si le paramètre li (HTMLLIElement) contient un sous menu.
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return bool
	 * 
	 * @access private
	 */
	
	_hasSubMenu:			function(li) {
								var ul = li.getElementsByTagName('ul');
								
								if(!ul || ul.length == 0) {
									return false;
								}
								return true;
							},
	/**
	 * retourne le sous-menu lié à l'élément du menu principal
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return HTMLUListElement|null
	 * 
	 * @access private
	 */
	 
	_getSubMenu:			function(li) {	
								var menu = li.getElementsByTagName('ul');
								if(!menu) {
									return false;
								}
								return $(menu[0]);
							},
	
	/**
	 * retourne la hauteur et la largeur de l'élément passé en paramètre, relativement au menu principal
	 * 
	 * @param HTMLLIElement topMenuElement
	 * @return Object
	 * 
	 * @access private
	 */
	 
	viewportOffset:			function(li) {
								var topMenuOffset = this.element.cumulativeOffset();
								var liOffset = li.cumulativeOffset();
								
								var viewportOffset = {
									'top' :		(parseInt(liOffset.top) - parseInt(topMenuOffset.top)), 
									'left':		(parseInt(liOffset.left) - parseInt(topMenuOffset.left))
								};
								
								return viewportOffset;
							},
	
							
	/**
	 * enregistre les différents gestionnaires d'évenements des sous-menus
	 * 
	 * @access private
	 */					
	observe:				function() {	
								for(var i=0;i<this.element.childNodes.length;i++) {
									this.element.childNodes[i].onmouseover = this.mouseOver.bindAsEventListener(this,this.element.childNodes[i]);
								}
								this.element.onmouseout = this.mouseOut.bindAsEventListener(this);
							},
	/**
	 * appelé lorsque la souris passe au-dessus d'un HTMLLIElement du menu principal
	 * 
	 * @param Event event - Objet Event lié à l'évènement
	 * 
	 * @access private  
	 */
	mouseOver:				function(event,li) {
								for(var i=0; i<this.element.childNodes.length; i++) {
									var currLI = this.element.childNodes[i];
									
									if((!Object.isUndefined(currLI.subMenu)) && (currLI.subMenu != false) && (currLI != li)) {
										currLI.subMenu.hide();
									}
								}
														
								if( (!Object.isUndefined(li.subMenu)) && (li.subMenu != false) ) {
									li.subMenu.show();
								}
							},
	
	
	/**
	 * appelé lorsque la souris sort d'un élément de la page (quelconque)
	 * 
	 * @param Event event - Objet Event lié à l'évènement
	 * 
	 * @access private
	 */
	 
	mouseOut:				function(event) {
								for(var i=0; i<this.element.childNodes.length; i++) {
									var li = this.element.childNodes[i];
									
									if( (!Object.isUndefined(li.subMenu)) && (li.subMenu != false) ) {
										li.subMenu.hide();
									}
								}
							}
							
});


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var SubMenu = Class.create({
	initialize:		function(element) {	
						this.element = $(element);					
						this.effect = false;
						this.element.style.display = 'none';	
						this.init();
					},
										
	toElement:		function() {
						return this.element;
					},
					
	init:			function() {
						for(var i=0;i<this.element.childNodes.length;i++) {
							var element = $(this.element.childNodes[i]);
							
							// stylisation
							element.setStyle({
								'backgroundColor'	: '#E2E2E2',
								'borderLeft' 		: '1px solid #BBBBBB',
								'borderRight' 		: '1px solid #BBBBBB',
								'borderBottom'		: '1px solid #BBBBBB',
								'clear'				: 'left',
								'cursor'			: 'pointer',
								'float'				: 'left',
								'width'				: '125px'
							});
							
							new ColoredLink(element.firstChild);
							this.observe(element);
						}
					},
					
	observe:		function(element) {
						var menu = this._getSubMenu(element);
						if(!menu) {
							return ;
						}
						element.subMenu = new SubSubMenu(menu,element);							
						element.onmouseover = element.subMenu.mouseOver.bindAsEventListener(element.subMenu);
					},
	
	/**
	 * vérifie si le paramètre li (HTMLLIElement) contient un sous menu.
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return bool
	 * 
	 * @access private
	 */

	_hasSubMenu:			function(li) {
								var ul = li.getElementsByTagName('ul');
								
								if(!ul || ul.length == 0) {
									return false;
								}
								return true;
							},

	/**
	 * retourne le sous-menu lié à l'élément du menu principal
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return HTMLUListElement|null
	 * 
	 * @access private
	 */

	_getSubMenu:			function(li) {	
								var menu = li.getElementsByTagName('ul');
								if(!menu) {
									return false;
								}
								return $(menu[0]);
							},

	/**
	 * retourne la hauteur et la largeur de l'élément passé en paramètre, relativement au menu principal
	 * 
	 * @param HTMLLIElement topMenuElement
	 * @return Object
	 * 
	 * @access private
	 */

	viewportOffset:			function(li) {
								var topMenuOffset = this.element.cumulativeOffset();
								var liOffset = li.cumulativeOffset();
								
								var viewportOffset = {
									'top' :		(parseInt(liOffset.top) - parseInt(topMenuOffset.top)), 
									'left':		(parseInt(liOffset.left) - parseInt(topMenuOffset.left))
								};
								
								return viewportOffset;
							},
					
	style:			function(style)	{
						this.element.setStyle(style);
					},
					
	show:			function() {				
						var options = {duration: 0.3};
						
						if(this.effect != false && this.effect.state != 'finished')	{
							this.effect.cancel();
						}
						
						this.effect = new Effect.Appear(this.element,options);
					},
					
	hide:			function() {
						var options = {
							duration: 	0.3,
							afterFinish:	function(effect) {
												for(var i=0;i<effect.element.childNodes.length;i++) {
													var li = effect.element.childNodes[i];
													if(li.subMenu != false && !(Object.isUndefined(li.subMenu))) {
														var ul = li.subMenu.toElement();
														ul.style.display = 'none';
													}
												}
											}
						};
						
						if(this.effect != false && this.effect.state != 'finished')	{
							this.effect.cancel();
						}						
						
						this.effect = new Effect.Fade(this.element,options);
					},
					
	setOffset:		function(offset) {
						this.style({
							'top':	new String(offset.top+'px'),
							'left':	new String(offset.left+'px')
						});
					}
});

var SubSubMenu = Class.create({
	initialize:				function(element,target) {
								this.target = $(target);
								this.element = $(element);
								this.element.style.display = 'none';
								this.effect = false;
								
								this.init();
							},
										
	toElement:				function() {
								return this.element;
							},
					
	init:					function() {
								for(var i=0;i<this.element.childNodes.length;i++) {
									var element = $(this.element.childNodes[i]);
									// stylisation
									element.setStyle({
										'backgroundColor'	: '#E2E2E2',
										'borderLeft' 		: '1px solid #BBBBBB',
										'borderRight' 		: '1px solid #BBBBBB',
										'borderBottom'		: '1px solid #BBBBBB',
										'clear'				: 'left',
										'cursor'			: 'pointer',
										'float'				: 'left',
										'width'				: '150px'
									});
									new ColoredLink(element.firstChild);
								}
							},
					
	mouseOver:				function(event) {				
								if(this.element.getStyle('display') == 'none') {
									var offset = this.viewportOffset(this.target);
									var dims = this.target.getDimensions();
									
									// stylisation du sous-menu
									this.style({
										'backgroundColor'		: '#AAAAAA',
										'borderTop'			: '1px solid #BBBBBB',
										'display'			: 'none',
										'float'				: 'left',
										'listStyleType' 		: 'none',
										'margin'			: '0',
										'padding'			: '0',
										'position'			: 'absolute',
										'width'				: '150px',
										'zIndex'			: '999'
									});
																							
									var newOffset = {
										top: (parseInt(offset.top) - 1),
										left: parseInt(dims.width) 
									};
			
									this.setOffset(newOffset);
									
									// on fait disparaitre les sous-sous-menus affichés
									
									var ul = $(this.target.parentNode);
									
									//alert('ligne 394 :'+this.target.parentNode.childNodes.length);
									
									for(var i=0;i<ul.childNodes.length;i++) {
										//alert('ligne 397 :'+this.target.parentNode.childNodes);
										var li = ul.childNodes[i];
										if(li != this.target) {
											li.subMenu.mouseOut();
										}
									}
									// on affiche le sous menu pour l'elemen survolé
								
									if(this.effect != false && this.effect.state != 'finished')	{
										this.effect.cancel();
									}
								
									this.effect = new Effect.Appear(this.element,{duration:0.3});
								}
							},
					
	
	mouseOut:				function(event) {
								var options = {duration: 0.3};
								
								if(this.effect != false && this.effect.state != 'finished')	{
									this.effect.cancel();
								}
								
								this.effect = new Effect.Fade(this.element,options);
							},
			
	/**
	 * vérifie si le paramètre li (HTMLLIElement) contient un sous menu.
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return bool
	 * 
	 * @access private
	 */

	_hasSubMenu:			function(li) {
								var ul = li.getElementsByTagName('ul');
								
								if(!ul || ul.length == 0) {
									return false;
								}
								return true;
							},

	/**
	 * retourne le sous-menu lié à l'élément du menu principal
	 * 
	 * @param HTMLLIElement li - Element du menu principal
	 * @return HTMLUListElement|null
	 * 
	 * @access private
	 */

	_getSubMenu:			function(li) {	
								return $(li.getElementsByTagName('ul')[0]);
							},

	/**
	 * retourne la position top et left de l'élément passé en paramètre, relativement au menu principal
	 * 
	 * @param HTMLLIElement topMenuElement
	 * @return Object
	 * 
	 * @access private
	 */

	viewportOffset:			function(li) {
								var topMenuOffset = this.target.parentNode.cumulativeOffset();
								var liOffset = li.cumulativeOffset();
								
								var viewportOffset = {
									'top' :		(parseInt(liOffset.top) - parseInt(topMenuOffset.top)), 
									'left':		(parseInt(liOffset.left) - parseInt(topMenuOffset.left))
								};
								
								return viewportOffset;
							},
					
	style:					function(style)	{
								this.element.setStyle(style);
							},
					
					
	setOffset:				function(offset) {
								this.style({
									'top':	new String(offset.top+'px'),
									'left':	new String(offset.left+'px')
								});
							}
});

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var ColoredLink = Class.create({
	initialize:		function(link) {
						this.element = $(link);
						this.effect = false;
						this.element.setStyle({'display':'block','backgroundColor':'inherit'});
						this.observe();
					},
					
	observe:		function() {
						Event.observe(this.element,'mouseover',this.highlightLink.bindAsEventListener(this));
						Event.observe(this.element,'mouseout',this.blurLink.bindAsEventListener(this));
					},
					
	toElement:		function() {
						return this.element;
					},
										
	highlightLink:	function(event) {
						this.element.style.backgroundColor = '#AA0000';
						this.element.style.color = 'white';
					},
					
	blurLink:		function(event) {
						this.element.style.backgroundColor = '#E2E2E2';
						this.element.style.color = '#AA0000';
					}
					 
	/**
	 * retourne la couleur du lien sous forme hexadécimale
	 * 
	 * @return string couleur du lien sous forme hexadécimale
	 */	
	 /*
	getHexaColor:	function() {
						var color = this.element.getStyle('color');
						// IE considère la couleur comme héxa, pas FF
						if(!Prototype.Browser.IE) {
							// on éclate les différentes composantes de la couleur courante (rgb)
							color = (color.substring(4,color.length-1)).split(',');
							
							// on fabrique la couleur hexadecimale
							color = '#'.concat(
								parseInt(color[0]).toColorPart(),
								parseInt(color[1]).toColorPart(),
								parseInt(color[2]).toColorPart()
							);
						}
						return color;
					}
	*/
});
