CreativeJuiz blog - Archives (mai 2012)

CreativeJuiz, blog de Webdesign et développement autour de HTML5, CSS3, WordPress, PHP et jQuery.

Le: 30 05 2012 à 21:31

Subtle Patterns est un site internet proposant des textures (ou motifs) gratuites au format PNG.
Compatibles avec le format pattern (.pat) de Photoshop, ce site propose également un système de recherche par mot clef qui vous permet de trouver rapidement des textures précises.

Développé et maintenu par Atle Mo, ce site est issu de la volonté de mettre à disposition des WebDesigners des ressources de qualité et entièrement gratuites.

Le contenu du site

Parcourez simplement la page d’accueil à la recherche des dernières textures. La liste des motifs est disponible avec un descriptif ou sous forme de miniature. Il est également possible de tester les texture à la volée directement sur l’image de fond du site Subtle Patterns. Cela vous permet de voir en application la texture avant de la télécharger.

Des bonus sont également disponibles à la page Subtle Patterns – Snacks, notamment des plugins et packs complets de textures au format PNG.

Petit arrêt sur le plugin WordPress

Subtle Patterns est également décliné sous la forme d’un plugin WordPress qui vous permet de prendre la main sur le fond imagé de votre site.

Attention, il me semble que pour fonctionner, votre thème WordPress doit autoriser les backgrounds customisés (ça semble logique).

Pour rappel

Une autre ressource intéressante déjà présentée sur ce blog pour trouver des textures : Tileables – Never ending patterns

J’espère que ça vous fera de quoi vous ressourcer :)

Le: 21 05 2012 à 00:00

Le plugin social subscribers counter développé par GeekPress est un outil très simple d’utilisation qui vous permet d’afficher à plusieurs endroits de votre site WordPress des statistiques globales des différents réseaux sociaux que vous utilisez.

Fonctionnalités

Ce plugin est très simple d’utilisation.
Après l’avoir activé, rendez-vous dans la page de réglages pour renseigner les adresses de vos différentes pages de réseaux sociaux.

Page de réglages du plugin

Proposant de compter le nombre de vos followers (abonnés Twitter), fans (abonnés Facebook) et lecteurs (abonnés au flux RSS feedburner), ce plugin ajoute ces chiffres dans l’administration de votre site WordPress, à la suite de vos statistiques globales.
Bien entendu, vous n’êtes pas obligés d’utiliser tous ces réseaux pour utiliser le plugin.

Tableau de bord

On regrettera peut-être l’absence de couleurs sur ces liens qui permettraient de distinguer plus rapidement les différents réseaux sociaux.

En plus de vous proposer un affichage des chiffres dans l’espace d’administration, un petit module est mis à votre disposition pour un aperçu de ces chiffres directement sur votre site.

Réglage du widget

Les réglages de ce module vous permettent d’afficher une accroche précise pour chacun des réseaux que vous utilisez, en plus du titre classique de module.

Un thème par défaut accompagne ce plugin et se veut simple et facilement personnalisable.

Thème graphique du module

Pour les amateurs de CSS, il vous sera possible de personnaliser l’apparence en écrasant les styles existants directement depuis votre feuille de styles.

Évolutions envisageables

D’après ce que j’ai cru entendre ci et là, l’auteur pourrait bien ajouter quelques réseaux sociaux à la liste de ceux déjà disponibles.
Un second thème graphique pourrait également être ajouté (bien que déjà existant :p) et vous permettre, depuis les paramètres du plugins, de choisir entre l’une ou l’autre des apparences.

À suivre donc :)

Télécharger le plugin
Social Subscribers Counter

Le: 16 05 2012 à 00:01

Si vous suivez le compte @NoupeMag sur Twitter (ça marche aussi pour mon compte), vous avez certainement vu passer mon slideshow en CSS3 datant de l’an dernier.
Ce n’était pas ma première tentative de slideshow comme le présentent ces premier et second travaux datant de mai 2010.

Ce tutoriel ne s’adresse pas aux débutants, il vous faudra un minimum de connaissances techniques pour vous y retrouver dans les tronçons de code qui vont suivre. Cependant, le code commenté reste – je l’espère – accessible.

Avant propos

La page de démonstration du slideshow full CSS3 vous propose des fichiers sources en téléchargement, profitez-en, notamment si vous souhaitez récupérer les images.

Les codes CSS fournis ici sont légèrement différents de ceux fournis dans l’archive zippée téléchargeable. En effet, la rédaction du tutoriel que vous allez lire m’a permis d’alléger, corriger et améliorer le code disponible en téléchargement. Il fera l’objet d’une refonte prochaine.

Les codes CSS3 présents sur ce tutoriel ne tiennent pas compte des préfixes parfois nécessaires (-webkit-, -moz-, -ms-, -o-) pour une question de gain de place dans le code. Ne les oubliez pas.

Les défauts des versions précédentes

Comme les expérimentations foireuses sont là pour faire ressortir les limites d’une technique, voyons ce qui nous manquait dans les versions précédentes (gardez-les sous les yeux pour tester, c’est mieux).
Sur la version contrôlable (la première) :

  • Un saut de page est visible au clic sur les flèches ;
  • Nous sommes obligés de multiplier les éléments (div pour les conteneurs, a pour les flèches) ;
  • il faut dupliquer des règles CSS à chaque image ajoutée.

Sur la version automatique (la seconde) :

  • Il n’y a pas de commandes (soit…)
  • Aucune possibilité de stopper l’animation
  • il faut dupliquer des règles CSS à chaque image ajoutée.

Certains de ces problèmes ne sont pas résolubles, j’ai décidé de me concentrer sur la fusion des fonctionnalités et sur la correction de certains points :

  • Fusionner le slideshow automatique et contrôlable
  • Ajouter une commande de stop et lecture de l’animation
  • Limiter la multiplication des éléments
  • Virer le saut au clic (grâce à l’astuce CSS de Vincent De Oliveira)

Les autres problèmes persisteront, vous le verrez.

Poser les fondations

Voici du code HTML (HTML5 en l’occurrence) que j’espère suffisamment parlant.

<section id="slideshow">
	<div class="container">
		<div class="c_slider"></div>
		<div class="slider">
			<figure>
				<img src="img/dummy-640x310-1.jpg" alt="" width="640" height="310" />
				<figcaption>The mirror of soul</figcaption>
			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-2.jpg" alt="" width="640" height="310" />
				<figcaption>Let's cross that bridge when we come to it</figcaption>
			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-3.jpg" alt="" width="640" height="310" />
				<figcaption>Sushi<em>(do)</em> time</figcaption>
			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-4.jpg" alt="" width="640" height="310" />
				<figcaption>Waking Life</figcaption>
			</figure>
		</div>
	</div>
	<span id="timeline"></span>
</section>

Ce code HTML pourrait être simplifié en prenant le risque de complexifier la CSS, mais cette dernière va déjà l’être suffisamment…
Pour faire simple nous avons une section pour le slideshow qui réunie le conteneur des images (.container), la partie qui glisse (.slider), les différentes images légendées (sous forme de figure > figcaption) et la petite barre de défilement du temps (#timeline).

Pour ceux qui s’interrogent sur la présence de commentaires HTML, je vous invite à lire cet autre article du blog : Display inline-block, une valeur trop peu utilisée.

Je n’ai mis aucun élément de commande pour le moment, nous verrons cela plus tard.

Voici le code CSS servant principalement à positionner, dimensionner et décorer les différents blocs, que je ne vais pas expliquer dans la mesure où ce n’est pas le cœur de l’article, mais il est un minimum commenté ;)

#slideshow {
	position: relative;
	width: 640px;
	height: 310px;
	padding: 15px;
	margin: 0 auto 2em;
	border: 1px solid #ddd;
	background: #FFF;
	/* CSS3 effects */
	background: linear-gradient(#FFF, #FFF 20%, #EEE 80%, #DDD);
	border-radius: 2px 2px 2px 2px;
	box-shadow: 0 0 3px rgba(0,0,0, 0.2);
}
 
/* avanced box-shadow
 * tutorial @
 * http://www.creativejuiz.fr/blog/les-tutoriels/ombre-avancees-avec-css3-et-box-shadow
*/
#slideshow:before,
#slideshow:after {
	position: absolute;
	bottom:16px;
	z-index: -10;
	width: 50%;
	height: 20px;
	content: " ";
	background: rgba(0,0,0,0.1);
	border-radius: 50%;
	box-shadow: 0 0 3px rgba(0,0,0, 0.4), 0 20px 10px rgba(0,0,0, 0.7);
}
#slideshow:before {
	left:0;
	transform: rotate(-4deg);
}
#slideshow:after {
	right:0;
	transform: rotate(4deg);
}

Avec ceci nous avons le support graphique des images. C’est un peu tout cassé, mais vous pouvez voir comment réaliser simplement un élément qui semble assez complexe, notamment au niveau des ombres et dégradés.
Gérons le débordement et l’alignement de tout ce contenu.

/* gestion des dimensions et débordement du conteneur */
#slideshow .container {
	position:relative;
	width: 640px;
	height: 310px;
	overflow: hidden;
}
/* on prévoit un petit espace gris pour la timeline */
#slideshow .container:after {
	position:absolute;
	bottom: 0; left:0;
	content: " ";
	width: 100%;
	height: 1px;
	background: #999;
}
/*
   le conteneur des slides
   en largeur il fait 100% x le nombre de slides
*/
#slideshow .slider {
	position: absolute;
	left:0; top:0;
	width: 400%;
	height: 310px;
}
/* annulation des marges sur figure */
#slideshow figure {
	position:relative;
	display:inline-block;
	padding:0; margin:0;
}
/* petit effet de vignette sur les images */
#slideshow figure:after {
	position: absolute;
	display:block;
	content: " ";
	top:0; left:0;
	width: 100%; height: 100%;
	box-shadow: 0 0 65px rgba(0,0,0, 0.5) inset;
}

Nous voici sur une mise en forme plus propre, les éléments figure sont placés sur une seule et même ligne et le débordement est caché.
Il ne nous reste plus qu’à présenter un peu mieux notre légende qui est actuellement planquée :

/* styles de nos légendes */
#slideshow figcaption {
	position:absolute;
	left:0; right:0; bottom: 5px;
	padding: 20px;
	margin:0;
	border-top: 1px solid rgb(225,225,225);
	text-align:center;
	letter-spacing: 0.05em;
	word-spacing: 0.05em;
	font-family: Georgia, Times, serif;
	background: #fff;
	background: rgba(255,255,255,0.7);
	color: #555;
	text-shadow: -1px -1px 0 rgba(255,255,255,0.3);
}

Et voilà qui est mieux.

Nous allons maintenant nous occuper de la phase automatique du slideshow.
Nous verrons dans une troisième partie comment gérer des actions pour contrôler notre slideshow.

Animer notre contenu : phase automatique

Cette phase va être quelque peu répétitive puisque nous allons devoir créer un certain nombre d’animations grâce à la fonction CSS @keyframes. Pour en savoir plus sur les animations, je vous invite à lire la partie « animation » de cet article sur le timing sur Alsacréations.

Pour obtenir une animation cohérente tout le long d’un cycle, vous devez vous poser la question suivante :
Combien de temps est nécessaire pour la compréhension de chaque slide ?

Bien entendu, la réponse va dépendre du contenu, mais imaginons que nous ayons 4 étapes, pas beaucoup de texte, 6 ou 7 secondes peuvent sembler suffisantes pour chaque étape. Il reste alors à estimer la durée d’une transition d’une étape à l’autre, 1 ou 2 secondes. Avec 8 secondes multipliées par 4, ça nous fait 32 secondes d’animation pour boucler un cycle complet.

Animation du conteneur

Commençons par animer le bloc qui contient nos images et légendes en le faisant glisser. Pour cela, créons notre animation :

/* fonction d'animation, n'oubliez pas de prefixer ! */
@keyframes slider {
	0%, 20%, 100%	{ left: 0 }
	25%, 45%		{ left: -100% }
	50%, 70%		{ left: -200% }
	75%, 95%		{ left: -300% }
}

Chaque étape est exprimée en pourcentage, aussi 50% signifie que nous en sommes à la 16ième seconde de notre animation.
Si plusieurs étapes ont la même valeur d’une propriété, ou si vous souhaitez créer un arrêt, il suffit de mettre la valeur sur la même ligne séparer par une virgule.
Par exemple, sur la première étape, nous avons 0, 20 et 100% qui cohabitent. Cela sous entend que de 0 à 20%, la valeur de left est de 0, nous créons donc un arrêt. Cela signifie aussi que de 95 à 100%, la valeur de left passe de -300% à 0. C’est un moyen facile de retourner à la valeur initiale pour créer une boucle.

Nous avons créer l’animation, il faut maintenant l’attribuer à notre élément de cette manière :

/* complétez le sélecteur : */
#slideshow .slider {
	/* ... avec la propriété animation */
	animation: slider 32s infinite;
}

Cette syntaxe de la propriété animation est le raccourci de animation-name, animation-duration, animation-iteration-count, dans cet ordre précisément ici.

Animation de la ligne de temps

Notre petite ligne d’un pixel de hauteur servant de ligne de temps va être animée sur le même principe.
Mais avant cela, donnons-lui quelques styles de couleur.

#timeline {
	position: absolute;
	background: #999;
	bottom: 15px;
	left: 15px;
	height: 1px;
	background: rgb(214,98,13);
	background: rgba(214,98,13,.8);
	width: 0;
	/* fonction d'animation */
	animation: timeliner 32s infinite;
}

Il est ainsi placé précisément en tenant compte des marges autour des photos, et nous lui attribuons tout de suite une animation nommée timeliner qu’il nous faut déclarer comme ceci :

@keyframes timeliner {
	0%, 25%, 50%, 75%, 100%	{ width: 0;		}
	20%, 45%, 70%, 90%		{ width: 640px;	}
}

Ici nous savons que la ligne doit être à son maximum à quatre reprise (avant chaque changement de slide). Il y a donc 4 étapes à 640px (largeur max), et 4 (si on confond 0 et 100) à 0.

Animation de la légende

Même procédé, nous allons faire monter et descendre notre légende à chaque slide.

@keyframes figcaptionner {
	0%, 25%, 50%, 75%, 100%						{ bottom: -55px;	}
	5%, 20%, 30%, 45%, 55%, 70%, 80%, 95%		{ bottom: 5px;		}
}

Puis nous accrochons cette animation à notre élément :

/* ajouter à l'élément : */
#slideshow figcaption {
	/* ... la propriété animation */
	animation: figcaptionner 32s infinite;
}

Je ne sais pas si vous avez vu, mais le vignettage des slides est animé. Comme vous avez compris le principe, je vous laisse vous amuser à trouver le code ;)

Nous avons désormais un slideshow qui fonctionne en mode automatique.
Maintenant, voyons comment procéder si l’on souhaite ajouter des boutons stop/marche, et suivant/précédent, ou « aller à la slide 3″, par exemple.

Contrôler notre contenu : phase manuelle

Lorsque l’on conçoit un slideshow, il est très recommandé de permettre à l’utilisateur de stopper l’animation, soit parce que ça le stresse, soit parce qu’il veut contempler une des images, soit… bref, voyons ce qu’on peut faire !

Pour rappel, nous n’avons encore aucun élément HTML pour ces contrôles, nous allons donc les rajouter progressivement.
Ces éléments de contrôles (des liens) vont cibler des ancres placés « à côté » de notre slideshow, en tant que frères indirects.

Juste avant notre élément #slideshow, placez donc ces éléments span :

<span id="sl_play" class="sl_command"></span>
<span id="sl_pause" class="sl_command"></span>
 
<span id="sl_i1" class="sl_command sl_i"></span>
<span id="sl_i2" class="sl_command sl_i"></span>
<span id="sl_i3" class="sl_command sl_i"></span>
<span id="sl_i4" class="sl_command sl_i"></span>

Ceux-ci ont des classes communes (parfois) qui nous permettrons des actions groupées par la suite.
Vous comprendrez leur utilité par la suite, ne vous faites pas de souci.

Bouton jouer et arrêter

Les boutons play et pause peuvent être ajoutés dans la section #slideshow, juste avant notre .container.

Il n’y a aucune obligation à les placer précisément ici, il est généralement conseillé de conserver ordre d’apparition dans le DOM et ordre d’apparition à la lecture de la page. Là nous allons les placer au milieu (verticalement) du slideshow :

<a class="play_commands pause" href="#sl_pause" title="Maintain paused">Pause</a>
<a class="play_commands play" href="#sl_play" title="Play the animation">Play</a>

Ces éléments peuvent prendre leur apparence avec quelques lignes de code uniquement, et sont par défaut cachés : ils n’apparaissent qu’à certains moments bien précis que nous définirons par la suite.

.play_commands {
	/* positionnement en haut à droite */
	position: absolute;
	top: 25px; right: 25px;
	z-index: 10;
	/* dimensionnement des icônes */
	width: 22px;
	height: 22px;
	text-indent: -9999px;
	border:0 none;
	/* placez l'opacité à 1 si vous souhaitez voir les commandes */
	opacity: 0;
	/* préparation de transition sur opacicty et right */
	transition: opacity 1s, right 1s;
}
/* on décale play légèrement sur la gauche */
.play { right: 55px; cursor: default; }
 
/* création de l'icône pause avec 2 pseudos éléments */
.pause:after,
.pause:before {
	position: absolute;
	display: block;
	content: " ";
	top:0;
	width:38%;
	height: 22px;
	background: #fff;
	background: rgba(255,255,255,0.5);
}
.pause:after { right:0; }
.pause:before {	left:0; }
 
/* création de l'icône play avec des bordures */
.play {
	width: 1px;
	height: 1px;
	/* les transparentes forment la flèche */
	border-top: 10px solid transparent;
	border-bottom: 10px solid transparent;
	border-left: 20px solid #fff;
	border-left: 20px solid rgba(255,255,255,0.5);
	/* renseignez 1 pour voir l'icône de suite */
	opacity: 0;
}
 
/* apparition du bouton pause au survole */
/* apparition des boutons au focus */
#slideshow:hover .pause,
.play_commands:focus {
	opacity: 1;
	outline: none;
}

Voilà, toutes ces lignes pour mettre en place nos deux liens. Ceux qui trouveront plus pertinent de charger des images ou un sprite, je ne leur en voudrais pas.
C’est bien, c’est beau, mais pas fonctionnel.

Nous allons maintenant utiliser la pseudo classe target pour agir sur notre animation en fonction du bouton que nous aurons cliqué.
Lorsque pause est cliqué, nous ciblons l’élément #sl_pause, lorsque lecture est cliqué, c’est #sl_play qui est ciblé.
Dans notre scénario, nous n’afficherons que le bouton utile : pause quand la lecture est effective, play lorsque la pause est en place.

/* stopper les animation */
.sl_command:target ~ #slideshow .slider,
.sl_command:target ~ #slideshow figcaption,
.sl_command:target ~ #slideshow #timeline,
.sl_command:target ~ #slideshow .dots_commands li:first-child a:after {
	animation-play-state: paused;
}
 
/* redémarrer les animations */
#sl_play:target ~ #slideshow .slider,
#sl_play:target ~ #slideshow figcaption,
#sl_play:target ~ #slideshow #timeline,
#sl_play:target ~ #slideshow .dots_commands li:first-child a:after {
	animation-play-state: running;
}
 
/* switch entre les boutons */
.sl_command:target ~ #slideshow .pause 		{ opacity:0; }
#sl_play:target ~ #slideshow:hover .pause,
#sl_play:target ~ #slideshow .pause:focus 	{ opacity:1; }
.sl_command:target ~ #slideshow .play 		{ opacity:1; right: 25px; cursor: pointer; }
#sl_play:target ~ #slideshow .play 			{ opacity:0; right: 55px; cursor: default; }

Le premier bloc permet de stopper les animations grâce à la propriété animation-play-state. Cette propriété placée à sa valeur paused permet de figer l’animation.
Les sélecteurs sont assez spéciaux : .sl_command:target ~ #slideshow .slider permet de cibler « L’élément .slider fils de #slideshow lorsque ce dernier est indirectement frère de .sl_command, uniquement lorsque ce dernier est ciblé. ». Autrement dit : si .sl_command est ciblé, alors on va chercher le frère #slideshow puis son fils .slider pour lui appliquer un stop.
On procède de la même manière pour les autres éléments (figcaption, #timeline et .dots_commands que nous verrons plus tard dans le bonux) qui ont une animation en route également.
Pour en savoir plus sur les sélecteurs d’adjacence indirecte, lisez cet autre article du blog : Sélecteur d’adjacence indirecte en CSS3.

Le dernier bloc de code permet d’afficher les boutons en fonction de situation précise, je vous laisse essayer de décortiquer leur signification.

Bonux : Les flèches « suivant » et « précédent »

Il va nous falloir une paire de liens par étape de notre slideshow en gardant en tête que la flèche de gauche de notre première slide nous permet d’aller à la dernière, la flèche de droite de notre dernière slide nous permet d’aller à la première (vous me suivez ?). Lisez les title pour comprendre l’utilité de chaque flèche. Vous pouvez placer ces liens après nos deux liens pause et lecture.

<a class="commands prev commands1" href="#sl_i4" title="Aller à la dernière slide">&lt;</a>
<a class="commands next commands1" href="#sl_i2" title="Aller à la 2ème slide">&gt;</a>
<a class="commands prev commands2" href="#sl_i1" title="Aller à la 1ère slide">&lt;</a>
<a class="commands next commands2" href="#sl_i3" title="Aller à la 3ème slide">&gt;</a>
<a class="commands prev commands3" href="#sl_i2" title="Aller à la 2ème slide">&lt;</a>
<a class="commands next commands3" href="#sl_i4" title="Aller à la 4ème slide">&gt;</a>
<a class="commands prev commands4" href="#sl_i3" title="Aller à la 3ème slide">&lt;</a>
<a class="commands next commands4" href="#sl_i1" title="Aller à la 1ère slide">&gt;</a>

C’est là que la pertinence du markup en prend un coup. Pour des raisons d’accessibilité (clavier ici) ces liens ne sont peut-être pas des plus utiles et pratiques à utiliser. Est peut-être à envisager l’ajout de l’attribut tabindex="-1" pour empêcher le focus sur ces éléments. En effet, nous utiliserons un second système de navigation juste après, qui lui est peut-être plus pertinent.
Donnons quelques styles à nos boutons et cachons ceux qui ne sont pas utiles.

#slideshow .commands {
	position: absolute;
	top: 45%;
	padding: 5px 13px;
	border-bottom:0;
	font-size: 1.3em;
	color: #aaa;
	text-decoration:none;
	background-color: #eee;
	background-image: linear-gradient(#fff,#ddd);
	text-shadow: 0 0 1px #aaa;
	border-radius: 50%;
	box-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
 
#slideshow .prev { left: -48px; }
#slideshow .next { right: -48px; }
 
#slideshow .commands { display:none; }
#slideshow .commands1 {	display: block; }

Très bien, nous avons des flèches… mais que va-t-on bien pouvoir bouger avec ?
Sur le même principe que précédemment, nous ciblons l’un des span abandonnés en début de code. Si vous cliquez sur une des flèches, pour le moment ça ne fait que stopper l’animation (oui, tous les span sont porteurs de la classe .sl_command, rappelez-vous, en en ciblant un, les animations s’arrête).
En fonction de l’élément ciblé, on pourrait stopper l’animation et changer les valeurs de left pour le slider, de width pour la timeline, et de bottom pour la légende. Ça serait cool hein ?
Oui mais non, parce qu’en fait ça ne fonctionne pas : les keyframes sont « prioritaires ».

C’est ce qui nous oblige à compléter notre code HTML légèrement avec ce petit morceau :

<div class="c_slider"></div>

Il est déjà présent dans le code fourni initialement (premier bloc de cet article).

Cet élément nous permet d’appliquer les images en image de fond. Ces mêmes images que nous avons déjà chargé dans le HTML, nous allons les appliquer en background CSS.
C’est en faisant bouger ce nouvel élément que nous allons donner l’illusion d’un slideshow classique. Je dis bien illusion, car vous aurez compris qu’ici on se restreint à l’idée d’un vrai diaporama, avec des images, et non du contenu textuel qu’il serait difficile de « dupliquer ».

#slideshow .c_slider {
	position: absolute;
	left:0; top:0;
	width: 400%;
	height: 310px;
	/* multiple background */
	background: url(img/dummy-640x310-1.jpg) 0 0 no-repeat,
	            url(img/dummy-640x310-2.jpg) 640px 0 no-repeat,
	            url(img/dummy-640x310-3.jpg) 1280px 0 no-repeat,
	            url(img/dummy-640x310-4.jpg) 1920px 0 no-repeat;
	transition: background 1s;
}

Cette division fournies de quelques images est cachées par la partie principale du diaporama pour le moment. Lorsque nous ciblerons le contenu avec l’une de nos flèches « suivant » ou « précédent », nous cacherons ce diaporama automatique (qui se sera stoppé) pour découvrir nos slides contrôlables qui bougeront en fonction de l’élément ciblé.
Vous n’allez pas m’aimer… :

/* on cache le slider */
.sl_i:target ~ #slideshow .slider									{ visibility: hidden }
/* on planque la 1ère pastille (cf. bonux suivant) */
.sl_i:target ~ #slideshow .dots_commands li:first-child a:after		{ display:none; }
/* pour afficher la 2ème pastille (cf. bonux suivant) */
.sl_i:target ~ #slideshow .dots_commands li:first-child a:before	{ display:block; }
 
/* lorsque on cible le premier slider */
/* on cache tous les "précédent" et "suivant" */
#sl_i1:target ~ #slideshow .commands								{ display: none; }
/* on affiche seulement deux flèches */
#sl_i1:target ~ #slideshow .commands1								{ display: block; }
/* correspond au décalage des images */
#sl_i1:target ~ #slideshow .c_slider								{ background-position: 0 0, 640px 0, 1280px 0, 1920px 0; }
/* on place la pastille tout à gauche */
#sl_i1:target ~ #slideshow .dots_commands li:first-child a:before	{ left:0; }
 
/* même procédé lorsqu'on cible le second slide */
#sl_i2:target ~ #slideshow .commands								{ display: none; }
#sl_i2:target ~ #slideshow .commands2								{ display: block; }
#sl_i2:target ~ #slideshow .c_slider								{ background-position: -640px 0, 0 0, 640px 0, 1280px 0; }
#sl_i2:target ~ #slideshow .dots_commands li:first-child a:before	{ left:18px; }
 
/* puis le 3ème */
#sl_i3:target ~ #slideshow .commands								{ display: none; }
#sl_i3:target ~ #slideshow .commands3								{ display: block; }
#sl_i3:target ~ #slideshow .c_slider								{ background-position: -1280px 0, -640px 0, 0 0, 640px 0; }
#sl_i3:target ~ #slideshow .dots_commands li:first-child a:before	{ left:36px; }
 
/* et enfin le 4ème */
#sl_i4:target ~ #slideshow .commands								{ display: none; }
#sl_i4:target ~ #slideshow .commands4								{ display: block; }
#sl_i4:target ~ #slideshow .c_slider								{ background-position: -1920px 0, -1280px 0, -640px 0, 0 0; }
#sl_i4:target ~ #slideshow .dots_commands li:first-child a:before	{ left:54px; }

À chaque étape nous déplaçons les images, cachons tous les liens « précédent » et « suivant » sauf ceux dont on peut avoir besoin, et on déplace la petite pastille de la navigation secondaire (voir bonus qui suit).

Bonux : « pagination » pour sauter vers une slide

Vous avez certaine souvent vu ces petits points au pied d’un slideshow qui servent un peu de pagination et qui, parfois, permettent de savoir précisément où on se trouve dans le déroulement des slides.
Nous allons en créer une. Pour commencer, ajoutons ce code HTML juste après l’élément timeline

<ul class="dots_commands"><!--
	--><li><a title="Afficher la slide 1" href="#sl_i1">Slide 1</a></li><!--
	--><li><a title="Afficher la slide 2" href="#sl_i2">Slide 2</a></li><!--
	--><li><a title="Afficher la slide 3" href="#sl_i3">Slide 3</a></li><!--
	--><li><a title="Afficher la slide 4" href="#sl_i4">Slide 4</a></li>
</ul>

Puis, ces quelques lignes de CSS pour donner un style bien propre à nos petits points.
N’hésitez pas à agrandir les dimensions si ça vous semble trop petit.

.dots_commands  {
	padding:0;
	margin:32px 0 0;
	text-align: center;
}
.dots_commands li {
	display: inline;
	padding:0; margin:0;
}
.dots_commands a {
	position: relative;
	display: inline-block;
	height:8px; width: 8px;
	margin: 0 5px;
	text-indent: -9999px;
	background: #fff;
 
	border-radius: 50%;
	box-shadow: 0 1px 2px rgba(0,0,0,0.55) inset;
}
/* quelques styles au focus */
.dots_commands a:focus {
	outline: none;
	background: orange;
}
.dots_commands li:first-child a { z-index: 25; }

Rien de sorcier ici.
On s’assure simplement en dernière ligne que le premier élément ait un z-index supérieur aux autres. Nous allons nous en servir pour l’animation qui suit.

Nous allons créer un petit disque par dessus ces puces pour représenter le slide visible par un point d’une couleur différente. Pour ce faire nous utilisons les pseudo-éléments.

/* on style after et before, on utilisera les deux */
.dots_commands li:first-child a:after,
.dots_commands li:first-child a:before {
	position: absolute;
	top: 0; left: 0;
	content: " ";
	width: 8px; height: 8px;
	background: #bd9b83;
	z-index:20;
	border-radius: 50%;
	box-shadow: 0 1px 2px rgba(0,0,0,0.55) inset;
}
/* on anime "after" */
.dots_commands li:first-child a:after {
	animation: dotser 32s infinite;
}
/* on cache "before", on l'utilise uniquement au clic (cf. bonux précédent) */
.dots_commands li:first-child a:before { display:none; }
 
/* c'est parti pour l'animation ! */
@keyframes dotser {
	0%, 100% 	{ opacity: 1; left: 0; 		}
 
	20%			{ opacity: 1; left: 0;		}
	22%			{ opacity: 0; left: 0;		}
	23%			{ opacity: 0; left: 18px;	}
	25%			{ opacity: 1; left: 18px;	}
 
	45%			{ opacity: 1; left: 18px;	}
	47%			{ opacity: 0; left: 18px;	}
	48%			{ opacity: 0; left: 36px;	}
	50%			{ opacity: 1; left: 36px;	}
 
	70%			{ opacity: 1; left: 36px;	}
	72%			{ opacity: 0; left: 36px;	}
	73%			{ opacity: 0; left: 54px;	}
	75%			{ opacity: 1; left: 54px;	}
 
	95%			{ opacity: 1; left: 54px;	}
	97%			{ opacity: 0; left: 54px;	}
	98%			{ opacity: 0; left: 0;	}
}

Comme nous l’avons prévu dans notre bonus précédent, nous n’avons rien besoin de gérer en plus. Ces liens ciblent les mêmes éléments que nos flèches latérales et ont donc le même effet. (stop de l’animation et slide contrôlable avec tous les effets qui y sont liés)
L’animation peut sembler compliquée, mais c’est la logique de « disparition, déplacement, apparition » multiplié par 4 (4 étapes). Pour information, jusqu’à très récemment, Google Chrome avait du mal avec les animations sur before ou after. Je ne sais pas si ça a changé, il me semble.

Et on en restera là !

Démonstration

Pour être sûr que tout fonctionne, j’ai effectué un test en suivant ce tutoriel et en préfixant pour Firefox uniquement, voici le résultat : Slideshow Full CSS3.

Lors de la rédaction de ce tutoriel certains éléments comme les infobulles ou le vignettage animés ont été volontairement omis pour alléger le contenu. Si certaines portions de ce tutoriel restent pour vous un mystère à cause d’un manque d’explications, l’espace de commentaires est là pour vous :)

Analyse personnelle

Ce qui est bloquant est gourmand en lignes de code ici, c’est la volonté de vouloir fusionner système automatique et système contrôlable au clavier, souris ou même touché.

Ce slideshow date de novembre 2011, les techniques se sont multipliées, il existe d’autres solutions full CSS3 passant par l’utilisation détournée des éléments label et input de type radio. En contrôlant la valeur de la coche avec la pseudo-classe checked il est possible d’agir sur les éléments, de la même manière que nous le faisons ici avec la pseudo-classe target.

Je vous invite à regarder ce qui peut se faire ailleurs, comme par exemple sur ce Slideshow Full CSS3 Responsive.

L’espace de commentaires est à vous !

Le: 07 05 2012 à 00:00

Cela fait maintenant deux années que le blog Creative Juiz vous propose des articles sur les technologies du web et le web design. Cette activité aussi passionnante que chronophage a amené un certain nombre de discussions ici, sur Twitter, ou sur les autres réseaux sociaux.

C’est ce type d’interactions et de participations qui me donne envie de continuer à écrire et à partager avec vous. Ce sont ces discussions qui permettent de générer de nouvelles idées, d’améliorer celles existantes, et bannir les mauvaises pratiques.

J’ai rencontré des lecteurs du blog lors de la dernière conférence web KiwiParty. Cette brève rencontre m’a rassuré et encouragé (merci les gars) à continuer à écrire dans l’idée de contribuer – à ma manière – au web francophone (mais pas uniquement).

Quelques chiffres

Sans prétention aucune, et comme je l’ai fait l’an dernier, je vous donne quelques chiffres pour le fun :

Les chiffres précis :

  • 138 articles (1 article tous les 5 jours)
  • 722 commentaires (1 commentaire par jour)
  • 10 catégories d’articles (2 nouvelles dans l’année)

Les moins précis

  • 750 visites (650 uniques) quotidiennes
  • 47000 pages vues en moyenne par mois
  • plus de 230 mentions dans des blogs de référence (français, anglophones, chinois, japonais)
  • 5200ème blog Français (Alexa rank)
  • une centaine de contacts par e-mail
  • une vingtaine de corrections d’articles grâce aux intervenants (merci !)

À venir

J’en profite également pour annoncer une refonte complète du blog courant de l’année (oui c’est vague) qui aura pour objectifs principaux de revoir la navigation aux travers des différentes thématiques phares du blog, mais également d’optimiser l’interface et le chargement du blog sur les différents terminaux (mobiles, tablettes, mini-pc, pc, etc.)
La newsletter devrait également être mise plus en avant dans les mois à venir (les inscriptions sont ouvertes si ça vous dit, il suffit de compléter le formulaire dans la petite colonne latérale).
Bref, tout plein de choses qui vont arriver progressivement dans le but de vous offrir un contenu de bonne qualité, je l’espère.

N’hésitez donc pas à profiter de l’occasion pour critiquer les points qui semblent ne pas vous convenir sur ce blog.

Merci

Je vais avoir du mal à être aussi précis que l’an dernier dans mes remerciements, par peur d’avoir une liste trop longue de personnes à remercier, par peur également d’oublier des personnes, alors merci à tous pour vos commentaires, encouragements et contributions.

Merci à vous pour cette troisième année que nous entamons ensemble !

Le: 30 04 2012 à 00:00

WordPress possède un formulaire de commentaire adapté à la plupart des blogs. Cependant, comment s’y prendre si vous souhaitez ajouter ou supprimer des champs et personnaliser l’affichage des commentaires ?

WordPress prévoit la possibilité de personnaliser le formulaire de commentaire grâce à la fonction comment_form( $args, $post_id ), cette fonction est intéressante mais quelque peu limitée. Nous allons plutôt aborder quelques crochets (hooks) s’y rapprochant.

Concrètement, il faut procéder en trois étapes :

  • insérer ou supprimer un champ dans le formulaire
  • permettre l’insertion des données renseignées dans la base de données
  • afficher les nouvelles données dans les commentaires

Je vous invite à éditer votre fichier functions.php pour effectuer des tests avec les codes que je vais fournir.
Allez, c’parti !

Insérer et supprimer des champs dans le formulaire de commentaire

Cette première étape va utiliser le hook comment_form_defaults et se présente sous la forme d’une manipulation de tableau PHP.
Les champs sont enregistrés dans l’entrée « fields » du tableau et peuvent être manipulés assez simplement. Ils contiennent du code HTML que nous allons reproduire pour nos champs personnalisés.

add_filter( 'comment_form_defaults', 'juiz_manage_default_fields');
 
// $default contient tous les messages du formulaire de commentaire
// il contient également "comment_field", le textarea du message
 
if ( !function_exists('juiz_manage_default_fields')) {
   function juiz_manage_default_fields( $default ) {
 
      // Récupération des infos connues sur le visiteur
      // Permet de pré-remplir nos nouveaux champs
 
      $commenter = wp_get_current_commenter();
 
      // Suppression d'un champ par défaut parmi : author, email, url
 
      unset ( $default['fields']['url'] );
 
      // Ajout des champs dans le tableau "fields"
      // $commenter[] contient les infos sur le visiteur
 
      $default['fields']['job'] = '<p class="comment-form-author-job comment-form-author">
      <label for="job">'. __('Your job') . '</label>
      <span class="required">*</span>
      <input id="job" name="job" value="'.$commenter['comment_author_job'].'" aria-required="true" size="30" type="text" />
      </p>';
 
      $sel_female = $sel_male = '';
      if ( $commenter['comment_author_gender'] != '') ${'sel_'.$commenter['comment_author_gender']} = ' checked="checked"';
 
      $default['fields']['gender'] = '<p class="comment-form-author-gender">
      <span class="label_like">'. __('Your gender') . '</span>
      <label for="female">F</label> <input '. $sel_female .' id="female" name="gender" value="female" type="radio" />
      <label for="male">M</label> <input '. $sel_male .' id="male" name="gender" value="male" type="radio" />
      </p>';
 
      // On retourne le tableau des champs
 
      return $default;
   }
}

Quelques explications s’imposent :
Concernant le HTML produit, je copie et adapte la structure par défaut de mon thème sur les champs de formulaire (ici TwentyEleven) dans le but de limiter les modifications futures sur la CSS (d’où la copie de la classe comment-form-author sur comment-form-author-job).

Le tableau des champs (fields) ressemble à cela :

array(
   'author' => '<p class="comment-form-author">…',
   'email'  => '<p class="comment-form-email">…',
   'url'    => '<p class="comment-form-url">…'
);

Pour ajouter un champ il me suffit donc de faire (en remplaçant « slug » par quelque chose de pertinent) :

$default['fields']['slug'] = '<p class="comment-form-author-slug">…';

La ligne 12 récupère les cookies enregistrés lorsque qu’un commentaire est posté par un utilisateur. Ils n’existent donc pas lorsqu’un visiteur n’a jamais commenté sur votre blog, mais permettent ensuite de pré-remplir les champs (ligne 26 et 30) si l’utilisateur revient poster un commentaire.
Nous verrons plus loin comment nous enregistrons les cookies pour nos nouveaux champs de formulaire.

À noter : Il existe le hook comment_form_defaults_fields qui permet de manipuler directement les champs (ex : unset($default['url']). Cependant j’ai une légère préférence pour le hook comment_form_defaults car il permet d’atteindre d’autres éléments du formulaire.
Par contre, si votre objectif est de supprimer simplement le champ url par exemple :

add_filter('comment_form_default_fields','juiz_remove_url_field');
if ( !function_exists('juiz_remove_url_field')) {
   function juiz_remove_url_field( $fields ) {
      unset($fields['url']); return $fields;
   }
}

Enregistrer les données des champs personnalisés

Cette seconde étape se découpe en deux sous-étapes si certains de vos champs sont obligatoires.
Le premier hook utilisé est comment_post qui permet d’intervenir lorsque le commentaire a été enregistré.
Le second est preprocess_comment qui intervient avant l’enregistrement des données en base, notamment pour les contrôler.

Nous allons donc d’abord contrôler notre champ obligatoire ‘job’ pour retourner une erreur s’il est vide :

add_filter( 'preprocess_comment', 'juiz_verify_comment_data' );
if ( !function_exists('juiz_verify_comment_data') ) {
   function juiz_verify_comment_data( $commentdata ) {
 
      // si job est vide on affiche une erreur
      if ( ! isset( $_POST['job'] ) )
         wp_die( __( 'Error: please fill the required field (job).' ) );
 
      // si job dépasse 45 caractères (arbitraire) on affiche une erreur
      elseif ( isset( $_POST['job'] ) AND strlen ( $_POST['job'] ) > 45 )
         wp_die( __( 'Error: 45 maximum char. for "job" field.' ) );
 
      return $commentdata;
   }
}

Une fois la donnée obligatoire contrôlée, nous enregistrons les données du commentaire :

add_action( 'comment_post', 'juiz_save_comment_data' );
if ( !function_exists('juiz_save_comment_data') ) {
   function juiz_save_comment_data( $comment_id ) {
 
      // définition de la durée de vie des cookies
      $comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
 
      if (isset($_POST['job'])) {
 
         // on enregistre l'info en base de données
         add_comment_meta( $comment_id, 'job', esc_html( $_POST['job'] ) );
 
         // on enregistre un cookie
         setcookie('comment_author_job_' . COOKIEHASH, esc_html( $_POST['job'] ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
      }
 
      // on vérifie que le champ gender respecte les valeurs prévues
      if (isset($_POST['gender']) AND in_array ( $_POST['gender'] , array('male', 'female'))) {
         // même schéma que précédemment
         add_comment_meta( $comment_id, 'gender', esc_html($_POST['gender']) );
         setcookie('comment_author_gender_' . COOKIEHASH, esc_html( $_POST['gender']), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
      }
   }
}

Le cookie est optionnel mais il permet de reproduire le comportement de WordPress qui ajoute un cookie par champ du formulaire de commentaire pour se souvenir des données entrées par le visiteur.

En l’état, nous avons ajouté les infos en base de données, nous avons créé des cookies, et nous avons pris soin, dans l’étape précédente, de récupérer ces cookies grâce à la fonction wp_get_current_commenter(). Sauf qu’en fait cette fonction récupère uniquement les cookies pour les champs « classiques » (Nom, url, e-mail). Il faut donc compléter cette fonction pour l’inviter à piocher dans nos cookies fraichement créés :

add_filter('wp_get_current_commenter', 'juiz_add_custom_comment_cookies');
function juiz_add_custom_comment_cookies($cookies) {
 
	$comment_author_job = '';
	if ( isset($_COOKIE['comment_author_job_'.COOKIEHASH]) )
		$comment_author_job = $_COOKIE['comment_author_job_'.COOKIEHASH];
 
	$comment_author_gender = '';
	if ( isset($_COOKIE['comment_author_gender_'.COOKIEHASH]) )
		$comment_author_gender = $_COOKIE['comment_author_gender_'.COOKIEHASH];
 
 
	$cookies['comment_author_job'] = $comment_author_job;
	$cookies['comment_author_gender'] = $comment_author_gender;
 
	return $cookies;
}

La variable $cookies est un tableau associatif (clé + valeur), dont la clé est le nom du cookie (sans le _cookiehash) et la valeur est la valeur du cookie que l’on récupère s’il existe.

Maintenant il faut afficher ces informations dans notre liste de commentaire !

Afficher les données personnalisées dans la liste de commentaires

Cette dernière étape permet d’afficher les informations dans la liste de commentaires. Il existe un certain nombre de hooks qui permettent d’intervenir sur des zones précises d’un commentaire. Je vais en utiliser deux ici qui sont : get_comment_author_link et get_avatar.

Je souhaite afficher le job à côté du nom de l’auteur d’un commentaire.

add_filter( 'get_comment_author_link', 'juiz_attach_custom_info_to_comments_list' );
if ( !function_exists('juiz_attach_custom_info_to_comments_list') ) {
   function juiz_attach_custom_info_to_comments_list( $author ) {
 
      // on récupère l'info job
      $job = get_comment_meta( get_comment_ID(), 'job', true );
 
      // si l'info existe, on l'ajoute entre parenthèse après l'auteur
      if ( $job )
         $author .= ' (' . $job . ')';
 
      // on retourne l'info
      return $author;
   }
}

La variable $author contient le code HTML qui affiche le nom de l’auteur (avec ou sans lien vers son site). On ne fait donc que rajouter du contenu à la suite de cette chaine.
Cette technique a l’avantage d’ajouter l’information également dans le widget qui traite des derniers commentaires postés.

Pour afficher la valeur de gender, j’aurais très bien pu faire la même chose en ajoutant l’information à la suite après l’avoir récupérée avec get_comment_meta(). Mais comme j’aime bien me compliquer la vie, j’ai décidé d’ajouter une classe autour de l’avatar de l’utilisateur.

add_filter ( 'get_avatar', 'juiz_attach_custom_gender_to_avatar');
if ( !function_exists('juiz_attach_custom_gender_to_avatar') ) {
   function juiz_attach_custom_gender_to_avatar( $avatar ) {
 
      $gender = get_comment_meta( get_comment_ID(), 'gender', true );
      $gender = $gender ? $gender : 'undefined';
      $avatar = '<span class="gender ' . $gender . '">' . $avatar . '</span>';
 
      return $avatar;
   }
}

La variable $avatar contient le code HTML de l’avatar de l’utilisateur, une simple image par défaut. Ici on englobe l’avatar d’un élément span porteur du classe gender ainsi que d’une classe dynamique qui peut être male, female ou undefined en fonction de l’info que l’on récupère en base de données.

Le métier placé à côté du nom d'auteur, et l'avatar customisé avec un symbole en fonction du sexe.

Et voilà, c’est tout pour cette longue astuce, pour le reste c’est à vous d’imaginer.

Option bonux 1 : éditer un champ existant

En restant dans le premier hook (comment_form_defaults) il est possible d’éditer les champs existants en les manipulants avec des expressions régulières, ou en les réécrivant :

$default['fields']['author'] = '
   <p class="comment-form-author">
      <label for="author">'. __('Name') . '</label>
      <span class="required">*</span>
      <input id="author" name="author" value="'.$commenter['comment_author'].'" placeholder="Votre nom ou pseudo" aria-required="true" size="30" type="text" />
   </p>
';

Ici je rajouter un attribut placeholder par exemple.
Inutile de changer quoi que ce soit dans le traitement des données, WordPress le prévoit déjà.
Merci à Nicolas pour la suggestion.

Option bonux 2 : redirection après un commentaire

J’ai croisé dans le cœur de WordPress le hook comment_post_redirect qui permet de choisir la page de redirection lorsqu’un utilisateur a posté un commentaire.
Par défaut cette page redirige vers le commentaire de l’utilisateur avec une ancre.
Voici comment la fonction se présente :

add_action('comment_post_redirect', 'juiz_new_comment_redirection');
if ( !function_exists('juiz_new_comment_redirection') ) {
   function juiz_new_comment_redirection( $location ) {
      // valeur par défaut donnée par WordPress
      // à vous de personnaliser $location en fonction de vos besoins
      $location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
      return $location;
   }
}

Option bonux 3 : le code complet

Pour ceux qui ont peur d’avoir raté une étape :

// ajout physique d'un champ
add_filter( 'comment_form_defaults', 'juiz_manage_default_fields');
 
// $default contient tous les messages du formulaire de commentaire
// il contient également "comment_field", le textarea du message
if ( !function_exists('juiz_manage_default_fields')) {
	function juiz_manage_default_fields( $default ) {
 
		$commenter = wp_get_current_commenter();
 
		// Suppression d'un champ par défaut parmi : author, email, url
 
		//unset($default['fields']['url']);
 
		// Ajout des champs dans le tableau "fields"
 
		$default['fields']['job'] = '<p class="comment-form-job comment-form-author">
		<label for="job">'. __('Your job') . '</label>
		<span class="required">*</span>
		<input id="job" name="job" aria-required="true" size="30" type="text" value="' . esc_attr($commenter['comment_author_job']) . '" />
		</p>';
 
		$sel_female = $sel_male = '';
		if ( $commenter['comment_author_gender'] != '') ${'sel_' . $commenter['comment_author_gender']} = ' checked="checked"';
 
		$default['fields']['gender'] = '<p class="comment-form-gender">
		<span class="label_like">'. __('Your gender') . '</span>
		<label for="female">F</label> <input id="female" '. $sel_female .' name="gender" value="female" type="radio" />
		<label for="male">M</label> <input id="male" '. $sel_male .' name="gender" value="male" type="radio" />
		</p>';
 
		// On retourne le tableau des champs
 
		return $default;
	}
}
 
 
// controle des champs obligatoires à l'enregistrement
add_filter( 'preprocess_comment', 'juiz_verify_comment_data' );
if ( !function_exists('juiz_verify_comment_data') ) {
	function juiz_verify_comment_data( $commentdata ) {
 
		if ( ! isset( $_POST['job'] ) )
			wp_die( __( 'Error: please fill the required field (job).' ) );
		elseif ( isset( $_POST['job'] ) AND strlen ( $_POST['job'] ) > 45 )
			wp_die( __( 'Error: 45 maximum char. for "job" field.' ) );
 
		return $commentdata;
	}
}
 
//ajout en base de données des champs
add_action( 'comment_post', 'juiz_save_comment_data' );
if ( !function_exists('juiz_save_comment_data') ) {
	function juiz_save_comment_data( $comment_id ) {
 
		$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
 
		if (isset($_POST['job']) AND strlen ($_POST['job']) < 45) {
			add_comment_meta( $comment_id, 'job', esc_html( $_POST['job'] ) );
			setcookie('comment_author_job_' . COOKIEHASH, esc_html( $_POST['job'] ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
		}
 
		if (isset($_POST['gender']) AND in_array ( $_POST['gender'] , array('male', 'female'))) {
			add_comment_meta( $comment_id, 'gender', esc_html($_POST['gender']) );
			setcookie('comment_author_gender_' . COOKIEHASH, esc_html( $_POST['gender']), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
		}
	}
}
 
 
// pour que get_commenter retourne nos cookies custom
add_filter('wp_get_current_commenter', 'juiz_add_custom_comment_cookies');
function juiz_add_custom_comment_cookies($cookies) {
 
	$comment_author_job = '';
	if ( isset($_COOKIE['comment_author_job_'.COOKIEHASH]) )
		$comment_author_job = $_COOKIE['comment_author_job_'.COOKIEHASH];
 
	$comment_author_gender = '';
	if ( isset($_COOKIE['comment_author_gender_'.COOKIEHASH]) )
		$comment_author_gender = $_COOKIE['comment_author_gender_'.COOKIEHASH];
 
	$cookies['comment_author_job'] = $comment_author_job;
	$cookies['comment_author_gender'] = $comment_author_gender;
 
	return $cookies;
}
 
 
// afficher l'info job dans la liste des commentaires
add_filter( 'get_comment_author_link', 'juiz_attach_custom_info_to_comments_list' );
if ( !function_exists('juiz_attach_custom_info_to_comments_list') ) {
	function juiz_attach_custom_info_to_comments_list( $author ) {
 
		$job = get_comment_meta( get_comment_ID(), 'job', true );
		if ( $job )
			$author .= ' (' . $job . ')';
 
		return $author;
	}
}
 
// afficher l'info gender graphiquement pas loin de l'avatar
add_filter ( 'get_avatar', 'juiz_attach_custom_gender_to_avatar');
if ( !function_exists('juiz_attach_custom_gender_to_avatar') ) {
	function juiz_attach_custom_gender_to_avatar( $avatar ) {
 
		$gender = get_comment_meta( get_comment_ID(), 'gender', true );
		$gender = $gender ? $gender : 'undefined';
			$avatar = '<span class="gender ' . $gender . '">' . $avatar . '</span>';
 
		return $avatar;
	}
}
 
// redirection personnalisée après un post de commentaire
add_action('comment_post_redirect', 'juiz_new_comment_redirection');
if ( !function_exists('juiz_new_comment_redirection') ) {
	function juiz_new_comment_redirection( $location ) {
		$location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
		return $location;
	}
}

L’espace de commentaire et là pour vous ;)