Babylon Design

par Samuel Le Morvan

Chez vous aussi, utilisez un Web de qualité

Tutoriels jQuery

Devenez un professionnel de la programmatique Javascript grâce à la librairie la plus efficace du marché !

Tutoriels jQuery

Un système de notation par étoiles accessible

Faire un système de notation par étoiles, c’est vachement Web 2.0. Encore faut-il que celui-ci soit bien fait et accessible ! Voici un petit tutoriel sans prétention qui permettra de pouvoir utiliser un tel système.

Pour les impatients, comme d’ab, le lien direct :

Un système de notation par étoiles accessible

Capture écran du résultat

Tout d’abord, un peu de code HTML

<ul class="notes-echelle">
	<li>
		<label for="note01" title="Note&nbsp;: 1 sur 3">1</label>
		<input type="radio" name="notesA" id="note01" value="1" />
	</li>
	<li>
		<label for="note02" title="Note&nbsp;: 2 sur 3">2</label>
		<input type="radio" name="notesA" id="note02" value="2" />
	</li>
	<li>
		<label for="note03" title="Note&nbsp;: 3 sur 3">3</label>
		<input type="radio" name="notesA" id="note03" value="3" />
	</li>
</ul>

Que noter de particulier sur ce code HTML ?

  • Utiliser des vrais champs de formulaires, des checkboxes en l’occurrence, afin de permettre sa lecture aux synthèse vocales (entre autre via un listage des champs de formulaires).
  • Utiliser une information textuelle et visuelle avec des chiffres pour indiquer les notes. Si les images sont désactivées, il faut que les notes soient toujours identifiables. Aussi cela sert à tout le monde pour se repérer dans le cas d’une notation fine, par exemple, dans une notation de 1 à 30, sans chiffres il serait difficile d’attribuer à coups sûr la note de 12.
  • Relier les étiquettes aux champs de formlaires. Utiliser des label reliés à des input via les attributs for et id pour les synthèses vocales d’une part et d’autre part pour avoir la possibilité de cliquer sur l’étiquette pour cocher le bouton radio.
  • Expliciter les étiquettes. Un title sur les label pour expliciter au mieux les notes, notamment en précisant sur combien la notation est possible. Si l’on navigue avec une synthèse vocale et qu’il n’y a pas de title explicites, on ne sait qu’au dernier chiffre la notation maximum.

Un peu de CSS aussi

En premier lieu, nous allons créer une mise en page comme si il n’y avait pas de Javascript de prévu par la suite. En effet, le Javascript doit toujours être un surcouche non obligatoire au bon fonctionnement.

Pour l’image de l’étoile, j’utilise un sprite CSS avec l’état inactif et actif. Les deux états sont séparés d’un espace vide sur l’image afin de permettre un grossissement de polices honorable.

Sprite des étoiles

Pour ce qui est du code CSS, ce n’est pas très compliqué :

ul.notes-echelle {
	margin:0;
	padding:0;
	font:.75em/1.2 Arial, Helvetica, sans-serif;
}
ul.notes-echelle li {
	float:left;
	margin:0;
	padding:0;
	list-style:none;
	min-width:20px;
	min-height:20px;
}
/* Correctif IE6 sur min-width & min-height */
* html ul.notes-echelle.js li {
	width:20px;
	height:20px;
}
ul.notes-echelle li label {
	display:block;
	text-align:center;
	line-height:20px;
	background:url(etoiles.gif) center top no-repeat;
	cursor:pointer;
}

Voici le résultat obtenu :

Capture écran du résultat sans Javascript

L’effet de jauge à la souris

En Javascript cette fois, nous allons donner ce fameux effet Web 2.0 de survol à la souris.

Nous avons donc besoin de prévoir en CSS l’état inactif. Pour cela nous allons créer une nouvelle classe CSS qui déplacera la position du sprite sur l’image de l’étoile inactive.

ul.notes-echelle li.note-off label {
	background-position:center -60px;
}

Ensuite, le code jQuery est expliqué dans les commentaires :

// Lorsque le DOM est chargé on applique le Javascript $(document).ready(function() {
	// On ajoute la classe "js" à la liste pour mettre en place par la suite du code CSS uniquement dans le cas où le Javascript est activé
	$("ul.notes-echelle").addClass("js");
	// On passe chaque note à l'état grisé par défaut
	$("ul.notes-echelle li").addClass("note-off");
	// Au survol de chaque note à la souris
	$("ul.notes-echelle li").mouseover(function() {
		// On passe les notes supérieures à l'état inactif (par défaut)
		$(this).nextAll("li").addClass("note-off");
		// On passe les notes inférieures à l'état actif
		$(this).prevAll("li").removeClass("note-off");
		// On passe la note survolée à l'état actif (par défaut)
		$(this).removeClass("note-off");
	});
	// Lorsque l'on sort du sytème de notation à la souris
	$("ul.notes-echelle").mouseout(function() {
		// On passe toutes les notes à l'état inactif
		$(this).children("li").addClass("note-off");
		// On simule (trigger) un mouseover sur la note cochée s'il y a lieu
		$(this).find("li input:checked").parent("li").trigger("mouseover");
	});
});

Effet de jauge à la souris

L’effet de jauge au clavier

Il faut bien sûr avoir le même rendu si l’on souhaite renseigner le formulaire au clavier. Pour cela, il faut agir directement sur les boutons radios.

$("ul.notes-echelle input")
	// Lorsque le focus est sur un bouton radio
	.focus(function() {
		// On passe les notes supérieures à l'état inactif (par défaut)
		$(this).parent("li").nextAll("li").addClass("note-off");
		// On passe les notes inférieures à l'état actif
		$(this).parent("li").prevAll("li").removeClass("note-off");
		// On passe la note du focus à l'état actif (par défaut)
		$(this).parent("li").removeClass("note-off");
	})
	// Lorsque l'on sort du sytème de notation au clavier
	.blur(function() {
		// Si il n'y a pas de case cochée
		if($(this).parents("ul.notes-echelle").find("li input:checked").length == 0) {
			// On passe toutes les notes à l'état inactif
			$(this).parents("ul.notes-echelle").find("li").addClass("note-off");
		}
	});

Cacher les boutons radios…

…de manière accessible

Ou comment les cacher visuellement sans les rendre invisibles aux synthèses vocales grâce au CSS.

Il faut éviter les règles CSS visibility:hidden ou display:none et préférer un positionnement hors de l’écran avec la méthode bien connue du position:absolute. Pour appliquer ce style, nous allons nous servir de notre classe CSS « js » qui s’applique uniquement lorsque le Javascript est activé :

ul.notes-echelle.js input {
	position:absolute;
	left:-999%;
}

…et sans perdre d’information

Hé oui ! Si on restait là, un utilisateur qui aurait les images désactivées n’aurait pas d’informations visuelles sur le positionnement de son focus ni des notes cochées.

Exemple de cas, voici une capture pour un tel utilisateur lorsqu’il a coché la note 4 :

Capture écran du problème dans le cas où seules les images sont désactivées

Pas très parlant n’est-ce pas !

Pour éviter ce problème, il faut aussi afficher un focus sur les chiffres lors d’une navigation au clavier et indiquer autrement que par l’image que la case est cochée. Ainsi, on peut indiquer la note cochée en gras car cela à un impact visuel sans utiliser d’image. De même, le focus sur la note peut être indiqué classiquement par une bordure en pointillés.

/* Effet lorsque une note est cochée */
 ul.notes-echelle li.note-checked {
	font-weight:bold;
}
/* Effet lorsque une note est tabulée au clavier */
 ul.notes-echelle.js li.note-focus {
	outline:1px dotted #000;
}

En Javascript, nous allons donc également placer/supprimer ces classes aux bons moments :

$("ul.notes-echelle input")
	// Lorsque le focus est sur un bouton radio
	.focus(function() {
		// On supprime les classes de focus
		$(this).parents("ul.notes-echelle").find("li").removeClass("note-focus");
		// On applique la classe de focus sur l'item tabulé
		$(this).parent("li").addClass("note-focus");
		// [...] cf. code précédent
	})
	// Lorsque l'on sort du sytème de notation au clavier
	.blur(function() {
		// On supprime les classes de focus
		$(this).parents("ul.notes-echelle").find("li").removeClass("note-focus");
		// [...] cf. code précédent
	})
	// Lorsque la note est cochée
	.click(function() {
		// On supprime les classes de note cochée
		$(this).parents("ul.notes-echelle").find("li").removeClass("note-checked");
		// On applique la classe de note cochée sur l'item choisi
		$(this).parent("li").addClass("note-checked");
	});

Ci-dessous, on voit que grâce au code ajouté la note choisie est visible et le focus aussi.

Capture écran de la solution dans le cas où seules les images sont désactivées

Appliquer l’effet au notes déjà cochées

Le système fonctionne mais il ne faut pas oublier d’appliquer de style de jauge sur les boutons radios cochés par défaut lors du chargement de la page.

// On simule un survol souris des boutons cochés par défaut
$("ul.notes-echelle input:checked").parent("li").trigger("mouseover");
// On simule un click souris des boutons cochés
$("ul.notes-echelle input:checked").trigger("click");

Et voilà le résultat final :

Résultat final

N’attendons plus, jetons un coup d’œil à la démo :

Un système de notation par étoiles accessible


Ce que nos lecteurs en disent :

  1. Bouctoubou

    Sympa comme tuto! Et la démo est classe! :)

  2. Vincent Valentin

    Belle performance, c’est chouette.

    Ce qui m’ennuie le plus ce sont les numéros en superposition des étoiles… je sens que dans la pratique, personne ne va en vouloir.

    Pour s’en dispenser il faudrait revoir sans doute toute la technique en insérer directement dans le HTML les images des étoiles.

  3. STPo

    Je viens de tester ton code, c’est chouette : bravo !
    +1 pour la remarque de Vincent au passage.

  4. CUT HERE

    Très bon tuto, merci

  5. bruno bichet

    Excellent, j’ai toujours été réticent à mettre en place un tel système de notation pour mes billets, mais là, rien que pour le plaisir, ça vaudrait la peine ;) Merci !

  6. Jeux

    Malgré la complexité du sujet, votre article a le mérite d’être clair et accessible. Très bon article et bonne continuation pour la suite.

  7. 0x1gene

    tuto d’une grande qualité ! les explications sont claires et le code bien commenté ! on pourrait peut être proposer une ouverture pour stocker les notes sur une base de donnée, en vérifiant l’ip(pour empêcher le double vote) et afficher ensuite la valeur par défaut comme moyenne des notes enregistrés…

Les commentaires sont clos.