
Créer un afficheur / masqueur de blocs
Vous êtes ici : Accueil / Articles / Formations en Javascript
Une page possède peu de place. Nous devons faire attention à bien l’agencer et la faire évoluer en fonction des attentes de l’utilisateur. Aussi, il est pratique de pouvoir masquer des éléments lorsque l’internaute ne pointe pas son curseur dessus.
Outre les problèmes de place, il se pose également la question de la focalisation : nous cherchons à transmettre un message est il est donc pour cela important de ne pas détourner l’attention de l’internaute par des éléments inutiles.
Voici pourquoi je vous propose maintenant de créer un afficheur/masqueur en javascript qui va faire évoluer la page de manière agréable par des fondus.
Il n’est pas nécessaire d’avoir une connaissance poussée de javascript pour le réaliser. La difficulté se pose plus du point de vue algorithmique : étant en situation de programmation événementielle, il faut prévoir le cas où l’utilisateur quitte l’élément alors qu’il n’a pas fini de s’afficher, ou inversement.
Prérequis : une fonction pour définir la transparence
Avant tout, nous avons besoin d’une fonction pour gérer la transparence. Comme l’opacité est implémentée sous forme de plusieurs propriétés CSS en fonction des navigateurs, nous avons besoin de créer une fonction javascript pour être compatible avec les principaux navigateurs.
Voici une fonction compatible avec Firefox, IE, Opéra et Safari.
Tools = {};
}
Tools.opacity = function( node, value ) {
node.style.filter='alpha(opacity='+(value*100)+')';
node.style.MozOpacity= value;
node.style.KhtmlOpacity = value;
node.style.opacity = value;
if( value == 1 ) {
node.style.filter = null;
node.style.MozOpacity = null;
node.style.KhtmlOpacity = null;
}
}
NB : La définition précédente présente la fonction opacity comme une méthode de l’objet Tools. L’utilisation d’un objet va nous permettre de pallier à un manque dans la syntaxe de javascript : les packages.
Une première version
Nous allons commencer par une première version simplifiée : on se contente d’afficher et de masquer l’objet en partant du principe que l’utilisateur va attendre que la transition soit terminée avant d’entamer une autre action. Cela va donc ôter les problèmes d’accès concurrents qui constitue l’essentiel de la difficulté de la programmation événementielle.
Les informations dont l’afficheur a besoin sont
l’objet qu’il affiche ou cache
sa direction d’affichage ( affiche ou cache )
sa valeur maximum et minimum de transparence
sa vitesse d’affichage
si au départ l’objet doit être affiché ou masqué
Voici donc la définition des propriétés :
this.node = node;
this.min = min;
this.max = max;
this.speed = speed;
this.value = shown ? max : min;
Tools.opacity( node, this.value );
}
Le code précédent permet de définir les propriétés de l’objet et d’initialiser l’affichage du bloc en fonction du flag show.
Nous allons devoirs fournir quelques méthodes pour manipuler l’objet
La méthode show() doit lancer l’affichage du bloc et hide() son masquage.
Nous sommes cependant confrontés au problème suivant : si nous effectuons une boucle pour modifier la transparence, l’affichage ne sera pas actualisé en temps réel. Le résultat sera donc l’affichage brusque du bloc sans passer sans une transition. Il est donc nécessaire d’avoir recours à la fonction setTimeout( code_javascript, delai )
La fonction setTimeout exécutera le code dans un thread parallèle et permettra donc à l’affichage de s’actualiser pendant ce temps.
L’utilisation de la fonction setTimeout pose une nouvelle contrainte : nous allons devoir créer une nouvelle méthode d’actualisation que nous nommerons update() et qui sera invoquée à intervalles réguliers jusqu’à ce qu’un des extrêmums soit atteint. Nous devons également savoir à se situe l’objet Displayer pour invoquer sa méthode update(). Nous allons donc la stocker dans un tableau et conserver sa position dans ce dernier :
// Initialisation des propriétés ( voir code précédent )
// Vérifie que le tableau est bien initialisé
if( !document.displayers ) {
document.displayers = new Array();
}
// Récupère l'index suivant du tableau et s'y ajoute
this.i = document.displayers.length;
document.displayers.push( this );
// Crée la fonction d'affichage
this.show = function() {
this.isShowing = true;
this.update();
}
// Crée la fonction de masquage
this.hide = function() {
this.isShowing = false;
this.update();
}
// Crée la fonction d'actualisation
this.update = function() {
// Modifie la transparence dans la direction indiquée
this.value += this.isShowing ? 0.05 : -0.05;
Tools.opacity( this.node, this.value );
// Si l'on n'a atteint aucun extremum
if( this.isShowing && this.value < this.max
|| !this.isShowing && this.value > this.min ) {
// Programme une actualisation
setTimeout( 'document.displayers[' + this.i + '].update()', this.speed );
}
}
}
Il ne reste qu’à l’utiliser :
onmouseover="DivDisplayer.show()"
onmouseout="DivDisplayer.hide()"
id="monDiv">
</div>
<script type="text/javascript">
var monDiv = document.getElementById( 'monDiv' );
var DivDisplayer = new Displayer( monDiv, 0, 1, 100, false );
</script>
Une version plus évoluée
La première version comporte déjà l’essentiel, mais un point important n’est pas traité. Si vous essayez de survoler l’objet puis de le quitter avant que celui-ci n’ait finit de s’afficher, le changement de direction s’effectuera, mais en revanche, la transition se fera 2x plus rapidement. Cette modification de vitesse s’explique par le lancement d’un nouveau Thread de transition alors qu’il en existe déjà un. Les 2 threads vont donc s’exécuter en parallèle, chacun modifiant la transparence dans le sens du flag isShowing. Il faut donc prendre en compte une nouvelle information : l’activation de la transition ou non : si celle-ci est déjà activée, il suffit de changer la direction. Si non, il faut définir la direction et lancer la transition.
Voici donc le code final prenant en compte les processus concurrents :
Tools = {};
}
Tools.opacity = function( node, value ) {
node.style.filter='alpha(opacity='+(value*100)+')';
node.style.MozOpacity= value;
node.style.KhtmlOpacity = value;
node.style.opacity = value;
if( value == 1 ) {
node.style.filter = null;
node.style.MozOpacity = null;
node.style.KhtmlOpacity = null;
}
}
function Displayer( node, min, max, speed, shown ) {
this.node = node;
this.min = min;
this.max = max;
this.speed = speed;
this.isMoving = false;
this.value = shown ? max : min;
Tools.opacity( node, this.value );
if( !document.displayers ) {
document.displayers = new Array();
}
// Récupère l'index suivant du tableau et s'y ajoute
this.i = document.displayers.length;
document.displayers.push( this );
// Crée la fonction d'affichage
this.show = function() {
this.isShowing = true;
this.start();
}
// Crée la fonction de masquage
this.hide = function() {
this.isShowing = false;
this.start();
}
// Lance un singleton transition
this.start = function() {
if( !this.isMoving ) {
this.isMoving = true;
this.update();
}
}
// Crée la fonction d'actualisation
this.update = function() {
// Modifie la transparence dans la direction indiquée
this.value += this.isShowing ? 0.05 : -0.05;
Tools.opacity( this.node, this.value );
// Si l'on n'a atteint aucun extremum
if( this.isShowing && this.value < this.max
|| !this.isShowing && this.value > this.min ) {
// Programme une actualisation
setTimeout( 'document.displayers[' + this.i + '].update()', this.speed );
}
else {
this.isMoving = false;
}
}
}



