Afficher des vignettes dans une fenêtre popup

Le but de ce projet est d'afficher une série de vignettes que l'utilisateur peut agrandir dans une fenêtre popup.

Une première solution consiste à préparer un jeu de vignettes en plus des photos de taille normale. Une autre solution, plus exigeante en programmation, permet d'éviter ces fastidieuses corvées de préparation de photos. Cette solution consiste à faire fabriquer les vignettes par le navigateur à partir des photos déjà présentes sur la page web. Lors du clic sur la vignette, la photo est affichée à sa taille réelle dans une fenêtre popup.

Commençons par afficher les photos dans la page web.

<body onload="mfReduction()">

<div class="galerie">
<img class="vignette" alt="St Juste St Rambert" src="../images/v_stjuststrambert.jpg" onclick="mfZoom(this)" />
<img class="vignette" alt="Chambles" src="../images/v_chambles.jpg" onclick="mfZoom(this)" />
<img class="vignette" alt="St Romain-le-Puy" src="../images/v_stromainlepuy.jpg" onclick="mfZoom(this)" />

</div>

</body>

Chaque photo comporte un gestionnaire d'événement onclick qui appelle la fonction mfZoom() en lui transmettant l'élément appelant (l'élément img) par l'intermédiaire de la référence this. L'élement body utilise le gestionnaire d'événement onload pour appeler la fonction mfReduction().

Redimensionnement des photos

Les photos sont redimensionnées dès que toute la page a été interprétée par le navigateur (événement onload). L'opération est nettement perceptible lorsque les photos sont de grandes dimensions, mais la technique reste néanmoins intéressante.

L'interpréteur JavaScript accède aux images d'une page Web par l'intermédiaire de l'objet DOM document.images. Comme dans tous les cas où il s'agit de représenter une collection d'objets, images est un tableau (Array) dont la propriété length nous indique la longueur. Il est donc possible de parcourir toutes les images du document au moyen d'une boucle for.

function mfReduction() {
var n = document.images.length ;
for (var i = 0 ; i < n ; i++) {

mfRedimensionne(i) ;


}
}

La fonction mfRedimensionne(i) reçoit l'indice i de la photo dans le tableau images, ce qui permet d'accéder à la photo pour récupérer ses propriétés width et height. On peut alors calculer q, le rapport entre la hauteur et la largeur. On affecte ensuite à la variable h la hauteur voulue et on recalcule w. Il ne reste plus qu'à affecter les variables w et h aux propriétés width et height.

function mfRedimensionne(i) {
var w = document.images[i].width ;
var h = document.images[i].height ;
var q = h / w ;
h = 50 ;
w = h / q ;
document.images[i].width = w ;
document.images[i].height = h ;
}

Notez que les variables w et h ne sont pas indispensables, mais qu'elles rendent le code plus lisible.

Penchons-nous maintenant sur la fonction mfZoom(photo). Elle doit afficher dans une fenêtre fille la photo qui lui est transmise en argument par le gestionnaire d'événement onclick. L'argument photo contient donc un élément <img> et on peut accéder à l'attribut src de cet élément pour connaître la source de la photo.

L'ouverture de la fenêtre fille ne devrait pas poser de problème : la méthode window.open() s'en charge. Mais comment faire en sorte que la bonne photo soit affichée dans le fenêtre ? Il n'y a qu'un moyen, c'est de modifier la valeur de l'attribut src de l'élément <img>. Or, la fenêtre fille est parfaitement vierge. Nous devons donc y placer dynamiquement du code html après qu'elle soit ouverte et il n'y a qu'un moyen de le faire, c'est d'utiliser JavaScript. Pour écrire dans une fenêtre fille depuis la fenêtre mère, celle-ci doit donc disposer d'une "poignée" (ang. handle) sur la fenêtre fille : elle doit donc utiliser la valeur de retour de la méthode window.open(), comme ceci :

p = window.open('', "zoom");

La variable p (p comme poignée !) est une fenêtre ! Et tout comme l'on écrit window.document.write(), on peut écrire p.document.write pour écrire dans la fenêtre fille depuis la fenêtre mère.

Dès que l'on a compris cela, le reste n'est plus que de l'écriture de code html par la méthode document.write(). Il faut bien prendre soin d'écrire tout le code html nécessaire, y compris les éléments <html>, <head>, <body> etc.

Une fois la photo affichée, la fenêtre doit adapter ses dimensions à celles de la photo. La méthode window.resizeTo() a été inventée pour cela. On peut demander à la fenêtre mère de redimensionner la fenêtre fille, comme ceci par exemple :

p.resizeTo(150, 100) ;

Seulement cela ne fonctionne pas avec Mozilla. La solution est donc de demander à la fenêtre fille d'ajuster elle-même ses propres dimensions à celles de la photo.Ceci ne peut se produire que grâce à un script placé dans la fenêtre fille. Il faut donc que la fenêtre mère écrive du JavaScript en JavaScript !

 

p.document.write('<script type="text/javascript">') ;

 

p.document.write("</script>") ;
function mfZoom(photo) {
var css = '<link href="../css/zoom.css" type="text/css" rel="stylesheet" />' ;
p = window.open('', "zoom", "resizable=no,scrollbars=no") ;
p.document.write("<html><head>") ;
p.document.write(css) ;
p.document.write("</head>") ;
p.document.write("<body>") ;
p.document.write("<table>") ;

// affichage du titre de la photo
p.document.write("<tr><td>") ;
p.document.write(photo.title) ;
p.document.write("</td></tr>") ;

// affichage de la photo
p.document.write("<tr><td>") ;
buf = "<img src=\"" + photo.src + "\" name=\"laphoto\"/>" ;
p.document.write(buf) ;
p.document.write("</td></tr>") ;

// affichage du bouton fermer
p.document.write("<tr><td class='btFermer'>") ;
p.document.write("<button onclick='window.close()'>Fermer la fenêtre</button>") ;
p.document.write("</td></tr>")
p.document.write("</table>") ;

// écriture du script javascript par javascript
p.document.write('<script type="text/javascript">') ;
p.document.write("w = document.laphoto.width + 100 ;") ;
p.document.write("h = document.laphoto.height + 150 ;") ;
p.document.write("window.resizeTo(w, h) ;") ;
p.document.write("</script>") ;
p.document.write("</body></html>") ;
}

L'affichage du titre de la photo ne pose aucun problème : il suffit de récupérer la valeur de l'attribut title de l'élément <img>

p.document.write(photo.title) ;

Par contre, notre script nous pose un gros problème : il affecte toutes les images du document. Comment faire en sorte qu'il se limite aux vignettes ?