Améliorer le module éditorial par un slideshow (glissement d'images)

retour à la caverne

Avant même de commencer ce tutoriel, gardez une copie des fichiers que vous modifierez au cas où vous rencontriez des problèmes. Dans ce tutoriel, nous utiliserons PHP (orienté Objet) - Javascript(JQuery) - XHtml/CSS - Smarty.

Préambule

Alors nous allons voir avec ce tutoriel comment améliorer le module éditorial de PrestaShop qui nous sert habituellement à insérer quelques infos sur la page d'accueil de notre beau site e-commerce. Mais... le trouvant un peu "platonique" (plutôt plat que tonique d'ailleurs), on va lui permettre d'accepter plusieurs images qu'il devra nous afficher avec un petit effet de slide (slideshow) que vous pourrez d'ailleurs paramétrer par la suite selon votre goût, plusieurs effets de slide assez sympa.

Le slide show (ou ch'truc qui gliche là comme on dirote din ch'nord) sera réalisé grâce au plugin jquery.cycle que vous pourrez télécharger ici si vous ne l'avez pas déjà.

Je n'ai pas d'exemple sous la main pour vous donner un aperçu de ce que nous allons faire mais sur le site cité ci-dessus, vous pourrez voir un peu de quoi il s'agit. Si le tutoriel vous sert et que vous mettez en pratique celui-ci, vous pouvez m'indiquer votre adresse de site afin de l'ajouter ici même pour avoir un aperçu du rendu final.

Prêt !? Alors on module.

Tout d'abord, on va s'occuper de placer correctement le plugin (fichier) jquery.cycle.js et afin d'essayer de respecter l'arborescence, on va le placer avec les scripts javascript qui régissent un peu tout le CMS. C'est à dire depuis la racine du site : /js/jquery/ (donc à placer dans le dossier "jquery")

Parce qu'un aperçu parle toujours plus :


Cliquez pour agrandir :


Au coeur de l'éditorial

Voilà ça y est ! On arrive déjà au moment où on va devoir mettre les mains dans le cambouis. Bon, on a pas à se plaindre, c'est du cambouis propre et en plus orienté objet, que demande le peuple (mise à part baisser les taxes qu'on nous... !! Enfin, c'est une autre histoire...)

On va aller chercher le fichier "editorial.php" qui se situe par ici : /module/editorial/ . Je vous mets pas d'aperçu pour celui-ci, il n'est pas difficile à trouver.

On ouvre donc ce fichier editorial.php (je vous laisse le survoler un peu...) et pour commencer, on va se créer un array (associé à la classe bien sûr - attribut) qui va nous simplifier un peu la tâche, celui-ci contiendra les noms des images pour le slide et donc déterminera également le nombre d'images qu'il y aura pour le slide.

J'ai choisis d'inclure 4 images et pour faire dans le basique, je les nomme "image", le plus important étant de leur donner le même nom et ajouter un chiffre (en bout de nom) différent, voici ce que ça donne : (Cette ligne est à inclure à la ligne 7 du fichier editorial.php)

        	private $listeImg = array('image1', 'image2', 'image3', 'image4');
        

Gardez bien ce "style", un seul nom pour toutes les images + un chiffre différent pour chaque nom.

Allez, maintenant on va créer les input qui vont nous permettre d'envoyer nos images depuis notre back office prestashop. Cherchez donc parmis toutes les méthodes de la classe, la fonction _displayForm() et vous cherchez la div qui contient l'input de type file De quoi !? Mais non, allez... rendez-vous à la ligne 212 (ou 211 selon la façon dont vous avez inclus la première ligne de code).

Et là on peut voir jusqu'à la ligne 216/217 ce morceau de code :

<?php
        
<label>'.$this->l('Homepage\'s logo').' </label>
<div class="margin-form">
	<img src="'.$this->_path.'homepage_logo.jpg" alt="" title="" style="" /><br />
	<input type="file" name="body_homepage_logo" />
	<p style="clear: both">'.$this->l('Will appear next to the Introductory Text above').'</p>
</div>
        
?>


Vous l'avez ? Bien. Donc on aura bien compris que ce code affiche l'image (logo) de la page d'accueil et nous propose d'en choisir une autre.

Et bien nous, on va faire mieux, on va lui faire nous proposer l'insertion de 4 images mais aussi leur suppression.

Voici le bout de code de remplacement qu'il nous faudra lui inclure, ne foncez pas tête baissée, faite attention de bien tout remplacer le code ci-dessus par celui ci-dessous (pas plus, pas moins et sans les <php ?> évidemment) :

<?php

<label>'.$this->l('Homepage\'s logo').' </label>';
    
$e=1; // Servira pour identifier le chiffre des noms des images

// On lance une boucle qui parcourt notre tableau d'images
for($i=0; $i<count($this->listeImg); $i++) {
	// Le nom de l'image
    $nameImg = $this->listeImg[$i];
    // Son chemin complet
	$cheminImg = $this->_path.$nameImg.'.jpg';
	
    // Et enfin notre div contenant 2 input
    // 1 pour envoyer une image
    // 1 autre de type checkbox qui nous permettra de pouvoir supprimer l'image
	$this->_html .= '
		<div class="margin-form"><hr /><br />
		Image '.$e.' : <input type="file" name="'.$nameImg.'" /><br /><br />
		<input type="checkbox" name="sup_'.$nameImg.'" /> Cochez la case pour supprimer l\'image ci-dessous après validation<br /><br />';
	
    // Bien sûr quand on aura envoyé une image, on l'affichera ici
    if(file_exists(dirname(__FILE__).'/'.$nameImg.'.jpg'))
		$this->_html .= '<img src="'.$cheminImg.'" alt="" title="" style="" />	';
	
    $this->_html .= '</div>';
	$e++; // On incrémente le numéro de l'image
}

// On oublie pas de réouvrir _html
$this->_html .='

?>


À ce stade, si vous vous rendez dans votre module "Editeur de page d'accueil" de votre arrière-boutique, vous devriez y voir du changement. Si non, alors c'est que vous avez un problème quelque part. Vous n'avez plus qu'à recommencer la manoeuvre.


Enregistrement et suppression des images

On pense souvent que c'est la partie la plus longue et la plus compliquée... J'ai une bonne nouvelle : Pas aujourd'hui ! Effectivement, les créateurs de PrestaShop nous ont considérablement mâcher le boulot.
Donc pour le coup, on va pratiquement conserver le même le code que l'on va "entourer" par une boucle for... allons voir ça.

On remonte un peu le curseur pour aller voir la fonction getContent() toujours dans ce même fichier editorial. La partie qui nous intéresse commence par un commentaire (qui parle) : /* upload the image */
Allez je vous aide, c'est à la ligne 89/90.

On peut alors voir cette condition :

<?php

if (isset($_FILES['body_homepage_logo']) 
	AND isset($_FILES['body_homepage_logo']['tmp_name']) 
	AND !empty($_FILES['body_homepage_logo']['tmp_name']))
{
	Configuration::set('PS_IMAGE_GENERATION_METHOD', 1);
	if ($error = checkImage($_FILES['body_homepage_logo'], $this->maxImageSize))
		$errors .= $error;
	elseif (!$tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS') 
    		OR !move_uploaded_file($_FILES['body_homepage_logo']['tmp_name'], $tmpName))
		return false;
	elseif (!imageResize($tmpName, dirname(__FILE__).'/homepage_logo.jpg'))
		$errors .= $this->displayError($this->l('An error occurred during the image upload.'));
	unlink($tmpName);
}

?>
    

Comme indiqué plus haut, on va l'entourer par une boucle for (qui va parcourir notre fameux tableau (de noms) d'images), récupérer chaque nom du tableau, et voir si une nouvelle image a été envoyé à ce nom ou si on a demandé sa suppression.

Notre boucle (qui remplacera donc tout le code ci-dessus) :

<?php

for($i=0; $i< count($this->listeImg); $i++) {
	$traiteImg = $this->listeImg[$i];
				
	if (isset($_FILES[$traiteImg]) AND isset($_FILES[$traiteImg]['tmp_name']) AND !empty($_FILES[$traiteImg]['tmp_name'])) {
		Configuration::set('PS_IMAGE_GENERATION_METHOD', 1);
		if ($error = checkImage($_FILES[$traiteImg], $this->maxImageSize))
			$errors .= $error;
		elseif (!$tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES[$traiteImg]['tmp_name'], $tmpName))
			return false;
		elseif (!imageResize($tmpName, dirname(__FILE__).'/'.$traiteImg.'.jpg'))
			$errors .= $this->displayError($this->l('An error occurred during the image upload.'));
		unlink($tmpName);
	}
		
	if(isset($_POST['sup_'.$traiteImg]))
    	unlink(dirname(__FILE__).'/'.$traiteImg.'.jpg');
}

?>

On a pas beaucoup de changement, j'ai pas jugé utile de commenter.

On y est presque... courage. Encore une petite modification sur ce fichier et on aura finit... pour celui-ci.
Direction la fin du fichier editorial.php où nous trouverons ceci :

$smarty->assign(array(
	'xml' => $xml,
	'homepage_logo' => file_exists('modules/editorial/homepage_logo.jpg'),
	'logo_subheading' => 'logo_subheading_'.$cookie->id_lang,
	'title' => 'title_'.$cookie->id_lang,
	'subheading' => 'subheading_'.$cookie->id_lang,
	'paragraph' => 'paragraph_'.$cookie->id_lang,
	'this_path' => $this->_path
));
Alors ce morceau de code sert à passer au générateur de template smarty, les différentes valeurs dont il aura besoin pour compléter sa mise en page.

Et là on s'aperçoit que... ben on ne retrouve pas nos fameuses images pour le slideshow, donc notre "template" ne pourra pas les afficher, on corrige cela avec ce bout de code (sans les <php ?> toujours):
<php

$smarty->assign(array(
	'xml' => $xml,
	'image1' => file_exists('modules/editorial/image1.jpg'),
	'image2' => file_exists('modules/editorial/image2.jpg'),
	'image3' => file_exists('modules/editorial/image3.jpg'),
	'image4' => file_exists('modules/editorial/image4.jpg'),
	'logo_subheading' => 'logo_subheading_'.$cookie->id_lang,
	'title' => 'title_'.$cookie->id_lang,
	'subheading' => 'subheading_'.$cookie->id_lang,
	'paragraph' => 'paragraph_'.$cookie->id_lang,
	'this_path' => $this->_path
));

?>

Vous remarquerez que "homepage_logo" n'est plus dans la liste, on en a plus besoin de celui-ci.

Voilà pour le fichier editorial.php. Pour le moment, le script tourne correctement depuis notre back-office mais malheureusement, rien ne s'affiche sur notre boutique... Effectivement, nous n'avons pas encore modifié le fichier qui traite cette aspect, alors en route...


Le slideshow... pas si chaud

Eh non, pas si chaud de faire un slideshow (qu'est ce que j'aime pas ce nom... ben oui mais c'est la mode ma pauvre Lucette)

Alors pour mettre en place le défilement des images, on va prendre cette fois le fichier editorial.tpl qui se trouve dans le même dossier que le .php

Je mets quand même le code qu'il contient (bah, quelqu'un n'est peut être pas sûr que ce soit le bon fichier) :


<div id="editorial_block_center" class="editorial_block">
	{if $xml->body->home_logo_link}
    	<a href="{$xml->body->home_logo_link|escape:'htmlall':'UTF-8'}" title="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}">{/if}
		
        {if $homepage_logo}
    	<img src="{$this_path}homepage_logo.jpg" 
        	alt="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}" />{/if}
    
    {if $xml->body->home_logo_link}</a>{/if}
	
    {if $xml->body->$logo_subheading}{$xml->body->$logo_subheading|stripslashes}{/if} 
    
	{if $xml->body->$title}<h2>{$xml->body->$title|stripslashes}</h2>{/if}
    
	{if $xml->body->$subheading}
    	<h3>{$xml->body->$subheading|stripslashes}</h3>{/if}
        
	{if $xml->body->$paragraph}
    	<div class="rte">{$xml->body->$paragraph|stripslashes}</div>{/if}
</div>

Je ne vais pas m'attarder sur le fonctionnement du code (les {if}...) je vais juste indiqué l'utilité de {literal}{/literal} que nous allons utiliser par la suite. C'est 2 "balises" permettent principalement d'indiquer au moteur de template de ne pas tenir compte de ce que contient ces balises, on lui demande de l'écrire point. Elles sont forts utiles pour écrire du javascript surtout. Voilà, je ne m'attarde pas là dessus, si vous souhaitez plus de renseignement c'est par ici

Ce qui nous intéresse dans le fichier .tpl, ceux sont les lignes 3 à 10 (dans le fichier original les lignes 3 à 5)
Nous allons remplacer ces lignes par notre slideshow. C'est à dire, inclure notre fichier jquery.cycle.js, préparer le défilement et afficher nos images si elles existent.

Ce qui nous donne :


<div id="editorial_block_center" class="editorial_block">


    <script type="text/javascript" src="{$base_dir}modules/editorial/jquery.cycle.js"></script>
	{literal}
        <script type="text/javascript">
        $(document).ready(function(){
            $("#img_slideShow").cycle({ fx: 'scrollHorz', 
                                        speed: '600', 
                                        prev: '#turn_left', 
                                        next: '#turn_right', 
                                        timeout: 7000 });
            $('#subscribe_btn').click(function () { 
                $('#subscribe_box').slideToggle('fast'); 
            });
        });
        </script>
    {/literal}
    
	<div id="slideShow">
		<div id="img_slideShow">
		{if $image1}
            <p><a href="#" title=""><img src="{$this_path}image1.jpg" alt="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}" /></a></p>
        {/if}
			
        {if $image2}
            <p><a href="#" title=""><img src="{$this_path}image2.jpg" alt="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}" /></a></p>
        {/if}
			
        {if $image3}
            <p><a href="#" title=""><img src="{$this_path}image3.jpg" alt="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}" /></a></p>
        {/if}
			
        {if $image4}
            <p><a href="#" title=""><img src="{$this_path}image4.jpg" alt="{$xml->body->$title|escape:'htmlall':'UTF-8'|stripslashes}" /></a></p>
        {/if}
		</div>
		
        <p id="turn_right" class="bt_turn">></p>
		<p id="turn_left" class="bt_turn"><</p>
	</div>             

    
	{if $xml->body->$logo_subheading}{$xml->body->$logo_subheading|stripslashes}{/if} 
	{if $xml->body->$title}<h2>{$xml->body->$title|stripslashes}</h2>{/if}
	{if $xml->body->$subheading}<h3>{$xml->body->$subheading|stripslashes}</h3>{/if}
	{if $xml->body->$paragraph}
    	<div class="rte">{$xml->body->$paragraph|stripslashes}</div>{/if}
</div>


Tout le nouveau contenu du fichier editorial.tpl est là, le code paraît assez long mais la colonne de ma page est assez petite aussi... Je vous laisse découvrir le code, il parle de lui même et est assez simple à comprendre.

Il ne vous reste plus désormais qu'à mettre un peu de CSS à tout ça dans le fichier css de votre theme
( /themes/nom_de_votre_theme/css/global.css )

Voici ce qu'on peut mettre par exemple :

/* block slideShox in the center column */
#slideShow {
	position: relative;
	width:555px; 
	height:250px; 
	overflow:hidden;
	text-align: center;
}
#slideShow #img_slideShow {
	z-index: 10;
	width:555px;
	position: absolute;
}
#slideShow #img_slideShow p { 
	width: 555px; 
    text-align: center; 
}
#slideShow p.bt_turn {
	z-index: 5000;
	width:23px;
	height:53px;
	position: absolute;
	margin-top: 80px;
	
	font-size:28px;
	color:#000;
	background:#ebebeb;
	opacity: 0.5;
	cursor: pointer;
}
#slideShow p#turn_right {
	margin-left: 530px;
}
#slideShow p.bt_turn:hover { 
	background:#000; 
    color:#fff; 
}

Et voilà, le tutoriel touche à sa fin. "Bah... tu nous as dit qu'on pourrait paramétrer le style de slide... ?"
Mais vous lâchez rien dit donc !

En effet rien de plus simple, pour changer la vitesse des effets ou le type de glissement, il vous suffit de vous rendre dan le fichier editorial.tpl et de changer les paramétres "fx" - "speed" - "timeout" de ces deux lignes

$("#img_slideShow").cycle({ fx: 'scrollHorz', 
                            speed: '600', 
                            prev: '#turn_left', 
                            next: '#turn_right', 
                            timeout: 7000 });
 	

Pour connaître les différents effets possibles, voici une démo des différents effets avec leur attribut pour "fx"
Sur ce...

A bientôt!

retour à la caverne