29-11-2011 : Remettre dans le débat politique les principes du Conseil National de la Résistance
17-02-2012 : Pétition pour une protection de l’apiculture et des consommateurs face au lobby des OGM
Logo de mon site
Logo de mon site
Faire un don

Luxpopuli / eZ Publish / Trucs & astuces / eZ Publish : créer une page de contact avec la librairie highSlide





Right menu

Logo du site ez.no  Logo XHTML 1.O du W3C  Logo XHTML 1.O du W3C  Site francophone officiel de Firefox
zero papier grâce aux catalogues et promos en ligne de bonial

eZ Publish : créer une page de contact avec la librairie highSlide

Date de publication: le vendredi 1 mai 2009 à 19h20
Dernière modification: par Pascal BOYER le lundi 4 mai 2009 à 18h54
« Article précédent: eZ Publish : créer une galerie d'images avec la librairie highSlide
» Article suivant: eZ Publish : création automatique d'une galerie d'images CSS - Partie I

L'objet de cet article est en lien direct avec celui-ci, eZ Publish : créer une galerie d'images avec la librairie highSlide , en ce qu'il en constitue en quelque sorte la suite. Il s'agit en effet de présenter ici la mise en oeuvre d'une page de contact utilisant, conjointement à la galerie d'images, la librairie highSlide. Cette mise en oeuvre justifie un article en raison des nombreux problèmes que posent et la double utilisation de highslide et l'utilisation de plusieurs templates par le système d'envoi de formulaires.

Exemple de page de contact

Ressources

Vous trouverez sur le site highslide.com beaucoup de renseignements utiles et particulièrement:

Problèmes rencontrés

  • Paramétrage distinct pour chaque page utilisant highSlide,
  • Affichage de la page de contact dès son chargement sans passer par un clic sur un lien,
  • Positionnement du bouton de fermeture de la popup,
  • Lier le bouton de fermeture de la popup à un lien de redirection,
  • Affichage dans la popup des différents templates du système d'envoi du formulaire,
  • Problème d'affichage avec IE7.

I - Le fichier highSlide-full.js

Le fichier javascript highSlide-full.js peut être téléchargé sur cette page: http://highslide.com/download.php

Comme nous serons amenés à modifier certaines valeurs de paramètres de ce fichier, mieux vaut ne pas télécharger dès à présent la version highSlide-full.packed.js. Il sera toujours temps d'obfusquer et/ou de compresser ce fichier ultérieurement.

Nous utilisons cette version complète (mais un peu lourde) pour être sûr, lors de la mise en oeuvre de la page de contact, de ne pas rencontrer de problèmes javascript liés à l'absence d'options dans le fichier highSlide.js

L'inclusion de ce javascript dans le template pagelayout.tpl requière le code suivant (juste après la balide <body>):

{section name=JavaScript loop=ezini( 'JavaScriptSettings', 'JavaScriptList', 'design.ini' ) }
    <script language="JavaScript" type="text/javascript" src={concat( 'javascript/',$:item )|ezdesign}></script>
{/section}

Ce qui implique de modifier ainsi le fichier de surcharge design.ini.append.php du siteaccess public:

[JavaScriptSettings]
JavaScriptList[]=highslide-full.js

Par ailleurs, sous la balise {/section}, nous ajoutons ces lignes:

{literal}
         <script type="text/javascript">
             hs.graphicsDir = '/design/plain_site/images/graphics/';
         </script>
{/literal}

La troisième ligne indique à highSlide le chemin vers le sous-répertoire graphics dans lequel il trouvera les différents éléments graphiques utilisés pour afficher la popup.

:
Il est tout à fait possible de ne pas inclure les 5 lignes ci-dessus et de modifier directement la ligne 55 de highSlide-full.js:

56 graphicsDir : '/design/plain_site/images/graphics/'

II - La galerie photo highSlide

Le template highSlide.tpl

Ayant légèrement modifié la classe d'objet et le code du template design/plain_site/override/templates/photos/ highSlide.tpl présenté par l'article eZ Publish : créer une galerie d'images avec la librairie highSlide , voici le code modifié (et commenté) de ce template:

1 {* CE TEMPLATE PERMET DE CREER UNE GALERIE D'IMAGES highSlide *}
2     {literal}
3     <script type="text/javascript">
4             hs.showCredits = true;              // Autorise l'affichage des options hs.lang au début de highslide.js
5             hs.align = 'center';                // Définit le positionnement de la popup
6             hs.transitions = ['expand', 'crossfade'];
7             hs.fadeInOut = 'true';
8             hs.outlineType = 'rounded-white';   // Définit le type d'encadrement (voir répertoire design/plain_site/images/graphics/outlines/)
9             hs.numberPosition = 'caption';      // Définit la position de l'affichage de "Image 1 of X"
10             hs.dimmingOpacity = 0.35;           // Définit l'opacité de fond extérieur à la popup
11             hs.addSlideshow({
12                 //slideshowGroup: 'group',
13                 interval: 5000,                 // Définit l'intervalle de temps entre deux image en mode slideshow
14                 repeat: true,                   // Retour à la première image une fois arrivé à la dernière
15                 useControls: true,              // Valide l'affichage des boutons de contrôle
16                 fixedControls: 'fit',
17                 overlayOptions: {
18                     opacity: .75,               // Opacité des boutons de contrôle
19                     position: 'bottom center',  // Position des boutons de contrôle
20                     hideOnMouseOut: true,       // Cache les boutons de contrôle lorsque la souris n'est plus au-dessus de l'image
21                 }
22             });
23     </script>
24     {/literal}
25 {*  $liste_galeries CONTIENT LA LISTE DES DOSSIERS INSTANCIES A PARTIR DE LA CLASSE gallery_photos *}
26 {def    $liste_galeries=fetch_alias(    children,
27                                         hash( 'parent_node_id', $node.node_id,
28                                         depth, 1,
29                                         class_filter_type, include,
30                                         class_filter_array, array( 'gallery_photos' )))
31         $i='1'}
32 {* POUR CHAQUE DOSSIER DE LA CLASSE gallery_photos *}
33 {foreach $liste_galeries as $gallery}
34  <div class="highslide-gallery">
35   {* SI LE DOSSIER CONTIENT DES IMAGES C'EST À DIRE S'IL CONTIENT DES OBJETS DE LA CLASSE image_music *}
36   {if gt($gallery.children_count,0)}
37    {* ALORS ON RECUPÈRE LE PREMIER OBJET image_music DANS LA VAIRIABLE $liste_images - CE PREMIER OBJET EST LA PREMIÈRE IMAGE DE LA GALERIE *}
38    {def $liste_images=fetch_alias(  children,
39                                     hash( 'parent_node_id', $gallery.node_id,
40                                     depth, 1,
41                                     limit, 1,
42                                     class_filter_type, include,
43                                     class_filter_array, array( 'image_music' )))}
44    {* ET ON ECRIT LE CODE HTML QUI AFFICHERA LA VIGNETTE DE LA GALERIE TRAITÉE - C'EST LA PREMIÈRE IMAGE DE LA GALERIE *}
45    <a id="thumb1" href={$liste_images.0.data_map.image.content.original.url|ezroot} class="highslide" {literal}onclick="return hs.expand(this, { slideshowGroup:{/literal} {$i} {literal}} )"{/literal}><img src={$liste_images.0.data_map.image.content.original.url|ezroot} alt="Highslide JS" title="Click to enlarge" /></a>
46    {* PUIS ON ECRIT LE COMMENTAIRE LIÉ À CETTE PREMIÈRE VIGNETTE *}
47    <div class="highslide-caption">{attribute_view_gui attribute=$liste_images.0.data_map.commentaire_image}</div>
48    {* PUIS ON REGARDE S'IL EXISTE D'AUTRES IMAGES DANS LA GALERIE *}
49    {if gt($gallery.children_count,1)}
50     <div class="hidden-container">
51      {* AUQUEL CAS ON RECUPÈRE LA LISTE DE CES AUTRES IMAGES - ON DECALE LE DÉBUT DE LA RECHERCHE À LA DEUXIÈME IMAGE: offset, 1 *}
52      {def $liste_images1=fetch_alias(   children,
53           hash( 'parent_node_id', $gallery.node_id,
54           offset, 1,
55           depth, 1,
56           class_filter_type, include,
57           class_filter_array, array( 'image_music' )))}
58      {* ET POUR CHACUNE DE CES AUTRES IMAGES *}
59      {foreach $liste_images1 as $image1}
60       {* ON ÉCRIT LE CODE HTML NECESSAIRE À LEUR AFFICHAGE *}
61       <a href={$image1.data_map.image.content.original.url|ezroot} class="highslide" {literal}onclick="return hs.expand(this, { thumbnailId: 'thumb1', slideshowGroup:{/literal} {$i} {literal} } )"{/literal} ></a>
62       {* AINSI QUE LE COMMENTAIRE AFFÉRENT *}
63       <div class="highslide-caption">{attribute_view_gui attribute=$image1.data_map.commentaire_image}</div>
64      {/foreach}
65     </div>
66    {/if}
67   {/if}
68   {* ON ECRIT ICI LE TITRE DE LA GALERIE = LE NOM DU DOSSIER gallery_photos *}
69   <div class="titreGalerie">{$gallery.data_map.nom_dossier.content}</div>
70  </div>
71  {* ON INCRÉMENTE LA VARIABLE $i DE UNE UNITÉ *}
72     {set $i=inc( $i )}
73 {/foreach}
74 <div class="break"></div>

:
Il est très important de commenter la ligne 12.

Voilà donc la galerie de photos highSlide fonctionnelles et utilisant ses propres paramètres.

III - La page de contact

Considérations générales

La page de contact affiche, dans son fonctionnement par défaut, le contenu du template design/plain_site/override/templates/full/ pagecontact.tpl.
Par ailleurs, par défaut, un élément highSlide ne s'affiche qu'après avoir cliqué sur un lien.
On peut donc s'attendre à avoir, par défaut, le fonctionnement suivant de la page contact « highslidesisée»:

  • L'utilisateur clique sur le menu Contact,
  • Une page s'affiche avec un lien (le formulaire du template pagecontact.tpl est caché par highSlide),
  • L'utilisateur clique sur le lien,
  • Le formulaire s'affiche dans la popup.

Autant dire que ce fonctionnement n'est pas satisfaisant du tout. Le but à atteindre est en effet que le formulaire s'affiche dans la popup dès que l'utilisateur clique sur le menu Contact.

Autre difficulté: le système de validation du formulaire fait appel aux deux templates suivants:

  • design/standard/templates/content/ collectedinfo_validation.tpl : page de validation présentant une erreur de saisie,
  • design/standard/templates/content/collectedinfo/ form.tpl : page récapitulative des informations effectivement envoyées.

Le premier, inclus dans le code du template du formulaire de contact, s'affiche donc, lorsqu'il est utilisé, dans la page affichant le contenu du template pagecontact.tpl.
Le deuxième utilise quant à lui sa propre page d'affichage.
L'affichage de chacun de ces deux templates devra donc également se faire à l'intérieur d'une popup highSlide.

Enfin, selon la page affichée, le formulaire ou la page de validation ou encore la page récapitulative, que voit l'utilisateur s'il clique sur le bouton Close de la popup ? Une page blanche. Or ceci non plus n'est pas acceptable. Il faut donc que le bouton de fermeture de la popup soit, par exemple, un lien vers la page d'accueil du site.

Le code du template pagecontact.tpl

Voici le code commenté du template pagecontact.tpl:

1 {literal}
2 <script type="text/javascript">
3 hs.addEventListener(window, "load", function() {
4    // click the element virtually:
5    document.getElementById("autoload").onclick();
6 });
7     hs.showCredits = false;         // On supprime l'affichage de "Powered by ..."
8     hs.dimmingOpacity = 0.55;       // Opacité du fond général
9     hs.expandDuration = 750;        // Temps d'affichage de la popup
10     hs.numberPosition = null;       // Supprime l'affichage de "Image 1 of X"
11     hs.headingText = 'FEMOCA';      // Définit le titre de la popup
12     hs.align = 'center';            // Définit la position de la popup
13     hs.marginLeft = -140;           // Redéfinit la marge à gauche relativement à la position centrale définit ci-dessus (ATTENTION : PAS DE VALEURS NEGATIVES A CAUSE DE IE !!!!!!!!! )
14     hs.onDimmerClick = function() { // Supprime la fermeture de la popup si on clic à l'extérieur de la popup
15       return false;                 // si on clique sur le fond général opaque
16     };
17     hs.registerOverlay({            // Surcharge certaines règles CSS de certaines classes
18         html: '<div class="closebutton" title="Fermer"><a href="http://monsite.fr" style="display: block; width: 30px; height: 30px; outline: none; margin: -2px -12px 0 0;"></a></div>',
19         position: 'top right',      // Position du bouton de fermeture
20         fade: 2, // fading the semi-transparent overlay looks bad in IE
21         useOnHtml: true             // Active la surcharge: TRES IMPORTANT.
22     });
23 </script>
24 {/literal}
25 <a id="autoload" href="#" {literal}onclick="return hs.htmlExpand(this, { outlineType: 'glossy-dark', wrapperClassName: 'draggable-header'})"{/literal}  class="highslide"></a>
26 <div class="highslide-maincontent">
27 <div class="content-view-full">
28     <div class="class-feedback-form">
29         {include name=Validation uri='design:content/collectedinfo_validation.tpl'
30                  class='message-warning'
31                  validation=$validation collection_attributes=$collection_attributes}
32
33         <div class="attribute-short">
34                 {attribute_view_gui attribute=$node.data_map.descriptif_formulaire}
35         </div>
36         <form method="post" action={"content/action"|ezurl}>
37
38         <div class="titreChamp">{$node.data_map.nom_expediteur.contentclass_attribute.name}<span class="champObligatoire"> (*)</span></div>
39         <div class="attribute-email">
40                 {attribute_view_gui attribute=$node.data_map.nom_expediteur}
41         </div>
42         <div class="titreChamp">{$node.data_map.mail_expediteur.contentclass_attribute.name}<span class="champObligatoire"> (*)</span></div>
43         <div class="attribute-email">
44                 {attribute_view_gui attribute=$node.data_map.mail_expediteur}
45         </div>
46         <div class="titreChamp">{$node.data_map.coordonnees_expediteur.contentclass_attribute.name}</div>
47         <div class="attribute-email">
48                 {attribute_view_gui attribute=$node.data_map.coordonnees_expediteur}
49         </div>
50         <div class="titreChamp">{$node.data_map.objet.contentclass_attribute.name}<span class="champObligatoire"> (*)</span></div>
51         <div class="attribute-email">
52                 {attribute_view_gui attribute=$node.data_map.objet}
53         </div>
54         <div class="titreChamp">{$node.data_map.message_expediteur.contentclass_attribute.name}<span class="champObligatoire"> (*)</span></div>
55         <div class="attribute-email">
56                 {attribute_view_gui attribute=$node.data_map.message_expediteur}
57         </div>
58
59         <div class="content-action">
60             <input type="submit" class="defaultbutton" name="ActionCollectInformation" value="{"Send form"|i18n("design/base")}" />
61             <input type="hidden" name="ContentNodeID" value="{$node.node_id}" />
62             <input type="hidden" name="ContentObjectID" value="{$node.object.id}" />
63             <input type="hidden" name="ViewMode" value="full" />
64         </div>
65         </form>
66         <br />
67     </div>
68 </div>
69 </div>
  • Lignes 3 et 5 : indiquent que le formulaire doit être affiché lors du chargement de la page. Ceci permet de ne pas devoir cliquer sur un lien lorsque s'affiche la page qui affiche le contenu du template pagecontact.tpl.

Le bouton de fermeture de la popup

  • Lignes 17 à 22 : surchargent la classe CSS closebutton et font de celui-ci un lien vers la page d'accueil du site.
    En complément de ces 6 lignes, il sera nécessaire d'adapter les lignes suivantes de la feuille de styles highslide.css:
133 .closebutton {
134     position: relative;
135     top: -15px;
136     left: 15px;
137     width: 30px;
138     height: 30px;
139     cursor: pointer;
140     background: url(../images/graphics/close.png);
141     /* NOTE! For IE6, you also need to update the highslide-ie6.css file. */
142 }
...
...
341 .draggable-header .highslide-header .highslide-close {  /* POSITION DU BOUTON PAR DEFAUT DE FERMETURE DE LA POPUP */
342     display: none;   /* Cache le bouton Close utilisé par défaut */

Le template de validation/contrôle collectedinfo_validation.tpl

Par défaut, le template de validation des saisies de l'utilisateur est design/standard/templates/content/ collectedinfo_validation.tpl. Ce template est appelé par la ligne 29 du template pagecontact.tpl.

Pour ne pas faire de surcharge tout en n'utilisant pas le template par défaut, il suffit de copier collectedinfo_validation.tpl dans le design du siteaccess public.

Si le répertoire content n'existe pas dans design/plain_site/templates/ lancez les trois commandes suivantes:

cp -Rp design/standard/templates/content/ design/plain_site/templates/

rm -R design/plain_site/templates/content/*

cp -p design/standard/templates/content/collectedinfo_validation.tpl design/plain_site/templates/content/

Si le répertoire content existe déjà dans design/plain_site/templates/ lancez la commande suivante:

cp -p design/standard/templates/content/collectedinfo_validation.tpl design/plain_site/templates/content/

Il devient dès lors possible de modifier à notre guise le template design/plain_site/templates/content/ collectedinfo_validation.tpl sans toucher à celui par défaut.

L'utilisation de ce template ne pose aucun problème avec highSlide et sans modification particulière sera affiché dans la popup.

Le template récapitulatif form.tpl

Le template utilisé par défaut pour présenter un récapitulatif des informations saisies et envoyées est design/standard/templates/content/collectedinfo/ form.tpl. Comme pour le template collectedinfo_validation.tpl, nous allons en faire une copie dans design/plain_site/templates/content/collectedinfo/

Si le répertoire collectedinfo n'existe pas dans design/plain_site/templates/content/ lancez les trois commandes suivantes:

cp -Rp design/standard/templates/content/collectedinfo/ design/plain_site/templates/content/

rm -R design/plain_site/templates/content/collectedinfo/*

cp -p design/standard/templates/content/collectedinfo/form.tpl design/plain_site/templates/content/collectedinfo/

Si le répertoire collectedinfo existe déjà dans design/plain_site/templates/content/ lancez la commande suivante:

cp -p design/standard/templates/content/collectedinfo/form.tpl design/plain_site/templates/content/collectedinfo/

Le code commenté du template form.tpl est le suivant:

1 {literal}
2 <script type="text/javascript">
3 hs.addEventListener(window, "load", function() {
4    // click the element virtually:
5    document.getElementById("autoload").onclick();
6 });
7     hs.showCredits = false;         // On supprime l'affichage de "Powered by ..."
8     hs.dimmingOpacity = 0.55;       // Opacité du fond général
9     hs.expandDuration = 750;        // Temps d'affichage de la popup
10     hs.numberPosition = null;       // Supprime l'affichage de "Image 1 of X"
11     hs.headingText = 'FEMOCA';      // Définit le titre de la popup
12     hs.align = 'center';            // Définit la position de la popup
13     hs.marginLeft = -140;           // Redéfinit la marge à gauche relativement à la position centrale définit ci-dessus
14     hs.onDimmerClick = function() { // Supprime la fermeture de la popup si
15       return false;                 // on clique sur le fond général opaque
16     };
17     hs.registerOverlay({            // Surcharge certaines règles CSS de certaines classes
18         html: '<div class="closebutton" title="Fermer"><a href="http://linuxorable.fr/femoca" style="display: block; width: 30px; height: 30px; outline: none; margin: -2px -17px 0 5px;"></a></div>',
19         position: 'top right',      // Position du bouton de fermeture
20         fade: 2, // fading the semi-transparent overlay looks bad in IE
21         useOnHtml: true             // Active la surcharge: TRES IMPORTANT.
22     });
23 </script>
24 {/literal}
25 <a id="autoload" href="#" {literal}onclick="return hs.htmlExpand(this, { outlineType: 'glossy-dark', wrapperClassName: 'draggable-header'})"{/literal}  class="highslide"></a>
26 <div class="highslide-maincontent">
27 {default collection=cond( $collection_id, fetch( content, collected_info_collection, hash( collection_id, $collection_id ) ),
28                           fetch( content, collected_info_collection, hash( contentobject_id, $node.contentobject_id ) ) )}
29
30 {set-block scope=global variable=title}{'Form %formname'|i18n('design/standard/content/form',,hash('%formname',$node.name|wash))}{/set-block}
31
32 <h1>{'Collected information'|i18n('design/standard/content/form')}</h1>
33
34 <h2>{$object.name|wash}</h2>
35
36 {section show=$error}
37
38 {section show=$error_existing_data}
39 <p>{'You have already submitted this form. The previously submitted data was:'|i18n('design/standard/content/form')}</p>
40 {/section}
41
42 {/section}
43
44 {section loop=$collection.attributes}
45
46 <h3>{$:item.contentclass_attribute_name|wash}</h3>
47
48 {attribute_result_gui view=info attribute=$:item}
49
50 {/section}
51
52 <p/>
53 {/default}
54 </div>

Après avoir vidé les caches, tout devrait fonctionner parfaitement.

Commentaires