Infoforall

Javascript 04 : WHILE et FOR nominatif

Nous allons utiliser le FOR numérique et nominatif associé à une structure de données particulière (le Array ou tableau) pour réaliser ceci :

Les 16 carrés en tri de couleur

Vous verrez également les boucles WHILE et nous finirons sur la réalisation de l'interface.

1 - La boucle WHILE - TANT QUE

Bien, passons aux boucles WHILE : on peut demander au programme de faire plusieurs fois la même chose tant qu’une condition précise est respectée (true).

Tant que la condition donnée est vraie, le programme va lancer les instructions à l’intérieur de la structure. Il est donc possible que cette instruction ne se fasse jamais si la condition n’est pas vérifiée initialement.

Cette boucle s'utilise comme ceci :

while (condition) {

    Instruction 1 à répéter;

    Instruction 2 à répéter;

}

Tout ce qui entre les accolades sera répété tant que la condition est vérifiée (true). Pensez donc à bien refermer votre accolade. La tabulation n'est ici qu'une indication visuelle pour le lecteur humain : il faut les respecter pour rendre votre code lisible mais l'ordinateur n'en tient aucun compte lui.

Voilà un premier exemple qui vous montre comment demander une note tant que la note est supérieure à 20.

Le code HTML ne fait que provoquer l'appel de votre fonction lorsqu'on appuie sur le bouton :

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8" />

        <title>Boucle WHILE</title>

        <meta http-equiv="content-Language" content="fr" />

        <link rel="stylesheet" href="style_1.css" />

        <script src="js_chap_04.js"></script>

    </head>


    <body>


        <header>

            <h1>Boucle while</h1>

        </header>


        <section>

            <p><input type="button" onclick="exemple_tantque()" value="Lancement du while/tant que"></p>

        </section>


    </body>

</html>

Le code js de la fonction exemple_tantque() :

function exemple_tantque() {

    // Acquisition des donnees note 1

    var note1 = 21;

    while (note1>20) {

        note1 = prompt("Donner votre note ");

        note1 = parseInt(note1);

    }

    alert("Votre note valide est "+note1);

}

CLIQUEZ SUR LE PREMIER BOUTON :

Réponse Tapée >>>

note1 :

01° Pourquoi rentre-t-on forcément au moins une fois dans la boucle ? Quelle est la fonction qui transforme la chaîne de caractères en integer ? Modifier le programme pour qu’il vérifie en plus que la note soit bien supérieure à 0.

...CORRECTION...

On rentre dans la boucle puisqu'on place arbitrairement 21 dans la variable note1. La condition du WHILE est donc vraie : 21 est bien strictement supérieur à 20.

La fonction int() permet de transformer le string de la réponse en entier.

Pour la condition double :

    while (note1>20 || note1<0) {

Une autre façon de faire : on part d’un test true et on le rend false lorsqu’on estime qu’on peut sortir :

function exemple_tantque() {

    // Acquisition des donnees note 1

    var note1 = 21;

    var test = true;

    while (test) {

        note1 = prompt("Donner votre note ");

        note1 = parseInt(note1);

        test = (note1>20) || (note1<0);

    }

    alert("Votre note valide est "+note1);

}

On remarque qu'on doit se compliquer la vie uniquement pour rentrer dans la boucle au moins une fois. En réalité, il existe une boucle plus adaptée à la situation : la boucle do {instructions;} while (condition);.

do {

    instruction_1;

    instruction_2;

} while (condition);

Cette boucle fait exactement ce qu'on veut : on rentre dans la boucle quelque soit les conditions initiales (do dans le sens "exécute" en français) et on teste la poursuite à la fin de la boucle plutôt qu'au début.

02° Compléter le code suivant pour qu'il fasse exactement comme le code précédent.

function exemple_tantque() {

    // Acquisition des donnees note 1

    var note1;


    // COMPLETER ICI


    alert("Votre note valide est "+note1);

}

...CORRECTION...

function exemple_tantque() {

    // Acquisition des donnees note 1

    var note1;


    do {

        note1 = prompt("Donner votre note ");

        note1 = parseInt(note1);

    } while (note1>20 || note1<0) ;


    alert("Votre note valide est "+note1);

}

Comme vous le voyez, on gagne en lignes de code dans les instructions de la boucle : on n'a plus à gérer la condtion avant d'entrer dans la boucle et de la modifier dans la boucle.

On teste simplement la condition finale pour savoir si on continue ou si on sort. N'oubliez pas le point-virgule à la fin du while dans cette configuration (alors qu'on en place pas dans un while "normal".

On retiendra donc qu'avec javascript, on peut utiliser while si dans certains cas on ne veut pas rentrer du tout dans la boucle et do .. while si on veut rentrer au moins une fois dans la boucle.

03° Tester votre code avec 3, 4.9, 20.3 ou même A... Voyez-vous le problème ?

Et oui. Comme, nous avons utilisé la fonction native parseInt, il convertit en entier. Bon, la solution est simple : il faut utiliser la fonction native parseFloat.

        note1 = parseFloat(note1);

Par contre, pour le deuxième problème, c'est plus embêtant : si on tape autre chose qu'un chiffre, il ne parvient pas à comparer, on obtient alors une condition fausse pour continuer et on finit par sortir. Il affiche alors NaN pour Not A Number.

Et si on veut vérifier que la chaîne tapée par l’utilisateur est bien un chiffre ?

Il faudrait utiliser la fonction native isNaN (pour is Not a Number) : isNaN(x) renvoie true si le string x ne peut pas être analysé comme un nombre. Si c'est un nombre (entier, réel, en notation scientifique...), elle renvoie false.

04° Modifier le code pour qu'il demande un nombre jusqu'à obtenir quelque chose d'interprétable comme un nombre, même 5e-3 par exemple. Il faudra utiliser un do...while et la fonction isNaN(x).

Attention, si vous avez travaillé correctement 12.6 devrait être reconnu comme un nombre alors que 12,6 non. Faites donc très attention entre la façon française de noter les nombres réels (12,6) et la façon anglosaxonne (12.60). Les codes informatiques usuels ne reconnaissent que la notation anglosaxonne.

...CORRECTION...

function exemple_tantque() {

    // Acquisition des donnees note 1

    var note1;


    do {

        note1 = prompt("Donner votre note ");

        note1 = parseFloat(note1);

    } while (note1>20 || note1<0 || isNaN(note1) ) ;


    alert("Votre note valide est "+note1);

}

2 - Lecture d’éléments avec une boucle itérative nominative FOR

Nous avons vu que Javascript est un langage performant : on peut lui ordonner de lire un à un les éléments de base constitutifs d’un objet (noté maSequence ci-dessous) plus complexe. On avait utilisé pour cela une boucle FOR numérique (avec un compteur). On lit ensuite les éléments en utilisant les crochets :

var maSequence = "Hello World !"

for (var index=0 ; index<maSequence.length; index++) {

    alert(maSequence.charAt(index));

}

var maSequence = "Hello World !"

for (var index=0 ; index< maSequence.length; index++) {

    alert(maSequence[index]);

}

Mais, on peut faire encore plus simple avec la boucle FOR nominative : on lui dit de faire des actions sur chaque element contenu dans maSequence .

Premier exemple : lecture d'un string

Nous allons créer une page qui ne contient qu'un input de type texte, le lire dans javascript et afficher un à un ses caractères dans la console avec un for .. in :

    for (var x in maSequence) {

<!DOCTYPE html>

<html>


    <head>

        <meta charset="UTF-8" />

        <title>Lecture avec js</title>

        <meta http-equiv="content-Language" content="fr" />

        <link rel="stylesheet" href="style_1.css" />

        <script src="js_chap_04.js"></script>

    </head>


    <body>


        <header>

            <h1>FOR dans un élément nominatif</h1>

        </header>


        <section>

            <p>Votre string :

                <input type="text" id="mon_string" onchange="lireCar()" value="Votre string.">

            </p>

        </section>


    </body>


</html>

Et pour le script js

function lireCar() {

    var maSequence = document.getElementById("mon_string").value;

    for ( var x in maSequence) {

        console.log(x);

    }

}

Voir l'exécution :

maSequence :

element :

>>>

05° Lancez le code et tentez de voir ce qui ne fonctionne pas !

Et oui, si vous testez le script avec Hello World !, vous allez obtenir :

Hello World !

0

1

2

3

4

5

6

7

8

9

10

11

12

Console : n'oubliez pas qu'on affiche le résultat dans la console du navigateur. Il vaut donc penser à l'afficher via le menu de votre navigateur.

06° A votre avis, à quoi correspondent les nombres ?

...CORRECTION...

Simplement au numéro du caractère, à son index.

N'oubliez pas que les index commencent à zéro :

Le x = 0 correspond à l'index du caractère 'H',

Le x = 1 correspond à l'index du caractère 'e'...

Contrairement à Python par exemple, lorsqu'on utilise un for ( var x in maSequence) sur un objet maSequence itérable, x correspond au numéro d'index de l'élément, pas l'élément lui même.

Si on veut voir le contenu de la "case", il faut utiliser la méthode charAt des objets String. Il faut donc noter ceci pour afficher le caractère contenu dans la case plutôt que le numéro de la case x : 

maSequence.charAt(x)

07° Modifier le code pour qu'il affiche les caractères un à un dans la console.

Hello World !

H

e

l

l

o

W

o

r

l

d

!

...CORRECTION...

function lireCar() {

    var maSequence = document.getElementById("mon_string").value;

    console.log(maSequence);

    for (var x in maSequence) {

        console.log(maSequence.charAt(x));

    }

}

08° Modifier une dernière fois le code pour obtenir :

Hello World !

Case 0 contient : H

Case 1 contient : e

Case 2 contient : l

Case 3 contient : l

Case 4 contient : o

Case 5 contient :

Case 6 contient : W

Case 7 contient : o

Case 8 contient : r

Case 9 contient : l

Case 10 contient : d

Case 11 contient :

Case 12 contient : !

...CORRECTION...

function lireCar() {

    var maSequence = document.getElementById("mon_string").value;

    console.log(maSequence);

    for (var x in maSequence) {

        console.log( "Case "+x+ " contient : "+maSequence.charAt(x) );

    }

}

Bref, le for .. in c'est un peu comme un for numérique sauf qu'on est certain de ne pas dépasser l'index maximum ...

En réalité, il existe une manière d'obtenir directement le caractère : ce n'est pas un for (var x in maSequence) qu'il faut utiliser mais un for (var x of maSequence). On change en réalité d'instruction : le programme va directement vous donner le contenu des cases.

Avec cette technique, on accéde directement au contenu :

function lireCar() {

    var maSequence = document.getElementById("mon_string").value;

    for (var element of maSequence) {

        console.log(element);

    }

}

Voir l'exécution :

maSequence :

element :

>>>

09° Utiiser la technique du for (var x of y) pour constater que cela fonctionne bien.

Cette fois, on devrait, enfin, avoir :

Hello World !

H

e

l

l

o

 

W

o

r

l

d

 

!

Qu'est qu'un string ? C'est une structure de données :

Une fois qu'on a défini le contenu d'un string, on ne peut plus y toucher. Par contre, on peut créer un autre string et le stocker dans une variable qui porte le même nom.

Passons à une petite application pratique de la lecture d'un string avec un for nominatif. Nous voudrions réaliser un pendu.

Le mot à trouver sera enregistré dans la variable motSecret.

Le mot modifié sera enregistré dans la variable motMoinsSecret et affiché sur la page dans la balise span d'id "mot_moins_secret".

La lettre à chercher ensuite sera enregistrée dans la variable maLettre et rentrée via la balise input d'id "ma_lettre".

Nous voudrions donc afficher un ensemble de caractères où les lettres sont remplacées par des étoiles *, sauf si le caractère est un espace ou un tiret. Dans ce cas, on laisse l'espace ou le tiret.

Exemple : Le string  Bonjour tout le monde  doit faire afficher  ****** **** ** *****  dans la balise span d'id "mot_moins_secret".

10° Le code ci-dessous permet d'afficher à l'identique le contenu de motSecret en lisant et affichant ces caractères un à un. Il faudra :

  1. Modifier le programme pour remplacer les caractères par des étoiles.
  2. Modifier ensuite le programme pour qu'il ne modifie pas les espaces ou les tirets (il faudra utiliser des IF).

Création du string motMoinsSecret : cette chaîne est créée par concaténation successive. On rajoute un caractère à la fois, à chaque fois qu'on fait la boucle.

<!DOCTYPE html>

<html>


    <head>

        <meta charset="UTF-8" />

        <title>Lecture avec js</title>

        <meta http-equiv="content-Language" content="fr" />

        <link rel="stylesheet" href="style_1.css" />

    </head>


    <body>


        <header>

            <h1>Mini-jeu du pendu</h1>

        </header>


        <section>

            <p>Le mot secret est :

                <span id="mot_moins_secret" ></span>

            </p>

            <p>La lettre à vérifier :

                <input type="text" id="ma_lettre" placeholder="Insérez ici la lette voulue">

            </p>

            <p><input type="button" onclick="verifier_presence()" value="Vérifier la présence de la lettre"></p>

        </section>


        <script src="js_chap_04.js"></script>

    </body>


</html>

function verifier_presence() {


    var motSecret = "Bonjour tout le monde";

    var motMoinsSecret = "";

    var maLettre = document.getElementById("ma_lettre").value;


    for (var element of motSecret) {

        motMoinsSecret = motMoinsSecret + element;

    }


    document.getElementById("mot_moins_secret").innerHTML = motMoinsSecret;

}

...CORRECTION...

function verifier_presence() {


    var motSecret = "Bonjour tout le monde";

    var motMoinsSecret = "";

    var maLettre = document.getElementById("ma_lettre").value;


    for (var element of motSecret) {

        if (element == '-' || element == ' ') {

            motMoinsSecret = motMoinsSecret + element;

        } else {

            motMoinsSecret = motMoinsSecret + '*';

        }

    }


    document.getElementById("mot_moins_secret").innerHTML = motMoinsSecret;

}

On a maintenant un affichage composé d'étoile. Compliquons encore un peu : on voudrait gérer la demande de l'utilisateur vis à vis d'une lettre à vérifier. Nous avons sa réponse dans la variable maLettre. Si la lettre est présente dans motSecret, on affiche la chaîne étoilée mais on place la lettre au endroit où elle se situe dans motSecret.

Exemple : Le string  Bonjour tout le monde  doit faire afficher  ****** **** ** ***** . Je veux savoir s'il y a des o, on doit alors afficher  *o**o** *o** ** *o*** .

11° Modifier le code de façon à ce qu'il gère correctement l'affichage après le choix de la lettre à tester.

...CORRECTION...

function verifier_presence() {


    var motSecret = "Bonjour tout le monde";

    var motMoinsSecret = "";

    var maLettre = document.getElementById("ma_lettre").value;


    for (var element of motSecret) {

        if (element == '-' || element == ' ' || element == maLettre) {

            motMoinsSecret = motMoinsSecret + element;

        } else {

            motMoinsSecret = motMoinsSecret + '*';

        }

    }


    document.getElementById("mot_moins_secret").innerHTML = motMoinsSecret;

}

Dernière chose : on peut tester la présence d’un caractère maLettre dans un string motSecret à l’aide de la méthode indexOf. Cette méthode renvoie l'index du premier caractère correspondant dans la chaîne ou -1 s'il n'en trouve pas.

On peut donc l'utiliser pour vérifier la présence : si la méthode renvoie 0 ou plus, c'est que le caractère est bien dans l'autre string.

    var motSecret = "Bonjour tout le monde";

    if (motSecret.indexOf('o') >= 0 ) {

        alert("Caractère détecté !");

    } else {

        alert("Caractère non détecté !");

    }

Le test suivant True car la méthode renvoie un résultat de 1:

    if ("Bonjour tout le monde".indexOf('o') >= 0 ) {

Le test suivant est False :

    if ("Bonjour tout le monde".indexOf('Z') >= 0 ) {

Application : on veut remplacer les consonnes par des étoiles mais les voyelles seront inchangées.

Exemple : Le string  Bonjour tout le monde  doit faire afficher  *o**ou* *ou* *e *o**e .

function verifier_presence() {


    var motSecret = "Bonjour tout le monde";

    var motMoinsSecret = "";

    var maLettre = document.getElementById("ma_lettre").value;


    for (var element of motSecret) {

        if ("AEYUIOaeyuio".indexOf(element) >= 0) {

            motMoinsSecret = motMoinsSecret + element;

        } else {

            motMoinsSecret = motMoinsSecret + '*';

        }

    }


    document.getElementById("mot_moins_secret").innerHTML = motMoinsSecret;

}

Voilà, c'est tout pour l’instant sur l’interaction entre string et boucle. Nous compléterons encore les choses par la suite. Dans l'activité suivante sur les strings, nous verrons un peu plus précisement l'ASCII et le fait que l'espace soit bien un caractère avec un numéro et pas un espace vide. Et nous verrons surtout qu'il existe beaucoup de méthodes applicables aux strings.

Si vous cherchez des renseignements complémentaires, w3schools.

Deuxième exemple : lecture d'un tableau (Array)

Bon, et si l'objet n’est pas composé d’un ensemble uniforme de composants de base ? Essayons. Dans le code suivant, tableau est composé d’integers, d’un string et même d’une concaténation. Nous verrons, dans la partie suivante, que tableau est ce qu’on appelle un Array : un ensemble ordonné d’éléments pouvant être différents les uns des autres. Ils sont assez semblables aux Listes de Python.

var tableau =[ 1, 2, 9, 8,"ah ah ah", 45, "a"+"b" ];

Les crochets servent à déterminer le début et la fin du Array.

Les éléments sont séprarés par des virgules.

Je vous présente ici un exemple de lecture où le script est directement inséré dans le code HTML :

<!DOCTYPE html>

<html>


    <head>

        <meta charset="UTF-8" />

        <title>Lecture Array avec js</title>

        <meta http-equiv="content-Language" content="fr" />

    </head>


    <body>

        <script>


var tableau =[1,2,9,8,"ah ah ah",45,"a"+"b"];

console.log(tableau);

for (var element of tableau) {

    console.log(element);

}


        </script>

    </body>


</html>

12° Créer le HTML. Alors, ça fonctionne ou non ? Avons-nous trouvé une première limite à ce que Javascript sait faire ?

Normalement, vous devriez voir ceci dans le journal de votre console web 

Array(7) [1, 2, 9, 8, "ah ah ah", 45, "a"+"b"]

1

2

9

8

ah ah ah

45

ab

Troisième exemple : lecture des mots d'une phrase

On peut également énoncer les mots d’une phrase plutôt que les caractères d’un mot.

Pour cela, il nous faut un string phrase par exemple.

On utilisera la méthode split(" ") pour séparer la phrase en ses différents composants, à savoir des mots séparés par des espaces.

tableauMots = phrase.split(" ")

On va créer un Array tableauMots qui va contenir les mots de la phrase.

Exemple avec une string phrase et le Array(tableau) tableauMots correspondant :

phrase = "Bonjour le monde"

tableauMots = [ "Bonjour, "le", "monde" ]

13° Utiliser le code suivant ( à remplacer dans le HTML précédent) pour vérifier que le programme parvient bien à séparer les mots de la phrase. Ca fonctionne ou non ? Est-ce parfait ?

<script>


var phrase = "Désormais, nous allons pouvoir gérer des phrases, longues ou courtes.";

var tableauMots = phrase.split(" ");

console.log(tableauMots);

for (var mot of tableauMots) {

    console.log(mot);

}


</script>

Vous devriez obtenir ceci sur votre console

Array(10) [ "Désormais,", "nous", "allons", "pouvoir", "gérer", "des", "phrases,", "longues", "ou", "courtes." ]

Désormais,

nous

allons

pouvoir

gérer

des

phrases,

longues

ou

courtes.

Vous pouvez vous documenter facilement sur la méthode split. Une simple recherche « javascript split » devrait vous amener vers de multiples sites vous offrant la documentation adéquate.

Bon, comment régler le problème de la virgule ? Une rapide inspection de split ne règle pas le problème : on peut faire un split(',') pour choisir la virgule comme paramètre séparateur. Mais il faudra alors faire un deuxième passage avec split(' ') puisqu’on ne peut utiliser qu’un caractère de séparation.

Pour revenir au problème, deux solutions s’offrent à nous en fouillant un peu les bibliothèques de fonctions ou en réfléchissant un peu : on supprime toutes les virgules et autres séparateurs

14° Résolution 1 : On supprime avant le split(" ") à l’aide de la méthode replace(old, new) qui permet de remplacer la chaîne de caractères old par la chaîne de caractères new). Nous allons habilement remplacer les virgules et points par … rien. En gros, cela va les supprimer, non ?

<script>


var phrase = "Désormais, nous allons pouvoir gérer des phrases, longues ou courtes.";


phrase = phrase.replace(',','');


var tableauMots = phrase.split(" ");

console.log(tableauMots);

for (var mot of tableauMots) {

    console.log(mot);

}


</script>

On voit que le Array tableauMots est bien mis à jour mais ...Zut. Une seule virgule a disparu !

Array [ "Désormais", "nous", "allons", "pouvoir", "gérer", "des", "phrases,", "longues", "ou", "courtes." ]

Désormais

nous

allons

pouvoir

gérer

des

phrases,

longues

ou

courtes.

Pour faire disparaitre les autres, il faut utiliser ce qu'on appelle une expression régulière : on va taper :

phrase = phrase.replace( /,/g , '' );

On voit qu'on remplace les guillemets (ouvrant et fermant) par des slashs (ouvrant et fermant) et qu'on utilise un g pour indiquer que la recherche doit être globale.

Pour le point, c'est plus compliqué : le point . est un mot-clé dans une expression régulière. Il veut dire "n'importe quel caractère". Si vous voulez exprimer que vous voulez chercher un point, il faut taper \. et pas juste .. On a ainsi :

phrase = phrase.replace( /\./g , '' );

14b° Résolution 1 (v2) : Modifier le script en utilisant une modification globale sur les caractères de type virgule, point, point-virgule... C'est fonctionne mieux non ?

<script>


var phrase = "Désormais, nous allons pouvoir gérer des phrases, longues ou courtes.";


phrase = phrase.replace( /,/g , '' );

phrase = phrase.replace( /\./g , '' );


var tableauMots = phrase.split(" ");

console.log(tableauMots);

for (var mot of tableauMots) {

    console.log(mot);

}


</script>

On voit que la liste mots est bien mise à jour (elle ne possède plus d’éléments avec des points ou des virgules).

Array(10) [ "Désormais", "nous", "allons", "pouvoir", "gérer", "des", "phrases", "longues", "ou", "courtes" ]

Désormais

nous

allons

pouvoir

gérer

des

phrases

longues

ou

courtes

Expressions régulières

La maitrise des expressions régulières méritera une activité spécifique.

Sachez qu'on peut faire beaucoup avec cet outil. Notamment, on peut indiquer avec ? que le caractère est cherché mais pas forçément nécessaire :

On pourrait remplacer les deux replace par

phrase = phrase.replace( /?,?\./g , '' );

La chaîne recherchée est donc :  ?,?\ :

On cherche éventuellement un point ou éventuellement une virgule.

Comme il y a un g à la fin, la rechercher se fait sur toute la chaîne, on ne s'arrête pas au premier caractère trouvé.

15° Résolution 2 : On supprime après le split à l’aide de la méthode replace :

<script>


var phrase = "Désormais, nous allons pouvoir gérer des phrases, longues ou courtes.";


var tableauMots = phrase.split(" ");

console.log(tableauMots);


for (var mot of tableauMots) {

    mot = mot.replace( /,/g , '' );

    mot = mot.replace( /\./g , '' );

    console.log(mot);

}


console.log(tableauMots);


</script>

Vous devriez voir ceci dans la console :

Array(10) [ "Désormais,", "nous", "allons", "pouvoir", "gérer", "des", "phrases,", "longues", "ou", "courtes." ]

Désormais

nous

allons

pouvoir

gérer

des

phrases

longues

ou

courtes

Array(10) [ "Désormais,", "nous", "allons", "pouvoir", "gérer", "des", "phrases,", "longues", "ou", "courtes." ]

Là, on constate un problème : tableauMots n'est pas modifié après la boucle. C’est normal : mot est défini à partir de tableauMots mais la modification de mot ne va donc pas modifier le tableau ensuite. C’est un problème qu’il va falloir résoudre par la suite.

Une courte remarque pour les curieux :

Si vous regardez d'autres scripts trouvés ça et là, vous risquez un jour de tomber sur ceci :

if (~(sTexte.indexOf(sCarac))) {

à la place de :

if (sTexte.indexOf(sCarac) (>= 0) {

On voit donc que le tilde ~ remplace le test >= 0. Ce tilde est clairement hors de propos ici. Il concerne la gestion des bits. Mais sachez juste que son utilisation incrémente la valeur de l'index de 1. Si la méthode ne trouve rien, elle place l'index à -1 et l'incrémentation place la condition à la valeur 0 ou false. Dans tous les autres cas, on obtient avec le +1 un nombre strictement positif que Javascript va interpréter en true. Et voilà comment un petit tilde fait gagner quelques caractères dans votre code mais risque de faire perdre le fil au lecteur qui ne connait pas cette petite manipulation.

Et ça va me servir à quoi ? Et bien, ça peut être très pratique pour parvenir à décoder une suite d'instructions qu'on donne via un Input. On tape des instructions et l'ordinateur parvient à les effectuer les unes à la suite des autres. Classe non ? Nous en exploiterons tout le potentiel dans la partie sur les animations.

En attendant et en conclusion, choisissez donc avec prudence votre façon de faire méthode 1 ou 2) en fonction de l'influence que vous voulez avoir sur la liste finale.

Nous allons maintenant nous attarder sur les tableaux (Arrays). C'est une structure de données très pratique pour stocker et modifier des données.

3 - Structure de données Array (tableau)

Cette partie va vous permettre d'utiliser la plupart des connaissances vues sur les deux activités traitant des tests et des boucles.

Nous allons maintenant voir les tableaux, un objet de classe Array en Javascript. C'est une structure de données qui va vous permettre de stocker des données créées en grand nombre lors de l'utilisation d'un TANT QUE ou d'une boucle FOR.

Dans l'activité précédente, nous avions créés des balises div colorées mais nous ne pouvions pas stocker leurs références pour pouvoir les modifier par la suite. Nous allons voir comment pallier à cela.

3.1 Première description des tableaux Array

Nous avons déjà vu plusieurs exemples de tableaux Array plus haut :

  • Le résultat d'un split :
  • ['Désormais', 'nous', 'allons', 'pouvoir', 'gérer', 'des', 'phrases', 'longues', 'ou', 'courtes']

  • L'exemple de la lecture directe avec un FOR nominatif :
  • var tableau =[1,2,9,8,"ah ah ah",45,"a"+"b"];

    for (var element of tableau) {

        console.log(element);

    }

Qu'est qu'un Array ? C'est une structure de données :

Le string est donc une structure de données proche du Array, mais le string n'est pas modifiable après création contrairement au tableau Array. Vous allez voir qu'on retrouve beaucoup de choses vues avec les strings d'ailleurs.

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

Cela crée un tableau de 7 éléments contenant les nombres 1, 2, 9, 8, le string "ah ah ah", le nombre 45 et le string "ab".

Si on veut afficher un tableau, alert(mon_tableau) fonctionne.

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

alert(tableau);

On obtient alors une fenêtre pop-up dans laquelle s'affiche ceci :

1, 2, 9, 8, ah ah ah, 45, ab

Si on veut connaitre le nombre d'éléments dans un Array tableau, il faut rechercher la propriété length :

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

alert(tableau.length);

On obtient alors le nombre d'éléments dans le tableau :

7

Par contre, attention : le premier élément a un index de 0 et le dernier un index de 6.

Si on veut accéder à l'un des éléments d'un Array , on cherchera l'index 2 si on cherche le 3e puisqu'on commence à 0. On utilisera les crochets :

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

alert(tableau[2]);

9

Attention, on le répète : le premier élément est l'élément 0. On affiche bien 9 qui possède l'index 2.

3.2 Array et boucle FOR

Première méthode :

Pour parcourir un tableau Array, il peut utiliser un for numérique ou nominatif. Voici un exemple avec l'affichage en console plutôt que dans une fenêtre 'alert' :

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

for (var numIndex=0 ; numIndex < tableau.length; numIndex++) {

    console.log(tableau[numIndex]);

}

Ce code permet d'afficher ceci dans la console web :

1

2

9

8

ah ah ah

45

ab

Deuxième méthode pour accéder aux numéros d'index : on peut utiliser un FOR-IN nominatif, comme avec les strings :

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

for (var numIndex in tableau) {

    console.log(tableau[numIndex]);

}

Cela donne le même affichage qu'avec la méthode 1.

Troisième méthode : le FOR-OF nominatif qui permet d'accéder directement au contenu, sans passer par les index :

var tableau = [1,2,9,8,"ah ah ah",45,"a"+"b"];

for (var element of tableau) {

    console.log(element);

}

Cela donne le même affichage qu'avec la méthode 1.

3.3 Array et stockage d'informations

Nous allons utiliser ceci dans le cadre du mini-projet Carrés colorés. Vous allez rencontrer plusieurs notions qui seront expliquées plus tard. Mais cela vous permettra de voir la puissance des Arrays en interaction avec les interfaces graphiques.

Présentation du mini-projet

Nous allons reprendre l'interface des carrés colorés de l'activité précédente, mais je voudrais maintenant rentrer des couleurs dans un tableau Array de façon à pouvoir changer à l'envie les couleurs de mes carrés colorés.

Par exemple :

var tableau_des_couleurs = [ 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow' ]

Voici la page HTML de base :

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8" />

        <title>Mini-projet</title>

        <meta http-equiv="content-Language" content="fr" />

        <link rel="stylesheet" href="interface1.css" />

        <script src="js_miniprojet.js"></script>

    </head>


    <body>


        <header>

            <h1>Mini-projet FOR et IF</h1>

        </header>


        <section>


            <p><input type="button" onclick="creation()" value="Lancer la création des carrés"></p>


            <div id="conteneur">

            </div>


        </section>


    </body>

</html>

Le CSS qu'il faudra nommer "interface1.css".

#conteneur {

    position : relative;

    margin: 0px;

    padding: 0px;

    border: 1px solid #660000;

    width: 500px;

    height: 500px;

}


.carre {

    display: inline-block;

    position : absolute;

    margin: 0px;

    padding: 0px;

    border: 1px solid black;

}

Voici le Javascript que nous avions utilisé :"js_miniprojet.js". Seule la boucle dans la fonction creation est à comprendre. La seule instruction importante vis à vis de notre projet est : rajouter_carre(x,y,"blue");. Les deux fonctions destruction et rajouter_carre sont juste utilisées, elles ne sont pas à modifier.

var largeur = 100;

var marge = 20;

var nombreCarres = 16;


function creation() {

    /*

    Cette fonction va détruire les anciens carrés puis créer les nouveaux carrés

    L'ensemble est créé dans la balise div d'id "conteneur"

    */

    destruction();

    alert("DEBUT DE LA CREATION DES CARRES");

    for (var numIndex=0; numIndex<nombreCarres; numIndex++) {

        var decalage = marge + (largeur+marge)*numIndex;

        var x = decalage%480;

        var y = marge + Math.floor(decalage/480)*(largeur+marge);

        rajouter_carre(x,y,"blue");

    }

}


function destruction() {

    /*

    Cette fonction permet de détruire tous les carrés colorés présents dans la div d'id "conteneur"

    */

    var listeNoeuds = document.getElementsByTagName(".carre");

    for (var i = 0; i < listeNoeuds.length; i++) {

        var noeud = listeNoeuds[i];

        var noeudParent = noeud.parentNode;

        noeudParent.removeChild(noeud);

    }

}


function rajouter_carre(x,y,couleur){

    /*

    Cette fonction permet de rajouter un carré dans la div conteneur

    Elle possède trois paramètres :

        La position horizontale x, un entier

        La position verticale y, un entier

        La couleur du fond coloré, sous forme d'un string

    */

    var refConteneur = document.getElementById("conteneur");

    var refCarre = document.createElement('div');

    refCarre.style.width = largeur+"px";

    refCarre.style.height = largeur+"px";

    refCarre.className = "carre";

    refCarre.style.left = x+"px";

    refCarre.style.top = y+"px";

    refCarre.style.backgroundColor = couleur;

    refConteneur.appendChild(refCarre);

}

16° Créer les 3 fichiers HTML-CSS-JS pour vérifier que cela fonctionne. Rajouter ensuite (aux dessus des fonctions, avec les autres variables globales) le tableau tableau_des_couleurs et modifier ensuite la ligne de la fonction creation pour que les couleurs soient définies en fonction du numéro du carré : on doit aller chercher la couleur d'un carré en utilisant son numéro comme index dans le tableau.

La ligne à modifier :

        rajouter_carre(x,y,"blue");

Vous devriez obtenir ceci :

Les 16 carrés en tri de couleur

...CORRECTION ...

var largeur = 100;

var marge = 20;

var nombreCarres = 16;


var tableau_des_couleurs = [ 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow' ];


function creation() {

    /*

    Cette fonction va détruire les anciens carrés puis créer les nouveaux carrés

    L'ensemble est créé dans la balise div d'id "conteneur"

    */

    destruction();

    alert("DEBUT DE LA CREATION DES CARRES");

    for (var numIndex=0; numIndex<nombreCarres; numIndex++) {

        var decalage = marge + (largeur+marge)*numIndex;

        var x = decalage%480;

        var y = marge + Math.floor(decalage/480)*(largeur+marge);

        rajouter_carre(x,y,tableau_des_couleurs[numIndex]);

    }

}

17° Modifier alors simplement les couleurs stockées dans votre liste pour obtenir ceci :

Les deux carrés rouge de suite

Ou alors ceci :

Contour rouge et intérieur bleu

3.4 Compléments sur le Array

Nous allons maintenant faire mieux : nous allons stocker les références refCarre de nos div dans un tableau. Pour information, elles créées sur cette ligne de la fonction rajouter_carre mais non sauvegardées hors de la fonction ensuite :

var refCarre = document.createElement('div');

Cela nous permettra de modifier la couleur des carrés à l'aide d'un bouton.

Néanmoins, pour faire cela, nous avons besoin d'en savoir un peu plus sur les tableaux : comment rajouter des éléments à la volée et comment détruire le contenu par exemple.

Rajouter des éléments dans un tableau

L'une des possibilités est d'utiliser la méthode push qui rajoute des éléments en fin de liste.

tableau_des_couleurs = [ 'red', "blue", 'yellow' ];

console.log(tableau_des_couleurs);

tableau_des_couleurs.push('green');

console.log(tableau_des_couleurs);

Si on exécute ce code, on obtient ceci :

Array(3) [ "red", "blue", "yellow" ]

Array(4) [ "red", "blue", "yellow", "green" ]

Cette méthode push permet donc de considérer les Arrays comme des piles de livres : on rajoute les éléments au dessus des derniers éléments.

push() rajoute au dessus de la pile

Pas d'affectation ! : on remarque que tableau_des_couleurs est modifié par la méthode, sans présence du signe =.

Il ne faut pas noter quelque chose comme

tableau_des_couleurs = tableau_des_couleurs.push('green');

Cela voudrez dire que vous voulez stocker le résultat de la méthode, méthode qui ne renvoie rien !

Attention aux rajouts d'Array : avec push, on rajoute l'élément fourni, on ne rajoute pas les éléments contenus dedans :

tableau_des_couleurs = [ 'red', "blue", 'yellow'];

console.log(tableau_des_couleurs);

tableau_des_couleurs.push( ['green','red'] );

console.log(tableau_des_couleurs);

Si on exécute ce code, on obtient ceci :

Array(4) [ "red", "blue", "yellow", (2) […] ]

push() rajoute au dessus de la pile

Cela veut dire qu'à l'index 3, on trouve un autre Array qui contient 2 éléments.

Le navigateur aurait pu afficher cela en gros :

Array(4) [ "red", "blue", "yellow", Array(2) [ "green", "red" ] ]

Attention, on n'obtient donc certainement pas ceci :

Array(6) [ "red", "blue", "yellow", "green", "red" ]

Et voilà. Nous savons maintenant comment stocker nos références automatiquement dans un tableau.

4 - Array et stockage de références de balises

18° Rajouter une variable globale qui contiendra un Array vide tableau_des_carres. Rajouter ensuite une ligne à la fonction rajouter_carre de façon à ce qu'on puisse stocker les références créées refCarre dans le tableau .

La variable globale à rajouter :

var tableau_des_carres = []

La fonction à modifier :

function rajouter_carre(x,y,couleur){

    /*

    Cette fonction permet de rajouter un carré dans la div conteneur

    Elle possède trois paramètres :

        La position horizontale x, un entier

        La position verticale y, un entier

        La couleur du fond coloré, sous forme d'un string

    */

    var refConteneur = document.getElementById("conteneur");

    var refCarre = document.createElement('div');

    refCarre.style.width = largeur+"px";

    refCarre.style.height = largeur+"px";

    refCarre.className = "carre";

    refCarre.style.left = x+"px";

    refCarre.style.top = y+"px";

    refCarre.style.backgroundColor = couleur;

    refConteneur.appendChild(refCarre);

}

...CORRECTION...

Il suffit de rajouter une ligne à la fin de la fonction :


    tableau_des_carres.push(refCarre);

Et pourquoi s'être compliqué ainsi la tâche pour avoir exactement le même résultat qu'avant ? Et bien la différence n'est pas visuelle mais elle est très importante : nous avons maintenant une liste contenant les références de nos carrés. Nous allons donc pouvoir agir sur eux.

Notamment à l'aide des boucles FOR nominatives par exemple...

Voici le code complet que vous devriez avoir :

var largeur = 100;

var marge = 20;

var nombreCarres = 16;


var tableau_des_carres = []

var tableau_des_couleurs = [ 'blue', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'red', "blue", 'yellow', 'yellow', "blue", 'yellow' ];


function creation() {

    /*

    Cette fonction va détruire les anciens carrés puis créer les nouveaux carrés

    L'ensemble est créé dans la balise div d'id "conteneur"

    */

    destruction();

    alert("DEBUT DE LA CREATION DES CARRES");

    for (var numIndex=0; numIndex<nombreCarres; numIndex++) {

        var decalage = marge + (largeur+marge)*numIndex;

        var x = decalage%480;

        var y = marge + Math.floor(decalage/480)*(largeur+marge);

        rajouter_carre(x,y,tableau_des_couleurs[numIndex]);

    }

}


function destruction() {

    /*

    Cette fonction permet de détruire tous les carrés colorés présents dans la div d'id "conteneur"

    */

    var listeNoeuds = document.getElementsByTagName(".carre");

    for (var i = 0; i < listeNoeuds.length; i++) {

        var noeud = listeNoeuds[i];

        var noeudParent = noeud.parentNode;

        noeudParent.removeChild(noeud);

    }

}


function rajouter_carre(x,y,couleur){

    /*

    Cette fonction permet de rajouter un carré dans la div conteneur

    Elle possède trois paramètres :

        La position horizontale x, un entier

        La position verticale y, un entier

        La couleur du fond coloré, sous forme d'un string

    */

    var refConteneur = document.getElementById("conteneur");

    var refCarre = document.createElement('div');

    refCarre.style.width = largeur+"px";

    refCarre.style.height = largeur+"px";

    refCarre.className = "carre";

    refCarre.style.left = x+"px";

    refCarre.style.top = y+"px";

    refCarre.style.backgroundColor = couleur;

    refConteneur.appendChild(refCarre);

    /*

    C'est ici qu'on enregistre dans le tableau

    */

    tableau_des_carres.push(refCarre);

}

Alors ça sert à quoi ?

On peut faire plein de choses à l'aide de la référence d'une balise nommée maBalise :

  • Modifier la couleur du fond en bleu :
  • maBalise.style.backgroundColor = 'blue';

  • Modifier la largeur :
  • maBalise.style.width = '150px';

  • Modifier la hauteur :
  • maBalise.style.height = '120px';

  • Modifier l'identifiant :
  • maBalise.id = 'mon_nouvel_identifiant';

  • Modifier la source si c'est une image :
  • maBalise.src = 'nouvelle_image.PNG';

  • Modifier la class :
  • maBalise.className = 'nouvelle_classe';

  • Connaitre la référence du conteneur de votre balise :
  • referenceConteneur = maBalise.parentNode

  • Supprimer la balise :

    referenceConteneur.removeChild(maBalise);

19° Utiliser l'interface HTML fourni ci-dessous qui possède trois boutons pour gérer les couleurs : les boutons doivent colorier les carrés en bleu, en rouge et en jaune.

Pour cela, il faudra :

Vous devriez en avoir pour plusieurs minutes de recherche puisque c'est la première fois que vous faites tout ça.

A vous de jouer : voici le code HTML. A vous de rajouter les trois fonctions voulues. Allez voir le code des boutons.

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8" />

        <title>Mini-projet</title>

        <meta http-equiv="content-Language" content="fr" />

        <link rel="stylesheet" href="interface1.css" />

        <script src="js_miniprojet.js"></script>

    </head>


    <body>


        <header>

            <h1>Mini-projet FOR et IF</h1>

        </header>


        <section>


            <p><input type="button" onclick="creation()" value="Lancer la création des carrés"></p>


            <div id="conteneur">

            </div>


            <p>

                <input type="button" onclick="en_bleu()" value="BLEU" >

                <input type="button" onclick="en_jaune()" value="JAUNE" >

                <input type="button" onclick="en_rouge()" value="ROUGE" >

            </p>


        </section>


    </body>

</html>

Voici une correction possible :

...CORRECTION...

function en_bleu() {

    alert("DEBUT DU CHANGEMENT EN BLEU");

    for ( var refCarre of tableau_des_carres ) {

        refCarre.style.backgroundColor = 'blue';

    }

}


function en_rouge() {

    alert("DEBUT DU CHANGEMENT EN ROUGE");

    for ( var refCarre of tableau_des_carres ) {

        refCarre.style.backgroundColor = 'red';

    }

}


function en_jaune() {

    alert("DEBUT DU CHANGEMENT EN JAUNE");

    for ( var refCarre of tableau_des_carres ) {

        refCarre.style.backgroundColor = 'yellow';

    }

}


Dernière étape : parvenir à créer un dernier bouton, le bouton cyclique qui modifie la couleur des Labels en fonction de la couleur actuelle :

Il nous faut maintenant 4 boutons :

            <p>

                <input type="button" onclick="en_bleu()" value="BLEU" >

                <input type="button" onclick="en_jaune()" value="JAUNE" >

                <input type="button" onclick="en_rouge()" value="ROUGE" >

                <input type="button" onclick="en_cycle()" value="CYCLIQUE" >

            </p>

Pour cela, il va falloir aller lire le contenu de l'attribut style.background et agir en conséquence.

RAPPEL :

Pour modifier un attribut, il faut utiliser par exemple :

maBalise.style.backgroundColor = 'blue';

Et pour lire le contenu d'un attribut, il faut utiliser par exemple :

laCouleur = maBalise.style.backgroundColor;

Voici une correction possible :

...CORRECTION...

function en_cycle() {


    for ( var refCarre of tableau_des_carres ) {


        var laCouleur = refCarre.style.backgroundColor;


        if ( laCouleur == 'blue' ) {

            refCarre.style.backgroundColor = 'red';

        } else if ( laCouleur == 'red' ) {

            refCarre.style.backgroundColor = 'yellow';

        } else {

            refCarre.style.backgroundColor = 'blue';

        }


    }

}


Voilà pour le moment. Il existe encore bien des choses à apprendre sur les tableaux. Nous verrons cela dans une activité propre à ceux-ci. Nous y verrons comment rajouter des éléments au début de tableau, en supprimer ... Cela sera pratique pour garder en mémoire le fait d'avoir cliqué sur un carré par exemple.

Dans l'activité suivante, nous allons voir assez précisement comment gérer les chaînes de caractères. La plupart des applications nécessitent en effet de vérifer les données rentrées par l'utilisateur.

Placement de la balise script

On peut placer la balise <script> dans la balise head mais dans ce cas, le chargement du fichier va prendre du temps et la page peut s'afficher avec plus de latence.

Sinon, on peut placer la balise <script> juste au dessus de la balise de fermeture </body>. Cela permet au script de se charger qu'en fin de page.

Néanmoins, si vous avez de grosses images ou des fichiers vidéos, il est possible que votre script soit néanmoins chargé avant que toutes les images et vidéos soient vraiment là. Tant que vous ne voulez pas les modifier avec votre script, tout va bien. Sinon ...

Comment faire alors ?

Vous pouvez indiquer via la balise que vous voulez que la page continue de se charger en parallèle du chargement du script : il faut rajouter l'attribut defer

        <script src="monscript.js" defer ></script>

5 - FAQ

Question : on peut convertir un string (réprésentant un nombre) dans autre chose que la base 10 ?