//////////////////////////////////////////////////////////////////////////////////
//	OBJET	:	Classe et fonctions javascript, permettant la gestion d'un menu	//
//				contextuel d'une page DHTML										//
//	DATE	:	13 février 2005													//
//	AUTEUR	:	GOLINSKI Ludwig													//
//////////////////////////////////////////////////////////////////////////////////



// CLASSE GERANT UN MENU OU UN SOUS-MENU
function Menu( indexMenu, styleMenu )
{
	// Index unique du menu
	this.index = indexMenu

	// Nom de la classe de style du menu
	this.style = styleMenu

	// Indique si le menu est affiché ou non
	this.isVisible = false

	// Tableau d'item du menu
	this.tableauItems = new Array

	// Méthodes de la classe
	this.Draw = Menu_Draw
	this.Add = Menu_Add
	this.Show = Menu_Show
	this.Hide = Menu_Hide
	this.FocusChange = Menu_FocusChange
	this.OnSelect = Menu_OnSelect
	this.SetPosition = Menu_SetPosition
}

// METHODE PERMETTANT DE DESSINER LE MENU
function Menu_Draw()
{
	// Crée le div représentant le menu avec le style approprié
	document.write( "<div id = 'MENU_" + this.index + "' " )
	document.write( "class = '" + this.style + "' " )
	document.write( "style = 'position: absolute; display: none; z-index:999' >" )

	// Parcourt les items du menu
	var indice = 0
	while( this.tableauItems[ indice ] != null )
	{
		// Dessine l'item courant
		this.tableauItems[ indice ].Draw()

		// Passe à l'item suivant
		indice ++
	}

	// Referme le div
	document.write( "</div>" )

	// Parcourt les sous-menus du menu
	var indice = 0
	while( this.tableauItems[ indice ] != null )
	{
		// Dessine le sous-menu courant
		if( this.tableauItems[ indice ].sousMenu != null )
			this.tableauItems[ indice ].sousMenu.Draw()

		// Passe au menu
		indice ++
	}
}



// METHODE PERMETTANT D'AJOUTER UN ITEM AU MENU
function Menu_Add( imageItem, texteItem, styleItem, styleOnFocus )
{
	// Recherche le premier index non utilisé
	var indice = 0
	while( this.tableauItems[ indice ] != null )
		indice ++

	// Crée puis ajoute l'item au tableau du menu
	this.tableauItems[ indice ] = new Item( this.index + "_" + indice, imageItem, texteItem, styleItem, styleOnFocus )

	// Retourne le nouvel item
	return this.tableauItems[ indice ]
}

// METHODE SERVANT A POSITIONNER ET RENDRE LE MENU VISIBLE
function Menu_Show( evenementSouris )
{
	// Récupère le cadre du menu
	var cadreMenu = GetElement( "MENU_" + this.index )

	// Affiche le menu ( 'inline' et non 'block' pour eviter les incompabilités avec Mozilla )
	cadreMenu.style.display = "inline"
	this.isVisible = true

	// Récupère la position du menu d'après le navigateur
	var positionX
	var positionY
	if( document.all )
	{
		var source = event.srcElement;
		//source.
		positionX = event.clientX + window.scrollX;
		positionY = event.clientY + window.scrollY;
	}
	else
	{
		positionX = evenementSouris.pageX;
		positionY = evenementSouris.pageY;
	}

	// Le menu sort par la droite du navigateur
	if( positionX + cadreMenu.offsetWidth > document.documentElement.clientWidth + document.documentElement.scrollLeft )
		cadreMenu.style.left = document.documentElement.clientWidth + document.documentElement.scrollLeft - cadreMenu.offsetWidth - 1
	else
		cadreMenu.style.left = positionX

	// Le menu sort par le bas du navigateur
	if( positionY + cadreMenu.offsetHeight > document.documentElement.clientHeight + document.documentElement.scrollTop )
		cadreMenu.style.top = document.documentElement.clientHeight + document.documentElement.scrollTop - cadreMenu.offsetHeight - 1
	else
		cadreMenu.style.top = positionY

	// Parcourt le tableau d'items
	var indice = 0
	while( this.tableauItems[ indice ] != null )
	{
		// Récupère l'élément représentant l'item et lui applique son style par défaut
		var cadreItem = GetElement( "ITEM_" + this.tableauItems[ indice ].index )

		// Applique le style par défaut à l'item
		this.tableauItems[ indice ].MakeUnfocused()

		// L'item contient un sous-menu
		if( this.tableauItems[ indice ].sousMenu != null )
		{
			// Récupère l'image de la flêche de l'item
			var cadreFleche = GetElement( "FLECHE_ITEM_" + this.tableauItems[ indice ].index )

			// Positionne l'image si elle existe
			if( cadreFleche != null )
				cadreFleche.style.left = cadreMenu.offsetWidth - cadreFleche.offsetWidth

			// Positionne le sous-menu de l'item
			this.tableauItems[ indice ].sousMenu.SetPosition( this.index, this.tableauItems[ indice ].index, true )
		}

		// Passe à l'item suivant
		indice ++
	}
}

// METHODE PERMETTANT DE POSITIONNER LE MENU D'APRES LA POSITION DE SON MENU PARENT
function Menu_SetPosition( indexMenuParent, indexItemParent, positionDroite )
{
	// Récupère les cadres du menu parent, de l'item contenant le menu et du menu
	var cadreMenuParent = GetElement( "MENU_" + indexMenuParent )
	var cadreItem = GetElement( "ITEM_" + indexItemParent )
	var cadreMenu = GetElement( "MENU_" + this.index )

	// Affiche le menu
	cadreMenu.style.display = "inline"

	// Calcul la position horizontale du menu par rapport à celle du menu parent
	var positionX = cadreMenuParent.offsetLeft + cadreMenuParent.offsetWidth + 1

	// Le menu peut être placer à droite du menu parent sans sortir de la page
	if( positionDroite && positionX + cadreMenu.offsetWidth < document.documentElement.clientWidth + document.documentElement.scrollLeft )
	{
		cadreMenu.style.left = positionX
	}
	else
	{
		// Positionne le menu à gauche du menu parent
		cadreMenu.style.left = cadreMenuParent.offsetLeft - cadreMenu.offsetWidth - 1
		positionDroite = false
	}

	// Calcul la position verticale du menu
	var positionY = cadreMenuParent.offsetTop + cadreItem.offsetTop - 1

	// Le menu ne sort pas par le bas de la page
	if( positionY + cadreMenu.offsetHeight < document.documentElement.clientHeight + document.documentElement.scrollTop )
	{
		cadreMenu.style.top = positionY
	}
	else
	{
		// Calcul la position du menu pour qu'il colle au bas de la page
		cadreMenu.style.top = document.documentElement.clientHeight + document.documentElement.scrollTop - cadreMenu.offsetHeight
	}

	// Parcourt les items du menu
	var indice = 0
	while( this.tableauItems[ indice ] != null )
	{
		// L'item courant possède un sous-menu
		if( this.tableauItems[ indice ].sousMenu != null )
		{
			// Appel la méthode de positionnement du sous-menu
			this.tableauItems[ indice ].sousMenu.SetPosition( this.index, this.tableauItems[ indice ].index, positionDroite )
		}

		// Passe à l'item suivant
		indice ++
	}

	// Cache le menu
	cadreMenu.style.display = "none"
}

// METHODE SERVANT A CACHER LE MENU ET SES SOUS-MENUS
function Menu_Hide()
{
	// Récupère le cadre du menu
	var cadreMenu = GetElement( "MENU_" + this.index )

	// Cache le menu
	cadreMenu.style.display = "none"
	this.isVisible = false

	// Parcourt ses items
	var indice = 0
	while( this.tableauItems[ indice ] != null )
	{
		// L'item courant contient un sous-menu
		if( this.tableauItems[ indice ].sousMenu != null && this.tableauItems[ indice ].sousMenu.isVisible )
			// Fait appel à la méthode du sous-menu
			this.tableauItems[ indice ].sousMenu.Hide()

		// Passe au sous-menu suivant
		indice ++
	}
}

// METHODE SERVANT A DETECTER QUEL ITEM A LE FOCUS
// RETOURNE UN BOOLEEN INDIQUANT SI LE FOCUS EST PRIS PAR UN DES ITEMS DU MENU
function Menu_FocusChange( evenementSouris )
{
	// Le menu est affiché
	if( this.isVisible )
	{
		// Parcourt le tableau d'items du menu
		var indiceItem = 0
		while( this.tableauItems[ indiceItem ] != null )
		{
			// L'item contient un sous-menu
			if( this.tableauItems[ indiceItem ].sousMenu != null )
			{
				// Le sous-menu est affiché
				if( this.tableauItems[ indiceItem ].sousMenu.isVisible )
				{
					// Le curseur se trouve sur un des items du sous-menu
					if( this.tableauItems[ indiceItem ].sousMenu.FocusChange( evenementSouris ) )
						return true
					else
						// Il ne peut y avoir qu'un sous-menu affiché
						break;
				}
			}
			else
			{
				// Applique le style par défaut à l'item
				this.tableauItems[ indiceItem ].MakeUnfocused()
			}

			// Passe à l'item courant
			indiceItem ++
		}

		// Parcourt le tableau d'items
		indiceItem = 0
		while( this.tableauItems[ indiceItem ] != null )
		{
			// Récupère l'instance sur le menu
			var cadreMenu = GetElement( "MENU_" + this.index )

			// Récupère l'instance sur l'item
			var cadreItem =	GetElement( "ITEM_" + this.index + "_" + indiceItem )

			var isOver = false
			if( ! document.all )
			{
				// Le curseur se trouve sur l'item
				if( evenementSouris.pageX > cadreMenu.offsetLeft + cadreItem.offsetLeft &&
				evenementSouris.pageX - 1 < cadreMenu.offsetLeft + cadreItem.offsetLeft + cadreItem.offsetWidth &&
				evenementSouris.pageY > cadreMenu.offsetTop + cadreItem.offsetTop &&
				evenementSouris.pageY - 1 < cadreMenu.offsetTop + cadreItem.offsetTop + cadreItem.offsetHeight )
					isOver = true
			}
			else
			{
				// Le curseur se trouve sur l'item
				if( event.clientX + document.documentElement.scrollLeft - 2 > cadreMenu.offsetLeft + cadreItem.offsetLeft &&
				event.clientX + document.documentElement.scrollLeft - 3 < cadreMenu.offsetLeft + cadreItem.offsetLeft + cadreItem.offsetWidth &&
				event.clientY + document.documentElement.scrollTop - 2 > cadreMenu.offsetTop + cadreItem.offsetTop &&
				event.clientY + document.documentElement.scrollTop - 3 < cadreMenu.offsetTop + cadreItem.offsetTop + cadreItem.offsetHeight )
					isOver = true
			}

			// Le curseur est au-dessus de l'item courant
			if( isOver )
			{
				// Applique le style approprié à l'item
				this.tableauItems[ indiceItem ].MakeFocused()

				// L'item contient un sous-menu
				if( this.tableauItems[ indiceItem ].sousMenu != null )
				{
					// Récupère le cadre du sous-menu et le rend visible
					var sousMenu = GetElement( "MENU_" + this.tableauItems[ indiceItem ].sousMenu.index )
					sousMenu.style.display = "inline"
					this.tableauItems[ indiceItem ].sousMenu.isVisible = true
				}

				// Parcourt le tableau d'item du menu
				var indice = 0
				while( this.tableauItems[ indice ] != null )
				{
					// L'item n'est pas celui ayant le focus, il contient un sous-menu et ce sous-menu est visible
					if( indice != indiceItem && this.tableauItems[ indice ].sousMenu != null && this.tableauItems[ indice ].sousMenu.isVisible )
					{

						// Cache le sous-menu
						this.tableauItems[ indice ].sousMenu.Hide()

						// Applique le style par défaut à l'item
						this.tableauItems[ indice ].MakeUnfocused()
					}

					// Passe à l'item suivant
					indice ++
				}

				return true
			}
			// Le curseur se trouve en dehors de l'item courant
			else
			{
				// L'item ne contient pas de sous-menu ou l'item contient un sous-menu et ce sous-menu est affiché
				if( this.tableauItems[ indiceItem ].sousMenu == null || ! this.tableauItems[ indiceItem ].sousMenu.isVisible )
				{
					// Applique le style approprié à l'item
					this.tableauItems[ indiceItem ].MakeUnfocused()
				}
			}

			// Passe à l'item suivant
			indiceItem ++
		}
	}

	// Indique à l'appelant que le focus n'est pas pris par un des items du menu, ni par un item de ses sous-menus
	return false
}

// METHODE SERVANT A APPELER LA FONCTION ASSOCIEE A L'ITEM SUR LEQUEL LE CLICK A EUT LIEU
function Menu_OnSelect( evenementSouris )
{
	// Le menu est affiché
	if( this.isVisible )
	{
		// Récupère le cadre du menu
		var cadreMenu = GetElement( "MENU_" + this.index )

		// Parcourt les items du menu
		var indiceItem = 0
		while( this.tableauItems[ indiceItem ] != null )
		{
			// Récupère le cadre de l'item
			var cadreItem =	GetElement( "ITEM_" + this.index + "_" + indiceItem )

			// L'item contient un sous-menu et ce sous-menu est affiché
			if( this.tableauItems[ indiceItem ].sousMenu != null && this.tableauItems[ indiceItem ].sousMenu.isVisible )
				// Fait appel à la méthode du sous-menu
				this.tableauItems[ indiceItem ].sousMenu.OnSelect( evenementSouris )

			// Vérifie si la sélection porte sur l'item courant, d'après le navigateur
			var isSelect = false
			if( document.all )
			{
				if( event.clientX + document.documentElement.scrollLeft - 2 > cadreMenu.offsetLeft + cadreItem.offsetLeft &&
				event.clientX + document.documentElement.scrollLeft - 3 < cadreMenu.offsetLeft + cadreItem.offsetLeft + cadreItem.offsetWidth &&
				event.clientY + document.documentElement.scrollTop - 2 > cadreMenu.offsetTop + cadreItem.offsetTop &&
				event.clientY + document.documentElement.scrollTop - 3 < cadreMenu.offsetTop + cadreItem.offsetTop + cadreItem.offsetHeight )
					isSelect = true
			}
			else
			{
				if( evenementSouris.pageX > cadreMenu.offsetLeft + cadreItem.offsetLeft &&
				evenementSouris.pageX - 1 < cadreMenu.offsetLeft + cadreItem.offsetLeft + cadreItem.offsetWidth &&
				evenementSouris.pageY > cadreMenu.offsetTop + cadreItem.offsetTop &&
				evenementSouris.pageY - 1 < cadreMenu.offsetTop + cadreItem.offsetTop + cadreItem.offsetHeight )
				{
					isSelect = true
				}
			}

			// L'item courant est celui sélectionné (cliqué)
			if( isSelect )
			{
				// Récupère l'instance sur l'item
				var item = this.tableauItems[ indiceItem ]

				if( item.functionOnClick != "none" )
					// Fait appel à la fonction associée à l'item
					eval( item.functionOnClick + "( '" + item.index + "', '" + item.texte + "' )" )

				if( item.URLOnClick != "none" )
					// Rediriger la page vers le lien associée à l'item
					eval( "location.href = '" + item.URLOnClick + "'" )
			}

			// Passe à l'item suivant
			indiceItem ++
		}

		// Cache le menu
		HideMenu()
	}
}
