Comment ouvrir de petites fenêtres (« popup ») avec des dimensions ajustables ?

Introduction
Comment appeler le script d'ouverture ?
Les différentes options possibles
Une fenêtre plein écran ?
Attention au focus
Comment refermer ces fenêtres ?
Comment passer les dimensions en paramètres ?
Redimensionnement dynamique des fenêtres
Communications entre la fenêtre mère et la fenêtre fille

Introduction

Tout repose sur la fonction javascript window.open() qui a 3 arguments, tous trois des chaînes de caractères ou des variables javascript contenant des chaînes de caractères, successivement :

  1. le fichier à charger dans la fenêtre,
  2. le nom de cette fenêtre, sous lequel cette fenêtre sera ultérieurement reconnue par le système (et qu'on pourra utiliser par la suite dans les TARGET pour charger d'autres pages dans la fenêtre)
  3. les paramètres définissant les dimensions de la fenêtre, sa position sur l'écran et ses différents attributs.

Comment appeler le script d'ouverture ?

Comme l'emploi direct de window.open() dans les liens apporte quelques surprises, on a intérêt à bâtir une nouvelle fonction au moyen d'un script du type
<SCRIPT langage="Javascript">
  function ouvre(fichier) {
  ff=window.open(fichier,"popup",
               "width=250,height=150,left=30,top=20") }
  </SCRIPT>
Dans ce script, la fenêtre s'appelle «popup» et elle s'ouvre avec les dimensions 250x150, à 30 pixels de la gauche de l'écran (left) et à 20 pixels du haut de l'écran (top). La variable ff remplie par la fonction est « l'objet Window » correspondant à la nouvelle fenêtre et on pourra s'en servir dans des scripts plus complexes.

On peut mettre d'autres attributs dans la chaine des paramètres ; on en verra quelques uns plus loin. Attention : tous ces attributs ne doivent être séparés que par des virgules (ne pas introduire d'espace!)

L'appel à cette fonction se fera soit par une URL javascript du genre
 <A HREF="javascript:ouvre('fichier.html')">cliquez ici</A> 
soit en appelant la fonction dans un onClick :
<A HREF=" " 
 onClick="ouvre('fichier.html');return false">cliquez ici</A>
Le return false a pour objectif d'empêcher le navigateur de poursuivre l'exécution de ce qu'il trouve dans la balise <A...>, et notamment d'aller sauter à l'adresse donnée dans le HREF (vide, dans la ligne ci-dessus).
Ce dernier type d'appel est très intéressant car il permet de maintenir partiellement le fonctionnement du lien pour les visiteurs qui auraient désactivé leur javascript, moyennant une légère complication, à savoir une double écriture du lien, à la fois classique et par javascript:
<A HREF="fichier.html" TARGET="popup" 
onClick="ouvre('fichier.html');return false">cliquez ici</A>
Le visiteur qui aura désactivé javascript n'aura droit qu'à une fenêtre classique, mais il pourra au moins lire la page référencée. Il serait souhaitable de faire systématiquement cet effort dans l'écriture des liens.
Il est tout de même ennuyeux d'avoir à répéter le nom du fichier et de la fenêtre à la fois dans le lien et dans la définition du script, et c'est une source d'erreur possible. On peut éviter ça en compliquant un peu le script, en passant le nom de la fenêtre en argument :
<SCRIPT langage="Javascript">
  function ouvrir(fichier,fenetre) {
  ff=window.open(fichier,fenetre,"width=250,etc...") }
</SCRIPT>  
et en réécrivant l'appel sous la forme :
<A HREF="fichier.html" TARGET="popup" 
onClick="ouvrir(this.href,this.target);return false">cliquez ici</A>

Ces bonnes résolutions étant dûment notées, il faut insister que la suite va concerner l'apparence de ces popups et qu'il sera indispensable d'avoir son javascript actif pour en juger.

Les différentes options possibles

Faites donc un premier essai avec le script précédent, juste en cliquant ici. Beaucoup des attributs usuels d'une fenêtre normale de navigateur sont manquants, mais avec des petites variantes d'un navigateur à l'autre. Parmi les points communs, cette fonction ouvre() ouvre une fenêtre mais on peut parfois avoir accès à un menu ; également, des ascenseurs peuvent apparaître, ou non, comme indiqué dans la table suivante :

  MacOS PC-Win

Menu
Ascenseurs
NN4.5
simplifié
aucun
IE5
complet
Si nécessaire
IE5
aucun
aucun
NN4.7
aucun
aucun

On peut modifier ces options en ajoutant des attributs dans le 3ème argument de window.open(). On insèrera notamment Nous avons indiqué en gras les options par défaut, c.à.d. pour lesquelles il est inutile de mettre l'attribut. Nous n'avons rien indiqué pour les lignes scrollbars et menubar parce que notre expérience, résumée dans le tableau précédent, nous a montré que les différents navigateurs n'en font qu'à leur tête.
Par exemple, l'addition des quatre premiers attributs ci-dessus à notre fonction de popup nous conduira au script suivant :
<SCRIPT>
  function ouvre2(fichier) {
  ff=window.open(fichier,"popup2",
     "width=250,height=150,left=320,top=20,scrollbars=yes"
   +",resizable=yes,menubar=yes,status=yes") }
</SCRIPT>

Pour voir la différence avec notre premier script, cliquez ici : vous allez ouvrir les deux popups en même temps, l'ancien à gauche et le nouveau à droite. Passez notamment sur la 2ème page ("longue") ; l'ascenseur vertical devrait apparaître dans tous les cas.

Il existe de nombreux autres attributs possibles, mais qui sont généralement spécifiques,
Nous reparlerons de fullscreen plus bas. L'attribut titlebar, commun à IE et NN, permettrait de supprimer le titre de la fenêtre, et donc de réduire au minimum le cadre de la fenêtre, mais son emploi passe par un script sécurisé plutôt difficile à mettre en oeuvre, et que le visiteur peut toujours refuser.

Une fenêtre plein écran ?

De temps à autre, quelqu'un demande comment ouvrir une fenêtre en plein écran. L'attribut fullscreen a précisément été conçu pour cela et il s'emploie comme suit:
<SCRIPT>
  function ouvre_plein_ecran(fichier) {
  ff=window.open(fichier,"pop","fullscreen=yes"}
</SCRIPT>
mais cela ne fonctionne que sur IE-Windows, pas sur IE-Mac, ni évidemment avec NN, quelle que soit la plate-forme. Par ailleurs, il y a un certain nombre de précautions de bon sens à prendre quand on utilise un tel mode. Nous revenons plus longuement sur cette question dans un autre article, avec un script plus général.

Attention au « focus »

On peut très bien ouvrir une fenêtre popup, puis cliquer sur la fenêtre principale. Celle-ci redevient la fenêtre active et on dit qu'elle prend le « focus ». Elle passe au premier plan et masque le popup, partiellement ou complètement. Cependant, par la suite, on peut cliquer sur un autre lien et recharger la même fenêtre popup avec une autre page ou passer sur un autre point d'ancrage dans le même fichier. Logiquement, ce popup devrait alors reprendre le « focus », c'est-à-dire repasser au premier plan. Il n'en est pas toujours ainsi, selon les navigateurs, lorsque ce popup est resté ouvert. Pour assurer qu'il reprend le focus, il suffit d'ajouter une ligne
              ff.focus()
dans les scripts précédents, après l'appel ff=window.open(...).

Comment refermer ces fenêtres ?

En règle générale, il faut éviter de multiplier les fenêtres popup pour ne pas trop tirer sur les ressources de la machine du visiteur, mais on court moins de risque avec ces fenêtres popup qu'avec les fenêtres ouvertes avec TARGET="_blank". En effet, si on fait un 2ème appel à notre fonction ouvre() sans avoir fermé le popup au préalable, on va simplement charger le nouveau fichier dans la même fenêtre, sans rien ouvrir de nouveau.

Le visiteur a toujours à sa disposition la case de fermeture de toute fenêtre, mais on peut aussi lui fournir un bouton plus accrocheur ou même rendre cette fermeture automatique — mais cette dernière ne fonctionne hélas pas toujours très bien :-((

Comment passer les dimensions en paramètres ?

Si on prévoit d'ouvrir plusieurs fenêtres toujours avec le même nom mais avec des tailles différentes, on prévoira une fonction avec 3 arguments, par exemple :
<SCRIPT>
  function ouvre3(fichier,w,h) {
     ff=window.open(fichier,"popup","width="+w
        +",height="+h+",left=10,top=10,scrollbars=no") }
</SCRIPT>
Si on prévoit des noms différents (par exemple si on veut afficher deux popups en même temps), on pourra ajouter le nom comme 4ème paramètre.

Les débutants seront déçus s'ils comptent sur une telle fonction pour exposer élégamment une série d'images sans trop d'efforts. La démarche la plus commune est de commencer par ouvrir une page « catalogue » ne comportant que des vignettes, chacune avec un lien vers un agrandissement. Si les liens se font avec un TARGET="_blank", les images agrandies se présentent très bêtement en haut à gauche d'un grand espace vide, alors qu'un lien vers une fenêtre popup ayant la taille de l'image devrait pouvoir fournir un encadrement naturellement adapté à l'image. Las! Une fois de plus, les navigateurs ont des comportements contradictoires d'une marque à l'autre et d'une machine à l'autre. On constate que la fenêtre ouverte a bien des dimensions intérieures égales aux valeurs spécifiées, mais l'image est déplacée vers le bas et la droite avec des valeurs dépendant du navigateur et du système :

IE5-windows   : 8px vers la droite, 8px vers le bas
IE5-mac         : aucun décalage
NN4.7-windows : 10px et 15px 
NN4.7-mac     : 8px et 8px 
iCab (mac)     : 8px et 8px, etc...
De tous nos essais, seul IE5-mac encadre parfaitement l'image, mais à condition de bien mettre scrollbars=no dans le script, sinon il ajoute 16 pixels à droite et en bas pour des ascenseurs fantômes...

Les marges qui apparaissent sont remplies avec la couleur de fond par défaut du visiteur, imprévisible... Bref, on ne peut pas avoir de solution satisfaisante avec une technique aussi simple; mais il est toutefois possible d'améliorer le script pour pallier ces difficultés.

Redimensionnement dynamique des fenêtres

Avec les scripts précédents, on prendra garde à refermer le popup avant de le rappeler avec des dimensions différentes (sinon, ces nouvelles dimensions ne sont pas prises en compte et le 2ème appel recharge la fenêtre initiale). Essayez avec deux images, l'une en 252x131 et l'autre en 188x257. Cela donnerait évidemment de l'intérêt aux techniques d'autofermeture des fenêtres si celles-ci étaient fiables, ce qui n'est malheureusement pas le cas... Nous allons maintenant voir une autre technique susceptible de recaler nos dimensions, hélas elle aussi avec de sérieuses difficultés.

On devrait pouvoir recadrer la fenêtre aux dimensions w x h en plaçant la ligne window.resizeTo(w,h) dans le script. Comme cette fonction n'existe que dans le javascript 1.2, son appel provoquera un message d'erreur avec les navigateurs anciens (versions "3" et en dessous), mais sans plus de conséquences dommageables.

Nous incorporerons cette fonction à notre script d'ouverture comme suit :
function ouvre4(fichier,w,h) {		
ff=window.open(fichier,"pop","left=10,top=10");			
if(ff) { ff.focus() ; ff.resizeTo(w,h)  }
	} 
Comme le resizeTo(w,h) se charge de remettre la fenêtre aux bonnes dimensions, il est inutile de mettre les informations sur width et height dans le window.open.

Essayez ce script, avec les deux mêmes images, d'abord en 252x131 puis en 188x257 (sans fermer le popup entre les deux clics). Ça devrait marcher sur PC-windows... mais hélas pas sur Mac, sauf pour NN6 ou ICab, encore ultra-minoritaires en ce début 2001, aussi vaut-il mieux ne pas utiliser cette méthode :-((

Communications entre la fenêtre mère et la fenêtre fille

Dans le sens mère–fille, la fenêtre fille (le popup) est considérée comme un cadre. Tout lien avec le nom du popup en TARGET (c.à.d. en cadre cible) provoquera le chargement de la nouvelle page dans le popup.

Dans l'autre sens, les choses restent simples si on est parti d'un frameset. Si on a des cadres «menu», «principal», etc... et qu'il y ait dans le popup un lien dont le TARGET désigne l'un de ces cadres comme cible, par exemple
<A HREF="page22.html" TARGET="principal">clic</a>
ce fichier «page22.html» sera chargé dans le cadre «principal».
  S'il n'y a pas de cadre dans la fenêtre principale, il faut recourir à la propriété javascript opener des objets de type "Window". Quand on est dans le popup, Comme on peut toujours sous-entendre le window initial, le lien ci-dessous dans le popup
<a href="#" 
  onClick="opener.location='page22.html'; return false">vers
  la page 22</a>
ouvrira la «page 22» dans la fenêtre principale.

Cette propriété opener peut aussi servir à donner un nom à la fenêtre mère quand celle-ci n'est pas issue d'un frameset, afin d'employer ensuite la syntaxe HTML classique pour les liens.

Cliquez ici pour une démonstration de cette propriété opener.

Charles