Pour votre progression, c'est très important de finir le sujet précédent avant de commencer celui-ci.
Vous devez travailler connectés (lien « Connexion » en haut à droite de la page). Sinon, vous rencontrerez des problèmes d'avancement et vous risquez d'être comptés absent. En étant connectés vous retrouverez l'endroit où vous en étiez à la séance suivante.
Commençons par une rapide révision des notions des sujets précédents.
<body>
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
ICI
function click_p(event){
console.log('click p',this,event.target);
}
</script>
</body>
Que faut-il écrire ICI pour que click_p soit appelée quand l'utilisateur clique sur <p> ?
(vous devez utiliser pj)
<body>
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
pj.addEventListener('click',click_p);
function click_p(event){
console.log('click p',this,event.target);
}
</script>
</body>
Quels éléments forment l'arbre DOM de ce document ? (complétez ceux qui manquent)
<body>Quand l'utilisateur clique sur le <p>, qu'est-ce qui s'affiche dans la console ?
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
pj.addEventListener('click',click_p);
function click_p(event){
console.log('click p',this,event.target);
}
</script>
</body>
<body>Quand l'utilisateur clique sur le <strong>, qu'est-ce qui s'affiche dans la console ?
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
pj.addEventListener('click',click_p);
function click_p(event){
console.log('click p',this,event.target);
}
</script>
</body>
<body>Quand l'utilisateur clique sur le <a>, qu'est-ce qui s'affiche dans la console ?
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
pj.addEventListener('click',click_p);
function click_p(event){
console.log('click p',this,event.target);
}
</script>
</body>
<body>Quand l'utilisateur clique sur le <a>, qu'est-ce qui s'affiche dans la console ?
<h1>Joe</h1>
<p>
<span>Joueur 5</span>:
<strong>Voir <a href="g">mon groupe</a></strong>
</p>
<script>
let pj=document.querySelector('p');
pj.addEventListener('click',click_p);
function click_p(event){
console.log('click p',this,event.target);
}
let ag=document.querySelector('a');
ag.addEventListener('click',click_a);
function click_a(event){
console.log('click a',this,event.target);
}
</script>
</body>
click_a: this
click_a: event.target
click_p: this
click_p: event.target
<body>Faites en sorte, sans utiliser de boucle, que mon_click soit appelée quand l'utilisateur clique sur un nom.
<ul>
<li>Joe</li>
<li>Leila</li>
<li>Driss</li>
<li>Naïma</li>
...
</ul>
<script>
ICI
function mon_click(event){
console.log('mon_click',this,event.target);
}
</script>
</body>
Pas tout à fait. querySelectorAll('li') vous donne une liste (NodeList... comme un tablreau) de tous les <li>.
addEventListener ne peut s'appliquer que sur un seul élément, pas sur toute une liste.
<body>Que faut-il écrire à la place de ICI pour que la ligne suivante soit exécutée seulement si l'utilisateur a cliqué sur un <li> et pas quand l'utilisateur a cliqué sur le <ul>.
<ul>
<li>Joe</li>
<li>Leila</li>
<li>Driss</li>
<li>Naïma</li>
...
</ul>
<script>
document.querySelector('ul').addEventListener('click',mon_click);
function mon_click(event){
console.log('mon_click',this,event.target);
ICI
console.log("C'est bien un click sur un li");
}
</script>
</body>
Écrivez une boucle for sur la variable i, qui affiche les nombre 12 à 25 (compris) dans la console.
A quoi correspond le 2e paramètre de la fonction document.addEventListener ?
efgh(abcd)
function abcd(){
console.log('abcd');
}
function efgh(x){
console.log('efgh');
}
Qu'affiche ce programme ?
efgh(abcd())
function abcd(){
console.log('abcd');
}
function efgh(x){
console.log('efgh');
}
Qu'affiche ce programme ?
(attention: la première ligne a changé)
exemple(function(){console.log('Coucou');});
function exemple(x){
XYZ
}
Que faut-il écrire à la place de XYZ pour appeler la fonction anonyme de la première ligne ?
Créez un objet contenant une propriété appelée « nom » associée à la valeur « Joe ».
Vous devez créer un objet SANS l'affecter dans une variable.
Créez un tableau JS contenant les valeurs suivantes « Joe » « Leila » et « Liam » .
(sans l'affecter dans une variable)
let tab=['Joe','Leila','Liam','Driss', ... ];
Écrivez une boucle utilisant la variable i (numérique) permettant d'afficher dans la console tous les éléments du tableau.
En JS on utilise souvent des fonction anonymes.
On peut simplifier leur écriture avec les « Arrow functions ». En français: « Fonctions fléchées ».
On peut supprimer « function » et utiliser une flèche =>
function(a,b,c){...} devient (a,b,c)=>{...}
function(a){...} devient a=>{...}
function(){...} devient ()=>{}
function(a,b,c){return a+b+c} devient (a,b,c)=>a+b+c
function(a){return 2*a} devient a=>2*a
document.addEventListener('click',()=>console.log('click'));
let tab=[100,50,320];
let total=0;
tab.forEach((v)=>total+=v);
Rappel : fonctions fléchées
Simplifiez au maximum la fonction suivante:
function(tab,v){return tab[v]}
Rappel : fonctions fléchées
Simplifiez au maximum la fonction suivante:
function(){console.log('coucou');return document.body;}
Rappel : fonctions fléchées
Transformez cette fonction fléchée en une fonction anonyme non fléchée
a=>a*a
Rappel : fonctions fléchées
Transformez cette fonction fléchée en une fonction anonyme non fléchée
(x,y,z)=>{console.log(x,y,z)}
Pour parcourir un tableau, on a utilisé des boucles for de la manière suivante:
let tab=['Liam','Joe','Leila'];
for(let i=0; i<tab.length; i++){ console.log(tab[i]); }
JavaScript propose d'autres manières de faire.
Pour un tableau, mais aussi pour d'autres objets dits « itérables », comme un NodeList, on peut utiliser ceci:
// Ceci affiche Liam, Joe et Lelila
for(const v of tab){console.log(v);}
C'est plus court et ça évite de définir une variable numérique (comme « i »), dont on n'a pas besoin en général.
Exemple avec NodeList:
let list=document.querySelectorAll('p');
for(const p of list){ console.log(p.textContent) ; }
// Ceci affiche Liam, Joe et Lelila
tab.forEach(function(v){console.log(v);});
tab.forEach(v=>console.log(v));
let nombres=[100,50,320];
let total=0;
nombres.forEach((v)=>total+=v);
Rappel : boucles
let els=document.querySelectorAll('.effacer');
Utilisez une boucle for ... of pour supprimer du DOM tous les éléments de la NodeList els.
Rappel: .remove() permet de supprimer un seul élément de l'arbre DOM
Pour la boucle, utilisez une variable appelée el
Rappel : boucles
let scores=[35,105,32,162,32,812];Écrivez une boucle for...of qui affiche dans la console uniquement les scores qui sont supérieurs à 100
Rappel : boucles
let parfums=['Vanille','Chocolat','Chocolat','Fraise','Pistache','Chocolat'];Écrivez une boucle forEach qui compte le nombre de fois où 'Chocolat' apparaît dans parfums
let nb=0;
Utilisez une variable appelée « p » pour le parfum courant et la variable nb pour le nombre (nb est déjà initialisée à 0 ci-dessus).
Utilisez une fonction fléchée, mais en gardant les accolades.
Rappel : boucles
Écrivez une boucle forEach qui affiche dans la console tous les paragraphes de la page.N'hésitez pas à essayer dans la console du navigateur avant de répondre.
Vous êtes sur la bonne voie. Le début est correct:
document.querySelectorAll('p').forEach(
Le problème est après
Dans les pages suivantes on va reprendre le jeu du Sujet-3.
Voici les fichiers HTML, CSS et JS.
Les seules modifications sont:
jeu.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Jeu</title>
<link href="jeu.css" rel="stylesheet" />
</head>
<body>
<div id="cadre">
<img id="tux" src="https://moodle.iutv.univ-paris13.fr/img/bjs/tux.png" alt="tux"/>
</div>
<p>Étape: <span id="etape">---</span> Score: <span id="score">---</span> Temps restant: <span id="temps">---</span></p>
<input id="commencer" type="button" value="Commencer"/>
<script src="jeu.js"></script>
</body>
</html>
jeu.css
body
{
margin: 10px;
}
#cadre
{
width: 500px;
height: 500px;
border: 1px solid black;
overflow: hidden;
}
#tux
{
position: absolute;
top: 100px;
left: 100px;
/* Les changements de top et left prennent 0,3 secondes */
transition: top .3s, left .3s;
border: 1px solid #eee;
}
.splat
{
/* Ceci permet de placer les splats avec top et left */
position: absolute;
/* La position de départ: en bas, au centre */
top: 500px;
left: 100px;
/* Agrandir 4 fois l'image */
transform: scale(4);
/* Définir les propriétés CSS à animer. Toutes en 1 seconde */
transition: top 1s,left 1s,transform 1s,opacity 3s;
}
jeu.js
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
// Variables globales : L'état du jeu
let score=0;
document.addEventListener('keydown',function(event){
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
On voudrait avoir 3 étapes dans le jeu:
On avait installé un gestionnaire mousedown pour envoyer des splats verts et on avait installé un gestionnaire keyup pour gérer les touches permettant de déplacer le pingouin.
On pourrait installer/désinstaller ces gestionnaires à chaque fois qu'on change d'étape ... mais ce serait lourd.
Donc, on va laisser ces gestionnaires (mousedown et keyup) et utiliser une variable globale « etape » qui nous dira dans quelle étape on se trouve.
Créez, à coté de « score », une variable globale appelée « etape »
Dans les gestionnaires (mousedown et keyup) faites en sorte qu'on quitte ces fonctions si etape n'est pas égale à 'Jeu'
Vérifiez que si vous mettez « Début » dans etape, le jeu est bloqué.
Vérifiez que si vous mettez « Jeu » dans etape, le jeu fonctionne.
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
// Variables globales : L'état du jeu
let score=0;
let etape='Jeu';
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
Maintenant on voudrait changer d'étape.
Écrivez une fonction « changer_etape » qui prend un paramètre appelé « nouvelleEtape ».
La fonction changer_etape doit
Quand l'utilisateur clique sur le bouton « commencer » appelez changer_etape('Jeu'), uniquement si l'étape actuelle est 'Début'
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
// Variables globales : L'état du jeu
let score=0;
let etape;
changer_etape('Début');
document.getElementById('commencer').addEventListener('click',function(){
if(etape==='Début'){changer_etape('Jeu');}
});
function changer_etape(nouvelleEtape)
{
etape=nouvelleEtape;
document.getElementById('etape').textContent=etape;
}
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
La fonction window.setInterval(fonction,delai) permet d’exécuter une fonction à intervalles réguliers.
Le delai est en millisecondes.
Que faut-il écrire pour afficher « bonjour » dans la console toutes les secondes ?
Essayez dans votre navigateur (mais sur une autre page, pour pouvoir recharger).
Indication: n'utilisez pas de fonction fléchée.
Rappel: la console n'affiche pas plusieurs fois le même message... elle augmente un petit compteur bleu à droite.
window.setInterval(function(){console.log('bonjour');},1000)
permet d'afficher « bonjour » dans la console toutes les secondes.
Mais comment l’arrêter ?
Si vous regardez dans la console, vous remarquerez que quand vous appelez setInterval un nombre est affiché.
Ce nombre identifie l'intervalle.
Vous pouvez ensuite utiliser la fonction window.clearInterval(nombre) pour arrêter l'intervalle.
Essayez window.clearInterval(...) dans la console.
Supposons qu'on ait le code suivant:
let interval=window.setInterval(ma_fonction,1000)Que faut-il écrire pour arrêter ce minuteur ?
On voudrait que la partie ne dure que 10 secondes.
On voudrait afficher chaque seconde le temps restant dans spanTemps.
1) Après les variables etape et score: créez une variable appelée temps et une variable appelée interval
2) Dans la fonction changer_etape, si la nouvelle étape est 'Jeu', alors mettez temps à 10 et lancez une fonction appelée « minuteur » toutes les secondes
3) Écrivez la fonction « minuteur ». Elle mettra à jour la variable temps et l'affichera. Si le temps restant atteint 0, elle appellera changer_etape pour changer l'étape à 'Fin'
4) Dans la fonction changer_etape, si la nouvelle étape est 'Fin', arrêtez le minuteur
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
// Variables globales : L'état du jeu
let score=0;
let etape;
let temps;
let interval;
changer_etape('Début');
document.getElementById('commencer').addEventListener('click',function(){
if(etape==='Début'){changer_etape('Jeu');}
});
function minuteur()
{
temps-=1;
spanTemps.textContent=temps;
if(temps<=0){
changer_etape('Fin');
}
}
function changer_etape(nouvelleEtape)
{
if(nouvelleEtape==='Jeu'){
temps=10;
spanTemps.textContent=temps;
interval=window.setInterval(minuteur,1000);
}
if(nouvelleEtape==='Fin'){
window.clearInterval(interval);
}
etape=nouvelleEtape;
document.getElementById('etape').textContent=etape;
}
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
// Variables globales : L'état du jeu
let score=0;
let etape;
let temps;
let interval;
changer_etape('Début');
document.getElementById('commencer').addEventListener('click',function(){
if(etape==='Début' || etape==='Fin'){changer_etape('Jeu');}
});
function minuteur()
{
temps-=1;
spanTemps.textContent=temps;
if(temps<=0){
changer_etape('Fin');
}
}
function changer_etape(nouvelleEtape)
{
if(nouvelleEtape==='Jeu'){
document.querySelectorAll('.splat').forEach(s=>s.remove());
tux.style.left="";
tux.style.top="";
score=0;
spanScore.textContent=score;
temps=10;
spanTemps.textContent=temps;
interval=window.setInterval(minuteur,1000);
}
if(nouvelleEtape==='Fin'){
window.clearInterval(interval);
}
etape=nouvelleEtape;
document.getElementById('etape').textContent=etape;
}
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
Faites disparaître le bouton « Commencer » au début de l'étape 'Jeu' et faites le re-apparaître à l'étape 'Fin'. (Indice: opacity)
À l'étape 'Fin', changez « Commencer » en « Recommencer »
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
const commencer=document.getElementById('commencer');
// Variables globales : L'état du jeu
let score=0;
let etape;
let temps;
let interval;
changer_etape('Début');
commencer.addEventListener('click',function(){
if(etape==='Début' || etape==='Fin'){changer_etape('Jeu');}
});
function minuteur()
{
temps-=1;
spanTemps.textContent=temps;
if(temps<=0){
changer_etape('Fin');
}
}
function changer_etape(nouvelleEtape)
{
if(nouvelleEtape==='Jeu'){
document.querySelectorAll('.splat').forEach(s=>s.remove());
tux.style.left="";
tux.style.top="";
score=0;
spanScore.textContent=score;
temps=10;
spanTemps.textContent=temps;
interval=window.setInterval(minuteur,1000);
commencer.style.opacity=0;
}
if(nouvelleEtape==='Fin'){
commencer.style.opacity=1;
commencer.value='Recommencer';
window.clearInterval(interval);
}
etape=nouvelleEtape;
document.getElementById('etape').textContent=etape;
}
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
HTML:
<p id="game-over">Game Over</p>
CSS:
#game-over
{
display: none;
position: absolute;
top : 11px;
left: 11px;
margin:0;
font-size: 80px;
width: 500px;
height: 500px;
line-height: 500px;
text-align: center;
color: #80f;
background-color: rgba(0,0,0,.2);
text-shadow: 0 0 10px white,0 0 10px white,0 0 10px white,0 0 10px white;
user-select: none;
}
JS:
// Des raccourcis
const tux=document.getElementById('tux');
const spanEtape=document.getElementById('etape');
const spanScore=document.getElementById('score');
const spanTemps=document.getElementById('temps');
const commencer=document.getElementById('commencer');
// Variables globales : L'état du jeu
let score=0;
let etape;
let temps;
let interval;
changer_etape('Début');
commencer.addEventListener('click',function(){
if(etape==='Début' || etape==='Fin'){changer_etape('Jeu');}
});
function minuteur()
{
temps-=1;
spanTemps.textContent=temps;
if(temps<=0){
changer_etape('Fin');
}
}
function changer_etape(nouvelleEtape)
{
if(nouvelleEtape==='Jeu'){
document.getElementById('game-over').style.display='none';
document.querySelectorAll('.splat').forEach(s=>s.remove());
tux.style.left="";
tux.style.top="";
score=0;
spanScore.textContent=score;
temps=10;
spanTemps.textContent=temps;
interval=window.setInterval(minuteur,1000);
commencer.style.opacity=0;
}
if(nouvelleEtape==='Fin'){
document.getElementById('game-over').style.display='block';
commencer.style.opacity=1;
commencer.value='Recommencer';
window.clearInterval(interval);
}
etape=nouvelleEtape;
document.getElementById('etape').textContent=etape;
}
document.addEventListener('keydown',function(event){
if(etape!=='Jeu'){return;}
console.log('Touche enfoncée:',event.key);
let rect=tux.getBoundingClientRect();
console.log(rect);
let d=100;
let left=rect.left;
let top=rect.top;
if(event.key==='ArrowRight'){left+=d;}
if(event.key==='ArrowLeft' ){left-=d;}
if(event.key==='ArrowDown' ){top+=d;}
if(event.key==='ArrowUp' ){top-=d;}
left=Math.max(10,left);
top =Math.max(10,top);
left=Math.min(510-rect.width ,left);
top =Math.min(510-rect.height,top);
tux.style.left=left+"px";
tux.style.top=top+"px";
});
document.addEventListener('mousedown',function (event)
{
if(etape!=='Jeu'){return;}
// Petit détail: éviter la sélection
event.preventDefault();
if(event.pageX-16<10 ||
event.pageY-16<10 ||
event.pageX-16+32>500+10 ||
event.pageY-16+40>500+10 ){return;}
let i=document.createElement('img');
i.src='https://moodle.iutv.univ-paris13.fr/img/bjs/splat.png';
i.className='splat';
document.body.append(i);
// Forcer le navigateur à prendre en compte la situation actuelle (position, scale).
// Ceci permettra au navigateur de s'apercevoir d'un changement futur des propriétés CSS.
window.getComputedStyle(i).top;
// Changer les propriétés CSS qui transitionnent.
// Le navigateur s'aperçoit du changement et déclenche la transition.
i.style.top =(event.pageY-16)+'px';
i.style.left=(event.pageX-16)+'px';
i.style.transform='scale(1)';
setTimeout(function(){
let rectTux=tux.getBoundingClientRect();
let rectSplat=i.getBoundingClientRect();
let touche=
rectSplat.top +rectSplat.height >= rectTux.top &&
rectSplat.top < rectTux.top +rectTux.height &&
rectSplat.left+rectSplat.width >= rectTux.left &&
rectSplat.left < rectTux.left +rectTux.width ;
if(touche){
i.src="https://moodle.iutv.univ-paris13.fr/img/bjs/splat2.png";
getComputedStyle(i).top;
i.style.opacity=0;
setTimeout(function(){i.remove();},3000);
score+=10;
}
else
{
i.style.zIndex=-1;
score-=5;
}
spanScore.textContent=score;
},1000);
});
Dans les pages suivantes, on va reprendre, ensemble, le tableau de joueurs. Il s'agira d'ajouter un bouton « modifier » à chaque ligne, pour pouvoir éditer un joueur existant.
Le HTML et le JS ont étés modifiés. Les modifications sont en gras.
joueurs.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>joueurs</title>
<link type="text/css" rel="stylesheet" href="joueurs.css"/>
</head>
<body>
<!--------------------->
<h2>Joueurs :</h2>
<p id="ajouter">
<label>nom: <input id="ajout-nom" type="text"/></label>
<label>score: <input id="ajout-score" type="text"/></label>
<input id="bouton-ajouter" type="button" value="ajouter"/>
</p>
<table id="joueurs">
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Leïla</td>
<td class="score">121</td>
</tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Driss</td>
<td class="score">153</td></tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Lian</td>
<td class="score">210</td>
</tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Joe</td>
<td class="score">32</td>
</tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Naïma</td>
<td class="score">261</td>
</tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Karim</td>
<td class="score">183</td>
</tr>
<tr>
<td class="effacer" ><img src="https://moodle.iutv.univ-paris13.fr/img/js/effacer.png" /></td>
<td class="modifier"><img src="https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png"/></td>
<td class="nom">Anon.</td>
<td class="score">0</td>
</tr>
</table>
<p>
total : <span id="total" >960</span><br/>
médiane : <span id="mediane">153</span>
</p>
<div id="popup">
<p><label for="popup-nom" >nom: </label><input id="popup-nom" type="text"/></p>
<p><label for="popup-score">score:</label><input id="popup-score" type="text"/></p>
<p>
<input id="popup-annuler" type="button" value="annuler"/>
<input id="popup-ok" type="button" value="ok"/>
</p>
</div>
<!--------------------->
<script src="joueurs.js"></script>
</body>
</html>
joueurs.css
body
{
font-family: sans;
}
h2
{
font-size: 16px;
}
#joueurs
{
box-shadow: 2px 2px 4px rgba(0,0,0,.2);
border-radius: 2px;
border-collapse: collapse;
margin-left: 40px;
}
#joueurs td
{
padding: 3px 10px;
}
#joueurs tr
{
background-color: #f0f0ff;
}
#joueurs tr:nth-child(2n)
{
background-color: #efe;
}
#ajouter input[type='text']
{
width: 80px;
}
#ajout-nom
{
margin-right: 10px;
}
joueurs.js
let bouton=document.getElementById('bouton-ajouter');
bouton.addEventListener('click',function(){
console.log('Click');
let joueur={
nom: document.getElementById('ajout-nom').value,
score: document.getElementById('ajout-score').value
};
ajouter_joueur(joueur);
document.getElementById('ajout-nom').value='';
document.getElementById('ajout-score').value='';
document.getElementById('total').textContent=calculer_total();
});
let joueurs=document.getElementById('joueurs');
joueurs.addEventListener('click',function(event){
console.log('Click sur table');
if(event.target.nodeName!=='IMG'){return;}
console.log('Click sur croix');
event.target.parentNode.parentNode.remove();
});
function calculer_total()
{
let total=0;
let tds=document.querySelectorAll('.score');
for(let i=0;i<tds.length;i++){
let score=parseInt(tds[i].textContent);
total+=score;
}
return total;
}
function ajouter_joueur(joueur)
{
console.log('ajouter_joueur',joueur);
let ligne =document.createElement('tr');
let effacer =document.createElement('td');
let modifier=document.createElement('td');
let nom =document.createElement('td');
let score =document.createElement('td');
let croix =document.createElement('img');
let crayon =document.createElement('img');
croix.src ='https://moodle.iutv.univ-paris13.fr/img/js/effacer.png';
effacer.append(croix);
crayon.src='https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png';
modifier.append(crayon);
nom.textContent=joueur.nom;
score.textContent=joueur.score;
effacer.className='effacer';
modifier.className='modifier';
nom.className='nom';
score.className='score';
ligne.append(effacer);
ligne.append(modifier);
ligne.append(nom);
ligne.append(score);
document.getElementById('joueurs').append(ligne);
}
Modifiez uniquement le fichier CSS pour obtenir un affichage similaire à celui-ci:
Indices:
#popup
{
position: absolute;
top: 10em;
left: 5em;
background-color: white;
border: 1px solid black;
padding: 1em;
box-shadow: 2px 2px 3px rgba(0,0,0,.5);
}
#popup label
{
display: inline-block;
min-width: 4em;
}
Dans le fichier CSS, cachez le popup avec « display: none ». On s'en occupera plus tard.
Cliquez sur un petit crayon. Que se passe-il ? Regardez la console.
En effet, pour gérer le click sur la croix, on a utilisé le bubbling comme ceci:
let joueurs=document.getElementById('joueurs');
joueurs.addEventListener('click',function(event){
console.log('Click sur table');
if(event.target.nodeName!=='IMG'){return;}
console.log('Click sur croix');
event.target.parentNode.parentNode.remove();
});
On se contente de vérifier si l'élément cliqué est une image:
if(event.target.nodeName!=='IMG'){return;}Or, maintenant, il y a une autre image - le crayon - dans le <tr> ...
Essayez
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
let joueurs=document.getElementById('joueurs');
joueurs.addEventListener('click',function(event){
console.log('Click sur table');
if(!event.target.matches('.effacer img')){return;}
console.log('Click sur croix');
event.target.parentNode.parentNode.remove();
});
En copiant ce qui a été fait pour le click sur la croix, faites en sorte d'afficher « Click sur modifier » quand l'utilisateur clique sur le crayon.
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
let bouton=document.getElementById('bouton-ajouter');
bouton.addEventListener('click',function(){
console.log('Click');
let joueur={
nom: document.getElementById('ajout-nom').value,
score: document.getElementById('ajout-score').value
};
ajouter_joueur(joueur);
document.getElementById('ajout-nom').value='';
document.getElementById('ajout-score').value='';
document.getElementById('total').textContent=calculer_total();
});
let joueurs=document.getElementById('joueurs');
joueurs.addEventListener('click',function(event){
console.log('Click sur table');
if(!event.target.matches('.effacer img')){return;}
console.log('Click sur croix');
event.target.parentNode.parentNode.remove();
});
joueurs.addEventListener('click',function(event){
if(!event.target.matches('.modifier img')){return;}
console.log('Click sur modifier');
});
function calculer_total()
{
let total=0;
let tds=document.querySelectorAll('.score');
for(let i=0;i<tds.length;i++){
let score=parseInt(tds[i].textContent);
total+=score;
}
return total;
}
function ajouter_joueur(joueur)
{
console.log('ajouter_joueur',joueur);
let ligne =document.createElement('tr');
let effacer =document.createElement('td');
let modifier=document.createElement('td');
let nom =document.createElement('td');
let score =document.createElement('td');
let croix =document.createElement('img');
let crayon =document.createElement('img');
croix.src ='https://moodle.iutv.univ-paris13.fr/img/js/effacer.png';
effacer.append(croix);
crayon.src='https://moodle.iutv.univ-paris13.fr/img/bjs/modifier.png';
modifier.append(crayon);
nom.textContent=joueur.nom;
score.textContent=joueur.score;
effacer.className='effacer';
modifier.className='modifier';
nom.className='nom';
score.className='score';
ligne.append(effacer);
ligne.append(modifier);
ligne.append(nom);
ligne.append(score);
document.getElementById('joueurs').append(ligne);
}
Quand l'utilisateur clique sur un crayon, mettez le nom et le score correspondants dans des variables appelées « nom » et « score ». Affichez ces deux variables dans la console.
Indice: vous devrez naviguer l'arbre DOM
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
joueurs.addEventListener('click',function(event){
if(!event.target.matches('.modifier img')){return;}
console.log('Click sur modifier');
let tr=event.target.parentNode.parentNode;
let nom =tr.querySelector('.nom' ).textContent;
let score=tr.querySelector('.score').textContent;
console.log(nom,score);
});
Quand l'utilisateur clique sur un crayon:
joueurs.addEventListener('click',function(event){
if(!event.target.matches('.modifier img')){return;}
console.log('Click sur modifier');
let tr=event.target.parentNode.parentNode;
let nom =tr.querySelector('.nom' ).textContent;
let score=tr.querySelector('.score').textContent;
console.log(nom,score);
tr.className='edition';
let popup=document.getElementById('popup');
popup.style.display='block';
document.getElementById('popup-nom' ).value=nom;
document.getElementById('popup-score').value=score;
});
Quand l'utilisateur appuie sur le bout Ok:
document.getElementById('popup-ok').addEventListener('click',function(){
let tr=document.querySelector('.edition');
tr.querySelector('.nom' ).textContent=document.getElementById('popup-nom' ).value;
tr.querySelector('.score').textContent=document.getElementById('popup-score').value;
let popup=document.getElementById('popup');
popup.style.display='none';
tr.className='';
});
En vous inspirant de ce qui a été fait pour Ok, écrivez le code pour gérer le bouton « annuler ».
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
document.getElementById('popup-annuler').addEventListener('click',function(){
let tr=document.querySelector('.edition');
let popup=document.getElementById('popup');
popup.style.display='none';
tr.className='';
});