JavaScript
JavaScript est un langage de programmation qui permet, entre autres, de modifier le contenu d'un document Web de façon interactive (clic souris, saisie clavier, etc).
Il existe deux moyens d'incorporer un programme JavaScript au sein d'un document Web. Le premier consiste
à renseigner le code source du script directement dans le document à l'aide de l'élément
script
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first JavaScript program</title>
</head>
<body>
<h1></h1>
<script>
let message = "Hello World Wide Web!";
document.querySelector("h1").textContent = message;
</script>
</body>
</html>
Le code source du script peut aussi être sauvegardé dans un fichier externe. L'attribut
src
de l'élément script
permet de renseigner le chemin et le nom
du fichier JavaScript.
/*
* Fichier hello.js dans le sous-répertoire js
*
*/
let message = "Hello World Wide Web!";
document.querySelector("h1").textContent = message;
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first JavaScript program</title>
</head>
<body>
<h1></h1>
<script src="js/hello.js"></script>
</body>
</html>
Arbre DOM (Document Object Model)
L'arbre DOM correspond à la représentation mémoire d'un document Web. Chaque élément HTML est représenté par un noeud et ses éléments imbriqués (enfants) apparaissent comme des ramifications. JavaScript propose un mécanisme permettant d'accéder à un élément donné du document et d'en modifier le contenu.
Modification d'un élément
L'objet JavaScript document
représente la racine de l'arbre DOM. La méthode
querySelector()
permet de formuler un sélecteur CSS afin d'accéder à un élément
HTML du document. L'objet JavaScript DOMELement
retourné dispose de plusieurs
propriétés dont textContent
qui contient, sous la forme d'une chaîne de caractères, le contenu textuel de l'élément.
Ainsi, pour modifier dynamiquement le contenu d'un document Web, il suffit de remplacer
la valeur de la propriété textContent
d'un élément par une nouvelle chaîne
de caractères. Dans l'exemple ci-dessus, le contenu (initialement vide) de l'élément
h1
est remplacé par la valeur de la variable message
.
Création d'un nouvel élément
La méthode createElement()
de l'objet document
permet de créer
un nouvel élément. Celui-ci peut ensuite être ajouté à l'arbre DOM avec la méthode
appendChild()
. L'exemple suivant illuste cette démarche.
variables
JavaScript est un langage à typage dynamique. Lors de la création d'une variable,
inutile de préciser son type. Il suffit juste d'utiliser le mot-clé let
.
let message = "Hello!"; // string
let width = 640; // number
let radius = 15.25; // number
let running = false; // boolean
Boucles
Comme dans beaucoup de langages de programmation, il est possible de créer des structures itératives (boucles). Leur syntaxe est différente de Python mais est très semblable à celle de langages comme Java, C, C++.
#
# 10 itérations
# i allant de 0 à 9
#
for i in range(10):
print(i)
/*
* 10 itérations
* i allant de 0 à 9
*/
for(let i=0; i<10; i++) {
console.log(i);
}
En JavaScript, les instructions à l'intérieur de la boucle sont
délimitées par les accolades ouvrante {
et fermante
}
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Multiplications by 7</title>
</head>
<body>
<ul></ul>
<script>
/*
* Récupération de l'élément ul dans
* l'arbre DOM
*/
let ul = document.querySelector("ul");
for (let i=0;i<=10; i++) {
/*
* Création d'un élément li
*/
let li = document.createElement("li");
/*
* Mise à jour du contenu de l'élément li à l'aide
* de la propriété innerHTML car la chaîne de caractères
* contient du code HTML (entité HTML)
*/
li.innerHTML = "7 × " + i + " = " + (7*i);
/*
* Ajout d'un nouvel enfant (dernier) à l'élément ul
*/
ul.appendChild(li);
}
</script>
</body>
</html>
Une boucle en JavaScript peut aussi être utilisée pour parcourir une liste
d'éléments. Par exemple, la méthode querySelectorAll()
retourne
une liste de DOMElement
.
Le code ci-dessous parcourt tous les éléments h2
afin de numéroter
automatiquement tous les titres de niveau 2 du fichier cartoon_physics.html
vu au chapitre Hypertexte.
let chapterNumber = 1;
let h2List = document.querySelectorAll("h2");
for (let i = 0; i < h2List.length; i++) {
let h2 = h2List[i];
h2.textContent = chapterNumber + '. ' + h2.textContent;
chapterNumber++;
}
Et une version alternative avec la structure for of
.
let chapterNumber = 1;
let h2List = document.querySelectorAll("h2");
for (let h2 of h2List) {
h2.textContent = chapterNumber + '. ' + h2.textContent;
chapterNumber++;
}
Exercice
Écrire un programme JavaScript qui génère automatiquement le sommaire du fichier
cartoon_physics.html
/*
* Récupération de l'élément ul dans
* l'arbre DOM
*/
let h1 = document.querySelector("h1");
/*
* Création d'un attribut id dans l'élément h1
*/
h1.setAttribute("id", "top");
/*
* Récupération de l'élément ul dans
* l'arbre DOM
*/
let ul = document.querySelector("ul");
let h2List = document.querySelectorAll("h2");
for (let i = 0; i < h2List.length; i++) {
let h2 = h2List[i];
/*
* Création d'un élément li
*/
let li = document.createElement("li");
/*
* Création d'un élément a
*/
let a = document.createElement("a");
/*
* Mise à jour du contenu de l'élément li à l'aide
* de la propriété innerHTML car la chaîne de caractères
* contient du code HTML (entité HTML)
*/
a.textContent = h2.textContent;
/*
* Création d'un attribut dans l'élément h2
*/
let idValue = "l" + (i + 1);
a.setAttribute("href", "#" + idValue);
/*
* Ajout de l'élément A à l'élément LI
*/
li.appendChild(a);
/*
* Ajout d'un nouvel enfant (dernier) à l'élément ul
*/
ul.appendChild(li);
/*
* Création d'un attribut dans l'élément h2
*/
h2.setAttribute("id", idValue);
/*
* Ajout de code HTML dans l'élément h2
*/
h2.innerHTML = h2.innerHTML + " <a href=\"#top\">↑</a>";
}
Tests
La syntaxe des tests est aussi différente de Python.
if hour<12:
print("Good morning)
else:
print("Good afternoon)
if (hour<12) {
console.log("Good morning");
}
else {
console.log("Good afternoon");
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<p></p>
<script>
// Récupération de la date courante
let now = new Date();
// Extraction de l'heure
let hours = now.getHours();
// Affectation du message en fonction de l'heure
let message = "";
if (hours<12) {
message = "Good morning";
}
else {
message = "Good afternoon";
}
// Modification du contenu du paragraphe (p)
document.querySelector("p").textContent = message;
</script>
</body>
</html>
Exercice
Concevoir un programme JavaScript qui affiche l'heure au format HH:MM:SS à laquelle la page a été ouverte
(l'heure est figée). Pour plus de détails, consulter la documentation de l'objet JavaScript
Date
.
10:07:01
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Time is frozen</title>
</head>
<body>
<time></time>
<script>
let now = new Date();
let hours = now.getHours();
if (hours<10) hours = "0" + hours;
let minutes = now.getMinutes();
if (minutes<10) minutes = "0" + minutes;
let seconds = now.getSeconds();
if (seconds<10) seconds = "0" + seconds;
document.querySelector("time").textContent = hours + ":" + minutes + ":" + seconds;
</script>
</body>
</html>
Fonctions
Une fonction JavaScript est définie à l'aide du mot-clé function
. Toujours
en raison du typage dynamique, il est inutile de préciser la nature de l'objet retourné
dans le prototype de fonction.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Function</title>
</head>
<body>
<p</p>
<script>
function hello() {
let now = new Date();
let hours = now.getHours();
if (hours<12) {
return "Good morning";
}
else {
return "Good afternoon";
}
}
document.querySelector("p").textContent = hello();
</script>
</body>
</html>
Exercice
Modifier le code du programme de l'exercice 36 en utilisant une fonction afin que l'affichage
de l'heure soit mis à jour toutes les secondes. Pour cela, consulter la documentation de la
méthode
window.setInterval()
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Time is running</title>
</head>
<body>
<time></time>
<script>
function displayDate() {
let now = new Date();
let hours = now.getHours();
if (hours<10) hours = "0" + hours;
let minutes = now.getMinutes();
if (minutes<10) minutes = "0" + minutes;
let seconds = now.getSeconds();
if (seconds<10) seconds = "0" + seconds;
document.querySelector("time").textContent = hours + ":" + minutes + ":" + seconds;
}
// Appel de la fonction displayDate toutes les 1000 millisecondes
window.setInterval(displayDate, 1000);
</script>
</body>
</html>
Programmation événementielle
Le principe de la programmation événementielle consiste à pouvoir déclencher un appel de fonction
lors de la survenue d'un événément (click
, keyup
, change
,
etc). La méthode addEventListener()
permet d'associer un événement à un appel
de fonction.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Event</title>
</head>
<body>
<button>Click me!</button>
<script>
let button = document.querySelector("button");
button.addEventListener("click", (event) => {
let red = Math.floor(Math.random()*256);
let green = Math.floor(Math.random()*256);
let blue = Math.floor(Math.random()*256);
button.style.backgroundColor = "rgb(" + red + "," + green + "," + blue + ")";
});
</script>
</body>
</html>
Exercice
Modifiez le fichier form.html
afin d'exiger une double saisie
du mot de passe. Une fonction JavaScript associée à l'événement
submit
du formulaire empêchera la transmission des informations
au serveur si les mots de passe ne sont pas identiques.
<!doctype html>
<html lang="fr">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<title>Inscription</title>
</head>
<body>
<div class="w3-content">
<h1>Inscription</h1>
<form name="signin" method="POST" enctype="multipart/form-data" action="https://iut-info.univ-reims.fr/users/nocent/web/tools/http_request_analyzer.php">
<label>Nom</label>
<input class="w3-input" type="text" name="lastname"
required pattern="[A-Za-z]+">
<label>Prénom</label>
<input class="w3-input" type="text" name="firstname"
required pattern="[A-Za-z]+">
<label>Date de naissance</label>
<input class="w3-input" type="date" name="birthdate" required>
<label>
<input class="w3-radio" type="radio" name="gender" value="female" checked>
Femme
</label>
<label>
<input class="w3-radio" type="radio" name="gender" value="male">
Homme
</label>
<br>
<label>Pays</label>
<select class="w3-select" name="country" required>
<option value="" disabled selected>Choisissez...</option>
<option value="1">Allemagne</option>
<option value="2">Belgique</option>
<option value="3">France</option>
</select>
<label>Courriel</label>
<input class="w3-input" type="email" name="email" required>
<label>Mot de passe</label>
<input class="w3-input" type="password" name="pswd1"
required pattern="[A-Za-z]+[@#%][1-9][0-9]{3,}">
<label>Confirmez le mot de passe</label>
<input class="w3-input" type="password" name="pswd2"
required pattern="[A-Za-z]+[@#%][1-9][0-9]{3,}">
<div id="alert" class="w3-panel w3-red" style="display: none">
<h2>Attention !</h2>
<p>Les mots de passe saisis sont différents.</p>
</div>
<label>Photo</label>
<input class="w3-input" type="file" name="photo" accept="image/jpeg, image/png">
<button class="w3-button w3-blue" type="submit">Envoyer</button>
<button class="w3-button w3-red" type="reset">Effacer</button>
</form>
</div>
<script>
let signin = document.forms.namedItem('signin');
signin.addEventListener("submit", (event) => {
let pswd1 = signin.elements.namedItem("pswd1").value;
let pswd2 = signin.elements.namedItem("pswd2").value;
if (pswd1 != pswd2) {
event.preventDefault();
document.querySelector("#alert").style.display = "block";
}
});
</script>
</body>
</html>
Exercice Cookie Clicker reboot
Complétez le code du fichier
cookie.html
afin de concevoir un idle game consistant à cliquer sur un cookie le
plus grand nombre de fois en 15 secondes.
Images à télécharger :
La fonction reset()
Elle remet le score à zéro et modifie l'interface du jeu : elle masque le bouton start et affiche la zone d'affichage du temps restant.
function reset() {
// Cache le bouton start
startButton.classList.toggle("hidden");
// Affiche le temps restant
timeDisplay.classList.toggle("hidden");
// Remise à zéro du score
clickCount = 0;
score.textContent = 0;
// Réinitialisation du temps restant
remainingTime = 15;
}
La fonction countdown()
Elle met à jour le compte à rebours et teste si la partie est terminée.
-
Si la partie est terminée, modifier la variable
playing
pour arrêter la partie et mettre à jour l'interface du jeu : afficher le bouton start et masquer la zone d'affichage du temps restant -
Sinon, afficher le nombre de secondes restantes en rouge (si
remainingTime
est inférieure ou égale à 5), en orange (siremainingTime
est inférieure ou égale à 10) ou en noir dans le cas contraire -
Décrémenter la variable
remaininTime
-
Enfin, appeler à nouveau la fonction
countdown()
dans une 1 seconde
function countdown() {
if (remainingTime == 0) { // Si le temps est écoulé
// Fin de la partie
playing = false;
// Affiche le bouton start
startButton.classList.toggle("hidden");
// Cache le temps restant
timeDisplay.classList.toggle("hidden");
}
else {
// Mise à jour des secondes restantes
time.textContent = remainingTime + " seconds left!";
// Modification de la couleur du texte en fonction du temps
if (remainingTime<=5)
time.style.color = "red";
else if (remainingTime<=10)
time.style.color = "orange";
else
time.style.color = "white";
// Mise à jour du temps restant
remainingTime--;
// Appel de la fonction countdown dans 1 seconde
window.setTimeout(countdown, 1000);
}
}
L'écouteur d'événement du cookie
Il consiste simplement à incrémenter le score lorsque la partie est en cours
(booléen playing
).
cookieImage.addEventListener("click", function(event) {
if (playing) { // Si la partie est en cours
// Mise à jour du score
clickCount++;
score.textContent = clickCount;
}
});
L'écouteur d'événement du bouton start
Il démarre la partie (booléen playing
), initialise la variable
startTime
et appelle les fonctions reset
et
countdown
.
startButton.addEventListener("click", function(event) {
// La partie est démarrée
playing = true;
// Réinitialisation de l'interface
reset();
// Démarrage du compte à rebours
countdown();
});
Exercice
Concevoir un programme pour jouer au jeu Rock, Paper, Scissors contre le navigateur :
- Le joueur fait son choix (rock, scissors ou paper) en cliquant sur une des 3 cases.
- Initialisation d'une variable entière
player
sachant querock
→ 0,scissors
→ 1 etpaper
→ 2. -
Initialisation d'une variable entière
computer
à l'aide d'un tirage aléatoire
Indication : documentation des méthodesMath.random()
etMath.floor()
. -
Comparaison des valeurs des variables
player
etcomputer
pour afficher le résultat:
Images à télécharger :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Rock, Scissors and Paper</title>
<style>
.hidden {
display: none;
}
</style>
</head>
<body>
<h1>Rock, paper, scissors</h1>
<figure id="game">
<img src="img/rock.png" alt="rock">
<img src="img/paper.png" alt="paper">
<img src="img/scissors.png" alt="scissors">
<figcaption>It's up to you, human</figcaption>
</figure>
<figure id="results" class="hidden">
</figure>
<script>
// Correspondance numéro - libellé
let label = ["rock", "paper", "scissors"];
let game = document.querySelector("#game");
let results = document.querySelector("#results");
function play(humanChoice) {
// Choix de l'ordinateur
let computerChoice = Math.floor( Math.random()*1000 ) % 3;
// Suppression du contenu de la figure #results
// par la destruction de tous les éléments enfants
while (results.firstChild) results.removeChild(results.firstChild);
// Création de l'image correspondant au choix du joueur
let humanImage = document.createElement("img");
humanImage.setAttribute("src", "img/" + label[humanChoice] + ".png");
humanImage.setAttribute("alt", label[humanChoice]);
results.appendChild(humanImage);
// Création de l'image correspondant au choix de l'ordinateur
let computerImage = document.createElement("img");
computerImage.setAttribute("src", "img/" + label[computerChoice] + ".png");
computerImage.setAttribute("alt", label[computerChoice]);
results.appendChild(computerImage);
// Création du libellé du résultat
let caption = document.createElement("figcaption");
if (humanChoice == computerChoice)
caption.textContent = "Draw";
else
if ( (humanChoice==0 && computerChoice==2) ||
(humanChoice==2 && computerChoice==1) ||
(humanChoice==1 && computerChoice==0) )
caption.textContent = "Human wins!";
else
caption.textContent = "Computer wins!";
results.appendChild(caption);
// Bascule de l'affichage : suppression/ajout de la classe CSS hidden
game.classList.toggle("hidden");
results.classList.toggle("hidden");
}
// Création des écouteurs d'événement
let rock = document.querySelector("#game [alt=rock]");
rock.addEventListener("click", function() { play(0); });
let paper = document.querySelector("#game [alt=paper]");
paper.addEventListener("click", function() { play(1); });
let scissors = document.querySelector("#game [alt=scissors]");
scissors.addEventListener("click", function() { play(2); });
</script>
</body>
</html>
Exercice
Modifier le code de l'exercice précédent pour jouer au jeu Rock, Scissors, Paper, Lizard, Spock. popularisé par la sérié télévisée Big Bang Theory.