/**

 * Menu déroulant vertical

 * par Romain Berton (romain.berton[ at]gmail.com)

 */



(function() {



var oO =

{

	/**

	 * Label et identifiant du menu associé

	 */

	'Menus': 'menus',





	/**

	 * Label et tags associés

	 */

	'Ul': 'ul',

	'Li': 'li',

	'A': 'a',





	/**

	 * Labels et classes CSS associées (affectées via JS)

	 */

	'Montre': 'Montre', // sous-menus

	'Cache': 'Cache', // sous-menus

	'FT': 'focusTitle', // entête des sous-menus à la prise de focus

	'BT': 'blurTitle', // entête des sous-menus à la perte de focus





	/**

	 * oO._bTest() -> Teste les méthodes recquises.

	 *                Retourne un booléen

	 */

	_bTest: function()

	{

		return document.getElementById && document.getElementsByTagName &&

		document.createElement && document.createTextNode;

	},





	/**

	 * oO._oId(sId) -> S'il existe, retourne l'élément dont l'id est sId.

	 */

	_oId: function(sId)

	{

		if(document.getElementById(sId))

			return document.getElementById(sId);



		return false;

	},





	/**

	 * oO._aTag(oEl, sTag) -> S'ils existent, retourne un tableau des éléments

	 *                        nommés sTag et inclus dans l'élément oEl.

	 */

	_aTag: function(oEl, sTag)

	{

		if(oEl && sTag && oEl.getElementsByTagName(sTag) != 0)

			return oEl.getElementsByTagName(sTag);



		return false;

	},





	/**

	 * oO._bElemNotLink(oEl) -> Teste si la valeur de l'élément oEl est non nulle

	 *                          et si c'est un lien.

	 *                          Retourne un booléen

	 */

	_bElemNotLink: function(oEl)

	{

		if(oEl)

			return oEl.nodeValue != null && oEl.nodeName.toLowerCase() != oO['A'];



		return false;

	},





	/**

	 * oO._oCreaEl(sTag) -> Retourne un élément nommé sTag si on lui demande. ^^

	 */

	_oCreaEl: function(sTag)

	{

		if(sTag)

			return document.createElement(sTag);



		return false;

	},





	/**

	 * oO._oCreaTxt(sTxt) -> Retourne un noeud texte de la chaîne sTxt si on lui

	 *                       demande.

	 */

	_oCreaTxt: function(sTxt)

	{

		if(sTxt)

			return document.createTextNode(sTxt);



		return false;

	},





	/**

	 * oO._CancelClick(e) -> Annule la propagation d'un événement

	 */

	_CancelClick: function(e)

	{

		if(e && e.stopPropagation && e.preventDefault)

		{

			e.stopPropagation();

			e.preventDefault();

		}

		else if(e && window.event)

		{

			window.event.cancelBubble = true;

			window.event.returnValue = false;

		}



		return false;

	},





	/**

	 * oO._Elem() -> Retourne un élément avec différents attributs et un texte

	 *               inclus.

	 */

	_Elem: function()

	{

		var aArg = arguments,

		    oElem = oO._oCreaEl(aArg[0]),

		    iI = 2,

		    aTab = aArg.length;



		for(iI; iI < aTab; iI++)

		{

			iI % 2 === 0 ?

				oO.sAtt = aArg[iI] :

				oO.sVal = aArg[iI];



			if(oO.sAtt && oO.sAtt === aArg[iI-1])

				oO.sAtt === 'class' ?

					oElem.className = oO.sVal :

					oElem.setAttribute(oO.sAtt, oO.sVal);

		}

		if(aArg[1] && typeof aArg[1] === 'string' && aArg[1] != '')

		{

			var oText = oO._oCreaTxt(aArg[1]);



			oElem.appendChild(oText);

		}



		return oElem;

	},





	/**

	 * oO._Connect(oElem, sEvType, fn, bCapture) -> Attache un événement à une

	 *                                              action.

	 */

	_Connect: function(oElem, sEvType, fn, bCapture)

	{

		return document.addEventListener ?

			oElem.addEventListener(sEvType, fn, bCapture):

			oElem.attachEvent ?

				oElem.attachEvent('on' + sEvType, fn):

				false;

	},





	/**

	 * oO._GetSource(e) -> Récupère la source d'un événement.

	 */

	_GetSource: function(e)

	{

		if(e)

			return e.target || e.srcElement;



		return false;

	},






	/**

	 * oO._InsertCtrlLinks(oMenus) -> Transforme les entêtes des sous-menus en

	 *                                liens de contrôle.

	 */

	_InsertCtrlLinks: function(oMenus)

	{

		if(!oMenus)

			return;



		var aLis = oO._aTag(oMenus, oO['Li']),

		    iI = aLis.length;



		if(iI === 0)

			return;



		while(iI-- > 0)

		{

			var oChildLi = aLis[iI].firstChild;



			if(!oChildLi)

				return;



			if(oO._bElemNotLink(oChildLi))

			{

				var oA = oO._Elem('a', oChildLi.nodeValue, 'href', '#ssmenu');



				aLis[iI].replaceChild(oA, oChildLi);

				oO._Connect(oA, 'click', oO._CancelClick, false);

			}

		}



		return oMenus;

	},





	/**

	 * oO._InitCptMenu(oMenus) -> Définit le comportement du menu en fonction

	 *                            de l'événement et de l'élément affecté.

	 */

	_InitCptMenu: function(oMenus)

	{

		if(!oMenus)

			return;



		var aA = oO._aTag(oMenus, oO['A']),

		    iI = aA.length;



		while(iI-- > 0)

			oO._Connect(aA[iI], 'click', oO._CtrlDisplay, false);



		return oMenus;

	},





	/**

	 * oO._InitStyle(oMenus) -> Définit les styles affectés au menu lorsque JS

	 *                          est actif.

	 */

	_InitStyle: function(oMenus)

	{

		if(!oMenus)

			return;



		var aUls = oO._aTag(oMenus, oO['Ul']),

		    iI = aUls.length;



		if(iI === 0)

			return;



		do if(aUls[--iI].className != oO['Montre'])

			aUls[iI].className = oO['Cache'];

		while(iI > 0);



		return oMenus;

	},





	/**

	 * oO._Actif() -> Affecte des liens de contrôle, des styles et un comportement

	 *                au menu.

	 */

	_Actif: function()

	{

		var oMenus = oO._oId(oO['Menus']);



		if(!oMenus)

			return;



		if(oO._InsertCtrlLinks(oMenus))

			if(oO._InitStyle(oMenus))

				return oO._InitCptMenu(oMenus);



		return;

	},





	/**

	 * oO._CtrlDisplay(e) -> Contrôle l'affichage / masquage

	 *                       des sous-menus.

	 */

	_CtrlDisplay: function(e)

	{

		var oRelatedNode = e.relatedTarget || oRelatedNode,

		    oSource = oO._GetSource(e),

		    oUl = oO._aTag(oSource.parentNode, oO['Ul'])[0];



		if(!oUl)

			return true;



		if(oUl.className === oO['Cache'])

		{

			oO._HideLastList();

			oUl.parentNode.firstChild.className = oO['FT'];

			oUl.className = oO['Montre'];



			if(!window.event)

				oSource.blur();

		}

		else

		{

			oUl.parentNode.firstChild.className = oO['BT'];

			oUl.className = oO['Cache'];

		}



		return;

	},





	/**

	 * oO._HideLastList() -> Cache la liste précédemment ouverte

	 */

	_HideLastList: function()

	{

		var oMenus = oO._oId(oO['Menus']),

		    aUls = oO._aTag(oMenus, oO['Ul']),

		    iI = aUls.length - 1;



		for(; iI >= 0; iI--)

			if(aUls[iI].className != oO['Cache'])

			{

				aUls[iI].parentNode.firstChild.className = oO['BT'];

				aUls[iI].className = oO['Cache'];

			}



		return;

	}

};



if(oO._bTest)

	oO._Connect(window, 'load', oO._Actif, false); // Lancement du script



})();
