/*****************
 * Classe permettant de gérer simplement un popin
 * 
 * v1.3 : Christophe Dolivet le 2009/03/20
 * 
 *------  
 * v1.3: 2009/03/20 : correctif de la methode set_style pour support de IE8 (et meilleur support navigateur de façon générale) et ajout du callback onBeforeClose
 * v1.2: 2007/10/18 : ajout de l'option 'modal'
 * v1.1: ajout du déplacement du popin 
 * v1.0: 1ère release  
 * 
 * Testé sous IE 6, IE7, IE8, Firefox 2, Opera 9 et Safari 2 avec ou sans Doctype 
 *
 * exemple d'utlisation:
 * 		var pop= new prestaPopin();
 * 		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
prestaPopinNav= new Object();	// variable contenant des infos sur les navigateurs
if((prestaPopinNav['isIE'] = (navigator.appName == "Microsoft Internet Explorer")))
	prestaPopinNav['isIE']= navigator.userAgent.replace(/^.*?MSIE ([0-9\.]*).*$/, "$1");
	
if(prestaPopinNav['isOpera'] = (navigator.userAgent.indexOf('Opera') != -1)){	
	prestaPopinNav['isOpera']= navigator.userAgent.replace(/^.*?Opera.*?([0-9\.]+).*$/i, "$1");
	prestaPopinNav['isIE']= false;	
}
prestaPopinNav['isSafari'] = (navigator.userAgent.indexOf('Safari') != -1)

 
/**
 * constructeur
 */    
function prestaPopin(){
	this.style_node	= false;
	this.id			= false;
	this.a_params	= new Array();
}



prestaPopin.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) 
	 * 		-params['onBeforeClose']: function a appeler juste avant la fermeture du popin
	 **/	 	
	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();
		this.a_params	= params;
		
		// 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(prestaPopinNav['isIE'] && (prestaPopinNav['isIE']<7 || document.compatMode!= "CSS1Compat") )
		{
			prestaPopin.prototype.static_display= false;
			background.style.position= "absolute";	
			contenu.style.position= "absolute";
		}
		else
			prestaPopin.prototype.static_display= true;
		
		// appel de la boucle gèrant la position et les dimension du popin 
		prestaPopin.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(prestaPopin.prototype.currently_moving_popin_id)=="undefined" || prestaPopin.prototype.currently_moving_popin_id!=id)	
					prestaPopin.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(prestaPopinNav['isSafari'])	// Safari
		{
			win_h= window.innerHeight;
			win_w= window.innerWidth;
		}
		else if (document.documentElement && document.documentElement.clientHeight && (prestaPopinNav['isIE'] || (document.compatMode && document.compatMode== "CSS1Compat" && !prestaPopinNav['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= prestaPopin.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(prestaPopin.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(prestaPopin.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(prestaPopin.prototype.currently_moving_popin_id)=="undefined" || prestaPopin.prototype.currently_moving_popin_id!=id)	
						prestaPopin.prototype.set_margin(contenu, ( - (contenu.offsetWidth/2)), (- (contenu.offsetHeight/2)));
				}
			}
			else
			{
				prestaPopin.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= prestaPopin.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("prestaPopin.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";
			
			var head= document.getElementsByTagName("head")[0];
			this.style_node= head.appendChild(new_style);
		}
		
		// met à jour le style
		if( this.style_node.styleSheet ) // IE
		{
			this.style_node.styleSheet.cssText = style;
		}
		else
		{ // W3C
			// supprime l'ancien style
			while( this.style_node.firstChild ) {
				this.style_node.removeChild( this.style_node.firstChild );
			}
			this.style_node.appendChild( document.createTextNode( style ) );
		}
	}
	
	
	/***
	 * fonction fermant le popin
	 */	 	
	,close: function()
	{
		if( contenu= document.getElementById(this.id))
		{
			// on s'occupe du callback onbeforeclose
			if( this.a_params['onBeforeClose'] )
			{
				try {
					this.a_params['onBeforeClose']();
				} catch (e) {}
			}
			
			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= prestaPopin.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
		prestaPopin.prototype.currently_moving_popin_id= id;
			
		var mouse_x= prestaPopin.prototype.getMouseX(e);
		var mouse_y= prestaPopin.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= prestaPopin.prototype.getMouseX(e);
			var mouse_y= prestaPopin.prototype.getMouseY(e);
			
			var move_elem= document.getElementById(prestaPopin.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));
			
			prestaPopin.prototype.set_margin(move_elem, (-move_elem.offsetWidth/2), (-move_elem.offsetHeight/2));

			return false;
		};
			
		document.onmouseup= function(e) {
			document.onmousemove= "";
			document.onmouseup= "";
			prestaPopin.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;
		}
	}
};


function popin_get_nom( id_popin )
{
	return 'pop_' + id_popin;
}

/**
 * Fonction permettant l'ouverture du popin depuis la fonction correspondante du helper
 */
function open_popin( id_popin, a_params, id_movable_element)
{
	var nom_popin = popin_get_nom( id_popin );

	// on commence par verifier que la popin n'est pas deja ouverte
	if( !document.getElementById(id_popin))
	{
		eval('window.' + nom_popin + ' = new prestaPopin();');
		eval(nom_popin + '.open("' + id_popin + '", a_params);');
	
		if( id_movable_element != '' && id_movable_element != 'undefined')
		{
			eval('pop_' + id_popin + '.set_moving_element("' + id_movable_element + '");');
		}
	}
}

/**
 * Fonction permettant l'ouverture du popin depuis la fonction correspondante du helper
 */
function open_popin_remote( id_popin, url, a_params_popin, a_params_ajax)
{
	// ouverture de la popin si necessaire
	open_popin( id_popin, a_params_popin);

	new Ajax.Updater(	id_popin, 
						url, 
						a_params_ajax);
}
