// Copyright B. Bruet 2010-2011 - tous droits réservés
var
   CodeCar =
   {
      CR          :  13,
      SP          :  32,
      FlecheGauche:  37,
      FlecheHaut  :  38,
      FlecheDroite:  39,
      FlecheBas   :  40,
      MoinsClavier:  54,
      PlusClavier : 107,
      MoinsPave   : 109,
      PlusPave    : 187
   };

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

String.prototype.Fois = function(n)
{
   var Résultat = '';
   while(n-->0) Résultat += this;
   return Résultat;
};

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

$ = function(Id)
{
   return document.getElementById(Id);
};

AdresseCourriel = function(BàL, Domaine)
{
   if(arguments.length<1 || !BàL     || !BàL    .replace(/ /g,'')) BàL     = 'postmaster';
   if(arguments.length<2 || !Domaine || !Domaine.replace(/ /g,'')) Domaine = document.domain;
   return BàL+"@"+Domaine;
};

Afficher = function(Url)
{
   window.open(Url);
   return false;
}

AjaxGetOnreadystatechange = function()
{
   if(this.readyState==4) this.ARappeler(this);
};

AjaxGet = function(Url, ARappeler)
{
   var Résultat = null;
   // Code inspiré de http://fr.wikipedia.org/wiki/XMLHttpRequest
   if(window.XMLHttpRequest) Résultat = new XMLHttpRequest(); // navigateurs récents (depuis 2005)
   else if(window.ActiveXObject) // Internet Explorer (IE) sous Windows
   {
      // Seconde et dernière chance : essayer les anciennes versions d'ActiveX IE
      var NomsActiveX = 
      [
         "Msxml2.XMLHTTP.6.0",
         "Msxml2.XMLHTTP.3.0",
         "Msxml2.XMLHTTP",
         "Microsoft.XMLHTTP"
      ];
      for(var i=0; Résultat==null && i<NomsActiveX.length; i++) 
      try
      {
         Résultat = new ActiveXObject(NomsActiveX[i]);
      }
      catch(Exception)
      {
      }            
   }
   if(Résultat==null) 
   {
      Alerte("Pas d'objet HTTP trouvé sur cette machine !");
      AjaxGet = function(){}; // "suicide" pour absence de message ultérieur...
   }
   else
   {
      var Asynchrone = typeof(ARappeler)=='function';
      Résultat.open("GET", Url, Asynchrone);
      if(Asynchrone) 
      {
         Résultat.onreadystatechange = AjaxGetOnreadystatechange;
         Résultat.ARappeler          = ARappeler;
      }
      Résultat.send(null);
   }
   return Résultat;
};

Alerte = function(Texte)
{
   alert(Texte);
   window.focus(); // bug Firefox : la fenêtre perd la focalisation (et donc les frappes au clavier) après un dialogue...
   return true;    // pour permettre l'emploi dans une expression
};

BulleVisible = function(IdBulle, Visibilité)
{
   // Effacement bulle précédente éventuelle
   if(Visible(this.Bulle, false) && MSIE) with(document.body.style)
   {
      // Bug IE : la partie de la bulle dépassant du conteneur sur l'arrière-plan reste affichée après effacement de la bulle ;
      // Astuce : forcer le réaffichage de l'arrière-plan par un changement de sa couleur...
      var Couleur     = backgroundColor;
      backgroundColor = "transparent";
      backgroundColor = Couleur;
   }
   var Bulle = $(IdBulle);
   if(arguments.length>=2) 
   {
      Visible(Bulle, Visibilité);
      this.Bulle = Bulle;
   }
   else
   {
      // Le test ci-dessous est destiné à éviter qu'une bulle affichée ne soit cachée immédiatement lors de la "remontée" de 
      // l'évènement 'click' dans le 'document' principal, remontée appelant 'BulleVisible' dans "index.php"...
      if(this.BulleJusteAffichée) this.BulleJusteAffichée = false;
      else
      {
         var Affichage = Bulle!=this.Bulle;
         this.Bulle = Bulle;
         if(Bulle && Affichage)
         {
            Visible(Bulle, true);
            this.BulleJusteAffichée = true;
         }
      }
   }
}

ClientAreaHauteur = function()
{
   return typeof(window.innerHeight)=='undefined' ? document.body.clientHeight : window.innerHeight;
};

ClientAreaLargeur = function()
{
   return typeof(window.innerWidth)=='undefined' ? document.body.clientWidth : window.innerWidth;
};

Cliquer = function(IdACliquer, Retour)
{
   if(IdACliquer) $(IdACliquer).onclick();
   return arguments.length>1 && Retour;
};

Confirmation = function(Texte)
{
   var Résultat = confirm(Texte);
   window.focus(); // bug Firefox : la fenêtre perd la focalisation (et donc les frappes au clavier) après un dialogue...
   return Résultat;
};

Courriel = function(This, BàL, Domaine, Sujet)
{
   if(arguments.length<4) Sujet = 'Message depuis le site '+document.domain;
   This.href = 'mailto:'+AdresseCourriel(BàL,Domaine)+'?Subject='+Sujet;
   return true;
}

EvènementConnexion = function(Elément, NomEvènement, Gestionnaire)
{
   if(Elément)
   {
           if(Elément.attachEvent     ) Elément.attachEvent("on"+NomEvènement, Gestionnaire);   
      else if(Elément.addEventListener) Elément.addEventListener(NomEvènement, Gestionnaire, false);   
      else                              Elément["on"+NomEvènement] = Gestionnaire;
   }
}   

EvenementDeconnexion = function(Elément, NomEvènement, Gestionnaire)
{
   if(Elément)
   {
           if(Elément.detachEvent        ) Elément.detachEvent("on"+NomEvènement, Gestionnaire);   
      else if(Elément.removeEventListener) Elément.removeEventListener(NomEvènement, Gestionnaire, false);   
      else                                 Elément["on"+NomEvènement] = null;   
   }
}   

Menu = function(Conteneur, MenuJson, ClassActif, ClassInactif, Indentation)
{
   var Niveau = 0;

   Menu = function(Parent, Index, MenuJson)
   {
      Focaliser = function()
      {
         var Principal    = this.Principal(),
             Résultat     = Principal.EnCours==this,
             Focalisation = arguments.length<=0;
         if(Focalisation)
         {    
            if(this.SurSelection) this.SurSelection();
            Principal.EnCours.Focaliser(false);
         }
         Visible($(this.IdAffichage), Focalisation);
         with(Principal) 
         {
            EnCours                = Focalisation ? this       : null;
            this.Libellé.className = Focalisation ? ClassActif : ClassInactif;
         }
         return Résultat;
      };
      Précédent = function()
      {
         var Résultat = this.Parent,
             Index    = this.Index-1;
         if(Index<0)
         {
            // Pas de remontée au menu principal (vide) et utilisation de son dernier sous-menu en lieu et place
            if(!Résultat.Parent) Résultat = Résultat.SousMenus[Résultat.SousMenus.length-1];
         }
         else
         {
            Résultat = Résultat.SousMenus[Index]; // sous-menu précédent de même niveau que 'Menu' dans leur menu parent
            // Recherche du tout dernier sous-menu visible dans son aborescence
            while(Visible(Résultat.Contenu)) Résultat = Résultat.SousMenus[Résultat.SousMenus.length-1];
         }
         return Résultat;
      };
      Principal = function()
      {
         return this.Parent ? this.Parent.Principal() : this;
      };
      Suivant = function()
      {
         var Résultat;
         if(arguments.length<=0 && Visible(this.Contenu)) Résultat = this.SousMenus[0];
         else
         {
            Résultat = this.Parent;
            var Index = this.Index+1;
            // Sous-menu suivant de même niveau que 'Menu' dans leur menu parent
            if(Index<Résultat.SousMenus.length) Résultat = Résultat.SousMenus[Index];
            // Pas de remontée au menu principal (vide) et utilisation de son premier sous-menu en lieu et place
            else Résultat = Résultat.Parent ? Résultat.Suivant(false) : Résultat.SousMenus[0];
         }
         return Résultat;
      };

      var Résultat = document.createElement('div');
      Résultat.Précédent = Précédent;
      Résultat.Principal = Principal;
      Résultat.Suivant   = Suivant;
      Résultat.Parent    = Parent;
      Résultat.Libellé   = document.createElement('div');
      Résultat.Index     = Index;
      with(Résultat.Libellé)
      {
         var Titre = MenuJson.shift();
         className = ClassInactif;
         id        = MenuJson.length>0 ? MenuJson.shift() : '';
         innerHTML = TexteHtml(!Titre ? '' : String('&nbsp;').Fois((Niveau-1)*(Indentation||5))+Titre);
         onclick   = function()
         {
            var Menu     = this.parentNode,
                Affiché  = Visible(Menu.Contenu),
                Focalisé = Menu.Focaliser();       
            Menu.AfficherContenu(!Affiché || !Focalisé);
         }
      }
      Visible(Résultat.Libellé, Texte(Résultat.Libellé)!='');
      Résultat.appendChild(Résultat.Libellé);
      Résultat.IdAffichage     = MenuJson.length>0 ? MenuJson.shift() : '';
      Résultat.Contenu         = null;
      Résultat.AfficherContenu = function(Affichage)
      {
         if(this.Parent && Affichage) this.Parent.AfficherContenu(Affichage);
         if(this.Contenu && (Affichage || this.Parent)) Visible(this.Contenu, Affichage);
      };
      Résultat.SousMenus = [];
      if(MenuJson.length>0)
      {
         Résultat.Contenu = document.createElement('div');
         Visible(Résultat.Contenu, false);
         Niveau++;
         for(var i=0; i<MenuJson.length; i++)
         {
            var SousMenu = Menu(Résultat, i, MenuJson[i]);
            Résultat.SousMenus.push(SousMenu);
            Résultat.Contenu.appendChild(SousMenu);
         }
         Niveau--;
         Résultat.appendChild(Résultat.Contenu);
      }
      if(Parent) Parent.Contenu.appendChild(Résultat); 
      else       Conteneur     .appendChild(Résultat);
      Résultat.Focaliser = Focaliser;
      return Résultat;
   }
   Frappe = function(Touche)
   {
      var EnCours = this.EnCours;
      if(EnCours) switch(Touche)
      {
      case CodeCar.CR: 
      case CodeCar.SP: 
         if(EnCours.Contenu) EnCours.AfficherContenu(!Visible(EnCours.Contenu)); 
         break;
      case CodeCar.FlecheGauche:
          // Remontée au menu parent seulement si non racine (ie, si son menu parent est non vide)
         if(EnCours.Parent.Parent) EnCours.Parent.Focaliser();
         break;
      case CodeCar.FlecheHaut:
         EnCours.Précédent().Focaliser();
         break;
      case CodeCar.FlecheBas:
         EnCours.Suivant().Focaliser();
         break;
      case CodeCar.MoinsClavier:
      case CodeCar.MoinsPave:
         EnCours.AfficherContenu(false);
         break
      case CodeCar.PlusClavier:
      case CodeCar.PlusPave:
      case CodeCar.FlecheDroite:
         EnCours.AfficherContenu(true);
         break
      }
   };

   var Résultat = Menu(null, 0, MenuJson);
   Résultat.ClassActif   = ClassActif;
   Résultat.ClassInactif = ClassInactif;
   Résultat.Touche       = Frappe;
   Résultat.EnCours      = Résultat.SousMenus[0];
   Résultat.EnCours.Libellé.onclick();  // affichage du menu par défaut (et de tous les autres d'ailleurs...)
   return Résultat;
};

Navigateur = function()
{
   var Navigateurs = [ 'MSIE', 'Firefox', 'Chrome', 'Safari', 'Opera' ];
   for(var i=0; i<Navigateurs.length && window.navigator.userAgent.indexOf(Navigateurs[i])<0; i++);
   return i<Navigateurs.length ? Navigateurs[i] : '';
};

Texte = function(Objet)
{
   var Résultat = MSIE ? Objet.innerText : Objet.textContent;
   if(arguments.length>1)
   {
      if(MSIE) Objet.innerText   = arguments[1];
      else     Objet.textContent = arguments[1];
   }
   return Résultat;
};

TexteHtml = function(Texte)
{
   return Texte.replace(/ /g,'&nbsp;');
};

Touche = function(event)
// Retourne la touche appuyée par l'utilisateur passée au gestionnaire d'évènement dans l'évènement 'event'
{
   // Le paramètre 'event' des "handlers" n'est pas défini par IE mais 'window.event' l'est, et c'est l'inverse pour FireFox...
   event = event || window.event;
   // Renvoi du code de touche évt retrouvé (sinon, 0) dans les diverses variantes de variables des navigateurs du marché...
   return !event ? 0 : event.keyCode || event.which || event.charCode;
};

Visible = function(Elément, Visibilité)
{
   var Résultat = false;
   if(Elément)
   {
      if(typeof(Elément)=="string") Elément = $(Elément);
      Résultat = Elément.style.display=="block";
      if(arguments.length>1) Elément.style.display = Visibilité ? "block" : "none";
   }
   return Résultat;
};

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

var MSIE = Navigateur()=='MSIE';

