// Infobulle

// Détection du navigateur
var agent = navigator.userAgent.toLowerCase();
var major = parseInt(navigator.appVersion);
var minor = parseFloat(navigator.appVersion);

var opera = (agent.indexOf("opera") != -1);
//var ffox = (agent.indexOf("firefox") != -1);
var netscape = ((navigator.appName).indexOf("Netscape") != -1);

var ie = ((agent.indexOf("msie") != -1) &&	(agent.indexOf("opera") == -1));
var ie7 = (ie && major == 4 &&	(agent.indexOf("msie 7.") != -1));

var Mouse_X;	// Position X en Cours de la souris
var Mouse_Y;	// Position Y en Cours de la souris
var Decal_X;	// Décalage X entre Pointeur souris et Bulle
var Decal_Y;	// Décalage Y entre Pointeur souris et Bulle

var Fenetre  = new privBulle_RECT();  // pour dimension fenêtre

var listeBulles=Array(); // liste des bulles à l'écran
var cssBulleDefaut; // CSS à utiliser par défaut

// Initialisation
// Appelé depuis le BODY
// * [int] p_numBulleCSS : numéro de bulle dans le CSS
// * [string] NomFeuilleStyle : chemin de la feuille de style
function Bulle_Initialisation(p_numBulleCSS, NomFeuilleStyle, Prechargement) 
	{
	cssBulleDefaut=p_numBulleCSS;
	
	// Ajoute la feuille de style
	document.write('<link href="' + NomFeuilleStyle + '" rel="stylesheet" type="text/css" media="screen,print">');

	// Préchargement des images de l'infobulle
	if (Prechargement)
		{
		document.write('<div style="position:absolute; left:0; top:0; visibility:hidden">');
		document.write(Prechargement);
		document.write('</div>');
		}
	
	privBulle_EvnmtAjoute( document, 'mousemove', privBulle_RenvoiePosSouris);
	}


	
			
// Affiche une info-bulle.
// * [object] p_objetAppelant : objet appelant (utiliser THIS)
// * [string] p_titre : titre
// * [string] p_texte : texte
// * [string] OPT_infossupp : infos supplémentaires
// * [string] forcerAffichage : G=affichage forcé à gauche, D=affichage forcé à droite
// * [int] OPT_affichageProgressif : évolution de l'opacité
// * [int] OPT_effacementProgressif : estompement de l'opacité
// * [int] OPT_affichageRetarde : affichage retardé (en ms)
// * [int] p_numBulleCSS : numéro du fichier CSS utilisé
// * [int] OPT_alignement : alignement du texte (0 : gauche, 1 centre, 2 : droite, 3 : justifié);
// * [int] OPT_suppressionOnKeyPress : supprime l'infobulle si on appuie sur une touche pour l'objet rattaché
// * [int] OPT_dureeAffichage : supprime l'infobulle après N ms
function Bulle(p_objetAppelant, 
	p_titre,
	p_texte, 
	OPT_infossupp, 
	OPT_forcerPositionAffichage, 
	OPT_affichageProgressif,	
	OPT_effacementProgressif,	
	OPT_affichageRetarde,
	OPT_numBulleCSS,
	OPT_alignement,
	OPT_suppressionOnKeyPress,
	OPT_dureeAffichage	)
	{

	// Valeurs par défaut
	if (typeof OPT_infossupp=='undefined' || OPT_infossupp===null) OPT_infossupp='';
	if (typeof OPT_forcerPositionAffichage=='undefined' || OPT_forcerPositionAffichage===null) OPT_forcerPositionAffichage='';
	if (typeof OPT_affichageProgressif=='undefined' || OPT_affichageProgressif===null) OPT_affichageProgressif=20;
	if (typeof OPT_effacementProgressif=='undefined' || OPT_effacementProgressif===null) OPT_effacementProgressif=30;
	if (typeof OPT_affichageRetarde=='undefined' || OPT_affichageRetarde===null) OPT_affichageRetarde=0;
	if (typeof OPT_numBulleCSS=='undefined' || OPT_numBulleCSS===null) OPT_numBulleCSS=cssBulleDefaut;
	if (typeof OPT_alignement=='undefined' || OPT_alignement===null) OPT_alignement=2;
	if (typeof OPT_suppressionOnKeyPress=='undefined' || OPT_suppressionOnKeyPress===null) OPT_suppressionOnKeyPress=false;
	if (typeof OPT_dureeAffichage=='undefined' || OPT_dureeAffichage===null) OPT_dureeAffichage=0;
	
	// Crée l'objet
	var idBulle='idBulle'+(Math.round(Math.random()*1000));
	var objetBulle=privBulle_CreeTypeObjet	('div', idBulle, document.body);
	
	
	// Style
	//privBulle_FixeStyle(objetBulle,'position:absolute;left:0px; top:0px;visibility:hidden;display:none');
	objetBulle.style.display='none';
	objetBulle.style.position = 'absolute';
	
	
	// Paramètres par défaut
	objetBulle.bulleAffichee=false;
	objetBulle.bulleEnCoursFin=false;
	objetBulle.evnmtOpaciteDiminue=0;
	objetBulle.evnmtOpaciteAugmente=0;
	objetBulle.evnmtDepartRetarde=0;
	objetBulle.affichageProgressif=OPT_affichageProgressif;
	objetBulle.effacementProgressif=OPT_effacementProgressif;
	objetBulle.dureeAffichage=OPT_dureeAffichage;
	objetBulle.debutAffichage=(new Date).getTime();
	//-- Récup dimension d'affichage 	
	privBulle_RenvoieDimNavig();			
			
	// Correction de bug graphique pour Firefox/IE5
	// Si le texte contient un table, il faut le transformer en table=100% et le faire précéder de div style=100%
	// table width=100 %, c'est pour firefox
	// div style=100% devant c'est pour IE5
	var texte2=p_texte.replace(/<table>/g, '<div style="width:100%"><table style="padding:0;margin:0" width="100%">');	
	if (texte2!=p_texte)
		p_texte=texte2.replace(/<\/table>/g, '</table></div>');	
	
	// Affichage
	var contenuBulle='<div class="infobulle' + OPT_numBulleCSS + '">';
	
	// Titre
	if (p_titre!=='')
		contenuBulle+='<h3>'+ p_titre + '</h3> ';
	else
		contenuBulle+='<h4>&nbsp;</h4> ';
	
	// Texte(justification du texte)
	switch (OPT_alignement)
		{
		case 0:	contenuBulle+='<div style="text-align:left;">';break;
		case 1:	contenuBulle+='<div style="text-align:right;">';break;
		case 2:	contenuBulle+='<div style="text-align:center;">';break;
		case 3:	contenuBulle+='<div style="text-align:justify;">';break;
		default:break;
		}
	contenuBulle+=p_texte + '</div>';
	

	if (OPT_infossupp)
		contenuBulle+='<span class="more' + OPT_numBulleCSS + '">' + OPT_infossupp + '</span>';		
	
	contenuBulle+='</div>';
	

	
	// Décale la bulle afin de ne pas la faire clignoter avec onMouseMove
	Decal_X=5;
	Decal_Y=5;
	objetBulle.innerHTML=contenuBulle;
	
	// Efface la bulle si appuie sur une touche de l'objet rattaché
	if (OPT_suppressionOnKeyPress)
		p_objetAppelant.onkeypress=function() {Bulle_Final(this);};


	objetBulle.forcerAffichage=OPT_forcerPositionAffichage;
	
	// Attribue les méthodes à l'objet
	objetBulle.privBulle_AfficheObjet=privBulle_AfficheObjet;
	objetBulle.privBulle_RenvoiePosSouris=privBulle_RenvoiePosSouris;

	// Met un ID aléatoire si aucun n'existe (obligatoire pour appeler onmouseout)
	if (p_objetAppelant.id==='')
		p_objetAppelant.id='idObjet'+(Math.round(Math.random()*1000));	
	
	p_objetAppelant.idBulle=idBulle; // Pour fermer la bulle rattachée à l'objet
	p_objetAppelant.onmouseout=function()
		{ if (Bulle_Final(this)) this.onmouseout=null; };		

	listeBulles.push(objetBulle.id);

	objetBulle.objetAppelant=p_objetAppelant.id;
	
	if (OPT_affichageRetarde>0)
		objetBulle.evnmtDepartRetarde=setTimeout('Bulle_Demarrage(\'' + objetBulle.id + '\')',OPT_affichageRetarde);
	else
		Bulle_Demarrage(objetBulle.id);		

}	


// Exécute le premier affichage
function Bulle_Demarrage(idObjetBulle)
	{
	
	var objetBulle=privBulle_RenvoieLienObjet(idObjetBulle);
	if (objetBulle)
		{
		
		// Correction d'un léger bug sous IE : premier affichage en dehors des limites
		//if (ie || affichageRetarde)
		objetBulle.privBulle_AfficheObjet( Mouse_X +Decal_X, Mouse_Y +Decal_Y, 100);
		
		// Supprime l'infobulle après N ms
		if (objetBulle.dureeAffichage>0)
			setTimeout('Bulle_Final(privBulle_RenvoieLienObjet(\'' + objetBulle.objetAppelant + '\'))', objetBulle.dureeAffichage);
		
		
		// Fixe l'opacité de la bulle pour le premier affichage
		if (objetBulle.affichageProgressif!==0)
			{
			objetBulle.valeurOpacite=40;
			privBulle_FixeOpacite(objetBulle);			

			// Temporisation car si appel direct bug sur IE6 (pas IE5 ni IE7)
			// (au prochain rappel, ne fonctionnait plus si opacité décroissante en quittant)
			objetBulle.evnmtOpaciteDiminue=0;
			setTimeout('Bulle_ProgressAllume(\'' + objetBulle.id + '\',true)',50);
			}
		else
			{
			objetBulle.valeurOpacite=92;
			privBulle_FixeOpacite(objetBulle);
			}			
			
		objetBulle.evnmtDepartRetarde=0;
		
		// Correction du bug d'IE car les combo sont tjs visibles, même si infobulle
		if (ie && !ie7) 
			privBulle_EstDefinieSwap(objetBulle, 'visible');

		objetBulle.bulleAffichee=true;
			
		}
	}
	
	
// Final des bulles
function Bulle_Final (p_objetAppelant)
	{
	var numBulle=privBulle_Recherche(p_objetAppelant.idBulle);
	if (numBulle!==null)		
		{
		var objetBulle=privBulle_RenvoieLienObjet(listeBulles[numBulle]);
		objetBulle.bulleEnCoursFin=true;
		
		// Annule affichage si retardé
		if (objetBulle.evnmtDepartRetarde>0)
			{
			clearTimeout(objetBulle.evnmtDepartRetarde);
			objetBulle.evnmtDepartRetarde=0;
			}
		if (objetBulle.effacementProgressif!==0)
			Bulle_ProgressEteint(objetBulle.id, true);
		else
			Bulle_Supprime(objetBulle);
		}
	}	
	

	
	
// Rend la bulle de moins en moins opaque
function Bulle_ProgressEteint(idObjetBulle, PremierAppel)
	{
	var objetBulle=privBulle_RenvoieLienObjet(idObjetBulle);
	if (objetBulle && objetBulle.bulleAffichee)
		{	
		if ((PremierAppel===false && objetBulle.evnmtOpaciteDiminue>0) || PremierAppel===true)
			{
			objetBulle.evnmtOpaciteDiminue=0;
			objetBulle.evnmtOpaciteAugmente=0;
			if (objetBulle.bulleAffichee===true)
				{
				objetBulle.valeurOpacite-=objetBulle.effacementProgressif;
				if (objetBulle.valeurOpacite<0) objetBulle.valeurOpacite=0;
				privBulle_FixeOpacite (objetBulle);
				
				if (objetBulle.valeurOpacite>0)
					objetBulle.evnmtOpaciteDiminue=setTimeout('Bulle_ProgressEteint(\'' + idObjetBulle + '\', false)', 30);
				else
					Bulle_Supprime(objetBulle);
				}
			}
		}
	}
	
	
	
// Rend la bulle de plus en plus opaque
function Bulle_ProgressAllume(idObjetBulle,PremierAppel)
	{
	
	var objetBulle=privBulle_RenvoieLienObjet(idObjetBulle);
	if (objetBulle)
		{
		
		if (objetBulle.evnmtOpaciteDiminue===0)
			{
				
			if ((PremierAppel===false && objetBulle.evnmtOpaciteAugmente>0) || PremierAppel===true)
				{
				objetBulle.evnmtOpaciteDiminue=0;
				objetBulle.evnmtOpaciteAugmente=0;
				if (objetBulle.bulleAffichee===true)
					{
					objetBulle.valeurOpacite+=objetBulle.affichageProgressif;
					if (objetBulle.valeurOpacite>92) objetBulle.valeurOpacite=92;
					
					privBulle_FixeOpacite (objetBulle);
					
					if (objetBulle.valeurOpacite<92)
						objetBulle.evnmtOpaciteAugmente=setTimeout('Bulle_ProgressAllume(\'' + idObjetBulle + '\', false)', 50);
					}
				}
			}
		}
	}	
	
	
// Supprime la bulle immédiatement de l'écran
function Bulle_Supprime(objetBulle)
	{
	// Supprime l'objet 
	var numBulle=privBulle_Recherche(objetBulle.id);

	// Retire la bulle de la liste
	listeBulles.splice(numBulle,1);					
	
	document.body.removeChild(objetBulle);
	}		
	
function privBulle_RECT()
	{
	this.Left   =0;
	this.Top    =0;
	this.Right  =0;
	this.Bottom =0;
	}

// Renvoie un objet
function privBulle_RenvoieLienObjet(nomObjet)
	{
	if (document.getElementById) 
		return document.getElementById(nomObjet);
	
	if (document.all)  
		return document.all[nomObjet];
	
	return( null);
	}


	




// Dimensions du navigateur
function privBulle_RenvoieDimNavig()
	{
	var L_Doc;
	var H_Doc;
	var DocRef;

	if( window.innerWidth)
		{
		Fenetre.Left   = window.pageXOffset;
		Fenetre.Top    = window.pageYOffset;
		Fenetre.Right  = window.innerWidth;
		Fenetre.Bottom = window.innerHeight;

		L_Doc = document.body.clientWidth;
		H_Doc = document.body.clientHeight;

		if( Fenetre.Right  > L_Doc && L_Doc>0) Fenetre.Right  = L_Doc;
		if( Fenetre.Bottom > H_Doc && H_Doc>0) Fenetre.Bottom = H_Doc;

		}
	else
		{ // Cas Explorer à part
		if (document.documentElement && document.documentElement.clientWidth)
			DocRef = document.documentElement;
		else
			DocRef = document.body;

		Fenetre.Left   = DocRef.scrollLeft;
		Fenetre.Top    = DocRef.scrollTop;
		Fenetre.Right  = DocRef.clientWidth;
		Fenetre.Bottom = DocRef.clientHeight;

		}
	//-- limite Maxi Fenêtre Affichage
	Fenetre.Right  += Fenetre.Left;
	Fenetre.Bottom += Fenetre.Top;

	}

	
	
function privBulle_RenvoiePosSouris(e) 
	{
	
	if (e && e.target)
		{
		Mouse_X = e.pageX;
		Mouse_Y = e.pageY;
		}
	else
		{
		var DocRef;
		if( document.documentElement && document.documentElement.clientWidth)
			DocRef = document.documentElement;
		else
			DocRef = document.body;

		Mouse_X = event.clientX +DocRef.scrollLeft;
		Mouse_Y = event.clientY +DocRef.scrollTop;
		}

		
	// Parcours les bulles pour décaler celles affichées
	for (var i=0;i<listeBulles.length;i++)
		{
		var objBulle=privBulle_RenvoieLienObjet(listeBulles[i]);
		
		if (objBulle)
			{
			if (!objBulle.bulleEnCoursFin && objBulle.bulleAffichee)
				objBulle.privBulle_AfficheObjet( Mouse_X +Decal_X, Mouse_Y +Decal_Y, 100);
			// Supprime la bulle si encore affichée après n secondes
			if (((new Date).getTime()-objBulle.debutAffichage)>5000)
				Bulle_Supprime(objBulle);
			}
		}	
	}

	


// Fixe l'opacité sur un objet
function privBulle_FixeOpacite(objetBulle)
	{
	var valeurOpacite=objetBulle.valeurOpacite;
	if (opera)
		objetBulle.style.opacity=valeurOpacite/100; // opera
	else if (ie)
		objetBulle.style.filter="alpha(opacity="+valeurOpacite.toString()+")"; // IE
	else if (objetBulle.style.setProperty)
		objetBulle.style.setProperty("-moz-opacity", valeurOpacite/100, ""); // Firefox			
	else
		objetBulle.style.filter="opacity="+ (valeurOpacite/100).toString()+")";
	}



// Affiche l'objet en prenant en compte les limites de la fenêtre du navigateur
function privBulle_AfficheObjet( x_, y_, z_)
	{
	var objetBulle=this;
	var MaxX, MaxY;
	var Haut, Larg;
	var SavY = y_;

	
	if (objetBulle)
		{
		//-- Récup. dimension du DIV
		if (netscape)
			{
			Larg = objetBulle.offsetWidth; Haut = objetBulle.offsetHeight;
			}
		else
			{
			Larg = objetBulle.scrollWidth; Haut = objetBulle.scrollHeight;
			}

		// Vérif : largeur à 0 si jamais affiché
		if (Larg===0)
			{
			// Affiche hors limite pour ne pas perturber l'affichage
			objetBulle.style.display = "block";
			objetBulle.style.left='0px';
			objetBulle.style.top='-1000px';
			Larg = objetBulle.scrollWidth; Haut = objetBulle.scrollHeight;
			
			}
		
		
		 
		//-- Réajuste dimension fenêtre
		MaxX = Fenetre.Right  - Larg;
		MaxY = Fenetre.Bottom - Haut;

		//-- Application Bornage
		switch (this.forcerAffichage)
			{
			case 'D': x_ = Fenetre.Left; break;
			
			case 'G': x_ = Mouse_X-Larg-5; break;
			
			default:
				if ( x_ > MaxX) x_ = Mouse_X-Larg-5; //MaxX
				if ( x_ < Fenetre.Left) x_ = Fenetre.Left;
				break;
			}
			
		if ( y_ > MaxY) y_ = Mouse_Y-Haut-5;// MaxY;
		if ( y_ < Fenetre.Top)  y_ = Fenetre.Top;			
		
		// Effectue un test d'erreur car un pb d'initialisation pourrait arriver (rare)
		try	{
			objetBulle.style.left       = x_ +"px";
			objetBulle.style.top        = y_ +"px";
			objetBulle.style.zIndex     = z_;
			objetBulle.style.visibility = "visible";
			objetBulle.style.display = "block";
			}
		catch (e)
			{}

		}
	}
	
// Fonction ajoutant un événement
function privBulle_EvnmtAjoute( obj_, event_, func_, mode_)
	{
	if( obj_.addEventListener)
		obj_.addEventListener( event_, func_, mode_? mode_:false);
	else
		obj_.attachEvent( 'on'+event_, func_);
	}		
	
// Fonction qui teste si une fonction existe
function privBulle_EstDefinieSwap(objetBulle, ElementVisible)
	{
	if (window.SwapSelect)
		SwapSelect(objetBulle.id, ElementVisible,' ');
	}
	
	
// Crée un type d'objet
function privBulle_CreeTypeObjet(type, name, objetParent) 
	{
	var nouvelElement;
	try
		{
		// IE (sinon, en raison d'un bug d'IE, on ne peut fixer le nom et l'ID après la  création de l'élément)
		nouvelElement = document.createElement('< '+type+' name="'+name+'"  id="'+name+'" />');
		} 
	catch(e) {}
		
	if (!nouvelElement)	
		{
		nouvelElement = document.createElement(type);
		nouvelElement.name=name;
		nouvelElement.id=name;
		
		// Rattache au parent
		objetParent.appendChild(nouvelElement);
		}
	return nouvelElement;
	}	
	

// Recherche une bulle
function privBulle_Recherche(idBulle)
	{
	var numBulle=null;
	var i=0;
	
	while (i<listeBulles.length && numBulle===null)
		{
		if (listeBulles[i]==idBulle)
			numBulle=i;
		else i++;
		}	
	return numBulle;
	}	
