Outils de base

Identification

Infoforall

7 - Outils de base


Logiciels : Il faudra utiliser un éditeur de code. On propose ici d'utiliser Atom produit par Githhub, aujourd'hui possédé par Google, ou Notepad ++ (Notepadqq sur Linux). Sublim Text est également une alternative de qualité.

Evaluation ✎ : questions 03-04-11.

1 - les tests

Commençons par voir comment gérer les tests.

Tests conditionnels

La structure est assez proche de Python.

Voici un exemple sur une recherche de maximum sur 3 nombres.

  • Si a est plus grand ou égal à b ET que a est plus grand ou égal à c : on renvoie a
  • Si b est plus grand ou égal à a ET que b est plus grand ou égal à c : on renvoie b
  • Sinon : on renvoie c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
function maximum(a, b, c) { /* Fonction qui renvoie la plus grande valeur parmi les nombres a, b et c :: param a (number) :: le premier nombre :: param b (number) :: le deuxième nombre :: param c (number) :: le troisième nombre :: return (number) :: la plus grande valeur parmi a, b ou c */ var reponse = 0; if (a >= b && a >= c) { reponse = a; } else if (b>=a && b>=c) { reponse = b; } else { reponse = c; } return reponse }

Les différences et analogies sont les suivantes

  • Le SI s'écrit if comme avec Python
  • Le SINON Si s'écrit else if contrairement au elif de Python
  • Le SINON s'écrit else comme avec Python
  • Ce sont les accolades d'ouverture { et de fermeture } qui définissent ce que contient chaque bloc.
  • Pas de : à la fin des lignes
  • Le ET s'écrit &&
  • Le OU s'écrit || (AltGr + 6)
  • Il faut encadrer les conditions par des parenthèses

01° Créer une page HTML et le fichier JS outils_base.js en utilisant les codes suivants pour le HTML et le JS.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Outils de base</title> <script src="outils_base.js"></script> </head> <body> <main> <h1>Les tests</h1> <form name="tests"> <input type="number" name="x"> <input type="number" name="y"> <input type="number" name="z"> <br> <input type="button" value="Chercher le maximum" onclick="tests.resultat.innerHTML = maximum(tests.x.value, tests.y.value, tests.z.value);"> La plus grande valeur est <output name="resultat">(non calculé pour l'instant)</output> </form> </main> </body> </html>

Voici le code du fichier outils_base.js 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
function maximum(a, b, c) { /* Fonction qui renvoie la plus grande valeur parmi les nombres a, b et c :: param a (number) :: le premier nombre :: param b (number) :: le deuxième nombre :: param c (number) :: le troisième nombre :: return (number) :: la plus grande valeur parmi a, b ou c */ var reponse = 0; if (a >= b && a >= c) { reponse = a; } else if (b>=a && b>=c) { reponse = b; } else { reponse = c; } return reponse }

Puisqu'on fournit juste le nom du fichier javscript, les deux fichiers HTML et JS doivent être placés dans le même répertoire.

📁 votre dossier de travail

📄 ma_page.html

📄 outils_base.js

Manipulation : utilisez la page, vous devriez parvenir à déterminer le maximum en cliquant sur le bouton.

Testez avec les valeurs 45, 100 et -2. Avez-vous une idée de l'échec dans ce cas ?

Comme d'habitude, le problème vient de la nature des arguments. La personne qui a créé la fonction était claire au niveau des préconditions, fournies dans la documentation de la fonction : a, b et c doivent être des nombres. Or, on leur transmet en réalité un string (tests.x.value est bien un string, pas un nombre.)

Le "problème" de javascript est que le typage est dynamique : on finit parfois par ne plus savoir le type. Pour forcer le type, on va donc simplement utiliser la fonction parseInt.

02° Modifier le code pour permettre un appel à la fonction avec de bonnes préconditions.

...CORRECTION...

Le plus facile est simplement de bien transmettre des entiers.

1 2
<input type="button" value="Chercher le maximum" onclick="tests.resultat.innerHTML = maximum(parseInt(tests.x.value), parseInt(tests.y.value), parseInt(tests.z.value));">

✎ 03° Analyser ce code. Ensuite, modifier le code pour permettre d'autres couleurs françaises que juste 'rouge'. Au moins 'bleu', 'vert' et 'jaune'.

Attention aux particularités du test par rapport à Python : parenthèses autour du test et accolades. Pensez à ouvrir la console de développement pour voir la nature de l'erreur si ça ne fonctionne pas.

Voici l'interface obtenue (seul 'rouge' fonctionne en français). Mais toutes les couleurs HTML anglaises ou numériques (red ou #FF0000) fonctionnent.

Le code HTML

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Choix couleur</title> <script src="outils_base.js"></script> </head> <body> <main> <h1>Les tests</h1> <form name="q3"> <input type="text" name="choix"> <input type="button" name="bouton" value="Alors, quelle couleur ?" onclick="modifier();"> </form> </main> </body> </html>

Le code Javascript initial :

1 2 3 4 5 6 7
function modifier() { let couleur = q3.choix.value; if (couleur == 'rouge') { couleur = '#DD0000'; } q3.bouton.style.backgroundColor = couleur; }

Passons à une interface un peu plus complexe.

✎ 04° Analyser et compléter ce code pour qu'on puisse vérifier si le résultat correspond bien à l'opération demandée.

Le code comporte un form comportant trois input de type nombre.

Vous pouvez modifier les deux premiers. Le but est de fournir la réponse dans le troisième.

Le travail à faire : compléter la fonction pour qu'elle compare la réponse de l'utilisateur à la somme des nombres qu'on place dans les deux premiers champs. Si la réponse est bonne, on veut que le fond de la case soit vert. Si la réponse est fausse, il faut qu'elle soit rouge par exemple.

Vous remarquerez que la fonction possède un squelette des choix logiques en Javascript. Il faudra bien entendu le modifier : ici on teste si c'est positif ou négatif !

Deuxième remarque : n'oubliez pas d'utiliser parseInt pour transformer les valeurs visibles dans les champs. Sinon value va vous ramener des chaînes de caractères.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href='monstyle.css' /> <meta charset="utf-8" /> </head> <body> <h1>Mini jeu calculatoire</h1> <form name="jeu"> <p> <input type="number" name="x" value="10"> + <input type="number" name="y" value="5"> = <input type="number" name="reponse" onchange="verification()"></p> </form> <script> function verification() { var reponse = parseInt(jeu.reponse.value); if (reponse > 0) { } else if (reponse < 0) { } else { } jeu.reponse.style.backgroundColor = '#BBBBBB'; } </script> </body> </html>

Nous n'irons pas plus loin dans la description des tests conditionnels. Cette activité suppose que vous les avez déjà rencontré de nombreuses fois avec un autre langage de programmation.

2 - Boucles non bornées

Javascript permet bien entendu de créer des bornes non bornées (while) ou des boucles bornées (for).

La syntaxe d'utilisation diffère de Python.

05° Observer le code ci-dessous. On veut afficher dans le formulaire 5 4 3 2 1 0 dans l'output si on rentre 5 dans le input.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Le While</title> </head> <body> <main> <h1>Exemple While</h1> <form name="q5"> <input type="number" name="choix" onchange="compter();"> <output name="decompte">Alors ?</output> </form> </main> <script> function compter() { let valeur = parseInt(q5.choix.value); let affichage = ""; while (valeur >= 0) { affichage = affichage + " " + valeur; } q5.decompte.innerHTML = affichage; } </script> </body> </html>

Ca ne fonctionne pas. Pourquoi ? La variable de boucle n'est jamais modifiée.

Proposer une correction du code pour qu'il fonctionne.

...CORRECTION...

Il faut juste diminuer la variable de boucle de un à chaque tour de boucle.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Le While</title> </head> <body> <main> <h1>Exemple While</h1> <form name="q5"> <input type="number" name="choix" onchange="compter();"> <output name="decompte">Alors ?</output> </form> </main> <script> function compter() { let valeur = parseInt(q5.choix.value); let affichage = ""; while (valeur >= 0) { affichage = affichage + " " + valeur; valeur = valeur - 1; } q5.decompte.innerHTML = affichage; } </script> </body> </html>

3 - Boucles bornées

Voici comment réaliser une boucle for pour laquelle la variable de boucle i vaut 0-1-2-3-4.

1 2
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 n'effectue donc pas la boucle pour i valant 5 puisque 5 n'est pas inférieur à 5. On retrouve la même chose qu'avec le range(5) de python : 0-1-2-3-4. On place un point-virgule à la fin de cette condition.

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

06° Observer le code ci-dessous. On veut afficher dans le formulaire 0 10 20 30 40 dans l'output si on rentre 4 dans le input.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Le For</title> </head> <body> <main> <h1>Exemple For</h1> <form name="q5"> <input type="number" name="choix" onchange="compter();"> <output name="decompte">Alors ?</output> </form> </main> <script> function compter() { let valeur = parseInt(q5.choix.value) + 1; let affichage = ""; for (let i = 0; i < valeur*10 ; i = i + 10) { affichage = affichage + " " + i; } q5.decompte.innerHTML = affichage; } </script> </body> </html>

Expliquez pourquoi on additionne 1 à la valeur lue dans le input ligne 19.

...CORRECTION...

On crée une boucle bornée en augmentant de 10 la variable de boucle à chaque tour.

La condition de poursuite est i < valeur*10. Si on laisse 4 par exemple, la boucle ne pourra pas atteindre le cas 40. Il suffit donc de rajouter 1 pour passer de 4 à 5.

Vous verrez la différence entre les notations 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.

4 - méthode getElementById

Pour trouver la référence d'une balise ayant provoqué un événement, nous avons utilisé le mot-clé this.

Sinon, on peut utiliser l'attribut name et placer ces balises dans un formulaire. C'est un moyen un peu détourné de gérer les choses, le formulaire étant surtout destiné à faciliter l'envoi des réponses vers un serveur distant. Mais bon, ça fonctionne en local également.

Mais comment faire pour modifier une balise ne gérant pas l'attribut name ?

L'une des manières de trouver la référence d'une balise quelconque est simplement d'attribuer un identifiant à la balise voulue.

  • On crée une balise dans le fichier html en lui donnant un attribut nommé id (valant ici "couleur")
  • 1
    <p>Couleur voulue : <span id="couleur">bleu</span></p>
  • On fait pointer le javascript vers cette balise avec cet identifiant avec la méthode getElementById.
getElementById

Cette méthode appliquée à l'objet document permet de récupérer la référence d'une balise possèdant un id.

1 - Dans HTML : on attribue un identifiant à une balise  :

HTML
<p>Couleur voulue : <span id="couleur">bleu</span></p>

2 - Dans Javascript : on retrouve la référence grace à getElementById et l'identifiant :

JS1
var reference_balise = document.getElementById('couleur');

Avec cet exemple, reference_balise contient la référence de la balise HTML d'id 'couleur'.

Pour récupérer le contenu interne de la balise, il suffit alors d'utiliser un code de ce type :

JS1 JS2
var reference_balise = document.getElementById('couleur'); var couleur_demandee = reference_balise.innerHTML;

On utilise cette décomposition si on sait qu'on veut agir plusieurs fois sur la balise. Sinon on sait qu'on ne va faire qu'une unique modification, on peut se passer de placer la référence dans une variable :

JS1+2
var couleur_demandee = document.getElementById('couleur').innerHTML;

Dans les deux cas, la variable couleur_demandee contient 'bleu' puisque c'est le contenu interne de la balise (voir la ligne HTML1).

07° Créer la page HTML ci-dessous qui intégre directement le script javascript. Lancer la page pour vérifier qu'elle fonctionne correctement : pour l'instant, javascript ne fait qu'une chose : il affiche le contenu interne d'un span dans une fenêtre-alerte.

On y crée :

  • ligne 12 : une balise span ayant un attribut id valant couleur
  • HTML-12
    <span id="couleur">
  • ligne 13 : une balise p ayant un attribut id valant texte
  • HTML-13
    <p id="texte">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Méthode getElementById</title> </head> <body> <main> <h1>Utilisation de getElementById</h1> <p>Couleur voulue : <span id="couleur">blue</span></p> <p id="texte">Le texte devrait avoir la couleur voulue maintenant.</p> </main> <script> function demarrage() { var choix_couleur = document.getElementById("couleur").innerHTML; alert(choix_couleur); } window.addEventListener("load",demarrage); </script> </body> </html>

08° Pourquoi se passe-t-il alors quelque chose lorsque la page est entièrement chargée ?

...CORRECTION...

La ligne 22 permet de voir qu'on lie l'événement load à la fonction demarrage : cette fonction est donc lancée automatiquement lorsque la page HTML est entièrement réalisée.

09° Rajouter les instructions nécessaires pour que le texte du paragraphe d'identifiant texte soit écrit dans la couleur indiquée dans la balise d'identifiant couleur.

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Méthode getElementById</title> </head> <body> <main> <h1>Utilisation de getElementById</h1> <p>Couleur voulue : <span id="couleur">blue</span></p> <p id="texte">Le texte devrait avoir la couleur voulue maintenant.</p> </main> <script> function demarrage() { var choix_couleur = document.getElementById("couleur").innerHTML; alert(choix_couleur); var paragraphe = document.getElementById("texte"); paragraphe.style.color = choix_couleur; } window.addEventListener("load",demarrage); </script> </body> </html>

Bien entendu, en termes d'interaction, on est au niveau 0. Deux solutions :

  • Permettre à l'utilisateur de modifier le span (pas top)
  • Remplacer le span par un input (il sert à ça)
Attribut contenteditable

Si vous voulez rendre une balise texte éditable par l'utilisateur, il suffit de rajouter un attribut contenteditable dans la balise

1
<p>Couleur voulue : <span contenteditable="true" id="couleur">bleu</span></p>

Par défaut, les balises ne sont pas éditables.

On peut bien entendu modifier l'attribut depuis Javascript si on connait la référence de la balise. Voici le code pour activer (ligne 2) ou désactiver (ligne 3) cette fonctionnalité :

1 2 3
var ref_balise = document.getElementById('couleur'); ref_balise.contentEditable = 'true'; ref_balise.contentEditable = 'false';

Attention à la présence de la majuscule en Javascript contrairement au HTML.

10° Modifier le span de la couleur de façon à ce qu'il soit éditable. On rajoutera donc l'attribut contenteditable. Vérifier qu'on puisse bien modifier le texte : cliquer dessus et taper quelque chose au clavier. Malheureusement, cela ne provoque pas encore changement de couleur... On change juste le texte. Pourquoi la couleur du texte n'est-elle pas modifiée ?

...CORRECTION...

Il s'agit d'insérer cela ligne 12:

12
<p>Couleur voulue : <span contenteditable="true" id="couleur">bleu</span></p>

Pourquoi la couleur ne change pas lorsqu'on change le texte ? Tout simplement car la fonction provoquant le changement de couleur n'est pas réactivée. Pour savoir faire cela, il va falloir gérer les événements sur la page. C'est l'objet de la question suivante.

✎ 11° Rajouter maintenant un attribut d'événement (onchange, onclick...) permettant à l'utilisateur de modifier la couleur du texte.

En conclusion, voici la solution n°2, celle avec un input. On notera les deux solutions : la solution A (un attribut id) et la solution B (un attribut name et un formulaire).

Couleur voulue :

Le texte devrait avoir la couleur voulue maintenant.

Solution A :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Méthode getElementById</title> </head> <body> <main> <h1>Utilisation de getElementById</h1> <p>Couleur voulue : <input type="text" id="couleur" onchange="demarrage();"></p> <p id="texte">Le texte devrait avoir la couleur voulue maintenant.</p> </main> <script> function demarrage() { var choix_couleur = document.getElementById("couleur").value; alert(choix_couleur); var paragraphe = document.getElementById("texte"); paragraphe.style.color = choix_couleur; } window.addEventListener("load",demarrage); </script> </body> </html>

12° Pourquoi avoir utilisé un value et pas un innerHTML sur le input ?

...CORRECTION...

Tout simplement car la balise input est une balise orpheline : la réponse de l'utilisateur n'est pas contenu dans le contenu interne (il n'y en a pas !) mais dans un attribut nommé value.

S'agissant d'une balise input, on aurait également pu la placer dans un formulaire et utiliser un attribut name pour retrouver sa référence. Voici cette solution :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8" /> <title>Méthode getElementById</title> </head> <body> <main> <h1>Utilisation de getElementById</h1> <form name="v2"> <p>Couleur voulue : <input type="text" name="couleur" onchange="demarrage();"></p> </form> <p id="texte">Le texte devrait avoir la couleur voulue maintenant.</p> </main> <script> function demarrage() { var paragraphe = document.getElementById("texte"); paragraphe.style.color = v2.couleur.value; } window.addEventListener("load",demarrage); </script> </body> </html>

En conclusion :

  • Trouver la balise ayant déclenchée un événement : mot-clé this
  • Trouver certaines références de balises liées au formulaire : attribut name
  • Sinon : attribut id en HTML et getElementById dans Javascript.

5 - FAQ

Comment peut-on tester le type d'une donnée ?

Opérateur typeof

Il ne s'agit ni d'une fonction ni d'une procédure puisqu'on ne fournit pas d'argument. Il s'agit d'un opérateur. En plaçant un espace et la variable à étudier juste derrière, on parvient à récupérer le type du contenu.

Les types usuels sont :

  • number pour les nombres
  • string pour les chaînes de caractères
  • object pour les objets, dont les références des balises HTML
  • boolean pour les booléens, true ou false en Javascript
  • undefined pour le contenu non défini. C'est un peu le None de Python.

On peut tester le type d'une variable en utilisant un test de ce type :

typeof maVariable == 'number';

Et comment peut-on modifier la classe d'une balise ? class est un mot-clé de Javascript !

On pourrait récupérer la valeur ou changer la valeur contenue dans la class d'une balise HTML. Il n'y aura aucune différence par rapport avec ce qu'on a fait avec id par exemple. Sauf, sauf, sauf que ... class est un mot-clé dans javascript. C'est un mot comme function, true ou false. On ne peut pas l'utiliser comme nom de variables ou autres. Comment faire alors ?

On remplacera class par className. Et le tour est joué.

1
ref_balise.className = 'maClasseCSSQueJeVeux';

Dans les prochaines activités, nous allons voir la réelle puissance des formulaires : leur capacité à envoyer les données au serveur distant.

Activité publiée le 10 07 2020
Dernière modification : 10 07 2020
Auteur : ows. h.