Infoforall

Javascript 03 : TEST LOGIQUE SI ET BOUCLE FOR NUMERIQUE

Nous allons aujourd'hui apprendre à réaliser une interface sans avoir à coder un à un toutes les balises div.

Les 16 carrés en tri de couleur

Comment ? Assez simplement : les langages de programmation ont la possibilité de faire des tests logiques SI qui permettent d'exécuter un code sous condition et des boucles POUR qui permettent d'effectuer plusieurs fois les mêmes instructions.

A titre d'exemple, voici une animation qui vous propose deux boutons : GAUCHE permet d'aller à gauche et DROITE permet d'aller ... à droite.

Oui mais que faire si on demande d'aller à droite alors qu'on est déjà au bout du rectangle ? Il faut refuser d'avancer. Le script fait donc bien un choix logique IF en fonction de la position x du cercle au moment où le mouvement doit avoir lieu.

En françaisCodage Javascript
SI on peut encore aller à droite alorsif (x < xmax) {
    Autoriser le déplacement à droite    Autoriser_droite();
SINON SI on peut encore aller à gauche alors} else if (x > xmin) {
    Autoriser le déplacement à gauche    Autoriser_gauche();
Fin du test}


X actuelle = 250
X minimale = 150
X maximale = 350
avec un test X > XMIN valant
avec un test X < XMAX valant

En introduction, voilà le codage de différents test de conditions logiques entre deux variables :

Vous pouvez toucher aux curseurs pour voir l'évolution des différentes réponses.

A = 50
B = 50
Symbole du testSignificationExempleResultat du test
==Est égal àA == B?
!=Est différent deA != B?
>Est supérieur àA > B?
>=Est supérieur ou égal àA >= B?
<Est inférieur àA < B?
<=Est inférieur ou égal àA <= B?

Javascript possède également deux tests supplémentaires que nous expliquerons plus loin:

Symbole du testSignificationExemple
===Est égal à ET même typeA === B
!==Est différent de OU de type différentA !== B

Chacun de ces tests ne peut donner normalement que deux résultats : true pour vrai ou false pour faux.

Attention, contrairement à Python, on ne place pas de majuscule au début de la valeur.

Deuxième chose importante : la comparaison s'écrit avec deux signes =, pas un seul ! Il va falloir faire attention.

1 - L’instruction conditionnelle SI – SINON

Commençons par voir comment choisir une action en fonction d’une entrée.

Application : Faisons un petit programme qui nous permet de lire un nombre rentré au clavier puis de dire s’il est positif, négatif ou nul.

Pour la page HTML

<!DOCTYPE html>

<html>


    <head>

        <meta charset="UTF-8" />

        <title>Test SI avec js</title>

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

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

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

    </head>


    <body>


        <header>

            <h1>LES TESTS SI</h1>

        </header>


        <section>

            <p>Nombre (entier, réel, négatif, positif ou nul):</p>

            <p><input type="text" id="e_nombre" onchange="changerAffichage()" placeholder="Votre nombre"></p>

            <p>Votre nombre est <strong id="affichage_du_type">?</strong></p>

        </section>


        <footer>

            <p>-- Footer --</p>

        </footer>



    </body>

</html>

Pour le script js

function changerAffichage() {

    var nNombre = parseFloat(document.getElementById("e_nombre").value);

    var sResultat = "bizarre";

    if (nNombre > 0) {

        sResultat = "positif";

    } else if (nNombre < 0) {

        sResultat = "négatif";

    } else if (nNombre == 0) {

        sResultat = "nul";

    }

    document.getElementById("affichage_du_type").innerHTML = sResultat;

}

CLIQUEZ SUR UN BOUTON-REPONSE :

nNombre :

sResultat :

Nous obtenons alors la structure suivante:

js_act3

index.html

chap_03.js

Remarque : Le copier-coller Explorateur vers Interpréteur est parfois un peu problématique : il peut créer un espace entre chaque ligne ! Plutôt que de les enlever une à une, vous pouvez aller dans le menu EDITION - Lignes - Enlever les lignes vides. Ca ira plus vite. Pour les tabulations, il faut demander gentiment à Notepad de le faire : EDITION – TRAITEMENT DES ESPACEMENTS – Transformer les espaces en tabulations.

01° Tester le code. A quoi sert le parseFloat ? Dans quel cas gardera-t-on "bizarre" dans sResultat ?

...CORRECTION...

L'utilisation du value renvoie un string puisque la balise input possède un attribut "text".

La fonction parseInt permet donc de convertir le string en entier, si c'est possible.

Lors de la tentative de convertion en float, la variable nNombre contiendra NaN (Not a Number) si elle ne parvient pas à transformer le texte lu dans le HTML en un nombre.

La variable sResultat ne peut contenir "bizarre" que si aucune des conditions n'a été validée. Comment ? Par exemple si on ne parvient pas à convertir le string en entier.

Comme vous l'avez vu, on ne rentre que dans un des cas disponibles :

Soit :

    if (nNombre > 0) {

        sResultat = "positif";

Soit :

    } else if (nNombre < 0) {

        sResultat = "négatif";

Soit :

    } else if (nNombre == 0) {

        sResultat = "nul";

Sinon, on garde la valeur de base. Nous aurions donc pu écrire un else à la fin :

    var sResultat = "pas de choix effectué";

    if (nNombre > 0) {

        sResultat = "positif";

    } else if (nNombre < 0) {

        sResultat = "négatif";

    } else if (nNombre == 0) {

        sResultat = "nul";

    } else (nNombre == 0) {

        sResultat = "bizarre";

    }

Voyons maintenant comment symboliser et expliquer tout ceci.

Description en français : l'action logique qu’on peut traduire en texte par

SI la première condition est vraie alors
    Fait les actions 1
SINON SI la deuxième condition est vraie alors
    Fait les actions 2
SINON
    Fait les actions 3
Fin du test

Représentation graphique : la même action logique sous forme graphique :

Le Si

On voit que la condition est un losange qui possède deux sorties uniquement.

Les instructions sont des rectangles.

Description en code Javascript : l'action logique se traduit en code par

En françaisCodage Javascript
SI la première condition est vraie alorsif (condition_1) {
    Fait les actions 1    Instructions_1;
SINON SI la deuxième condition est vraie alors} else if (condition_2) {
    Fait les actions 2    Instructions_2;
SINON} else {
    Fait les actions 3    Instructions_3;
Fin du test}

On remarquera d’abord qu’on met des accolades { et } après la condition de if, else if ou else.

Cela permet à l’interpréteur de savoir quand commence la condition à tester (après le if, else if ou else) et quand la condition est finie (au }).

Autre point important : c’est la tabulation (ou 4 espaces) qui permet de savoir visuellement qu’une instruction est rattachée au bloc. Contrairement à Python, il ne s'agit que d'une convention visuelle de compréhension du code. La navigateur ne serait pas perdu si vous ne les placez pas. Mais il faut le faire pour garantir que d'autres personnes puissent comprendre votre code. Dans Notepad++, on peut faire s'afficher les tabulations à l'aide du menu AFFICHAGE - SYMBOLES SPECIAUX - AFFICHER ESPACES ET TABULATIONS

02° Compléter le code suivant : il doit demander si oui ou non vous êtes un humain. Il doit répondre "Bonjour humain !" si la réponse est "oui", et "Bonjour robot !" sinon.

Pour la page HTML

<!DOCTYPE html>

<html>


    <head>

        <meta charset="UTF-8" />

        <title>Test SI avec js</title>

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

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

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

    </head>


    <body>


        <header>

            <h1>LE TEST D'HUMANITE</h1>

        </header>


        <section>

            <p>Etes-vous humain (oui/non) ?</p>

            <p><input type="text" id="reponse_humain" onchange="changerAffichage()" placeholder="Votre réponse"></p>

            <p><strong id="affichage">?</strong></p>

        </section>


        <footer>

            <p>-- Footer --</p>

        </footer>


    </body>

</html>

Pour le script js

function changerAffichage() {

}

Convention personnelle : j'ai choisi de prendre des id html comportant des underscores et des variables js utilisant des majuscules. Utiliser une convention fixe de ce type permet d'éviter de se tromper lorsqu'on veut utiliser une variable.

...CORRECTION...

function changerAffichage() {

    var lectureReponse = document.getElementById("reponse_humain").value;

    var messageFinal = "";

    if (lectureReponse == "oui") {

        messageFinal = "Bonjour humain !";

    } else {

        messageFinal = "Bonjour robot !";

    }

    document.getElementById("affichage").innerHTML = messageFinal;

}

03° Tester avec une réponse avec une mauvaise réponse, comme chien ou chat par exemple. Conclusion ?

Voilà : le programme fait ce que vous lui avez demandé, pas ce que vous vouliez.

04° Modifier le programme pour qu'il affiche :

...CORRECTION...

function changerAffichage() {

    var lectureReponse = document.getElementById("reponse_humain").value;

    var messageFinal = "";

    if (lectureReponse == "oui") {

        messageFinal = "Bonjour humain !";

    } else if (lectureReponse == "non") {

        messageFinal = "Bonjour robot !";

    } else {

        messageFinal = "Erreur de saisie";

    }

    document.getElementById("affichage").innerHTML = messageFinal;

}

On peut exécuter plusieurs instructions dans le if ou le elif(else if). Python attend simplement le elif ou else suivant et comprend en attendant qu’il s’agit d’un bloc à exécuter si la condition est validée. On peut même imbriquer un bloc if dans un if.

05° Rajouter une demande supplémentaire lorsqu'on rentre dans le cas "humain" : on doit demander via un prompt "Etes vous un homme ? (oui/non)". Dans ce cas (et uniquement dans ce cas) :

Dans le if testant si l'utilisateur est humain, il faudra donc déjà rajouter une ligne du style :

var lectureReponse2 = prompt("Etes vous un homme ? (oui/non)");

...CORRECTION...

function changerAffichage() {

    var lectureReponse = document.getElementById("reponse_humain").value;

    var messageFinal = "";

    if (lectureReponse == "oui") {

        var lectureReponse2 = prompt("Etes vous un homme ? (oui/non)");

        if (lectureReponse2 == "oui") {

            messageFinal = "Bonjour monsieur !";

        } else if (lectureReponse2 == "non") {

            messageFinal = "Bonjour madame !";

        } else {

            messageFinal = "Erreur de saisie";

        }

    } else if (lectureReponse == "non") {

        messageFinal = "Bonjour robot !";

    } else {

        messageFinal = "Erreur de saisie";

    }

    document.getElementById("affichage").innerHTML = messageFinal;

}

Si on analyse le code en terme de blocs imbriqués l'un dans l'autre, on obtient ceci :

    if (lectureReponse == "oui") {

        var lectureReponse2 = prompt("Etes vous un homme ? (oui/non)");

     if (lectureReponse2 == "oui") {

         messageFinal = "Bonjour monsieur !";

     } else if (lectureReponse2 == "non") {

         messageFinal = "Bonjour madame !";

     } else {

         messageFinal = "Erreur de saisie";

     }

    } else if (lectureReponse == "non") {

        messageFinal = "Bonjour robot !";

    } else {

        messageFinal = "Erreur de saisie";

    }

Il reste à tester des conditions doubles. Une condition renvoie un booléen qui est true ou false. On peut tester plusieurs conditions à la fois à l’aide des codages suivants :

Voici comment :

TEST LOGIQUEEn FrançaisEn Python
&&code ETA && B : Renvoie true si les deux conditions A et B sont true.
||code OUA || B : Renvoie true si l'une deux conditions au moins est true.
!code NON!A : Renvoie true si A == false et renvoie false si A == true.

Pour obtenir |, il faut taper ALT GR + 6 sur votre clavier. C'est l'un des symboles de la touche 6.

Exemple : Réalisons un script à partir du code HTML suivant. Il doit afficher

On vous impose d'utiliser des ET et/ou des OU.

Le code HTML

<!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="chap_03.js"></script>

    </head>


    <body>

        <header>

            <h1>LES TESTS ET LES BOUCLES</h1>

        </header>


        <section>

            <p>Première note :</p>

            <input type="text" id="note_1" onchange="changerAvis()" placeholder="Votre première note">

            </p>

            <p>Deuxième note :</p>

            <input type="text" id="note_2" onchange="changerAvis()" placeholder="Votre deuxième note">

            </p>

            <p>L'avis est <strong id="affichage_avis">?</strong></p>

        </section>


        <footer>

            <p>-- Footer --</p>

        </footer>

    </body>

</html>

Pour vous simplifier la vie, on applique la fonction changerAvis() lorsqu'une note change.

Voici le début du code js :

function changerAvis() {

    var note1 = parseInt(document.getElementById("note_1").value);

    var note2 = parseInt(document.getElementById("note_2").value);

    var messageFinal = "";


    if (note1>=16 && note2>=16) {

            messageFinal = "TRES BIEN";

    } else if (note1>=10 && note2>=10) {

        if (note1>=16 || note2>=16) {

            messageFinal = "BIEN";

        } else {

            messageFinal = "MOYEN";

        }

    } else {

        messageFinal = "PAS BIEN";

    }

    document.getElementById("affichage_avis").innerHTML = messageFinal;

}

06° Tester le code. Rajouter le test permettant d'afficher INQUIETANT.

Si votre code ne fonctionne pas, pensez à regarder la console et le debogueur :

changerAvis et Deboguer

D'ailleurs, si vous utilisez le debogueur, vous aurez toujours la possibilité de voir le code du ou des scripts utilisés sur la page. Plutôt pratique pour voir comment on provoque tel ou tel effet.

...CORRECTION...

function changerAvis() {

    var note1 = parseInt(document.getElementById("note_1").value);

    var note2 = parseInt(document.getElementById("note_2").value);

    var messageFinal = "";


    if (note1>=16 && note2>=16) {

            messageFinal = "TRES BIEN";

    } else if (note1>=10 && note2>=10) {

        if (note1>=16 || note2>=16) {

            messageFinal = "BIEN";

        } else {

            messageFinal = "MOYEN";

        }

    } else if (note1<=8 || note2<=8) {

            messageFinal = "INQUIETANT";

    } else {

        messageFinal = "PAS BIEN";

    }

    document.getElementById("affichage_avis").innerHTML = messageFinal;

}

07° Compléter le code de la fonction ci-dessous qui doit :

function changerAvis() {

    var rouge = 220;

    var vert = 100;

    var bleu = 50;


    /* CODE A COMPLETER ICI */


    alert("Intensité 'rouge' : "+rouge);

    alert("Intensité 'vert' : "+vert);

    alert("Intensité 'bleu' : "+bleu);

}

Une correction possible :

...CORRECTION...

function changerAvis() {

    var rouge = 220;

    var vert = 100;

    var bleu = 50;


    if (rouge>vert && rouge>bleu) {

        rouge = rouge+50;

        alert("Le rouge est l'élément principal.");

    } else if (rouge>vert || rouge>bleu) {

        alert("Le rouge n'est l'élément principal mais est plus grand que l'une des autres intensités.");

    }


    if (rouge>255) {

        rouge = 255;

    }

    alert("Intensité 'rouge' : "+rouge);

    alert("Intensité 'vert' : "+vert);

    alert("Intensité 'bleu' : "+bleu);

}

On voit que cette solution n'est pas optimisée : on va toujours tenter le test de la valeur supérieure à 255 même quand on ne change pas la valeur de rouge. Est-ce une faute ? Ca dépend :

Si on analyse le test ET / AND :

a b a and b
VRAI VRAI VRAI
FAUX VRAI FAUX
VRAI FAUX FAUX
FAUX FAUX FAUX

Si on analyse le test OU / OR :

a b a or b
VRAI VRAI VRAI
FAUX VRAI VRAI
VRAI FAUX VRAI
FAUX FAUX FAUX

2 - la boucle itérative POUR (FOR) par itérateur chiffré

On peut utiliser un FOR pour faire une boucle revenant à réaliser les mêmes instructions X fois.

Comment fonctionne une boucle for ? Le cas le plus simple est facile à comprendre : on prend une variable i qui commence à la valeur zéro. On l'augmente de 1 à chaque tour tant qu'elle ne dépasse pas strictement une valeur de seuil iMAX telle que i < iMAX.

Si vous n'êtes pas familier avec le concept, utilisez le script ci-dessous :

Valeur initiale (initialisation) de la variable i:

On continue tant que i < Valeur de test:

Je vais commencer par vous présenter l’utilisation basique de la boucle for (initialisation de la variable; condition pour continuer; incrémentation). Comme ça, ça semble compliqué mais en fait, non.

08° Utiliser les entrées de la boucle présentée ci-dessus pour répondre aux questions suivantes : Quelles sont les différentes valeurs prises par i si on utilise 0 initialement et i<5 pour le test de continuité ? Va-t-on réellement jusqu’à 5 ou s’arrête-t-on juste avant ?

Et oui. On ne compte que jusqu'à 4, on s'arrête avant 5.

Pourquoi ?

Nous verrons plus loin la raison exacte mais si on regarde ce qui est affiché ...

0

1

2

3

4

... on voit qu'on compte jusqu'à 4 mais qu'on a bien 5 nombres : 0 - 1 - 2 - 3 - 4.

Et ca se code comment avec javascript ?

La boucle FOR en javascript

Le code de la boucle for précédente donne ceci en javascript ?

for (var i =0; i < 5 ; i++)

En terme de codage, l'initialisation se fait avec var i=0. On notera qu'on place un point-virgule pour séparer l'intialisation de la condition de poursuite.

Comment note-t-on cette condition ? Par i<5. On s'arrête donc lorsque i vaut 5. On place encore un point-virgule.

L'incrémentation peut se noter i=i+1 mais on utilise plutôt i++ qui veut dire presque la même chose.

Bref, le code de la boucle for précédente est for (var i =0; i < 5 ; i++).

Nous expliquerons la différence entre les codes i=i+1, i++ et ++i un peu plus tard. Souvenez-vous pour l'instant que dans les trois cas, nous allons augmenter i de 1. La différence se fait au niveau du moment où on incrémente réellement i. Avec i++, on incrémente i après avoir fait l'instruction, avec ++i, on incrémente i avant de faire l'instruction.

Regardons comme utiliser ceci dans un cas plutôt simple : on veut faire bouger le point en suivant le trajet. Vous pouvez utiliser les curseurs pour définir deux boucles FOR : une pour le déplacement à droite et une autre pour le déplacement vers le bas :

for (var i=0 ; i< IMAX; i++) {

    va_a_gauche();

}


for (var j=0 ; j< JMAX; j++) {

    va_en_bas();

}

A droite : IMAX = 0
En bas : JMAX = 0

...CORRECTION...

Il faut régler IMAX sur 4 pour avoir 4 étapes : 0-1-2-3.

Il faut régler JMAX sur 7 pour avoir 7 étapes : 0-1-2-3-4-5-6.

Il faut donc se souvenir qu'on commence ici avec le compteur à 0 car on note var i = 0.

Pour la suite de cette partie, nous allons utiliser la console web pour visualiser les résultats. Pensez à l'afficher.

Voilà le code HTML de base:

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8" />

        <title>Boucle FOR</title>

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

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

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

    </head>


    <body>


        <header>

            <h1>Boucle for numérique</h1>

        </header>


        <section>

            <p><input type="button" onclick="bouclage()" value="Lancement de l'exemple"></p>

        </section>


    </body>

</html>

Le code javascript de la fonction bouclage() est

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console de votre navigateur pour voir les valeurs de i");

    for (var i=0;i<5;i++) {

        console.log("On rentre dans la boucle avec i = "+i);

    }

    alert("FIN DU BOUCLAGE");

}

CLIQUEZ POUR VOIR L'ANIMATION :

i :

09° Tester ce code en recréant les fichiers HTML et js. Ensuite, modifier le code pour afficher les chiffres de 0 à 20 inclus avec cette boucle FOR.

...CORRECTION...

    for (var i=0;i<21;i++) {

10° Regarder le code ci-dessous et prévoir ce qu’il va afficher à l’écran. Vérifier en lançant le code.

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var i=0;i<11;i++) {

        console.log(i+" x 2 = "+i*2);

    }

    alert("FIN DU BOUCLAGE");

}

11° Réaliser un programme ne comprenant qu’une seule boucle FOR qui affiche (pour chaque valeur de x variant de 0 à 6) le carré de x et la puissance trois de x.

Remarque : En Javascript, la puissance 2 (le carré) se calcule avec x*x ou Math.pow(x,2) : Ainsi 62 se calcule aussi avec Math.pow(6,2). Il faut donc utiliser la méthode pow de la classe native Math. Pourquoi pow ? Pour power, puissance en anglais pour ceux qui ne suivent pas.

Si on veut que le compteur ne commence pas à 0, il suffit de la préciser lors de l'initialisation for (var i = 2 ; i < 6 ; i++) va donc prendre les valeurs 2, 3, 4 et 5.

12° Réaliser un programme qui affiche un à un les nombres compris entre 32 et 127.

Dans l'activité HTML sur les images, nous avons vu que les images ne sont que des successions de nombres stockés dans le fichier image.

C'est la même chose pour les caractères : String.fromCharCode(valeur) permet de connaître le caractère associé au nombre entier valeur. Comme vous le voyez, cette méthode appartient à l'objet global String.

13° Réaliser un programme qui affiche (dans la console) un à un les caractères associés aux nombres compris entre 32 et 127 sous la forme :

        Le caractère X correspond au code XXX

...CORRECTION...

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var i=32;i<128;i++) {

        console.log( "Le caractère "+ String.fromCharCode(i)+ " correspond au code "+i);

    }

}

Tous les caractères sont-ils "imprimables" ?

On remarquera que le code 32 correspond à la touche espace et que le caractère 127 affiche quelque chose d'assez étrange. En réalité, ce code correspond à delete.

14° Essayer les caractères de 0 à 31. S'agit-il de caractères imprimables ? Que se passe-t-il pour le 10 ?

...CORRECTION...

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var i=0;i<11;i++) {

        console.log( "Le caractère "+ String.fromCharCode(i)+ " correspond au code "+i);

    }

}

Si vous faites une recherche sur code ASCII, vous devriez découvrir assez facilement ce que code les codes de 0 à 10. Tous sont des caractères non imprimables. Le 9 correspond à la tabulation et le 10 correspond au saut de ligne (linefeed).

On peut également changer l'incrémentation. i-- diminue i de 1 plutôt que l'augmenter, i+=2 va augmenter i de 2 plutôt que d'augmenter de un en un. On aurait pu noter également i=i+2.

Si le pas est négatif, on compte en sens inverse : for (var i=9;i>1;i--) donne : 9 8 7 6 5 4 3 2, mais pas 1 puisque la condition n'est alors plus vérifiée.

15° Créer un programme qui affiche automatiquement une lettre sur 2 de A (code 65) à Z (code 90) puis qui affiche les lettres de Z à A. Utiliser les boucles FOR associées au code ASCII.

...CORRECTION de A à Z...

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var i=65;i<91;i=i+2) {

        console.log( "Le caractère "+ String.fromCharCode(i)+ " correspond au code "+i);

    }

}

...CORRECTION de A à Z...

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var i=90;i>64;i=i-2) {

        console.log( "Le caractère "+ String.fromCharCode(i)+ " correspond au code "+i);

    }

}

On ne l'utilisera pas ici mais sachez que String.fromCharCode(100, 101, 102) fonctionne également et renvoie la chaîne "def". Merveilleux non ? 100 pour d, 101 pour e et 102 pour f.

Il existe également une possibilité pour lire une chaîne de caractères string caractère par caractère en utilisant un FOR numérique : une chaîne de caractères n’est rien d’autre qu’une sorte de tableau ordonné de caractères.

Le string monTexte = "Bonjour, je suis ici." peut se voir comme le tableau suivant :

Case 00 : contient : B
Case 01 : contient : o
Case 02 : contient : n
Case 03 : contient : j
Case 04 : contient : o
Case 05 : contient : u
Case 06 : contient : r
Case 07 : contient : ,
Case 08 : contient :  
Case 09 : contient : j
Case 10 : contient : e
Case 11 : contient :  
Case 12 : contient : s
Case 13 : contient : u
Case 14 : contient : i
Case 15 : contient : s
Case 16 : contient :  
Case 17 : contient : i
Case 18 : contient : c
Case 19 : contient : i
Case 20 : contient : .

Attention : comme d’habitude en informatique, le premier élément est l’élément 0.

On peut accéder aux différents caractères stockées dans la chaîne de caractéres à l'aide d'une boucle FOR NUMERIQUE. On dit que le String est un objet :

  • itérable car il contient une succession d'éléments (des caractères)
  • séquentiel car on peut y accéder en suivant un certain ordre.

Si on veut connaître la taille d’un string monTexte (son nombre de cases), on peut utiliser la propriété length (longueur en anglais) des strings : monTexte.length renvoie un integer qui vaut … 21. Le tableau va jusqu’à 20 mais la première case est la case 0. D’où 20+1=21. On notera que l’espace est bien stocké dans une case : on stocke bien l’information « laisser un espace » dans la chaîne de caractères.

Nous pouvons accéder à l’élément n°X d’une chaîne de caractères monTexte en utilisant :

  • soit monTexte.charAt( X )
  • soit monTexte[ X ]

Où X est un integer, monTexte est une chaîne de caractères définie préalablement. On notera l’utilisation des crochets [ ] avec le deuxième façon de faire.

La différence entre les deux façons de faire ? Pas grand chose quand la conversion se passe bien. Mais ce sont les détails qui font qu'un programme peut planter ou non. Utilisez plutôt charAt : si vous demandez une case qui n'existe pas, elle va vous renvoyer une chaine vide plutôt qu'une erreur.

A titre d'exemple, voilà un programme qui permet de définir une chaîne de caractères monTexte, de stocker dans nLongueur le nombre de caractères de la chaîne et qui demande quel numéro de caractère nCase afficher. On affiche alors le caractère numéro nCase.

Votre chaîne de caractères:

Position désirée :

La chaîne possède - caractères.

Le caractère voulu est

La chaine jusqu'à ce caractère est

Voici la page html

<!DOCTYPE html>

<html>

    <head>

        <meta charset="UTF-8" />

        <title>Les Strings</title>

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

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

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

    </head>


    <body>


        <header>

            <h1>Recherche de caractères dans une chaîne de caractères</h1>

        </header>


        <section>

            <p>Votre chaîne de caractères:</p>

            <p><input type="text" id="chaine9" placeholder="Votre texte"></p>


            <p>Position désirée :</p>

            <p><input type="text" id="position9" placeholder="Votre position"></p>


            <p><input type="button" onclick="positionCar()" value="Rechercher le caractère à cette position"></p>


            <p>La chaîne possède <span id="reponse8">-</span> caractères.</p>

            <p>Le caractère voulu est <span id="reponse9"></span></p>

            <p>La chaine jusqu'à ce caractère est <span id="reponse10"></span></p>

        </section>


    </body>

</html>

Comme vous le voyez, j'ai pris des noms différents de ceux proposés dans l'énoncé pour le HTML :

On va faire le lien avec les vrais noms dans le javascript. Pourquoi ne pas avoir pris dans le html des id plus compréhensible ? C'est une bonne question. Comme vous allez le voir, le script n'est pas très compréhensible avec des noms comme ça. Je ne vais pas le faire souvent. Mais je voulais vous montrer l'importance de prendre des noms de variables ou d'id explicites. Ici, elles ne sont pas claires et ça va rendre le script un peu plus compliqué à comprendre. Et ce n'est jamais positif.

J'ai ajouté une balise span d'id reponse10 pour plus tard. Elle ne sert à rien pour l'instant.

Voilà le code javascript et la corresondance entre id et nom de variable :

function positionCar() {

    var monTexte = document.getElementById("chaine9").value;

    var nCase = parseInt(document.getElementById("position9").value);

    var nLongueur = monTexte.length;

    var sReponse = monTexte.charAt(nCase);

    document.getElementById("reponse8").innerHTML = nLongueur;

    document.getElementById("reponse9").innerHTML = sReponse;

}

Comme vous le voyez, ce n'est pas facile à comprendre. D'autant plus que les noms d'id ne sont pas EXPLICITES.

Un peu d'aide : les correspondances entre les codes js et les identifiants html sont :

SignificationVariable jsId HTML
La chaîne de caractères étudiée par l'utilisateur monTexte Balise input chaine9
La position voulue dans la chaîne nCase Balise input position9
La longeur de la chaîne nLongueur Balise p reponse8
La réponse du caractère voulu sReponse Balise p reponse9

Vous voyez, c'est parfois un peu pénible de devoir jongler entre trois niveaux de programmation (html, css et javascript). Angular js est un langage qui permet en gros d'écrire du code directement à partir de la page elle-même. Cela évite les corresondances parfois malheureuses où les élements ne possèdent pas le même nom. Il deviendra peut-être l'incontournable langage des années à venir.

16° Rajouter un test IF au code ci-dessus : on ne doit pas accepter de traiter un numéro de case inférieur à 0 ou supérieur à son plus grand numéro. Attention : la propriété length donne la longueur de la chaîne. Si elle renvoie 45, c’est qu’on peut lire les caractères du numéro 0 au numéro 44. Le caractère 45 n’existe pas !

17° Créer maintenant un code qui affiche le texte caractère par caractère jusqu’à la case demandée. Vous devrez pour l’exercice utiliser un FOR associé à un itérateur chiffré pour lire le contenu de la case 0, la placer dans un variable string, concatener la case 1, puis la case 2 … Il faudra envoyer la réponse dans l"id reponse10 du html.

...CORRECTION 16 - 17 ...

function positionCar() {

    var monTexte = document.getElementById("chaine9").value;

    var nCase = parseInt(document.getElementById("position9").value);

    if (nCase >= 0 && nCase <= monTexte.length) {

        var nLongueur = monTexte.length;

        var sReponse = monTexte.charAt(nCase);

        document.getElementById("reponse8").innerHTML = nLongueur;

        document.getElementById("reponse9").innerHTML = sReponse;

    }

}

3 - Exemple de création d'interface

Voyons ce qu'on peut en faire dans une interface Web. Je voudrais générer une application de 500 px sur 500 px.

Dans cette application, je veux créer un certain nombre de carrés bleus de 100 px de côté, separés entre eux par 20 px.

Les carrés seront des balises div , de classe carre, ayant initialement une couleur de background bleu.

Ces balises div , de classe carre, vont être générées par une fonction nommée creation qu'on activera avec un bouton.

Les carrés seront alors créés à l'intérieur d'une balise div d'identifiant conteneur.

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_chap_03.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;

}

Pour l'instant, vous ne connaissez pas de structure de données permettant de stocker les références des balises div de classe carre sans les associer à une variable. Nous allons donc simplement les créer sans nous soucier de pouvoir les modifier ensuite. Pour cela, je vais vous fournir deux fonctions, destruction et rajouter_carre, que vous n'aurez pas à comprendre mais simplement à utiliser .

Voici le javascript qu'il faudra nommer "js_chap_03.js":

var largeur = 50;

var marge = 20;

var nombreCarres = 3;


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 i=0;i<nombreCarres;i++) {

        var x = marge + (largeur+marge)*i;

        var y = marge;

        rajouter_carre(x,y,"blue");

    }

}

Que fait ce script ?

Il faudra rajouter les codes des deux fonctions à la fin de votre fichier js. Ces fonctions ne seront pas expliquées ici. Vous verrez leur fonctionnement dans d'autres activités. Contentez vous de les copier aujourd'hui.

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'était long ! Pffff ! Comme vous le voyez, décrire un projet, ce n'est pas toujours très facile. Il faut savoir en dire assez, mais pas trop. Tout est histoire d'équilibre, et comme cela dépend de la perception des uns et des autres, il faut surtout trouver votre propre équilibre. Bien, passons à l'activité.

18° Analyser le programme, créer et sauvegarder les trois fichiers (html, css et js), lancer le html. Puis modifier le js pour que les carrés soient bien des carrés ayant la bonne largeur (100 pixels). Pensez à utiliser la variable largeur justement.

Le code est incomplet : si on demande 6 carrés, il trace n'importe quoi. Vous pouvez tenter.

Pour palier à cela, nous allons utiliser l'opérateur % qui fournit le modulo d'une division :

De cette façon, la coordonnée en x ne pourra jamais dépasser 500.

Et comment savoir qu'on veut placer le carré en ligne 0, 1, 2 ? Pour savoir cela, nous allons utiliser Math.floor(x/500) qui renvoit la valeur entière de la division de x par 500:

Voici le nouveau code avec la gestion des changements de lignes :

var largeur = 50;

var marge = 20;

var nombreCarres = 3;


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 i=0;i<nombreCarres;i++) {

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

        var x = decalage%500;

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

        rajouter_carre(x,y,"blue");

    }

}

19° Tester le code avec 12 carrés. C'est presque ça, mais pas vraiment ! Trouver la valeur remplacant le 500 pour obtenir un affichage correct dans notre cas.

...CORRECTION...

Il suffit de ne pas inclure la marge finale dans la division.

Si la marge est de 20, il faut donc utiliser 480 plutôt que 500.

C'est bien mais c'est bleu...

Rajoutons des carrés rouge et jaune. Voici les codes à utiliser pour obtenir un carré rouge par exemple :

rajouter_carre(x,y,"red");

Rajoutons un test SI : nous voudrions que les carrés soient alternativement bleu, vert, rouge.

Pour cela, il suffit de prendre la variable i de la boucle FOR et d'en faire le modulo 3 :

20° A l'aide de la description précédente des valeurs obtenues par un modulo 3, réaliser une interface qui rajoute des carrés alternativement bleu, rouge et jaune.

Pour voir le résultat attendu, cliquer sur le bouton Q20 dans l'interface présentée sous la question 19.

Et si vous bloquez, voici une correction possible :

...CORRECTION...

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 i=0;i<nombreCarres;i++) {

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

        var x = decalage%500;

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

        if (i%3 == 0) {

            rajouter_carre(x,y,"blue");

        } else if (i%3 == 1) {

            rajouter_carre(x,y,"red");

        } else {

            rajouter_carre(x,y,"yellow");

        }

    }

}

Voilà. Il nous reste à voir le TANT QUE et le FOR nominatif.

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>

4 - FAQ

Question : comment sortir d'une boucle for avant la fin ?

On utilise l'instruction break. Exemple : on lance une boucle avec un compteur évoluant de 0 à 20 mais on sort définitivement de la boucle lorsque le compteur vaut 5 :

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var compteur=0;compteur<11;compteur++) {

        alert(compteur);

        if (compteur == 5) {

            break;

        }

    }

    alert("FIN DU BOUCLAGE");

}

CLIQUEZ SUR UN BOUTON-REPONSE :

compteur :

Sur la console, on voit bien qu'on ne revient pas dans la boucle pour le cas 6 et plus :

0

1

2

3

4

5

Remarque : même s'il reste des instructions sous le break, on ne les exécute pas : on quitte immédiatement la boucle.

Question : Je voudrais compter de 0 à 6 mais sans passer par 5, c'est possible ?

On utilise l'instruction continue. On lance une boucle avec un compteur évoluant de 0 à 6 mais sans agir pour 5 en forçant un retour au début de la boucle :

function bouclage() {

    alert("DEBUT DU BOUCLAGE : ouvrez la console pour voir les valeurs calculées.");

    for (var compteur=0;compteur<7;compteur++) {

        if (compteur == 5) {

            continue;

        }

        alert(compteur);

    }

    alert("FIN DU BOUCLAGE");

}

CLIQUEZ SUR UN BOUTON-REPONSE :

compteur :

Comme vous le voyez, je n'ai même pas besoin de mettre un else après le if. L'exécution du programme va répartir au début de la boucle dès qu'elle rencontrera continue.

Sur la console, on voit bien qu'on a sauté l'exécution du print pour le 5 :

0

1

2

3

4

6

Remarque : même s'il reste des instructions sous le continue, on ne les exécute pas : on remonte immédiatement la boucle pour faire l'itération suivante.