// Code javascript SIFACILE de gestion de menus au survol ou d'infobulles
// cross browser, transparence progressive. 1 seule infobulle ouverte à l'instant t : l'ouverture 
// d'une autre infobulle provoque la fermeture de la précédente éventuelle
// fermeture sur le mouse_out. Indépendant script_layer (gestion de popup via layers) car une popup peut contenir des menus ou infobulles
// alert("name="+navigator.appName+"\nVersion="+navigator.appVersion+"\nCodename="+navigator.appCodeName)
// modif du 20/11/08 : si le step=100, on ne modifie pas la transparence avec IE6. Cause : pb avec rounded-corners
var x=navigator.userAgent.toLowerCase()
if(x.indexOf("opera")>-1) sf_NAV='Opera'
else if(x.indexOf("safari")>-1) sf_NAV='Safari'
else if(x.indexOf("msie")>-1) sf_NAV='IE'
else if(x.indexOf("mozilla")>-1 && x.indexOf("firefox")>-1) sf_NAV='Mozilla'
else if(self.document.layers) sf_NAV='NS'
else sf_NAV='?'
//alert(' \nsf_NAV='+sf_NAV+'\n\nAgent='+x)

var sf_bon='';		// mémo du nom des bulles ouverte
var sf_bopac=0;		// opacité de la bulle en cours
var sf_bstart=0;	// transparence de départ par défaut
var sf_bdel,sf_bblrefresh,sf_bblstep=0;
var sf_docbubble=Array();	// mémo des bulles, pour affichage à la fin du document
var sf_mopac=false;		// masque de body en place (true) ou pas (false)


// ouverture de la bulle d'infos (x=1) ou fermeture avec inertie (x=0)
// inertie nécessaire pour permettre un déplacement facile de la souris vers la bulle
// s=step de transparence chaque 25 msec
// m=true : repositionner pour tenir à l'écran
// start=transp. initiale à l'ouverture
function sf_bulle(name,x,s,m,start) {
	if(!x) {
		clearTimeout(sf_bblrefresh)
		sf_bdel=setTimeout('sf_bdisplay("' + name + '",0)',50);
	}
	else {
		if(!start) var start=0
		clearTimeout(sf_bdel);
		sf_bdisplay(name,1,s,m,start);
	}
}

// ouverture / extinction d'une infobulle
// x=0(éteindre)  1(allumer)
// s=step de transparence (0..100) chaque 25 msec (0 -> pas de transparence progressive)
// ok_move = true/false : repositionner pour tenir à l'écran (true)
// start=transparence de départ au moment de l'allumage (0-100)
// cont :faux = init de l'extinction / allumage, 1 -> suite (modif transparence)
// mask=xx:yy
// xx= pre -> allume le fond avant l'image, post -> allume l'image avant le fond
// yy= pre -> éteint le fond avant l'image, post -> éteind l'image avant le fond
function sf_bdisplay(name,x,s,ok_move,start,cont) {
	if(!sf_docbubble[name]) sf_docbubble[name]={'mask':'', 'center':1, 'x':0, 'y':0, 'click':''}
	if(sf_docbubble[name]['mask']) {
		var mask=sf_docbubble[name]['mask'].split(':')
		if(!mask[0]) mask=Array('none','none')
		else if(!mask[1]) mask[1]=mask[0]
	} else mask=new Array('none','none')
	delai_plus=0	// Allumage/extinction maskage -> délai supplémentaire avant action sur l'infobulle
	if(!cont) {		// INITS
		var cont=false;
		if(!x && mask[1]=='pre' && sf_bon==name) {	// bulle à éteindre et mask='pre' -> extinction du masque
			document.getElementById('sf-bodymask').style.display='none'		// estompage du body END
			delai_plus=150		// délai avant la suite des opérations
		}
		else if(x && mask[0]=='pre') {				// bulle à aluumer et mask = 'pre'-> allumage du masque
			document.getElementById('sf-bodymask').style.display='block'	// estompage du body START
			delai_plus=200
		}
		if(sf_bon) {
			if(sf_bon!=name) sf_closebulle(sf_bon)	// 	bulle à allumer/éteindre <> bulle active -> extinction immédiate de l'active
			else cont=true
		}
	}

	if(document.getElementById(name)) {
		var z=document.getElementById(name).style
		if(!s) s=sf_bblstep; else sf_bblstep=s		// pas +/-à utiliser
		if(!x && s>0) s=-s							// début d'inversion
		if(!start) var start=sf_bstart; else sf_bstart=start
		if(sf_bon) ok_move=false		// déplacement auto : uniquement avant l'ouverture
		if((x && sf_bopac<100) || (!x && sf_bopac>start)) {	// Modif de transparence en cours
			if(x && !cont) {		// INIT ALLUMAGE
				sf_bon=name;
				// si le step est =100, pas touche à l'alpha (utilisé pour résoudre le pb d'IE6 avec rounded corners)
				if(Math.abs(s)!=100) z.filter='progid:DXImageTransform.Microsoft.alpha(opacity=0)';
				z.opacity=0
				z.display='block'	// permet de connaitre sa largeur et hauteur
				var mx=0,my=0

				// calcul offset/largeur fenêtre
				var doc=document.compatMode && document.compatMode=="BackCompat" ?
				  document.body : document.documentElement
				var doc1=sf_NAV=='Safari'? document.body : doc		// Forcage obligatoire avec 3.1 (525.13)
				var w_r=doc.clientWidth								// largeur de la fenêtre
				var w_b=doc.clientHeight							// et sa hauteur
				var w_x=doc1.scrollLeft								// offset X
				var w_y=doc1.scrollTop								// offset Y
				//alert('width='+w_r+'\nheight='+w_b+'\noffset x='+w_x+'\noffset y='+w_y);
				var b_r=document.getElementById(name).offsetWidth	// largeur de la bulle
				var b_b=document.getElementById(name).offsetHeight	// et sa hauteur

				// Centrage a milieu de l'écran
				var postype=sf_docbubble[name]['center']
				if(postype=='1') {
					var b_x=w_x+Math.round((w_r-b_r)/2)
					var b_y=w_y+Math.round((w_b-b_b)/2)
				}
				
				// Positionnement relatif vs le <a> déclencheur si sf_docbubble[name]['center']=='0' ou rien, ou avec l'élément dont le ID est passé dedans sinon
				else {
					w_r-=3;w_b-=3	// marge de 3 pt avant le bord de la fenêtre
					container=document.getElementById(postype=='0' || postype=='' ? 'a_'+name : sf_docbubble[name]['center'])
				
					// Correction des bugs, en dynamique pour que la page reste cachable
					if(sf_NAV=='Safari') container.style['vertical-align']='top'		// bug Safari PC (cf doc_script_bubbles.txt)

					// Calcul du point haut/gauche du <a> container
					var x=sf_returnXY(container),
						b_x=sf_docbubble[name]['x']+x[0],
						b_y=sf_docbubble[name]['y']+x[1]
					b_r+=b_x;b_b+=b_y										// coin bas/droite de l'objet

					// calcul offset/largeur fenêtre avec marge de -5 pt autours
					var doc=document.compatMode && document.compatMode=="BackCompat" ?
					  document.body : document.documentElement
					var doc1=sf_NAV=='Safari'? document.body : doc	// Forcage obligatoire avec 3.1 (525.13)
					var w_x=doc1.scrollLeft			// offset X
					var w_y=doc1.scrollTop			// offset Y
					var w_r=doc.clientWidth+w_x-5	// bord droit limite
					var w_b=doc.clientHeight+w_y-5	// bas limite

					// calcul nouvelle pos, en cas de débordement
					if(ok_move) {
						if(b_r>w_r) mx=w_r-b_r			// déplacer vers la gauche
						if(b_x+mx<w_x) mx=w_x-b_x		// mais sans dépasser le bord
						if(b_b>w_b) my=w_b-b_b			// déplacer vers le haut
						if(b_y+my<w_y) my=w_y-b_y		// mais sans dépasser le bord
					}
				}
		
				// positionnement
				document.getElementById(name).style.left=(b_x+mx)+'px'
				document.getElementById(name).style.top=(b_y+my)+'px'
			}
			// modif de la transparence (on et off)
			if(!delai_plus) {
				sf_bopac+=s? s : 100
				if(sf_bopac>100) sf_bopac=100
				if(Math.abs(s)!=100) z.filter='progid:DXImageTransform.Microsoft.alpha(opacity='+sf_bopac+')';
				z.opacity=sf_bopac/100
				// IE 5.5+ : on peut utiliser 'progid:DXImageTransform.Microsoft.alpha(opacity='+sf_bopac+')';
			}
			if(!cont ||((x && sf_bopac<100) || (!x && sf_bopac>start)))
			  sf_bblrefresh=setTimeout('sf_bdisplay("' + name + '",'+x+',' + s +','+ok_move+','+start+',1)',25+delai_plus);
  			if(x && sf_bopac>=start && mask[0]=='post')
				setTimeout("document.getElementById('sf-bodymask').style.display='block'",200)	// délai_plus...
		}
		if(!x && sf_bopac<=start) {
			sf_closebulle(name)		// fin d'extinction -> RAZ all
			if(mask[1]=='post') setTimeout("document.getElementById('sf-bodymask').style.display='none'",100)
		}
	}
}

function sf_closebulle(name) {
	clearTimeout(sf_bblrefresh);
	document.getElementById(name).style.display='none';
	sf_bopac=0;sf_bon='';sf_bblstep=0;sf_mopac=false;sf_bstart=0
}

function sf_putbulle(name,content) {
	txt=  '<div id="'+name+'" style="z-index:999;position:absolute;left:0;top:0;display:none"'
		+ (sf_docbubble[name]['mask'] ?
			(sf_docbubble[name]['click']? 'onclick="sf_bulle(\''+name+'\',0)"' : '')
		  : ' onmouseover="sf_bulle(\''+name+'\',1)" '
		    + (sf_docbubble[name]['click'] ? 'onclick' : 'onmouseout')
		    + '="sf_bulle(\''+name+'\',0)"')
		+ '>'+ content+ '<'+'/div>';
	document.write(txt);
}


// Retourne la position X/Y de l'objet X dans la fenêtre
// Remonte l'arborescence des nodes container pour ajouter les offset des <div> quand c'est nécessaire
function sf_returnXY(x) {
	var x0=x.offsetLeft, y0=x.offsetTop, x1, y1,prevpos, thispos=''
	while(x.parentNode && x.parentNode.tagName!='BODY') {
		x=x.parentNode
		if(x.tagName=='DIV') {
			x1=typeof(x.offsetLeft)=='number' ? x.offsetLeft : 0
			y1=typeof(x.offsetTop)=='number' ? x.offsetTop : 0
			prevpos=thispos
//alert('tagname='+x.tagName+'\nprevpos='+prevpos+'\nthis pos='+thispos + '\nx='+x1+' / y='+y1);
			thispos=typeof(document.defaultView)=='undefined' ?		// IE 6/7. Ne pas tester sur currentStyle car Opera10 le reconnait
				x.currentStyle.position : document.defaultView.getComputedStyle(x, null).position
//alert('prevpos='+prevpos+'\nthis pos='+thispos+'\nx='+x1+' / y='+y1);
			switch(thispos) {
			case 'static':
				if(prevpos && prevpos!='absolute') { x1=0; y1=0 }
				else if(!prevpos)  { x1=0; y1=0 }		// Chablais
				break
			}
			x0+=x1; y0+=y1
		}
	}
	return(new Array(x0,y0))
}

// ouverture de la layer d'id "id" pour confirmer l'action "action" (download d'un ficher, saut, etc.
// what=0 -> fermet la fenêtre, 1=>l'ouvrir
// Cette courte routine est regroupée ici car son ouverture se fait via sf_bdisplay (en douceur)
var sf_confirm=new Array()
function sf_openConf(id,what,action) {
	var x=document.getElementById(id)
	if(x) {
		sf_confirm=what? Array(action,id) : Array()
		// Allumage/extinction : on bloque la transparence progressive avec IE6 (cause rounded corners) si le nom de class démarre par "ie6proof-"
		var s=x.className && x.className.substr(0,9)=='ie6proof-' && sf_NAV=='IE'? 100 : 20	
		sf_bulle(id,what,s,false)
	}
	else alert('fenêtre de confirmation introuvable : '+id)
}

function sf_exeConf() { eval(sf_confirm[0]); sf_openConf(sf_confirm[1],0) }
