Exercice 3 — analyse et interprétation du code JavaScript, dans l’esprit des sessions 2023–2025
La page carte.html du site VéloCité permet de recharger une carte d’abonné. Son formulaire (figure 1) est contrôlé par les fonctions du fichier externe controleVelo.js (figure 2), dont la fonction verifier() est incomplète.
Figure 1 — code HTML de carte.html :
1 <body onload="inconnue()">
2 <form id="f" action="abonnement.php" method="post" onsubmit="return verifier()">
3 <label>N° de carte :</label> <input type="text" id="carte" name="carte" maxlength="8"><br>
4 <label>Formule :</label>
5 <select id="formule" name="formule">
6 <option>Choisir une formule</option>
7 <option value="F1">Journalier</option>
8 <option value="F2">Mensuel</option>
9 <option value="F3">Annuel</option>
10 </select><br>
11 <label>Début :</label> <input type="date" id="debut" name="debut"><br>
12 <label>Stations favorites (3 au plus) :</label>
13 <input type="checkbox" name="station[]" value="1">Bab Bhar
14 <input type="checkbox" name="station[]" value="2">Sfax Jadida Nord
15 <input type="checkbox" name="station[]" value="3">Jardin Taparura
16 <input type="checkbox" name="station[]" value="4">Gare<br>
17 <p id="message"></p>
18 <input type="submit" value="Valider"> <input type="reset" value="Annuler">
19 </form>
20 </body>Figure 2 — extrait de controleVelo.js :
1 function inconnue()
2 {
3 const d = new Date()
4 let m = d.getMonth() + 1
5 if (m < 10)
6 m = "0" + m
7 document.getElementById("debut").value = d.getFullYear() + "-" + m + "-01"
8 }
9 function stations()
10 {
11 const cases = document.getElementsByName("station[]")
12 let n = 0
13 for (let i = 0; i < cases.length; i++)
14 if (cases[i].checked)
15 n = n + 1
16 return n
17 }
18 function verifier()
19 {
20 let carte = document.getElementById("carte").value.trim()
21 let ok = ……①…… // Tâche_1
22 let i = 0
23 while (i < ……②…… ……③…… ok) // Tâche_2, Tâche_3
24 {
25 let c = ……④…… // Tâche_4
26 if (c < "0" || c > "9")
27 ok = false
28 else
29 i = i + 1
30 }
31 if (……⑤…… (ok && carte.length == 8)) // Tâche_5
32 { ……⑥……("Le numéro de carte doit comporter 8 chiffres") // Tâche_6
33 return false }
34 if (document.getElementById("formule").selectedIndex == 0)
35 { alert("Il faut choisir une formule")
36 return false }
37 let n = stations()
38 if (n == 0 || n > 3)
39 { document.getElementById("message").innerHTML = "Cochez entre 1 et 3 stations"
40 return false }
41 return true
42 }1. Pour chaque ligne de la fonction verifier() contenant des pointillés, on propose trois expressions dont une seule réalise la tâche indiquée. Compléter le tableau en écrivant le numéro de l’expression correcte correspondant à chaque « Tâche ».
- Tâche_1 (Initialiser ok à vrai) : 1. True ; 2. true ; 3. vrai
- Tâche_2 (Récupérer la longueur de carte) : 1. carte.length() ; 2. length(carte) ; 3. carte.length
- Tâche_3 (Utiliser l’opérateur logique ET) : 1. && ; 2. AND ; 3. ||
- Tâche_4 (Récupérer le iᵉ caractère de carte) : 1. carte.charCodeAt(i) ; 2. carte.charAt(i) ; 3. charAt(i)
- Tâche_5 (Utiliser l’opérateur de négation) : 1. not ; 2. <> ; 3. !
- Tâche_6 (Afficher un message dans une boîte de dialogue) : 1. echo ; 2. alert ; 3. write
| Tâche | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| N° de l’expression |
2. On considère les trois exemples suivants, saisis avant un clic sur « Valider » (la fonction verifier() étant complétée) :
- Exemple 1 : N° de carte « 20A60417 », formule « Mensuel », stations cochées : Bab Bhar et Gare.
- Exemple 2 : N° de carte laissé vide, formule « Annuel », aucune station cochée.
- Exemple 3 : N° de carte « 20260417 », formule « Mensuel », stations cochées : Bab Bhar, Jardin Taparura et Gare.
a. Pour l’exemple 1, donner les valeurs successives de i, c et ok lors de l’exécution de la boucle while (lignes 23 à 30), puis la valeur retournée par verifier() et le message affiché.
b. Pour l’exemple 2, combien de fois la boucle while s’exécute-t-elle ? Donner la valeur de ok à la sortie de la boucle, la valeur retournée par verifier() et le message affiché. Que se passerait-il si le test carte.length == 8 n’existait pas ?
c. Pour l’exemple 3, donner, à chaque tour de la boucle for de la fonction stations(), les valeurs de i, de cases[i].checked et de n, puis la valeur retournée par stations() et celle retournée par verifier().
3. On s’intéresse à la fonction inconnue().
a. Quand cette fonction est-elle exécutée ?
b. Pourquoi ajoute-t-on 1 à la ligne 4, et pourquoi ajoute-t-on « 0 » devant m à la ligne 6 ?
c. En déduire le rôle de la fonction inconnue().
4. Indiquer devant chaque rôle l’élément du langage JavaScript qui lui correspond :
- Méthode qui supprime les espaces au début et à la fin d’une chaîne.
- Propriété qui donne le rang de l’option choisie dans une liste déroulante.
- Propriété qui modifie le contenu HTML d’un élément.
- Méthode qui retourne la liste des éléments ayant le même nom.
- Propriété qui indique si une case est cochée ou non.
- Méthode qui retourne le mois d’une date, de 0 (janvier) à 11 (décembre).
- Méthode qui retourne l’élément ayant un identifiant donné.
- Propriété qui contient le contenu d’un champ de saisie.
Version A :
function stations()
{
const cases = document.getElementsByName("station[]")
let n = 0
for (const i = 0; i < cases.length; i++)
if (cases[i].checked)
n = n + 1
return n
}Version B :
function stations()
{
const cases = document.getElementsByName("station[]")
let n
for (let i = 0; i < cases.length; i++)
if (cases[i].checked)
n = n + 1
return n
}Version C :
function stations()
{
const cases = document.getElementsByName("station[]")
let n = 0
let i = 0
while (i < cases.length)
{ if (cases[i].checked == true)
n++
i++ }
return n
}Version D :
function stations()
{
const cases = document.getElementsByName("station[]")
let n = 0
for (let i = 1; i <= cases.length; i++)
if (cases[i].checked)
n = n + 1
return n
}Voir la correction commentéeAprès avoir posé votre démarche
1. Idée : en JavaScript, la casse et les parenthèses comptent — true en minuscules, length est une propriété (sans parenthèses), charAt est une méthode appelée sur la chaîne, ! et && sont les opérateurs logiques.
| Tâche | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| N° | 2 | 3 | 1 | 2 | 3 | 2 |
Tâche_1 : true (True et vrai ne sont pas des valeurs JavaScript : la casse compte) ; Tâche_2 : carte.length ; Tâche_3 : && ; Tâche_4 : carte.charAt(i) (charCodeAt renvoie un code numérique) ; Tâche_5 : ! ; Tâche_6 : alert (echo est du PHP).
2.a Idée : la boucle avance tant que le caractère courant est un chiffre ; au premier caractère qui n’en est pas un, ok passe à false et la boucle s’arrête.
| Tour | c | ok | i (fin du tour) |
|---|---|---|---|
| 1 | "2" | true | 1 |
| 2 | "0" | true | 2 |
| 3 | "A" | false | 2 |
Sortie de boucle avec i = 2 et ok = false : la condition !(ok && carte.length == 8) est vraie. verifier() affiche la boîte de dialogue « Le numéro de carte doit comporter 8 chiffres » et retourne false : le formulaire n’est pas envoyé.
2.b Idée : une chaîne vide a une longueur 0, donc la condition i < carte.length est fausse dès le départ. La boucle s’exécute 0 fois et ok reste true. Mais carte.length == 8 est faux, donc !(true && false) est vrai : alerte « Le numéro de carte doit comporter 8 chiffres » et retour false. Sans ce test, la condition deviendrait !ok, fausse ici : une carte vide passerait le contrôle du numéro (aucun caractère n’est refusé), et il en irait de même pour un numéro de moins de 8 chiffres. Pour l’exemple 2, verifier() continuerait : la formule « Annuel » a le rang 3 (≠ 0), puis stations() retourne 0 ; le paragraphe message affiche alors « Cochez entre 1 et 3 stations » et verifier() retourne false.
2.c La carte « 20260417 » passe la boucle (8 chiffres), la formule a le rang 2 (≠ 0). Trace de stations() :
| i | cases[i].checked | n |
|---|---|---|
| 0 | true | 1 |
| 1 | false | 1 |
| 2 | true | 2 |
| 3 | true | 3 |
stations() retourne 3, compris entre 1 et 3 : verifier() retourne true, les données sont envoyées à abonnement.php.
3.a Au chargement de la page, grâce à onload="inconnue()" (ligne 1 de carte.html).
3.b getMonth() renvoie le mois de 0 (janvier) à 11 (décembre) : on ajoute 1 pour obtenir le numéro usuel. Le « 0 » écrit les mois 1 à 9 sur deux chiffres (« 03 » et non « 3 ») : un champ type="date" attend une valeur de la forme aaaa-mm-jj.
3.c inconnue() initialise le champ « Début » (id debut) au premier jour du mois en cours : par exemple « 2026-03-01 » si la page est ouverte le 15 mars 2026.
4.
| Rôle | Élément |
|---|---|
| Méthode qui supprime les espaces au début et à la fin d’une chaîne. | trim() |
| Propriété qui donne le rang de l’option choisie dans une liste déroulante. | selectedIndex |
| Propriété qui modifie le contenu HTML d’un élément. | innerHTML |
| Méthode qui retourne la liste des éléments ayant le même nom. | getElementsByName() |
| Propriété qui indique si une case est cochée ou non. | checked |
| Méthode qui retourne le mois d’une date, de 0 (janvier) à 11 (décembre). | getMonth() |
| Méthode qui retourne l’élément ayant un identifiant donné. | getElementById() |
| Propriété qui contient le contenu d’un champ de saisie. | value |
5. Idée : pour chaque version, vérifier l’initialisation du compteur, le compteur de boucle et les bornes des indices.
- Version A : F — le compteur i est déclaré
const: l’instructioni++provoque une erreur à la fin du premier tour. - Version B : F — n n’est pas initialisé (
undefined) :n + 1donneNaN, la fonction retourne NaN dès qu’une case est cochée (etundefinedsi aucune ne l’est). - Version C : V — boucle while équivalente : n initialisé à 0, i de 0 à cases.length − 1,
n++ajoute 1. - Version D : F — les indices vont de 0 à cases.length − 1 : la case d’indice 0 (Bab Bhar) est ignorée et
cases[cases.length]n’existe pas, d’où une erreur au dernier tour.