/*****************
 * Classe permettant de gérer simplement un popin
 * 
 * v1.2 : Christophe Dolivet le 18/10/2007
 * 
 *------  
 * v1.2: ajout de l'option 'modal'
 * v1.1: ajout du déplacement du popin 
 * v1.0: 1ère release  
 * 
 * Testé sous IE 6, IE7, Firefox 2, Opera 9 et Safari 2 avec ou sans Doctype 
 *
 * exemple d'utlisation:
 * 		var pop= new PFW_Popin();
 * 		var params= new Object();
 * 		params['contenu']= "bouh";  
 * 		if(pop.open("mon_id", params))					// le popin est affiché ici et contient bouh
 * 			pop.set_moving_element("id_element");		// facultatif, défini l'element ayant comme id "id_element", comme étant un élément permettant de déplacer le popin
 * 		pop.close();     
 *****************/
 

//--- récupération d'informations sur les navigateurs
PFW_popin_nav= new Object();	// variable contenant des infos sur les navigateurs
if((PFW_popin_nav['isIE'] = (navigator.appName == "Microsoft Internet Explorer")))
	PFW_popin_nav['isIE']= navigator.userAgent.replace(/^.*?MSIE ([0-9\.]*).*$/, "$1");
	
if(PFW_popin_nav['isOpera'] = (navigator.userAgent.indexOf('Opera') != -1)){	
	PFW_popin_nav['isOpera']= navigator.userAgent.replace(/^.*?Opera.*?([0-9\.]+).*$/i, "$1");
	PFW_popin_nav['isIE']= false;	
}
PFW_popin_nav['isSafari'] = (navigator.userAgent.indexOf('Safari') != -1)

 
/**
 * constructeur
 */    
function PFW_Popin(){
	this.stylesheet= false;
	this.id= false;
}



PFW_Popin.prototype= {
	
	/****
	 * fonction a appeler pour afficher le popin
	 * 
	 * @id:	id de l'element qui sera créé
	 * @params: tableau de paramètres pour l'affichage du popin. Ce tableau est facultatif
	 * 		-params['contenu']: le contenu html qui sera affiché dans le popin à l'affichage
	 * 		-params['bg_color']: couleur du fond recouvrant la page
	 * 		-params['bg_opacity']: un chiffre entre 0 et 1 indicant le degré d'opacité du fond qui recouvre la page
	 * 		-params['style']: une chaine de css qui peut etre associée au popin (eg: div.popin{border: solid black 1px;} )
	 * 		-params['width']: spécifie une largeur pour le popin
	 * 		-params['height']: spécifie une hauteur pour le popin
	 * 		-params['class']: spécifie une class pouvant être associée au popin	 
	 * 		-params['modal']: défini si le popin est modal ou pas (modal par défaut) 
	 **/	 	
	open: function(id, params)
	{	
		// on créé le popin s'il n'y a pas déjà un element dans la page avec cet ID
		if(document.getElementById(id))
			return false;

		this.id= id;
		if(!params)
			params= new Array();
		
		// ajout du style du popin
		style="div.popin_background {top: 0px; left: 0px; width:100%; height:100%; position: fixed; z-index: 999998;";
		if(params["bg_color"])
			style+="background-color: "+ params["bg_color"] +";";
		if(params["bg_opacity"])
			style+="opacity: "+ params["bg_opacity"] +"; -moz-opacity: "+ params["bg_opacity"] +"; filter:alpha(opacity="+ params["bg_opacity"]*100 +"); -khtml-opacity: "+ params["bg_opacity"] +"; ";
		style+="} ";
		style+="div.popin_contenu { background-color: #FFFFFF; display: block; position: fixed; top: 50%; left: 50%; overflow: auto; z-index: 999999;}";
	
		// cache le fond pour le mode modal
		if(params["modal"]!="undefined" && params["modal"]==false)
			style+= " div.popin_background { display: none; } ";
		
		if(params["style"])
			style+= params["style"];
	
		this.set_style(style);
			
		// création du popin
		var background= document.createElement("div");
		background.id= "background_"+id;
		background.className= "popin_background";
		document.body.appendChild(background);
		
		var contenu= document.createElement("div");
		contenu.id= id;
		var class_contenu= "popin_contenu";
		if(params["class"])
			class_contenu+=" "+params["class"];
		contenu.className= class_contenu;
		document.body.appendChild(contenu);	
		
		contenu.decal_x=0;
		contenu.decal_y=0;
		
		if(params["contenu"])
			contenu.innerHTML= params["contenu"];
		if(params["width"])
			contenu.style.width= params["width"];
		if(params["height"])
			contenu.style.height= params["height"];
			
		
		// positionnement du popup
		contenu.style.marginLeft= (-contenu.offsetWidth/2)+"px";
		contenu.style.marginTop= (-contenu.offsetHeight/2)+"px";

		// pour IE il faut mettre le popin en position absolute pour la suite des opérations si c'est IE <7 ou qu'il n'y pas pas de compat mode (dtd)
		if(PFW_popin_nav['isIE'] && (PFW_popin_nav['isIE']<7 || document.compatMode!= "CSS1Compat") )
		{
			PFW_Popin.prototype.static_display= false;
			background.style.position= "absolute";	
			contenu.style.position= "absolute";
		}
		else
			PFW_Popin.prototype.static_display= true;
		
		// appel de la boucle gèrant la position et les dimension du popin 
		PFW_Popin.prototype.correct_popin_pos(this.id);
		
		return true;
	}
	
	/**
	 * fonction publique pouvant être appelée après que le contenu du popin ai été changé, 
	 * pour que le repositionnement du popin soit immédiat 
	 */	 	
	,refreshDisplay: function()
	{
		this.correct_popin_pos(this.id);
	}

	
	/**
	 * fonction private ou static gérant le repositionement du popin au cas ou son contenu est modifié
	 * 
	 * @id: id du popin à fournir dans le cas d'un appel static		 
	 */	 	
	,refresh_static_size: function(id)
	{
		
		if(!id)
			id= this.id;
		if(id)
		{
			if(contenu= document.getElementById(id))
			{		
				if(typeof(PFW_Popin.prototype.currently_moving_popin_id)=="undefined" || PFW_Popin.prototype.currently_moving_popin_id!=id)	
					PFW_Popin.prototype.set_margin(contenu, (-contenu.offsetWidth/2), (-contenu.offsetHeight/2));
			}
		}
	}
	
	/**
	 * fonction statique retournant les dimensions de la fenetre
	 */	
	,get_window_size: function()
	{
		var win_w,win_h;
		
		if(PFW_popin_nav['isSafari'])	// Safari
		{
			win_h= window.innerHeight;
			win_w= window.innerWidth;
		}
		else if (document.documentElement && document.documentElement.clientHeight && (PFW_popin_nav['isIE'] || (document.compatMode && document.compatMode== "CSS1Compat" && !PFW_popin_nav['isOpera'])))
			// Explorer 6 ou Firefox in Strict Mode
		{
			win_w = document.documentElement.clientWidth;
			win_h = document.documentElement.clientHeight;
		}
		else if (document.body) // other 
		{
			win_w = document.body.clientWidth;
			win_h = document.body.clientHeight;
		}
		
		return {'w': win_w, 'h': win_h};
	}
	
	/**
	 * fonction statique gérant les marges du contenu du popin avec le déplacement du popin
	 */	
	,set_margin: function(elem, marginLeft, marginTop)
	{
		// récupère les dimension de la fenetre
		var win_size= PFW_Popin.prototype.get_window_size();
		var win_w= win_size['w'];
		var win_h= win_size['h'];
		
		// vérifie qu'on sort pas en haut de l'ecran
		var new_decal_y= Math.max(elem.decal_y, -(win_h-elem.offsetHeight)/2);
		// vérifie qu'on sort pas en bas de l'ecran
		new_decal_y= Math.min(new_decal_y, (win_h-elem.offsetHeight)/2);
		if(new_decal_y!=elem.decal_y)
			elem.decal_y= new_decal_y;
		
		
		// vérifie qu'on sort pas à gauche de l'ecran		
		var new_decal_x= Math.max(elem.decal_x, -(win_w-elem.offsetWidth)/2);
		// vérifie qu'on sort pas à droite de l'ecran
		new_decal_x= Math.min(new_decal_x, (win_w-elem.offsetWidth)/2);	
		if(new_decal_x!=elem.decal_x)
			elem.decal_x= new_decal_x;
		
		// corrige les marges pour le cas ou le navigateur ne supporte pas la position static	
		if(PFW_Popin.prototype.static_display== false )
		{
			var html = document.getElementsByTagName("html")[0];
			marginTop+= html.scrollTop + document.body.scrollTop;
			marginLeft+= html.scrollLeft + document.body.scrollLeft;
		}
			
		elem.style.marginTop= (marginTop+new_decal_y)+"px";
		elem.style.marginLeft= (marginLeft+new_decal_x)+"px";
	}
	
	/**
	 * fonction statique de correction de position
	 */	 	
	,correct_popin_pos: function(id)
	{

		if(contenu= document.getElementById(id))
		{
			// pour IE il faut mettre le popin en position absolute pour la suite des opérations si c'est IE <7 ou qu'il n'y pas pas de compat mode (dtd)
			if(PFW_Popin.prototype.static_display== false )
			{
				if(background= document.getElementById("background_"+id))
				{
					var html = document.getElementsByTagName("html")[0];
					var height= (html.clientHeight==0)?document.body.clientHeight:html.clientHeight;
					var width= (html.clientWidth==0)?document.body.clientWidth:html.clientWidth;
					
					background.style.height= height+"px";
					background.style.width= width+"px";
					background.style.top= (html.scrollTop + document.body.scrollTop) +"px";
					background.style.left= (html.scrollLeft + document.body.scrollLeft) +"px";
					
					
					contenu.style.top= (height/2)+"px";
					contenu.style.left= (width/2)+"px";
			
					if(typeof(PFW_Popin.prototype.currently_moving_popin_id)=="undefined" || PFW_Popin.prototype.currently_moving_popin_id!=id)	
						PFW_Popin.prototype.set_margin(contenu, ( - (contenu.offsetWidth/2)), (- (contenu.offsetHeight/2)));
				}
			}
			else
			{
				PFW_Popin.prototype.refresh_static_size(id);
			}
			
			//------------ vérif que les dimensions du contenu ne sont pas plus grandes que l'ecran --------------
			
			// récupère les dimension de la fenetre
			var win_size= PFW_Popin.prototype.get_window_size();
			var win_w= win_size['w'];
			var win_h= win_size['h'];
			
			
			
			// vérifie la hauteur
			var curr_h= contenu.scrollHeight;
			var prev_h= contenu.getAttribute('previous_height');
			var modif_h_en_cours= contenu.getAttribute('modif_h_en_cours');
	
			if(modif_h_en_cours=="oui")
			{
				if(prev_h<=win_h)
					contenu.setAttribute('modif_h_en_cours', 'non');
				contenu.style.height= Math.min(win_h, prev_h)+"px";
			}		
			else if(curr_h>win_h)
			{
				contenu.setAttribute('previous_height', curr_h);
				contenu.setAttribute('modif_h_en_cours', 'oui');
				contenu.style.height= win_h+"px";
			}
			// vérifie la largeur
			var curr_w= contenu.scrollWidth;
			var prev_w= contenu.getAttribute('previous_width');
			var modif_w_en_cours= contenu.getAttribute('modif_w_en_cours');
			
			if(modif_w_en_cours=="oui")
			{
				if(prev_w<=win_w)
					contenu.setAttribute('modif_w_en_cours', 'non');
				contenu.style.width= Math.min(win_w, prev_w)+"px";
			}		
			else if(curr_w>win_w)
			{
				contenu.setAttribute('previous_width', curr_w);
				contenu.setAttribute('modif_w_en_cours', 'oui');
				contenu.style.width= win_w+"px";
			}
			//-------------------------------------------------------------------------------
			
			setTimeout("PFW_Popin.prototype.correct_popin_pos('"+id+"')", 50);
		}
	}
	
	/**
	 * fonction définissant via le DOM le style utilisé par ce popin
	 */	 	
	,set_style: function(style)
	{
		// Si une feuille de style n'a pas encore étées crée pour le style du popin, on créé une feuille de style dans le DOM
		if(!this.style_node)
		{
			var new_style = document.createElement("style");
			new_style.type="text/css";
			new_style.media="all";
			new_style.id= "PFW_popin_style_"+ this.id;
			
			var head= document.getElementsByTagName("head")[0];
			this.style_node= head.appendChild(new_style);
			/**
			 * dans le cas ou des balises css sont définies dans la page, le dernier element de document.styleSheets
			 * ne correspond pas au dernier style ajouté. On essai donc de retrouver le bon élément par son id 
			 * (si le navigateur le permet).
			 */			 			 
			try{
				this.stylesheet = document.styleSheets("PFW_popin_style_"+ this.id);
			}
			catch(e){
				// récupère le stylesheet associé à la feuille de style créée 
				// ca ne marche pas pour Safari, mais safari n'utilise pas l'objet stylesheet
				this.stylesheet=  new_style.sheet;
			};
		}
		
		var cssrules = style.split("}");
		
		if(PFW_popin_nav['isSafari'])	// safari
		{
			// supprime les anciennes regles de style
			while (this.style_node.firstChild) {
				this.style_node.removeChild(this.style_node.firstChild);
			}
			
			// ajoute le nouveau style		
			for(i=cssrules.length-2;i>=0;i--) {
				this.style_node.appendChild( document.createTextNode(cssrules[i]+"}") ); 
			}
		}
		else if(this.stylesheet.addRule) { //IE
			// supprime les anciennes regles de style
			while(this.stylesheet.rules.length>0)
				this.stylesheet.removeRule(0);
			
			// ajoute le nouveau style		
			for(i=cssrules.length-2;i>=0;i--) {
				var newrule = cssrules[i].split("{");
				var selectors= newrule[0].split(",");	// IE doesn't manage multiple selectors at once
				for(var k=0; k<selectors.length; k++)
				{
					this.stylesheet.addRule(selectors[k],newrule[1])
				}
			}
		}
		else if(this.stylesheet.insertRule) { //Firefox etc
			// supprime les anciennes regles de style
			try
			{
				while(this.stylesheet.cssRules.length>0)
					this.stylesheet.deleteRule(0);
			}catch(e){};
			
				
			// ajoute le nouveau style
			for(i=cssrules.length-1;i>=0;i--) {
				if(cssrules[i].indexOf("{")!=-1){
					this.stylesheet.insertRule(cssrules[i]+"}",0);
				}
			}
		}
	}
	
	
	/***
	 * fonction fermant le popin
	 */	 	
	,close: function()
	{
		if(contenu= document.getElementById(this.id))
		{
			document.body.removeChild(contenu);
			// remove elements
			if(background= document.getElementById("background_"+this.id))
				document.body.removeChild(background);
		
			// on supprime les iframes potentiellement contenues ds le popin (les iframes sont mal supprimées ds les navigateurs sinon)
			frame_tab= contenu.getElementsByTagName("iframe");
			for(var i=0; i<frame_tab.length; i++)
			{
				try {
					var name= frame_tab[i].getAttribute("name");
					delete window.frames[name];
				} catch (e) {}
			}
			this.set_style("");
			this.id= false;
		}
	}

	
	/*********************************************/
	/*******   Moving popin functions  ***********/
	/*********************************************/
	
	
	/**
	 * define the id of the element that will allow to move the popin
	 */	 	
	,set_moving_element: function(id) {
		if(elem= document.getElementById(id))
		{
			elem.popin_id= this.id;
			elem.onmousedown= PFW_Popin.prototype.start_move;
			elem.onmouseover= function (){elem.style.cursor= "move"; };
			elem.onmouseout= function (){elem.style.cursor= "auto"; };
		}
	}
	
	/**
	 * static function called when the mousedown event is called on the movable element
	 */	 	
	,start_move: function(e)
	{
		if(!e)
			e= event;
		
		// retrieve the popin id
		var node= (e.target || e.srcElement);
		while(node.parentNode && !node.popin_id)
			node= node.parentNode;
		
		id= node.popin_id;
		
		// set a static attribute for retriving the popin while moving mouse
		PFW_Popin.prototype.currently_moving_popin_id= id;
			
		var mouse_x= PFW_Popin.prototype.getMouseX(e);
		var mouse_y= PFW_Popin.prototype.getMouseY(e);
		
		var move_elem= document.getElementById(id);
		
		move_elem.start_mouse_x = mouse_x;
		move_elem.start_mouse_y = mouse_y;
		move_elem.start_decal_x = move_elem.decal_x;
		move_elem.start_decal_y = move_elem.decal_y;
		
		document.onmousemove= function(e){
			if(!e)
				e= event;
			var mouse_x= PFW_Popin.prototype.getMouseX(e);
			var mouse_y= PFW_Popin.prototype.getMouseY(e);
			
			var move_elem= document.getElementById(PFW_Popin.prototype.currently_moving_popin_id);
			
			move_elem.decal_y= parseInt(parseInt(move_elem.start_decal_y) + mouse_y - parseInt(move_elem.start_mouse_y));
			move_elem.decal_x= parseInt(parseInt(move_elem.start_decal_x) + mouse_x - parseInt(move_elem.start_mouse_x));
			
			PFW_Popin.prototype.set_margin(move_elem, (-move_elem.offsetWidth/2), (-move_elem.offsetHeight/2));

			return false;
		};
			
		document.onmouseup= function(e) {
			document.onmousemove= "";
			document.onmouseup= "";
			PFW_Popin.prototype.currently_moving_popin_id="";		
			return false;
		};
		
		return false;
	}
	
	/**
	 * retrieve mouse coordinates
	 */	 	
	,getMouseX: function (e){
	
		if(e!=null && typeof(e.pageX)!="undefined"){
			return e.pageX;
		}else{
			return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft;
		}
	}
	
	/**
	 * retrieve mouse coordinates
	 */	
	,getMouseY: function(e){
		if(e!=null && typeof(e.pageY)!="undefined"){
			return e.pageY;
		}else{
			return (e!=null?e.y:event.y)+ document.documentElement.scrollTop;
		}
	}
};
