Troisième et dernier tutoriel de la série, visant à modifier l’affichage des images dans WordPress.
Après nous être occupé des images de taille « thumbnail » et « medium », ainsi que des galeries, nous allons ajouter un effet de découpage aux images « large » avec jQuery.
Aujourd’hui, nous allons seulement rajouter quelques lignes très simples dans le fichier functions.php de notre thème, et créer un petit plugin jQuery. Le CSS dont nous avons besoin est celui des deux précédents tutoriels.
Roadmap
Au programme dans ces 3 tutoriels :
- Partie 1 : customiser les images. -XHTML, CSS3, php-
- Partie 2 : customiser les galeries d’images. -XHTML, CSS3, php-
- Partie 3 : découpage d’images. -jQuery, XHTML, php-
Dans cette série de tutoriels, nous utilisons les dimensions d’images suivantes (je prend pour hypothèse que le contenu d’un article va faire 560px de large) :
- Miniature : 150 x 150px.
- Moyenne : 168 x 168px. Cette taille d’images sera uniquement utilisée dans la galerie (prochain tutoriel), d’où ces dimensions un peu bâtardes, liée à la largeur d’un article.
- Large : 560 x ???px. Ici, il s’agit d’une image qui prend toute la largeur d’un article, hauteur non fixée. Ce sera l’objet du 3ème tutoriel.
Il vous faudra modifier ces valeurs selon votre usage.
Checkpoint : créer notre plugin jQuery
Commençons par l’écriture générale d’un plugin jQuery. Nous appelons notre plugin WPpolaSlice. Lorsque l’on crée un plugin en jQuery, voici comment nous devons l’écrire :
0102030405060708091011
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
// Some code here
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Normalement nous avons également droit à une ligne supplémentaire pour la gestion des paramètres. Comme nous n’en auront pas besoin, nous nous passeront de cette ligne. A noter, la ligne return this;. Son rôle est de rendre « chaînable » l’utilisation ultérieure du plugin.
Pour terminer, avec notre plugin nous ciblons la caption d’origine contenant notre image « large », c’est à dire le span portant la classe CSS wp-caption560.
L’étape suivante consiste à rajouter la fonction jQuery each() afin que notre plugin fonctionne avec chaque image « large » qu’il trouvera dans la page.
01020304050607080910111213141516
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
// Some code here
this.each(function(i){
// Main code here
});
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Ainsi, le code à l’intérieur du each() s’exécutera à chaque fois qu’il va rencontrer une image « large » dans la page. Le code situé avant, s’exécutera une seule fois, et peut être utilisé pour déclarer des variables par exemple (et c’est précisément ce que nous feront).
Voyons maintenant ce dont notre code aura besoin pour fonctionner.
Mais au fait, que va faire notre plugin?
Supposons que vous ayez utilisé le shortcode caption dans un article pour afficher une image « large » (560px de large donc dans notre cas) avec un texte de légende. Dans les 2 tutoriels précédents, nous avons personnalisé ce shortcode en filtrant une fonction de WordPress, personnalisé les images de taille « thumbnail », et celles de taille « medium » avec du CSS, mais rien pour les images de taille « large ». Ici, nous allons faire du neuf avec du vieux, puisque nous n’allons pas ajouter du CSS pour personnaliser ces images, mais utiliser jQuery pour découper chaque image « large » en 6 images « medium ». Nous réutilisons donc le CSS des images « medium ». Tant que nous y sommes, nous feront en sorte d’afficher l’image complète grâce à une lightbox en cliquant sur l’une des 6 images.
Revenons donc à notre première interrogation : de quoi a besoin notre code pour construire ces 6 polaroids?
Il lui faudra l’url de l’image d’origine, l’attribut alt de cette image servira pour la lightbox, le texte de la légende.
Commençons donc à rentrer tout ceci dans des variables.
01020304050607080910111213141516171819
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
// Some code here
this.each(function(i){
caption = new Array; // An array with all we need for the image, the link and the caption
caption['img'] = $(this).find('img');
caption['src'] = caption['img'].attr('src');
caption['alt'] = caption['img'].attr('alt');
caption['txt'] = $(this).find('.wp-caption-text').html();
var output = '';
});
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Nous déclarons la variable caption de type Array et nous y stockons dedans caption[‘img’] qui est l’image d’origine sous forme d’objet jQuery, caption[‘src’] qui est l’url de l’image, caption[‘alt’] qui est son attribut alt et caption[‘txt’] qui est sa légende. Nous déclarons également la variable output en tant que chaine vide, elle contiendra le résultat final.
Maintenant que nous avons les informations nécessaires, nous devons créer nos 6 polaroids. Nous utiliserons une boucle « for » dans ce but.
01020304050607080910111213141516171819202122232425
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
// Some code here
this.each(function(i){
caption = new Array; // An array with all we need for the image, the link and the caption
caption['img'] = $(this).find('img');
caption['src'] = caption['img'].attr('src');
caption['alt'] = caption['img'].attr('alt');
caption['txt'] = $(this).find('.wp-caption-text').html();
var output = '';
for(j=0; j<6; j++) {
// Code for the loop here
}
});
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Comment va-t-on faire maintenant?
Comme nous le disions, nous allons créer 6 petites images. Chacune affichera une portion de l’image d’origine. L’astuce consistera à afficher 6 images png transparentes, auxquelles nous allons attribuer l’image d’origine en image de fond, avec un décalage en x et y différent à chaque fois.
Avec 6 images, donc 3 images par ligne, cela nous donnerait en CSS :
- Image 1 : background: transparent url(‘….jpg’) 5% 5% no-repeat;
- Image 2 : background: transparent url(‘….jpg’) 5% 50% no-repeat;
- Image 3 : background: transparent url(‘….jpg’) 5% 95% no-repeat;
- Image 4 : background: transparent url(‘….jpg’) 95% 5% no-repeat;
- Image 5 : background: transparent url(‘….jpg’) 95% 50% no-repeat;
- Image 6 : background: transparent url(‘….jpg’) 95% 95% no-repeat;
Pour cela, nous allons créer 2 nouvelles variables de type Array avant la boucle for (car ces valeurs seront communes à toutes les images « large »), et y rentrer ces valeurs pour x et y.
0102030405060708091011121314151617181920212223242526
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
var bgxpos = new Array(5,50,95,5,50,95); // Arrays for the background positions and fill it whith the values in "%" for all images
var bgypos = new Array(5,5,5,95,95,95);
this.each(function(i){
caption = new Array; // An array with all we need for the image, the link and the caption
caption['img'] = $(this).find('img');
caption['src'] = caption['img'].attr('src');
caption['alt'] = caption['img'].attr('alt');
caption['txt'] = $(this).find('.wp-caption-text').html();
var output = '';
for(j=0; j<6; j++) {
// Code for the loop here
}
});
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Ce n’est pas la manière la plus propre de faire, mais avec seulement 6 images, pourquoi s’embêter à créer une fonction supplémentaire qui va calculer ces valeurs, et finalement, prendre un peu de ressource pour rien lors de l’exécution?
Voyons maintenant le contenu de notre boucle for. Il nous faut créer un span englobant un lien vers l’image complète (pour la lightbox), notre image transparente et la légende.
1516171819202122
for(j=0; j<6; j++) {
output += '<span class="wp-caption wp-caption168 alignleft" style="width: 168px"><a href="'+caption['src']+'">'
+'<img src="'+templdir+'/js/WPpolaSlice/blank.png" '
+'style="display: block; width: 168px; height: 168px; background:transparent url(''+caption['src']+'') '+bgxpos[j]+'% '+bgypos[j]+'% no-repeat;" '
+'alt="'+caption['alt']+'" />'
+'</a><span class="wp-caption-text">'+caption[txt]+'</span></span>';
}
Quelques explications :
Vous avez peut-être remarqué la variable templdir dans l’url de l’image transparente. Nous verrons comment définir sa valeur un peu plus loin.
Nous nous servons de j pour trouver les bonnes valeurs dans bgxpos et bgypos en %.
L’attribut alt est utilisé par la lightbox que j’utilise dans cette série de tutoriels (prettyPhoto), il sert à afficher un titre au-dessus de l’image. Selon votre lightbox, vous aurez peut-être besoin de créer un attribut title sur l’image ou sur le lien lui-même.
Amélioration :
Montrer la légende sous chaque polaroid n’est peut-être pas du meilleur effet. A la place nous allons l’afficher une seule fois, sous le 1er polaroid de la seconde ligne, c’est à dire la 4ème image, donc lorsque j est égal à 3 (puisque nous commençons à zéro).
1516171819202122232425
for(j=0; j<6; j++) {
if (j == 3) captiontxt = caption['txt']; // If we want the caption text (under the 4th image)
else captiontxt = ' ';
output += '<span class="wp-caption wp-caption168 alignleft" style="width: 168px"><a href="'+caption['src']+'">'
+'<img src="'+templdir+'/js/WPpolaSlice/blank.png" '
+'style="display: block; width: 168px; height: 168px; background:transparent url(''+caption['src']+'') '+bgxpos[j]+'% '+bgypos[j]+'% no-repeat;" '
+'alt="'+caption['alt']+'" />'
+'</a><span class="wp-caption-text">'+captiontxt+'</span></span>';
}
Nous ne sommes pas loin de la fin et le plus dur est passé. Notre variable output contient nos 6 images, il ne nous reste plus qu’à les afficher et supprimer l’image d’origine avec ceci :
262728
$(this).wrap('<div class="gallery" id="gallery-0'+i+'" />') // We wrap the initial in a div
.parent('.gallery')
.html(output+'<span style="clear: both; display: block; margin-bottom: 20px;"> </span>'); // We delete the initial and put our images
Ce que nous avons fait :
Nous créons une div qui va englober notre caption d’origine, nous déplaçons le sélecteur vers cette div, puis nous écrasons son contenu (la caption d’origine avec l’image et la légende donc) et le remplaçons par nos 6 polaroids et un span pour annuler les floats.
Le plugin est terminé! Ce qui donne :
0102030405060708091011121314151617181920212223242526272829303132333435
//------------------------------------------------------------------------------ Caption large : slice "large" images in 6 polaroids
(function($){$.fn.WPpolaSlice=function(){
var bgxpos = new Array(5,50,95,5,50,95); // Arrays for the background positions and fill it whith the values in "%" for all images
var bgypos = new Array(5,5,5,95,95,95);
this.each(function(i){
caption = new Array; // An array with all we need for the image, the link and the caption
caption['img'] = $(this).find('img');
caption['src'] = caption['img'].attr('src');
caption['alt'] = caption['img'].attr('alt');
caption['txt'] = $(this).find('.wp-caption-text').html();
var output = '';
for(j=0; j<6; j++) {
if (j == 3) captiontxt = caption['txt']; // If we want the caption text (under the 4th image)
else captiontxt = ' ';
output += '<span class="wp-caption wp-caption168 alignleft" style="width: 168px"><a href="'+caption['src']+'">'
+'<img src="'+templdir+'/js/WPpolaSlice/blank.png" '
+'style="display: block; width: 168px; height: 168px; background:transparent url(''+caption['src']+'') '+bgxpos[j]+'% '+bgypos[j]+'% no-repeat;" '
+'alt="'+caption['alt']+'" />'
+'</a><span class="wp-caption-text">'+captiontxt+'</span></span>';
}
$(this).wrap('<div class="gallery" id="gallery-0'+i+'" />') // We wrap the initial in a div
.parent('.gallery')
.html(output+'<span style="clear: both; display: block; margin-bottom: 20px;"> </span>'); // We delete the initial and put our images
});
return this;
}})(jQuery);
jQuery(document).ready(function($){
$('.wp-caption560').WPpolaSlice();
});
Maintenant allez dans le dossier de votre thème, créez un dossier appelé « js », puis enregistrez le script dans un fichier WPpolaSlice.js à l’intérieur de ce dossier. Dans ce dossier « js » créez un autre dossier, appelé « WPpolaSlice » et mettez y une image .png de 1px de côté transparente appelée blank.png.
Arrival : launching the script
Dernière étape, lancer le script. Ouvrez le fichier functions.php de votre thème, nous avons quelques lignes à y ajouter.
Première chose, enregistrer en mettre « en file d’attente » le script :
123456
// ----------------------------------------------------------------------------- WPpolaSlice scripts
function sf_scripts_in_footer() { // Scripts in footer
wp_register_script('WPpolaSlice', get_bloginfo('template_directory').'/js/WPpolaSlice.js', array('jquery'), '1.0', true);
wp_enqueue_script('WPpolaSlice');
}
add_action('wp_print_scripts', 'sf_scripts_in_footer');
Pour ceux qui connaissent déjà la fonction wp_register_script(), vous remarquerez que jQuery est mentionné comme dépendance du script, et que le script est chargé dans le footer.
Deuxième chose, indiquer le chemin vers blank.png en déclarant la variable javascript templdir entre des balises script :
08091011
function WPpolaSliceInit() { // Define your template directory. Needed for blank.png
echo '<script type="text/javascript">var templdir="'.get_bloginfo('template_directory').'";</script>';
}
add_action('wp_footer', 'WPpolaSliceInit');
Assurez-vous que la fonction wp_footer() est bien présente dans le footer de votre thème (à posteriori, il y a de grandes chances que ce soit dans le fichier footer.php.
Le code complet pour functions.php :
0102030405060708091011
// ----------------------------------------------------------------------------- WPpolaSlice scripts
function sf_scripts_in_footer() { // Scripts in footer
wp_register_script('WPpolaSlice', get_bloginfo('template_directory').'/js/WPpolaSlice.js', array('jquery'), '1.0', true);
wp_enqueue_script('WPpolaSlice');
}
add_action('wp_print_scripts', 'sf_scripts_in_footer');
function WPpolaSliceInit() { // Define your stylesheet directory. Needed for blank.png
echo '<script type="text/javascript">var templdir="'.get_bloginfo('template_directory').'";</script>';
}
add_action('wp_footer', 'WPpolaSliceInit');
Conclusion
D’une grande image munie de sa légende, nous obtenons 6 petits polaroids grâce à jQuery et à du CSS3. L’utilisation simultanée d’une lightbox agrémentera le tout afin de visualiser l’image au complet.
Ainsi s’achève cette série de tutoriels sur la personnalisation de vos images dans WordPress et j’espère ceux-ci vous ont plu. Quelques modifications dans les déclarations CSS et le script, et tout ceci devrait s’adapter à votre thème sans trop de peine.
Nota
Pour les plus exigeants, je devrais sortir ce script sous forme de plugin jQuery plus complet d’ici quelques jours ici même, le temps de revoir quelques derniers détails et de faire l’article avec les démos. Il disposera de beaucoup de paramètres comme la largeur/hauteur des images, position de la légende, gestion des attributs alt et title, avec ou sans lien, plage de valeurs pour le background-position, et même un mode shuffle pour mélanger les images.
Commentaires
Commentaire de dway.
Petite précision pour le chargement des scripts (register et enqueue). D’après la doc, il ne faut pas utiliser l’action wp_print_scripts mais plutôt une fonction d’init comme…. ‘init’ :) Voir le texte sous « Example » là : http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Example
Et puis pour eviter de charger les scripts du côté admin, un petit if (!is_admin()) { avant le register/enqueue :)
Merci pour ce tuto en tout cas :)
Commentaire de Greg.
En effet, j’avais vu la page mais pas la toute petite phrase avec le lien renvoyant vers la discussion en question (allez avoue, elle est bien cachée ;) ).
Je sais qu’à un moment j’utilisais l’un ou l’autre (init ou wp_print_scripts) et j’avais eu des soucis avec l’un, mais je ne sais plus lequel. Du coup, j’ai sûrement inversé.
D’après ce que j’ai compris, c’est juste une histoire de timing, d’ordre dans lequel sont effectuées ces actions. Et pour appuyer cette hypothèse, je viens de trouver une page que je cherchais depuis très longtemps sans savoir si elle existait : http://codex.wordpress.org/Plugin_API/Action_Reference
Sur cette page, sont listées les actions lors du chargement d’une page (front-end ou admin).
Du coup, je ne mettais pas le test if (!is_admin()) {, pensant que l’action wp_print_scripts s’effectuait seulement en front-end et pas dans l’admin. Cette page me prouve donc le contraire puisqu’on retrouve cette action dans les 2 listes.
Bref, je vais avoir des corrections à faire demain :-S (d’oh!)
Merci beaucoup pour ces précisions o/
EDIT : je me souviens du problème que j’avais eu à l’époque. En fait, lors de l’init, « is_single() » et autre « is_page() » ne peuvent pas encore être testés. Donc je vais continuer à utiliser wp_print_scripts dans la plupart des cas ;)