formateur informatique

Traitements récursifs optimisés en Javascript

Accueil  >  Technique  >  Javascript  >  Javascript Débutant  >  Traitements récursifs optimisés en Javascript
Livres à télécharger


Pour partager cette vidéo sur les réseaux sociaux, voici son url absolue :

Pour l'intégrer sur votre site internet ou blog, vous pouvez l'embarquer :

Sujets et formations similaires :


Les boucles de traitement en Javascript

Dans ce quatrième volet des formations Javascript, nous proposons de monter une petite application à partir de laquelle l'utilisateur aura la possibilité de personnaliser son environnement. Concrètement, sur la page d'accueil d'un site, des carreaux de couleur lui sont proposés. Un clic sur l'un d'entre eux modifie globalement l'aspect de la page en adaptant la couleur des calques à celle choisie.



Préférences et personnalisations de couleur internaute sur page Web réglées par code Javascript

Ces calques matérialisés par les rubriques cliquables sur la capture du dessus peuvent être nombreux et évolutifs. C'est la raison pour laquelle il paraît absurde de coder une instruction par élément à adapter. D'une part le code serait trop lourd et d'autre part il ne serait pas capable de s'adapter si d'aventure, des rubriques étaient ajoutées ou supprimées.

Le Javascript comme tout langage de programmation propose les boucles qui permettent de réaliser des traitements récursifs. En passant en revue chacun des objets dans une instruction itérative, nous améliorons la performance du code mais aussi la clarté de sa structure. Et surtout, nous remplaçons une multitude de lignes statiques par un petit bloc d'instruction dynamique et évolutif.

Structure de la page Html
Pour concentrer nos travaux sur le code Javascript, nous proposons de récupérer une page Web préconçue avec toutes ses ressources externes. Quelques fichiers Html apparaissent à la racine. Il s'agit des pages Web liées par la page principale, celle de l'accueil. Vous notez aussi la présence de deux sous dossiers dans lesquels sont stockées les ressources telles que les images et feuille de styles, pour la mise en forme et la mise en page.
  • Ouvrir le fichier traitements_recursifs.html avec un navigateur tel que Firefox,
Comme vous le constatez, il s'agit de la page d'accueil à partir de laquelle nous allons travailler. La structure Html est prête ainsi d'ailleurs que les effets de styles, régis par la feuille de styles mef.css située dans le sous dossier Styles.

Page Web avec effets ombre au survol de la souris par les styles CSS

Cette page Web propose quatre cadres de couleurs représentant des rubriques du site Web. Au survol de la souris sur ces calques, vous remarquez un effet d'ombre portée apparaître. Il en va d'ailleurs de même pour la petite barre verticale en haut à gauche, schématisant des carreaux de couleur.
  • Depuis l'explorateur Windows, ouvrir le fichier traitements_recursifs.html avecun éditeur tel que le Notepad++,
  • Toujours depuis l'explorateur Windows, accéder au sous dossier styles,
  • Puis, ouvrir le fichier mef.css avec le même éditeur,
  • Dans l'éditeur, afficher le contenu du fichier traitements_recursifs.html,
Première remarque, dans la section head, vous notez la référence à la feuille de styles par cette ligne de code Html :

<link href='styles/mef.css' rel='stylesheet' type='text/css' />

C'est la raison pour laquelle, tout style de mise en forme défini dans cette feuille s'applique aux éléments de la page Html qui en font référence.

Entre les lignes 23 à 29 pour un éditeur Notepad, figurent les liens de la construction de la petite barre des carreaux de couleur.

<div style='position:absolute; width:50px; height:auto; border:#666666 1px solid; z-index:100; top:100px; box-shadow: 6px 6px 0px #aaa;'>
<div class='carre_couleur' style='background-color:#c00000;'></div>
<div class='carre_couleur' style='background-color:#9dc3e6;'></div>
<div class='carre_couleur' style='background-color:#a9d18e;'></div>
<div class='carre_couleur' style='background-color:#f4b183;'></div>
<div class='carre_couleur' style='background-color:#bfbfbf;'></div>
</div>


Chacun de ces cinq calques propose une couleur de fond différente, définie par son attribut style (style='background-color:#c00000;'). Le reste de leur mise en forme est dictée par le style carre_couleur de la feuille de styles et appelé par l'attribut class. C'est lui qui se charge des dimensions et des positionnements.

Plus loin, entre les lignes 50 et 55 pour un éditeur Notepad, figure la structure des rubriques agencées elles aussi, sous forme de calques, comme il est de coutume sur le Web.

<div style='width:800px;display:inline-block;' id='conteneur'>
<div class='rubrique' id='rub1'><img src='images/app.png' /><br /><a href='applications.html' target='_self'>Nos applications</a></div>
<div class='rubrique' id='rub2'><img src='images/jeux.png' /><br /><a href='jeux.html' target='_self'>Nos jeux</a></div>
<div class='rubrique' id='rub3'><img src='images/musique.png' /><br /><a href='musique.html' target='_self'>Nos albums</a></div>
<div class='rubrique' id='rub4'><img src='images/livres.png' /><br /><a href='livres.html' target='_self'>Nos livres</a></div>
</div>


Chacun de ces calques renferme une image (balise img) contenue dans le sous dossier images. Il s'agit d'une représentation de la rubrique. Vous notez de même la présence de la balise pour les liens en dur (<a href...) qui permet de diriger vers les rubriques annoncées. Chacun de ces calques possède un identifiant unique grâce à l'attribut id (id='rub1'). Ces identifiants sont indispensables pour pouvoir piloter ces éléments par le code car, souvenez-vous, l'objectif est de modifier leur couleur de fond en fonction des préférences de l'internaute. Enfin notez la présence pour chacun, de la référence au style issu de la feuille de styles, grâce à l'attribut class. Vous êtes désormais positionné sur le style auquel les calques des rubriques font références. .rubrique

{
float:left;
width:350px;
height:150px;
margin:21px;
background-color:#954eca;
border:#666666 1px solid;
box-shadow: 6px 6px 0px #aaa;
color:#EDEEEE;
font-size:20px;
font-weight:bold;
}

On y trouve les propriétés Html permettant de définir la couleur de fond par défaut, la couleur de police ainsi que sa taille, les dimensions du calque etc...

Comme l'avait mis en valeur la formation Javascript précédente sur la gestion des événements par le code, tout ce qui peut être réalisé en CSS plutôt qu'en Javascript doit l'être. C'est la raison pour laquelle figure juste en-dessous, le style dérivé : .rubrique:hover.

.rubrique:hover
{
box-shadow: 12px 12px 0px #666;
cursor:pointer;
}


L'attribut hover permet de déclencher des effets de mise en forme spécifique sur l'événement détecté du survol de la zone, soit de l'élément auquel le style est appliqué, donc le calque. La propriété box-shadow permet donc d'enclencher une ombre portée, selon des distances et couleur définies en paramètre. Ce même effet est présent pour le style appliqué aux calques des carreaux de couleurs avec des distances plus petites, pour un effet plus léger.



Ouvrir un lien au clic sur un calque en Javascript
Maintenant que les présentations sont faites, il est temps de passer au code. Sur la page d'accueil dans le navigateur internet, si vous cliquez précisément sur le nom d'une rubrique, vous constatez que la page liée s'ouvre en lieu et place. Vous pouvez revenir sur cette dernière en cliquant sur le logo vert situé en haut à gauche du site. Mais si vous cliquez partout ailleurs sur le calque de la rubrique, son icône par exemple, rien ne se produit. Seul le texte est en effet encadré par la balise a href dont nous avons parlé plus haut pour les liens en dur, ce qui est tout à fait logique.

Nous souhaitons donc obtenir le même résultat partout sur le calque de la rubrique, pour conduire à la page liée. Nous devons générer un événement onClick, comme nous l'avons appris dans la formation précédente et exploiter le code Javascript pour conduire à l'url. C'est l'événement open de l'objet window qui permet en Javascript de désigner une adresse de destination. La syntaxe est la suivante :window.open(‘url', target='mode_ouverture').
  • Dans l'éditeur de code, basculer sur le fichier traitements_recursifs.html,
  • En ligne 51, pour le premier div (rub1), ajouter l'événement onClick comme suit :
onClick='Javascript:window.open('applications.html', target='_self');'

Sur l'événement du clic sur le calque, nous déclenchons un code Javascript (Javascript:). En premier paramètre de la méthode open pour l'objet window, nous désignons l'url à atteindre. Comme la page en question se situe elle aussi à la racine, le nom du fichier suffit. En deuxième paramètre nous indiquons de l'ouvrir en lieu et place, soit dans le même onglet et non dans une nouvelle page. Il s'agit d'ailleurs de la propriété par défaut si nous ne l'avions pas spécifiée. Mais comme nous sommes puristes, nous renseignons tous les arguments de la méthode.
  • De la même façon, pour les trois autres calques (rub2, rub3 et rub 4), créer l'événement onClick permettant de rediriger vers l'url référencée par sa balise a href,
<div style='width:800px;display:inline-block;' id='conteneur'>
<div class='rubrique' id='rub1' onClick='Javascript:window.open('applications.html', target='_self');'><img src='images/app.png'/><br /><a href='applications.html' target='_self'>Nos applications</a></div>
<div class='rubrique' id='rub2' onClick='Javascript:window.open('jeux.html', target='_self');'><img src='images/jeux.png'/><br /><a href='jeux.html' target='_self'>Nos jeux</a></div>
<div class='rubrique' id='rub3' onClick='Javascript:window.open('musique.html', target='_self');'><img src='images/musique.png'/><br /><a href='musique.html' target='_self'>Nos albums</a></div>
<div class='rubrique' id='rub4' onClick='Javascript:window.open('livres.html', target='_self');'><img src='images/livres.png'/><br /><a href='livres.html' target='_self'>Nos livres</a></div>
</div>
  • Enregistrer les modifications et basculer sur le navigateur,
  • Rafraîchir la page à l'aide de la touche F5 du clavier,
  • Puis, cliquer sur l'une des rubriques, en dehors du texte, par exemple sur l'icône,
Redirection Javascript vers url sur événement du clic internaute sur élément Html

Comme vous le constatez, chaque clic conduit vers sa rubrique, comme si nous avions cliqué directement sur le texte. Certes ces pages sont vierges car elles servent de relai à titre d'essai. Pensez à l'icône verte en haut du site pour revenir sur la page d'accueil. Il est important de savoir qu'un lien Javascript n'est pas suivi par les robots d'indexation. En conséquence, il n'est pas retenu pour le référencement naturel. C'est pourquoi il est important de doubler ces destinations avec des liens en dur, comme nous l'avons fait avec les balises a href. Quoiqu'il en soit, le résultat est plus satisfaisant et ergonomique pour l'internaute. Et nous avons bien réussi à rediriger l'utilisateur vers de nouvelles pages en Javascript sur événement.

Traitements itératifs - Les boucles en Javascript
Désormais nous devons nous occuper de la fonctionnalité principale de cette page d'accueil, destinée à l'internaute. Un clic sur un petit carreau de couleur doit permettre d'adapter les couleurs globales de la page, selon les préférences ainsi émises. Plus précisément, il s'agit d'adapter les couleurs des calques des rubriques. Ce traitement doit englober tous les calques à la fois, par esprit d'optimisation et de productivité. Ce sont les boucles en programmation qui permettent de réaliser des traitements similaires, autant de fois qu'il est nécessaire (4 fois ici pour 4 calques). Le résultat permet en outre d'optimiser le code et d'en simplifier la lecture.

Pour ce faire, nous proposons de créer une fonction Javascript qui sera appelée au clic sur chacun des carreaux de couleur. Et pour cela, nous devons commencer par créer la section du script en bas de la page Html.
  • Entre les balises body et html fermantes, ajouter la section de script, comme suit :
...</body>
<script type='text/javascript' language='javascript'>

</script>

</html>
  • Dans la section du script, déclarer la fonction mef comme suit :
function mef(couleur)
{
}


Pour réaliser son traitement qui consiste à changer l'arrière-plan des calques des rubriques, cette fonction a nécessairement besoin de connaître la couleur à appliquer. C'est la raison pour laquelle, nous lui attribuons un paramètre (couleur) qui lui sera fourni lors de l'appel par clic sur les petits carreaux de couleur.

La boucle for permet de réaliser des traitements récursifs en fonction d'une variable incrémentée, entre une borne inférieure et une borne supérieure. Cela sous-entend donc que ces bornes sont connues et fixes. Sa syntaxe est la suivante :

for(variable=0 ;variable=4 ;variable++)
{
Traitements
}


Cette boucle réalise 5 traitements. Elle part d'une borne inférieure définie à 0 (variable=0) jusqu'à une borne supérieure définie à 4 (variable=4), en étant incrémentée à chaque passage (variable++). Les deux symboles + consécutifs signifient l'incrémentation en Javascript, tout comme en Php ou en C#. L'expression variable++ est équivalente à l'expression : variable = variable + 1.
  • Dans les bornes de la fonction, ajouter le code Javascript suivant :
var indice;

for (indice=1;indice<=4;indice++)
{
document.getElementById('rub' + indice).style.backgroundColor = couleur;
}


Nous prenons soin d'abord de déclarer la variable que nous allons exploiter pour l'incrémentation de la boucle (var indice;). Puis, nous réalisons un traitement sur quatre passages en partant de 1 (indice=1) pour aller jusqu'à 4 (indice<=4). Il y a en effet quatre rubriques matérialisées par quatre calques possédant un identifiant similaire mais incrémenté (rub1, rub2 etc...). A chaque passage dans la boucle, nous accédons donc au calque désigné par l'indice en cours, grâce comme toujours à la méthode getElementById de l'objet document (getElementById('rub' + indice)). Et pour chacun d'entre eux, nous déroulons les propriétés (style.backgroundColor=couleur) afin d'appliquer la valeur de la couleur à leur arrière-plan.

Le code est déjà terminé. Quelques lignes suffisent pour réaliser un traitement récursif. Ici quatre calques Html sont concernés. S'il y en avait 1000, il n'y aurait pas plus de lignes d'instructions. Il suffirait de remplacer le chiffre 4 par le nombre 1000 dans la boucle for. C'est tout l'intérêt des boucles d'instruction en programmation.

Néanmoins, pour s'exécuter, cette fonction doit être appelée avec le paramètre approprié. Comme nous l'avons appris lors de la formation précédente, nous allons générer un événement onClick pour chaque div matérialisant les carreaux de couleur. Cet événement aura pour mission de déclencher un code Javascript appelant cette fonction en lui passant la valeur de la couleur du carreau en question.
  • Entre les lignes 24 et 28 pour un éditeur Notepad, ajouter l'événement onClick pour chaque calque concerné, comme suit :
<div style='position:absolute; width:50px; height:auto; border:#666666 1px solid; z-index:100; top:100px; box-shadow: 6px 6px 0px #aaa;'>
<div class='carre_couleur' style='background-color:#c00000;' onClick='mef('#c00000')'></div>
<div class='carre_couleur' style='background-color:#9dc3e6;' onClick='mef('#9dc3e6')'></div>
<div class='carre_couleur' style='background-color:#a9d18e;' onClick='mef('#a9d18e')'></div>
<div class='carre_couleur' style='background-color:#f4b183;' onClick='mef('#f4b183')'></div>
<div class='carre_couleur' style='background-color:#bfbfbf;' onClick='mef('#bfbfbf')'></div>
</div>


Il faut bien penser à adapter la couleur du carreau dans l'appel. Notez que le paramètre est encadré de côtes. Il est en effet considéré comme une valeur de type texte.
  • Enregistrer les modifications, basculer sur le navigateur et rafraîchir la page (F5),
  • Cliquer tour à tour sur les carreaux de couleur de la petite barre d'outils en haut à gauche,
Appliquer couleur à la page Html sur événement du clic intercepté par code Javascript

Instantanément, tous les arrière-plans des rubriques s'adaptent au choix réalisé par le clic. La couleur du carreau est répliquée de façon récursive sur l'ensemble des calques traités par la boucle de traitement.

Outre la boucle for, il existe la boucle while en Javascript. Les bornes de cette dernière ne sont pas définies par des valeurs fixes mais par un critère. Cela signifie que son traitement se poursuit tant que le critère est vérifié. Sa syntaxe est la suivante :

while(critere)
{
traitements
}


Dans notre cas, le critère consiste à vérifier que la valeur de la variable indice n'a pas atteint 4. Car au-delà de cet indice, il n'y a plus de calque. La variable indice doit donc être initialisée avant la boucle et incrémentée à chaque passage dans cette dernière. /*for (indice=1;indice<=4;indice++)
{
document.getElementById('rub' + indice).style.backgroundColor = couleur; }*/
  • Puis, à la suite du code, ajouter la boucle while comme suit :
indice = 1;
while(indice<5)
{
document.getElementById('rub' + indice).style.backgroundColor = couleur;
indice++;
}


Nous n'oublions pas d'initialiser la variable (indice = 1) avant de l'exploiter comme critère de la boucle while. Puis nous initialisons une boucle while sur quatre passages puisque le critère de la boucle est une inégalité stricte. Nous aurions aussi pu écrire :indice<=4. Le traitement reste le même afin d'adapter la couleur de fond des calques concernés. Mais surtout, il est impératif d'incrémenter la variable de la boucle avant de borner (indice++). Sinon sa valeur reste figée, le test est toujours vérifié et on tombe dans ce que l'on appelle on boucle infinie. Son traitement ne s'arrête jamais et emprunte énormément de ressources machine.
  • Enregistrer les modifications, basculer sur le navigateur et rafraîchir la page (F5),
  • Cliquer tour à tour sur les carreaux de couleur de la petite barre d'outils en haut à gauche,
Le résultat est le même mais il est intéressant de savoir que la boucle while peut être exploitée pour réaliser des traitements récursifs selon un critère à vérifier qui ne sera pas forcément numérique. Il peut s'agir d'un contexte d'application par exemple.



Traitements récursifs dynamiques et évolutifs
Le code que nous venons de réaliser est satisfaisant mais néanmoins limité. Son traitement est statique dans la mesure où il considère des bornes fixes. En d'autres termes, il traite une page constituée de quatre calques, ni plus ni moins. Mais si cette dernière venait à évoluer parce que de nouvelles rubriques venaient de voir le jour, il ne les traiterait pas. C'est ce que nous allons vérifier.
  • Dans le bloc Html des rubriques, ajouter à la suite celle des films et des vêtements, comme suit :
<div style='width:800px;display:inline-block;' id='conteneur'>
<div class='rubrique' id='rub1' onClick='Javascript:window.open('applications.html', target='_self');'><img src='images/app.png' /><br/><a href='applications.html' target='_self'>Nos applications</a></div>
<div class='rubrique' id='rub2' onClick='Javascript:window.open('jeux.html', target='_self');'><img src='images/jeux.png' /><br/><a href='jeux.html' target='_self'>Nos jeux</a></div>
<div class='rubrique' id='rub3' onClick='Javascript:window.open('musique.html', target='_self');'><img src='images/musique.png'/><br /><a href='musique.html' target='_self'>Nos albums</a></div>
<div class='rubrique' id='rub4' onClick='Javascript:window.open('livres.html', target='_self');'><img src='images/livres.png' /><br/><a href='livres.html' target='_self'>Nos livres</a></div>
<div class='rubrique' id='rub5' onClick='Javascript:window.open('films.html', target='_self');'><img src='images/films.png' /><br /><a href='films.html' target='_self'>Nos films</a></div>
<div class='rubrique' id='rub6' onClick='Javascript:window.open('vetements.html', target='_self');'><img src='images/vetements.png' /><br /><a href='vetements.html' target='_self'>Nos vêtements</a></div>

</div>


Les pages liées (vetements.html et films.html) se situent à la racine comme les autres. Les images quant à elles (films.png et vetements.png) se trouvent dans le sous dossier images.
  • Enregistrer les modifications, basculer sur le navigateur et rafraîchir la page,
  • Cliquer tour à tour sur les icônes de couleur pour modifier l'apprence,
Boucles de traitement Javascript aux bornes fixes omettant des éléments Html à traiter

C'est une confirmation, les deux nouveaux calques matérialisant les deux nouvelles rubriques ne sont pas considérés par le traitement des boucles Javascript.

Ce dont nous avons besoin, c'est d'une boucle for each, soit d'une boucle capable de traiter tous les éléments enfants d'un élément parent et ce, quel que soit leur nombre, même s'il venait à évoluer. En d'autres termes, le code Javascript doit être en mesure de traiter tous les calques enfants (rub1, rub2 etc...) du calque parent dont l'identifiant est conteneur. Mais la boucle for each n'existe pas en Javascript. Cependant, nous pouvons la simuler.

Pour ce faire, nous allons créer une variable objet représentant le calque parent. Grâce à cet objet, nous allons pouvoir créer une variable objet héritée représentant tous les calques enfants qu'il contient. Cette variable se transformera naturellement en tableau de variables.
  • Revenir dans l'éditeur de code de la page Html,
  • Passer les instructions de la boucle while en commentaires,
  • Puis, à la suite du code, ajouter les deux déclarations suivantes :
var parent = document.getElementById('conteneur');
var enfants = parent.getElementsByTagName('div');


L'objet parent pointe ainsi sur le calque conteneur grâce à la méthode getElementById de l'objet document. La méthode getElementsByTagName de l'objet ainsi créé permet de récupérer tous les éléments enfants dont le nom de la balise est passé en paramètre (div). Nous pourrions tout aussi bien ne traiter que les images en passant le paramètre img. Cette affectation est réalisée dans la variable enfants qui connaît désormais le nombre dynamique de div contenus dans le calque parent. Et à ce titre, elle propose la propriété length qui renvoie ce nombre. Il suffit donc de boucler sur ce nombre pour parcourir tous les calques et ainsi modifier leur aspect.
  • A la suite du code, ajouter la boucle for suivante :
for (var i = 0; i < enfants.length; i++)
{
enfants[i].style.backgroundColor=couleur;
}


Comme nous partons de la valeur 0, nous bouclons jusqu'à length-1 (i < enfants.length). Constatez que pour changer, nous déclarons la variable directement dans la boucle cette fois (var i = 0). Comme la variable enfants est un tableau, nous pointons sur chacun de ses éléments en précisant l'indice entre crochets (enfants[i]). Nous aurons l'occasion de traiter les tableaux de variables dans le détail, dans une formation à venir. Le reste, pour l'affectation de couleur, nous le connaissons déjà bien.
  • Enregistrer les modifications, basculer sur le navigateur et rafraichir la page,
  • Cliquer tour à tour sur des carreaux de couleur,
Traitement dynamique en Javascript de tous les éléments HTML évolutifs

Cette fois, comme vous le constatez, tous les calques sont indifféremment considérés. Grâce à ce procédé qui permet de simuler une boucle for each (Pour tous les calques enfants dans le calque parent), si leur nombre venait à évoluer, le code les traiterait. Et seules quatre lignes ont été nécessaires pour traiter a priori un nombre illimité d'éléments Html.

Pour cette formation, l'application est terminée, bien qu'elle ne soit pas encore satisfaisante. En effet, les préférences de l'internaute ne sont pas mémorisées si bien qu'à chaque nouvelle ouverture, les couleurs sont réinitialisées. Comme il s'agit d'une application Web, ces données doivent être stockées sur la machine du client. Et ce sont les cookies qui permettent ainsi de laisser des traces à exploiter. Nous aborderons ces cookies en Javascript dans une prochaine formation.

Le code complet de l'application, commentaires compris, est le suivant :

<script type='text/javascript' language='javascript'>
function mef(couleur)
{
//var indice;

/*for (indice=1;indice<=4;indice++)
{
document.getElementById('rub' + indice).style.backgroundColor=couleur;
}*/

/*indice = 1;
while(indice<5)
{
document.getElementById('rub' + indice).style.backgroundColor=couleur;
indice++;
}*/

var parent = document.getElementById('conteneur');
var enfants = parent.getElementsByTagName('div');

for (var i = 0; i < enfants.length; i++)
{
enfants[i].style.backgroundColor=couleur;
}

}
</script>


 
Sur Facebook
Sur G+
Sur Youtube
Les livres
Contact
Mentions légales



Partager la formation
Partager sur Facebook
Partager sur Google+
Partager sur Twitter
Partager sur LinkedIn