Contenu principal
WP Ajax Gallery

Une galerie ajax pour WordPress

Pour un projet personnel de site tournant avec WordPress, j’ai créé un petit plugin créant une galerie de photos.
Encore une galerie de photos? Oui, en effet, mais celle-ci comporte quelques particularités que je n’ai pas trouvées dans des plugins existants.

Que fait cette galerie?

Cette galerie était destinée à un blog d’artiste peintre. Je voulais une galerie pouvant afficher TOUS les tableaux du blog au même endroit, et bien sûr, permettant la navigation de tableau en tableau. Pas de défilement automatique, juste des boutons de navigation « Suivant » et « Précédent ».
Pour chaque tableau, un nouvel article est créé sur le blog et une photo du tableau est « mise à la une ». Ce que ce plugin va donc faire, c’est fouiller la base de donnée à la recherche des images à la une. En plus, ces articles sont classés dans deux catégories, donc tant que nous y sommes, il faudrait que la galerie affiche les tableaux de la catégorie dans laquelle nous sommes (donc 3 possibilités : catégorie parente, 1ère catégorie, seconde catégorie).
Ainsi, pas besoin d’indiquer au plugin quelles photos afficher, il va s’en charger tout seul : pas de paramétrage ou de second upload de toutes les photos.

Deuxième point, et le plus important :
Au moment où j’écris ce billet, le site comporte 61 tableaux. Dans le pire des cas, lorsque l’on veut afficher la catégorie parente, et donc tous les tableaux, cela fait 61 photos de taille relativement conséquente à afficher. Autant dire que les afficher d’un coup au chargement de la page est absolument mal venu.
La galerie va donc les afficher après le chargement de la page via requête ajax grâce à jQuery.
De là, découlent d’autres subtilités :

  • Même si la galerie charge les photos après l’affichage de la page, les incorporer toutes en même temps dans la page va poser problème puisque toutes vont se charger au même moment. Et donc peut-être que la 17ème sera prête avant la première, etc. J’ai donc fait en sorte que le script incorpore chaque image une à une, et seulement lorsque la précédente est totalement chargée.
  • Encore une chose : hors de question de faire une requête ajax pour chaque photo, cela reviendrait à faire 61 requêtes vers la base de donnée en quelques secondes. Donc une seule requête pour toutes les photos suffira et ensuite on se débrouille avec.
  • Dernier point : vu que les photos sont chargées au fur et à mesure, pourquoi attendre que toutes soient chargées pour commencer à visionner les premières? Dès que la 1ère photo est prête, la galerie va l’afficher, et dès que la 2ème et prête, on peut commencer à naviguer dans la galerie.

Bref, voilà l’idée, optimiser le plus possible pour ne pas surcharger la base de données, ne pas ralentir la navigation sur le blog, et commencer le visionnage dès que possible.

Côté visiteur

Durant le chargement des photos, une zone affiche l’état des téléchargements dans la partie haute de la galerie : nombre de photos chargées et barre de remplissage.
Dès que la 1ère photo est chargée, elle est affichée.
Dès que la 2ème photo est chargée, les boutons « Suivante » et « Précédente » sont affichés. Sur la 1ère photo, si on clique sur « Précédente » durant le chargement des autres photos, on se retrouve sur la dernière photo disponible.
Lorsque la dernière photo est chargée, la zone affichant l’état des téléchargements disparait et des boutons d’avance rapide et de recul rapide apparaissent (sauts de 5 photos vers l’avant ou 5 photos vers l’arrière).
Liens vers la photo en taille « d’origine » (pour une lightbox), et vers l’article en question.
Ces 6 boutons s’affichent au survol de la souris, selon l’endroit survolé sur la galerie.
La hauteur des photos étant variable, la galerie s’adapte en fonction (largeur fixe par contre). Effet de fading entre chaque photo.
Les photos sont classées de l’article le plus récent au plus ancien.

Côté scripts

SQL :
4 requêtes au total. Une qui va chercher le chemin vers le dossier « uploads », une qui renvoie le numéro des catégories (j’utilise la méthode $wp_query->query_vars de WordPress puis la requête va mettre de l’ordre dans les catégories filles/parente), une qui va renvoyer l’id des photos et les mettre dans une variable javascript array, la dernière (en ajax, échanges de données en json) va renvoyer toutes les données dont la galerie a besoin (largeur, hauteur, url, etc).
A noter que la dernière requête renvoie les données concernant les photos en taille large.
Pour afficher les photos en taille medium ou thumbnail, ouvrir le fichier wp-ajax-gallery.php et modifier la ligne 70 en remplaçant les 3 occurrences de ‘large’ par ‘medium’ par exemple :

676869707172

$thumbs = array();
for ($num = 0; $num < count($sashimi); $num++) {
$thumbtmp = unserialize($sashimi[$num]->thumbmetas);
$thumbs[$num] = array('href' => $thumbtmp['file'], 'src' => $thumbtmp['sizes']['large']['file'], 'width' => $thumbtmp['sizes']['large']['width'], 'height' => $thumbtmp['sizes']['large']['height'], 'caption' => $sashimi[$num]->thtitle, 'pid' => $sashimi[$num]->pid);
}
echo json_encode($thumbs);

PHP :
orienté objet avec une classe wp_ajax_gallery. Le fichier JavaScript est construit par php.

javascript :
jQuery avec utilisation de $.getJSON() pour la requête ajax. La fonction de callback va insérer une <li> avec les liens et la 1ère photo. Quand la photo est chargée, la fonction est lancée à nouveau pour insérer la deuxième <li>, etc.
A noter que sur le blog en question, j’utilise la lightbox Fancy Gallery (dont je me suis inspiré pour les boutons). Comme les images sont insérées après l’exécution de la lightbox, ces nouvelles photos n’étaient pas prises en compte par Fancy Gallery. J’ai d’abord pensé à la fonction « live » de jQuery mais les ralentissements étaient trop importants. A la place, Fancy Gallery est relancé à chaque nouvelle ligne, en ciblant uniquement cette nouvelle photo. Un fallback est prévu si vous n’utilisez pas cette lightbox ou si elle est désactivée, afin de ne pas planter le script. Voir dans le fichier ajax.js.php à la ligne 55 :

48495051525354555657

if(!$.isFunction($.fancybox)) {
	(function($){$.fn.fancybox=function() {
		return this;
	}})(jQuery);
}
$(seaweed)
	.appendTo("#gallery-wrapin")
	.find('.fancybox').unbind("click").fancybox(params)
	.end()
	etc...

Ces lignes seront donc à modifier selon vos besoins.

Installation

Dans la page où doit apparaitre la galerie, il suffit d’insérer un appel vers la fonction wpAG().
Exemple : la galerie apparaitra seulement si on est dans les catégories 6, 7 ou 8, et n’affichera que les photos correspondantes.

1234

if ( class_exists('wp_ajax_gallery') && is_category(array(6, 7, 8)) ) {
	echo '<h2>Galerie</h2>';
	wpAG();
}

Concernant les fichiers css :
J’ai préféré inclure les styles css directement dans le thème du blog afin de ne pas avoir une requête http supplémentaire inutile. Donc aucune balise link n’est créée dans le head du blog. Il y a un style normal, un style pour IE7 et un pour IE6. Vérifiez bien le chemin des « background-image » pour IE6 car j’ai utilisé des png24, et donc, le filtre microsoft pour la transparence, ayant besoin d’un chemin absolu, dépendant donc de votre thème et de votre installation. En plus, mon IE6 plante depuis quelques jours pour je ne sais quelles raisons, donc je n’ai pas pu tester le css.
Pour IE7, j’ai eu un comportement inattendu lié au survol des boutons. J’ai dû créer une image supplémentaire, toujours en png24 mais sans ombres. Encore pire, le survol n’était pas pris en compte si les div survolées n’avaient pas une couleur de fond ou une image de fond (une première pour moi oO ). Problème résolu en ajoutant une image transparente en background (il y a de quoi se taper la tête contre les murs parfois).
Pour IE8 je n’ai pas pu tester car je n’ai pas ce navigateur (hé ho, je suis un Mac user et j’en ai 2 sur 3, c’est déjà pas mal hein ;) ).

Pour les images :
Placer le second dossier « wp-ajax-gallery » (celui contenant les images bien sûr) dans le dossier « images » de votre thème.

Le dossier « wp-ajax-gallery » global du plugin est évidemment à placer dans le dossier « plugins » du blog. Au final il ne reste que les 2 fichiers php dedans (et le READ_ME).

Voilà, au final ce n’est pas un plugin complet que nous avons là mais plutôt une base pour quelque chose de mieux fini et adaptable partout. Allez, on va dire que c’est une bêta qui tourne déjà bien ;)
Comme je le dis souvent sur ce blog, à la base je suis intégrateur, je ne me prétend pas développeur. Il y a donc sûrement des coquilles qui trainent ou de meilleurs moyens pour réaliser ce que j’ai fait là (surtout côté php). Donc si vous avez des améliorations à proposer ou des remarques à faire, laissez un commentaire.
Ho et puis dans tous les cas, laissez moi un commentaire, ça fait toujours plaisir :)