/***************** * 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 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.style_node = false; this.id = false; this.a_params = new Array(); } 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) * -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(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"; 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