Contenu principal
Du pola dans wordpress - partie 2

Du pola dans WordPress (2/3) : customiser les galeries

Le deuxième tutoriel de cette série de trois, visant à modifier l’affichage des images dans WordPress.
Nous allons modifier la galerie d’images de WordPress et ajouter une nouvelle transition à nos polaroids.

Aujourd’hui nous allons filtrer une autre fonction de WordPress afin de modifier la galerie par défaut de WordPress et utiliser du CSS3, avec notamment transform et transition.

Roadmap

Au programme dans ces 3 tutoriels :

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 : filtrer les galeries

Commençons par voir ce donne le shortcode gallery comme balisage html dans nos articles :

01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
<style type='text/css'>
	#gallery-1 {
		margin: auto;
	}
	#gallery-1 .gallery-item {
		float: left;
		margin-top: 10px;
		text-align: center;
		width: 33%;
	}
	#gallery-1 img {
		border: 2px solid #cfcfcf;
	}
	#gallery-1 .gallery-caption {
		margin-left: 0;
	}
</style>

<!-- see gallery_shortcode() in wp-includes/media.php -->
<div id='gallery-1' class='gallery galleryid-73'>
	<dl class='gallery-item'>
		<dt class='gallery-icon'>
			<a href='http://....jpg' title='...'><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		</dt>
		<dd class='gallery-caption'>
			Légende
		</dd>
	</dl>
	<dl class='gallery-item'>
		<dt class='gallery-icon'>
			<a href='http://....jpg' title='...'><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		</dt>
		<dd class='gallery-caption'>
			Légende
		</dd>
	</dl>
	<dl class='gallery-item'>
		<dt class='gallery-icon'>
			<a href='http://....jpg' title='...'><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		</dt>
		<dd class='gallery-caption'>
			Légende
		</dd>
	</dl>
	<br style="clear: both" />
	<dl class='gallery-item'>
		<dt class='gallery-icon'>
			<a href='http://....jpg' title='...'><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		</dt>
		<dd class='gallery-caption'>
			Légende
		</dd>
	</dl>
	<br style="clear: both" />
</div>

Le marquage est propre et cohérent, avec utilisation des balises dl, dt et dd qui semblent appropriées à ce type de contenu. Nous pouvons noter qu’un br apparait à la suite de chaque « rangée horizontale » de miniatures (dans ce cas, 3 miniatures par rangée) et un autre à la fin de la galerie. Comme je souhaite que ma galerie prenne toute la largeur de l’article (la taille de mes miniatures et le CSS employé est prévu pour ça), je vais m’en passer et ne garder que le tout dernier de la galerie.
Par contre, une chose qui ne me plait guerre, c’est la balise style au début, qui surgit, là, on ne sait pas bien pourquoi. En plus, non valide xhtml, et elle nous sera complètement inutile. Nous allons donc la supprimer.

Au final, je voudrais avoir ce marquage :

01020304050607080910111213141516171819
<div id='gallery-1' class='gallery galleryid-73'>
	<span id="attachment_218" class="wp-caption wp-caption168 alignleft" style="width: 168px">
		<a href="http:....jpg" rel="..."><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		<span class="wp-caption-text">Légende</span>
	</span>
	<span id="attachment_219" class="wp-caption wp-caption168 alignleft" style="width: 168px">
		<a href="http:....jpg" rel="..."><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		<span class="wp-caption-text">Légende</span>
	</span>
	<span id="attachment_220" class="wp-caption wp-caption168 alignleft" style="width: 168px">
		<a href="http:....jpg" rel="..."><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		<span class="wp-caption-text">Légende</span>
	</span>
	<span id="attachment_221" class="wp-caption wp-caption168 alignleft" style="width: 168px">
		<a href="http:....jpg" rel="..."><img width="168" height="168" src="http:....jpg" class="attachment-medium" alt="..." title="..." /></a>
		<span class="wp-caption-text">Légende</span>
	</span>
	<br style='clear: both;' />
</div>

Attendez, ça ne vous rappelle rien ce balisage de miniature ? Ha mais si, ça ressemble fortement au tutoriel précédent!
Et comment va-t-on faire ça? Il va falloir filtrer une fonction de WordPress, mais laquelle?
La réponse est dans le balisage d’origine de la galerie :

19
<!-- see gallery_shortcode() in wp-includes/media.php -->

Bien, nous avons notre point de départ, nous allons copier cette fonction dans wp-includes/media.php et la modifier afin d’appliquer un filtre.
Je vous donne d’abord le pavé de code en entier, commenté où il y a eu des modifications, et les explications ensuite. Ceci sera à mettre dans le fichier functions.php de votre thème.

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102103104105106107108
// ----------------------------------------------------------------------------- gallery -----------------
add_filter('post_gallery', 'sf_post_gallery', 10, 2);

function sf_post_gallery($null, $attr = array()) {
	global $post, $wp_locale;
	static $instance = 0;
	$instance++;
						// We don't need the "apply_filters" function here, unless you want to mess up all. So we delete it
	// We're trusting author input, so let's at least make sure it looks like a valid orderby statement
	if ( isset( $attr['orderby'] ) ) {
		$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
		if ( !$attr['orderby'] )
			unset( $attr['orderby'] );
	}
	extract(shortcode_atts(array(
		'order'      => 'ASC',
		'orderby'    => 'menu_order ID',
		'id'         => $post->ID,
		'itemtag'    => '',		// We don't need 'dl'
		'icontag'    => '',		// We don't need 'dt'
		'captiontag' => '',		// We don't need 'dd'
		'columns'    => 3,
		'size'       => 'medium',	// We'll use medium instead of thumbnail
		'include'    => '',
		'exclude'    => ''
	), $attr));

	$id = intval($id);
	if ( 'RAND' == $order )
		$orderby = 'none';

	if ( !empty($include) ) {
		$include = preg_replace( '/[^0-9,]+/', '', $include );
		$_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

		$attachments = array();
		foreach ( $_attachments as $key => $val ) {
			$attachments[$val->ID] = $_attachments[$key];
		}
	} elseif ( !empty($exclude) ) {
		$exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
		$attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
	} else {
		$attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
	}

	if ( empty($attachments) )
		return '';

	if ( is_feed() ) {
		$output = "n";
		foreach ( $attachments as $att_id => $attachment )
			$output .= wp_get_attachment_link($att_id, $size, true) . "n";
		return $output;
	}

	$itemtag = tag_escape($itemtag);
	$captiontag = tag_escape($captiontag);
	$columns = intval($columns);
	$itemwidth = $columns > 0 ? floor(100/$columns) : 100;
	$float = is_rtl() ? 'right' : 'left';

	$output = "<div id='gallery-{$instance}' class='gallery galleryid-{$id}'>";	// We don't need the style tag, so we delete it

	if($itemtag != '' && $icontag != '' && $captiontag != '') {			// If we have specified the tags in the shortcode, let's use them with the original structure
		$i = 0;
		foreach ( $attachments as $id => $attachment ) {
			$link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);

			$output .= "<{$itemtag} class='gallery-item'>";
			$output .= "
				<{$icontag} class='gallery-icon'>
					$link
				</{$icontag}>";
			if ( $captiontag && trim($attachment->post_excerpt) ) {
				$output .= "
					<{$captiontag} class='gallery-caption'>
					" . wptexturize($attachment->post_excerpt) . "
					</{$captiontag}>";
			}
			$output .= "</{$itemtag}>";
			if ( $columns > 0 && ++$i % $columns == 0 )
				$output .= '<br style="clear: both" />';
		}
	} else {												// Else, we use our custom gallery
		foreach ( $attachments as $id => $attachment ) {
			$thumb = wp_get_attachment_image_src( $id, $size );					// We get the medium size image representing, it returns an array [url] [width] [height]
			$caption = wptexturize($attachment->post_excerpt);					// The caption text
			$output .= '[caption id="attachment_'.$id.'" align="alignleft" width="'.$thumb[1].'" caption="' . $caption . ' "]';	// We use the caption shortcode
			if (isset($attr['link']) && 'file' == $attr['link']) {					// If we want to link directly to the file
				$image = wp_get_attachment_image_src( $id, 'full' );				// We get the full size image representing, we'll use it to retrieve its url with $image[0]
				$output .= '<a href="'.$image[0].'" rel="prettyPhoto[pp'.$instance.']">';	// The link: $image[0] is the url, we put a rel attribute for a lightbox (you can put what you want)
				$output .= '<img class="attachment-'.$size.'" width="'.$thumb[1].'" height="'.$thumb[2].'" title="'.$caption.'" alt="'.$caption.'" src="'.$thumb[0].'" />';	// The "thumbnail"
				$output .= '</a>';
			} else {
				$output .= wp_get_attachment_link($id, $size, true, false);			// Link to the attachment page
			}
			$output .= '[/caption] ';								// We close the caption shortcode
		}
		$output = do_shortcode($output);								// We finally apply a do_shortcode for the... caption shortcodes
	}

	$output .= "
			<br style='clear: both;' />
		</div>n";											// Clear the thumbs floats and close the gallery div

	return $output;
}

Au début de la fonction, il y avait un apply_filters, que j’ai supprimé. En effet, cette fonction sera inutile ici, et en plus, cela nous évitera de faire tout planter avec une boucle infinie.

Dans l’extraction des attributs passés à la galerie, deux choses : premièrement, je remplace les valeurs par défaut de itemtag (‘dl’), icontag (‘dt’) et captiontag (‘dd’) par des chaines vides ( ») car nous feront un test sur leur valeur plus tard. Deuxièmement, dans notre cas nous allons utiliser la taille « medium » pour nos polaroids, donc je mets ‘medium’ pour size par défaut pour ne pas avoir à la préciser en paramètre à chaque galerie. A vous de voir si vous préférez garder ‘thumbnail’.

Vers le milieu du code (ligne 63), je vais supprimer la balise style qui me gênait tant et passer directement au début de notre div.
A la ligne suivante, je pose une condition if. Utilité : si vous indiquez dans les paramètres de la galerie des balises à utiliser (il faut indiquer les 3 : itemtag et icontag et captiontag), alors la fonction va utiliser la structure d’origine de WordPress, avec vos balises. Sinon, elle utilisera notre structure modifiée, et avec nos balises par défaut.

A partir de la ligne 87, nous apportons nos modifications avec notre nouvelle structure html.
D’abord nous allons chercher quelques informations utiles sur notre image de polaroid avec la fonction wp_get_attachment_image_src(). Il faut lui passer deux paramètres : l’ID de l’image et la taille que l’on souhaite utiliser (on peut indiquer un 3ème paramètre qui ne nous est pas utile ici). Ces informations nous sont déjà disponibles avec les variables $id et $size. Cette fonction nous renvoie un tableau sous la forme [0]=>[url], [1]=>[width], [2]=>[height], qui sont l’url, la largeur et la hauteur de notre image.

Ensuite nous utilisons le shortcode caption en lui indiquant les paramètres id, largeur de l’image et texte de la légende. L’avantage de cette méthode c’est de réutiliser un code déjà présent plutôt que de le réécrire, et nous gardons ainsi le même balisage html que nos polaroids précédents (voir tutoriel précédent). A noter, l’espace insécable que je rajoute en fin de légende, afin de garder l’espace blanc sous l’image du polaroid, dans le cas où celle-ci ne serait pas disponible.

Ensuite on utilise une condition if pour déterminer si le lien mène vers un fichier (la grande image) ou vers la page du fichier (grande image dans une page).
Premier cas, lien vers l’image elle même :
C’est le cas qui conviendra à l’utilisation une lightbox. Plutôt que d’utiliser une fonction présente dans WordPress pour afficher le lien d’un coup, je vais construire ce lien afin de pouvoir y ajouter l’attribut rel. Cet attribut est fort utile pour l’utilisation d’une lightbox. En effet, c’est lui qui va permettre de lier entre eux tous les liens de la galerie (car ils auront le même attribut rel), et de pouvoir faire défiler les photos dans la lightbox. Dans cet exemple, j’avais utilisé la lightbox jQuery prettyPhoto. A vous de modifier cet attribut selon votre lightbox.
Nous avons d’abord besoin de l’url de la grande image afin de créer le lien, nous utilisons donc à nouveau wp_get_attachment_image_src() avec le même id mais en taille ‘full’. Nous utilisons ensuite la variable $image[0] dans le lien et nous indiquons notre attribut rel pour la lightbox.
A la ligne suivante (93), nous créons notre image polaroid avec toutes les variables dont nous disposons : taille, url, largeur, hauteur et la légende pour le texte alternatif et le titre.
Second cas, lien vers la page de l’image :
Je reprends la fonction utilisée dans la galerie d’origine avec $output .= wp_get_attachment_link($id, $size, true, false);, tout simplement.

Nous fermons ensuite le shortcode caption et nous sommes à la fin de notre première condition (si on utilise notre galerie customisée par défaut).

Partie importante : nous utilisons la fonction do_shortcode(), sinon notre shortcode caption ne va pas se transformer comme par magie en image avec caption.

Pour terminer, nous ajoutons la balise br pour ne pas que nos polaroids « débordent » de la boite et nous fermons notre div de galerie.

Arrival : CSS

C’était long, et nous avons failli oublier le principal, la mise en forme. Comme nous l’avons vu, nous réutilisons le tutoriel précédent avec le shortcode caption, nous avons donc déjà des déclarations CSS existante, que nous n’auront pas besoin de réécrire :

010203040506070809101112
/* ----------------------------------------------------------------------------- Caption ------------------------------ */
.wp-caption {
	position: relative;
	line-height: 0;
}
.wp-caption .wp-caption-text {
	line-height: 22px;
	color: #55443a;
	display: block;
	padding: 2px 0;
	text-indent: 0.6em;
}

La partie qui va concerner la galerie à présent :

12345
/* ----------------------------------------------------------------------------- Gallery Captions ------------------------------ */
.gallery {
	margin: 20px 0;
	z-index: 20;
}

Nous mettons juste un peu d’espace en haut et en bas de la galerie avec margin, et plus important, nos polaroids auront besoin de « gagner » de la hauteur avec z-index quand nous passeront la souris dessus, il nous faut donc aussi indiquer un z-index à notre div de galerie pour ne pas avoir de problème.

Passons à nos polaroids :

0607080910111213141516171819202122232425262728
.wp-caption168 {
	margin: 3px;
	padding: 6px 6px 0;
	background-color: #eee;

	-moz-border-radius: 2px;
	-webkit-border-radius: 2px;
	-khtml-border-radius: 2px;
	border-radius: 2px;

	-moz-box-shadow: 0 0 10px #000;
	-webkit-box-shadow: 0 0 10px #000;
	-khtml-box-shadow: 0 0 10px #000;
	box-shadow: 0 0 10px #000;

	-webkit-transform: rotate(0deg);
	-moz-transform: rotate(0deg);
	-o-transform: rotate(0deg);

	-webkit-transition: -webkit-transform .15s linear;
	-moz-transition: -moz-transform .15s linear;
	-o-transition: -o-transform .15s linear;
}

Nous retrouvons un code similaire au tutoriel précédent, à la différence du rotate qui est mis à 0 degrés par défaut, histoire d’avoir une valeur de base, une valeur de départ.

Maintenant il nous faut incliner nos polaroids « au hasard ». Comme le hasard n’existe pas en CSS à ma connaissance, nous allons utiliser la pseudo-classe :nth-child() pour simuler cet effet de hasard :

2930313233343536373839404142434445464748
.wp-caption168:nth-child(odd) {
	-webkit-transform: rotate(6deg);
	-moz-transform: rotate(6deg);
	-o-transform: rotate(6deg);
}
.wp-caption168:nth-child(4n+1) {
	-webkit-transform: rotate(-6deg);
	-moz-transform: rotate(-6deg);
	-o-transform: rotate(-6deg);
}
.wp-caption168:nth-child(5n+4) {
	-webkit-transform: rotate(3deg);
	-moz-transform: rotate(3deg);
	-o-transform: rotate(3deg);
}
.wp-caption168:nth-child(6n+2) {
	-webkit-transform: rotate(-2deg);
	-moz-transform: rotate(-2deg);
	-o-transform: rotate(-2deg);
}

En fait, nous utilisons :nth-child() pour sélectionner les polaroids impairs (odd), puis le 1er, le 5ème et le 9ème (4n+1), etc. pour leur appliquer un angle différent à chaque fois.

Il ne reste plus qu’à rajouter « l’effet hover » :

49505152535455565758596061626364
.wp-caption168:hover {
	-moz-box-shadow: 0 0 16px #000;
	-webkit-box-shadow: 0 0 16px #000;
	-khtml-box-shadow: 0 0 16px #000;
	box-shadow: 0 0 16px #000;
	
	-webkit-transform: rotate(0deg);
	-moz-transform: rotate(0deg);
	-o-transform: rotate(0deg);
	
	-webkit-transform: scale(1.25);
	-moz-transform: scale(1.25);
	-o-transform: scale(1.25);
	
	z-index: 100;
}

Deux nouveautés ici : le z-index pour que le polaroid passe au-dessus des autres, et surtout, une nouvelle transformation : scale.
Elle a pour effet de faire « grossir » la taille de l’élément ciblé (ou la diminuer). Ici, nous agrandissons nos polaroids de 25% (1.25). Attention à ne pas en faire trop, sinon notre image vas pixeliser puisqu’elle est « up-scalée ». Déjà, 125% c’est la limite je trouve.

Et puis… Nous avons fini.
Voici notre style CSS complet :

010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
/* ----------------------------------------------------------------------------- Gallery Captions ------------------------------ */
.gallery {
	margin: 20px 0;
	z-index: 20;
}
.wp-caption168 {
	margin: 3px;
	padding: 6px 6px 0;
	background-color: #eee;
	-moz-border-radius: 2px;
	-webkit-border-radius: 2px;
	-khtml-border-radius: 2px;
	border-radius: 2px;
	-moz-box-shadow: 0 0 10px #000;
	-webkit-box-shadow: 0 0 10px #000;
	-khtml-box-shadow: 0 0 10px #000;
	box-shadow: 0 0 10px #000;
	-webkit-transform: rotate(0deg);
	-moz-transform: rotate(0deg);
	-o-transform: rotate(0deg);
	-webkit-transition: -webkit-transform .15s linear;
	-moz-transition: -moz-transform .15s linear;
	-o-transition: -o-transform .15s linear;
}
.wp-caption168:nth-child(odd) {
	-webkit-transform: rotate(6deg);
	-moz-transform: rotate(6deg);
	-o-transform: rotate(6deg);
}
.wp-caption168:nth-child(4n+1) {
	-webkit-transform: rotate(-6deg);
	-moz-transform: rotate(-6deg);
	-o-transform: rotate(-6deg);
}
.wp-caption168:nth-child(5n+4) {
	-webkit-transform: rotate(3deg);
	-moz-transform: rotate(3deg);
	-o-transform: rotate(3deg);
}
.wp-caption168:nth-child(6n+2) {
	-webkit-transform: rotate(-2deg);
	-moz-transform: rotate(-2deg);
	-o-transform: rotate(-2deg);
}
.wp-caption168:hover {
	-moz-box-shadow: 0 0 16px #000;
	-webkit-box-shadow: 0 0 16px #000;
	-khtml-box-shadow: 0 0 16px #000;
	box-shadow: 0 0 16px #000;
	-webkit-transform: rotate(0deg);
	-moz-transform: rotate(0deg);
	-o-transform: rotate(0deg);
	-webkit-transform: scale(1.25);
	-moz-transform: scale(1.25);
	-o-transform: scale(1.25);
	z-index: 100;
}

Conclusion

Nous obtenons un effet de polaroids « presque jetés sur la table », et le tout très facilement utilisable dans l’administration de WordPress.
Ainsi, il suffira d’attacher nos images à notre article ou notre page, de remplir les champs nécessaires (titre, texte alternatif, légende), puis de créer une galerie en cliquant seulement sur un bouton (choisir « Lien vers le fichier »).
Nous obtiendrons le shortcode suivant dans l’article :

1
[gallery link="file"]

Une image attachée à l’article qui ne doit pas apparaitre dans la galerie? Une image non attachée qui doit y apparaitre?
Très simple, utiliser exclude et include.

1
[gallery exclude="165" include="223" link="file"]

Rendez-vous dans quelques jours pour la dernière partie de ce tutoriel : nous allons nous occuper de nos images en taille large, réutiliser en partie ce deuxième tutoriel, rajouter un peu de jQuery, et mélanger tout ça.

EDIT : Allez, pour la peine je vous met prettyPhoto dans la démo et l’archive téléchargeable.