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.
<p>bonjour</p>
let a=document.querySelector('p');
XYZ
function coucou(){
console.log('coucou');
}
Que faut-il écrire à la place de XYZ pour que la fonction coucou soit appelée lorsque l'utilisateur clique sur « bonjour » ?
(vous devez utiliser a)
Pas tout à fait ... Attention à l'orthographe et aux majuscules dans addEventLi....
Dans l'expression suivante:
a.addEventListener('click',coucou);
Réécrivez en une seule ligne le code suivant, en utilisant une fonction anonyme
a.addEventListener('click',coucou);Faites bien attention aux accolades et parenthèses.
function coucou(){
console.log('coucou');
}
<span id="a1">Chien</span><span id="a2">Chat</span><span id="a3">Souris</span>
document.getElementById('a1').addEventListener('click',abcd);
document.getElementById('a2').addEventListener('click',abcd);
document.getElementById('a3').addEventListener('click',abcd);
function abcd(){
console.log(XYZ);
}
Que faut-il écrire à la place de XYZ pour afficher l'animal cliqué ?
...
<h1>bonjour</h1>
<script>
console.log('A');
let v=document.querySelector('h1');
console.log('B');
v.addEventListener('click',ma_fonction);
console.log('C');
function ma_fonction()
{
console.log('D');
}
console.log('E');
</script>
...
<body>
<p>Vanille</p>
<p>Framboise</p>
</body>
On voudrait ajouter un paragraphe au document précédent pour obtenir ceci:
<body>
<p>Vanille</p>
<p>Framboise</p>
<p>Chocolat</p>
</body>
La création d'un élément puis son insertion se fait en plusieurs étapes:
let p=document.ABC('p');Que faut-il écrire à la place de ABC ?
p.CDE='Chocolat';
document.body.FGH(p);
<body>
<p>Vanille</p>
<p>Framboise</p>
</body>
On voudrait ajouter un paragraphe au document précédent pour obtenir ceci:
<body>
<p>Vanille</p>
<p>Framboise</p>
<p>Chocolat</p>
</body>
La création d'un élément puis son insertion se fait en plusieurs étapes:
let p=document.createElement('p');Que faut-il écrire à la place de CDE ?
p.CDE='Chocolat';
document.body.FGH(p);
<body>
<p>Vanille</p>
<p>Framboise</p>
</body>
On voudrait ajouter un paragraphe au document précédent pour obtenir ceci:
<body>
<p>Vanille</p>
<p>Framboise</p>
<p>Chocolat</p>
</body>
La création d'un élément puis son insertion se fait en plusieurs étapes:
let p=document.createElement('p');Que faut-il écrire à la place de FGH ?
p.textContent='Chocolat';
document.body.FGH(p);
Dans les pages suivants on va découvrir le « bubbling » ... comment les événements remontent par étapes.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Bubbling</title>
<link href="bubbling.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
<script>
</script>
</body>
</html>
bubbling.css
body:after
{
content: "body";
position: absolute;
right: .3em;
top: 0em;
}
p
{
position: relative;
width: 20em;
margin: 2em;
padding: 2em;
background-color: #ff8080;
}
p:after
{
content: "p";
position: absolute;
right: .3em;
top: 0em;
}
a
{
margin: 2em;
padding: 1em;
background-color: #aecf00;
position: relative;
display: inline-block;
}
a:after
{
content: "a";
position: absolute;
right: .3em;
top: 0em;
}
span
{
display: inline-block;
margin: 2em;
padding: 1em;
background-color: #7777ff;
position: relative;
}
span:after
{
content: "span";
position: absolute;
right: .3em;
top: 0em;
}
Quand l'utilisateur clique sur le « Toc ! », faites en sorte qu'une fonction (non anonyme) « click_sur_a » soit appelée. Cette fonction affichera « click_sur_a » dans la console. Vérifiez que ça s'affiche correctement dans la console.
É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 toc=document.querySelector('a');
toc.addEventListener('click',click_sur_a);
function click_sur_a()
{
console.log('click_sur_a');
}
Faisons la même chose pour le span:
Quand l'utilisateur clique sur le « Tac ! », faites en sorte qu'une fonction (non anonyme) « click_sur_span » soit appelée. Cette fonction affichera « click_sur_span » dans la console. Vérifiez que ça s'affiche correctement dans la console.
let toc=document.querySelector('a');
toc.addEventListener('click',click_sur_a);
function click_sur_a()
{
console.log('click_sur_a');
}
let tac=document.querySelector('span');
tac.addEventListener('click',click_sur_span);
function click_sur_span()
{
console.log('click_sur_span');
}
Que fait la fonction addEventListener dans le code suivant ?
tac.addEventListener('click',click_sur_span);
Elle attend que l'utilisateur clique sur le span « tac » pour appeler la fonction click_sur_span
tac.addEventListener('click',click_sur_span);
Un gestionnaire d'événements est une fonction qui a vocation à être appelée lorsqu'un événement survient.
Le gestionnaire d’événements est la fonction click_sur_span
Elle est enregistrée sur le span « Tac ! ».
Si l'utilisateur clique sur le
span, le navigateur verra que click_sur_span est enregistré sur ce span et l’appellera.
Sur Firefox, faites « clique droit -> Inspecter » sur le span.
Vous devrez voir «event » a coté du span. Si vous cliquez sur cet « event» vous verez que c'est la fonction click_sur_span.
Même chose sur le <a> « Tac » pour click_sur_a.
Vous voyez bien que ces fonctions sont bien enregistrées sur ces éléments.
Maintenant faisons la même chose pour le paragraphe:
let toc=document.querySelector('a');
toc.addEventListener('click',click_sur_a);
function click_sur_a()
{
console.log('click_sur_a');
}
let tac=document.querySelector('span');
tac.addEventListener('click',click_sur_span);
function click_sur_span()
{
console.log('click_sur_span');
}
let para=document.querySelector('p');
para.addEventListener('click',click_sur_p);
function click_sur_p()
{
console.log('click_sur_p');
}
Mettez à jour votre code et vérifiez que tout fonctionne.
Que s'affiche-t-il dans la console quand vous cliquez sur le <a> « Toc ! » ?
C'est bizarre ! Vous avez cliqué sur <a> et le navigateur vous dit que vous avez aussi cliqué sur <p> !
Essayons autre chose.
Enlevez tout le JS sauf celui qui concerne le paragraphe. Il ne doit rester que:
let para=document.querySelector('p');
para.addEventListener('click',click_sur_p);
function click_sur_p()
{
console.log('click_sur_p');
}
Vérifiez que ca marche quand vous cliquez sur <p>
Quelles affirmations sont vraies ?
Cette remontée s’appelle le « bubbling ». C'est très utile.
Dans le code suivant on a installé des gestionnaires d'événements sur tous les éléments:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Bubbling</title>
<link href="bubbling.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
<script>
let toc=document.querySelector('a');
toc.addEventListener('click',click_sur_a);
function click_sur_a()
{
console.log('click_sur_a');
}
let tac=document.querySelector('span');
tac.addEventListener('click',click_sur_span);
function click_sur_span()
{
console.log('click_sur_span');
}
let para=document.querySelector('p');
para.addEventListener('click',click_sur_p);
function click_sur_p()
{
console.log('click_sur_p');
}
let b=document.querySelector('body');
b.addEventListener('click',click_sur_body);
function click_sur_body()
{
console.log('click_sur_body');
}
let h=document.querySelector('html');
b.addEventListener('click',click_sur_html);
function click_sur_html()
{
console.log('click_sur_html');
}
</script>
</body>
</html>
Qu'affiche la console si on clique sur « Tac ! » ?
(Essayez de répondre d'abord, avant d'exécuter le code.)
Qu'affiche la console si on clique sur <p> ?
(Essayez de répondre d'abord, sans exécuter le code.)
Sur quels éléments peut-on cliquer pour provoquer l'affichage dans la console de click_sur_html ?
En effet... tous les événements remontent jusqu'à <html> puis à document.
C'est pratique. Par exemple, si on veut réagir à tous les clicks, où qu'ils soient sur la page, il suffit d'installer un gestionnaire d'événements sur document (ou <html>). C'est qu'on à fait pour le pingouin au Sujet-1:
pingouin.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Pingouin</title>
<style>
.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;
}
</style>
</head>
<body>
<img src="https://moodle.iutv.univ-paris13.fr/img/bjs/tux.png" alt="tux"/>
<script>
document.addEventListener('mousedown',ajouter_splat);
function ajouter_splat(event)
{
// Petit détail: éviter la sélection
event.preventDefault();
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)';
}
</script>
</body>
</html>
Si on veut réagir à une touche appuyée n'importe où sur la page, on peut faire pareil. C'est ce qu'on a fait au sujet3, au jeu, pour déplacer le pingouin avec le clavier:
jeu.js
...
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";
});
...
Quand on utilise le bubbling, il faut distinguer
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
</body>
document.body.addEventListener('click',function() {
console.log(this);
console.log(event.target);
});
L'utilisateur clique sur le span. Dans la fonction anonyme, quelles affirmations sont vraies ?
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
</body>
document.body.addEventListener('click',function() {
console.log(this);
console.log(event.target);
});
L'utilisateur clique sur p. Dans la fonction anonyme, a quel élément correspond "this" ?
(donnez juste son nom)
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
</body>
document.querySelector('a').addEventListener('click',function() {
console.log(this);
console.log(event.target);
});
L'utilisateur clique sur a. Dans la fonction anonyme, a quel élément correspond "this" ?
(donnez juste son nom)
(le code changé est indiqué en gras)
<body>
<p>
<a>Toc !</a>
<span>Tac !</span>
</p>
</body>
document.querySelector('p').addEventListener('click',function() {
console.log(this);
console.log(event.target);
});
L'utilisateur clique sur a. Dans la fonction anonyme, à quel élément correspond "event.target" ?
(donnez juste son nom)
(le code changé est indiqué en gras)
Dans les pages suivantes on va reprendre le morpion et le simplifier en utilisant le bubbling.
Créez le fichier morpion-bubbling.html suivant. Pour l'instant c'est le même code que l'ancien. On va le modifier ensemble, dans les pages suivantes.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Morpion</title>
<style>
table
{
border-collapse: collapse;
}
td
{
border: 1px solid black;
width: 40px;
height: 40px;
font-size: 30px;
text-align: center;
cursor: pointer;
}
td:hover
{
background-color: #ffc;
}
</style>
</head>
<body>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
<script>
let tds=document.querySelectorAll('td');
for(let i=0;i<tds.length;i++)
{
tds[i].addEventListener('click',click_td);
}
let joueur='X';
function click_td(event)
{
console.log('Click');
if(this.textContent!=''){return;}
this.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}
</script>
</body>
</html>
Dans l'ancienne version, on a utilisé une boucle pour installer le gestionnaire d'événements click_td sur chacun des <td>:
let tds=document.querySelectorAll('td');On peut faire plus simple avec le bubbling!
for(let i=0;i<tds.length;i++)
{
tds[i].addEventListener('click',click_td);
}
Remplacez ce code, avec un code qui installe click_td uniquement sur la table. Vérifiez que « Click » s'affiche toujours sur la console quand on clique sur un <td>
Avec le changement qu'on à fait, que valent, dans click_td, les variables suivantes:
Notre code actuel est le suivant:
let tab=document.querySelector('table');
tab.addEventListener('click',click_td);
let joueur='X';
function click_td(event)
{
console.log('Click');
if(this.textContent!=''){return;}
this.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}
Le "this" est celui de l'ancien programme (où c'était un <td>).
Avec notre changement,
Modifiez le code pour qu'il fonctionne.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Morpion</title>
<style>
table
{
border-collapse: collapse;
}
td
{
border: 1px solid black;
width: 40px;
height: 40px;
font-size: 30px;
text-align: center;
cursor: pointer;
}
td:hover
{
background-color: #ffc;
}
</style>
</head>
<body>
<table>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
<script>
let tab=document.querySelector('table');
tab.addEventListener('click',click_td);
let joueur='X';
function click_td(event)
{
console.log('Click');
if(event.target.textContent!=''){return;}
event.target.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}
</script>
</body>
</html>
Dans notre code, on a installé click_td sur <table> et on suppose que event.target est toujours un <td>.
Or <table> a d'autres descendants (des <tr> et <tbody> ajouté automatiquement).
Donc pour être certain qu'on agit uniquement sur les <td>, il faut le vérifier:
la propriété nodeName nous donne le nom de la balise (en majuscules).
let tab=document.querySelector('table');
tab.addEventListener('click',click_td);
let joueur='X';
function click_td(event)
{
console.log('Click');
if(event.target.nodeName!=='TD'){return;}
if(event.target.textContent!=''){return;}
event.target.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}
Au Sujet-3 on avait crée un panier. On veut le simplifier en utilisant le bubbling.
Utilisez les mêmes idées que l'on a vu précédemment:
Voici le code initial, que vous devez transformer vous mêmes:
panier-bubbling.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Jeu</title>
<style type=>
#parfums span
{
padding: .5em;
margin: 1em;
border: 1px solid blue;
}
#parfums span:hover
{
background-color: #ffa;
}
</style>
</head>
<body>
<p id="parfums"><span>Fraise</span><span>Chocolat</span><span>Vanille</span><span>Framboise</span></p>
<h4>Panier:</h4>
<ul id="panier">
</ul>
<script>
let parfums=document.querySelectorAll('#parfums span');
for(let i=0;i<parfums.length;i++)
{
parfums[i].addEventListener('click',function(event){
console.log('Click');
let ligne=document.createElement('li');
ligne.textContent=this.textContent;
let panier=document.getElementById('panier');
panier.append(ligne);
});
}
</script>
</body>
</html>
Changez le code, avec les mêmes idées qu'on a utilisé pour le morpion.
É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 p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
let panier=document.getElementById('panier');
panier.append(ligne);
});
Quand l'utilisateur clique sur un parfum déjà dans le panier (partie du bas), on voudrait le supprimer.
Réfléchissez pour essayer de trouver tout seul une solution...
On va le faire, ensemble, dans les pages suivantes.
Rappel:
panier-bubbling.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Jeu</title>
<style type=>
#parfums span
{
padding: .5em;
margin: 1em;
border: 1px solid blue;
}
#parfums span:hover
{
background-color: #ffa;
}
</style>
</head>
<body>
<p id="parfums"><span>Fraise</span><span>Chocolat</span><span>Vanille</span><span>Framboise</span></p>
<h4>Panier:</h4>
<ul id="panier">
</ul>
<script>
let p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
let panier=document.getElementById('panier');
panier.append(ligne);
});
</script>
</body>
</html>
<p id="parfums"><span>Fraise</span><span>Chocolat</span><span>Vanille</span><span>Framboise</span></p>Pour l'instant, les <li> de panier <ul> n'existent pas.
<h4>Panier:</h4>
<ul id="panier">
</ul>
<script>A quel moment est-ce que le code XYZ est exécuté ?
let p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
let panier=document.getElementById('panier');
panier.append(ligne);
});
XYZ
</script>
<p id="parfums"><span>Fraise</span><span>Chocolat</span><span>Vanille</span><span>Framboise</span></p>XYZ est exécuté au démarrage de la page lorsqu'il les <li> n'existent pas encore.
<h4>Panier:</h4>
<ul id="panier">
</ul>
<script>
let p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
let panier=document.getElementById('panier');
panier.append(ligne);
XYZ
});
</script>
let panier=document.getElementById('panier');
let p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
panier.append(ligne);
});
panier.addEventListener('click',function(event){
console.log('Click ul');
});
Vérifiez que si vous ajoutez des parfums dans le panier, puis que vous cliquez dessus, que « Click ul » est bien affiché dans la console.
panier.addEventListener('click',function(event){Pour supprimer un élément, on peut utiliser la fonction remove(). Elle s'applique sur un élément. Voir la documentation.
console.log('Click ul');
ICI
});
Que faut-il écrire « ICI » pour supprimer l'élément <li> du panier quand l'utilisateur clique dessus ?
Indice: trouvez d’abord comment on récupère l'élément <li> cliqué...
(vérifiez dans votre navigateur avant de répondre)
Mettez à jour votre code:
panier.addEventListener('click',function(event){
console.log('Click ul');
event.target.remove()
});
Ajoutez des parfums et vérifiez que ça marche. Que se passe-il si vous cliquez à gauche des points dans le panier ?
Si vous cliquez à gauche des points, votre click se trouve dans le <ul> et non pas le <li>... vous supprimez donc le <ul> tout entier !!
Inspirer vous de ce qui a été fait précédemment pour vérifier que le click est bien dans un <li>
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Jeu</title>
<style type=>
#parfums span
{
padding: .5em;
margin: 1em;
border: 1px solid blue;
}
#parfums span:hover
{
background-color: #ffa;
}
</style>
</head>
<body>
<p id="parfums"><span>Fraise</span><span>Chocolat</span><span>Vanille</span><span>Framboise</span></p>
<h4>Panier:</h4>
<ul id="panier">
</ul>
<script>
let panier=document.getElementById('panier');
let p=document.getElementById('parfums');
p.addEventListener('click',function(event){
console.log('Click');
if(event.target.nodeName!=='SPAN'){return;}
let ligne=document.createElement('li');
ligne.textContent=event.target.textContent;
panier.append(ligne);
});
panier.addEventListener('click',function(event){
console.log('Click ul');
if(event.target.nodeName!=='LI'){return;}
event.target.remove();
});
</script>
</body>
</html>
On va reprendre le tableau de joueurs du sujet-5. Des petites croix ont été ajoutées à chaque ligne.
Créez les fichiers suivants (ou reprenez les vôtres en mettant à jour le tableau HTML)
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="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="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="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="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="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="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="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>
<!--------------------->
<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();
});
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 nom =document.createElement('td');
let score=document.createElement('td');
nom.textContent=joueur.nom;
score.textContent=joueur.score;
nom.className='nom';
score.className='score';
ligne.append(nom);
ligne.append(score);
document.getElementById('joueurs').append(ligne);
}
function ajouter_joueur(joueur)
{
console.log('ajouter_joueur',joueur);
let ligne =document.createElement('tr');
let effacer=document.createElement('td');
let nom =document.createElement('td');
let score =document.createElement('td');
let croix=document.createElement('img');
croix.src='https://moodle.iutv.univ-paris13.fr/img/js/effacer.png';
effacer.append(croix);
nom.textContent=joueur.nom;
score.textContent=joueur.score;
effacer.className='effacer';
nom.className='nom';
score.className='score';
ligne.append(effacer);
ligne.append(nom);
ligne.append(score);
document.getElementById('joueurs').append(ligne);
}
On voudrait réagir lorsque l'utilisateur clique sur une croix.
Le HTML des joueurs ajoutés (ligne dans le tableau) n'existe pas au démarrage de la page... on ne peut donc pas faire des addEventListener sur les croix au démarrage.
On va donc utiliser le bubbling. Faites en sorte d'afficher « Click croix » dans la console, uniquement quand l'utilisateur clique sur une croix (et pas ailleurs).
Indices:
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');
});
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 nom =document.createElement('td');
let score =document.createElement('td');
let croix=document.createElement('img');
croix.src='https://moodle.iutv.univ-paris13.fr/img/js/effacer.png';
effacer.append(croix);
nom.textContent=joueur.nom;
score.textContent=joueur.score;
effacer.className='effacer';
nom.className='nom';
score.className='score';
ligne.append(effacer);
ligne.append(nom);
ligne.append(score);
document.getElementById('joueurs').append(ligne);
}
Dans le code suivant:
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 sera l'image.
On veut supprimer la ligne <tr> quand l'utilisateur clique sur la croix.
Que faut-il taper pour supprimer la ligne tout entière ?
Indices:
Que ce soit pour le panier ou pour le tableau joueur, on a deux situations où:
Dans ces deux cas on ne peut pas utiliser addEventListener au démarrage de la page, car les éléments (panier: <li>, joueurs: <tr>) n'existent pas encore. On exploite alors le bubbling: on utilise addEventListener sur un parent qui existe au démarrage (panier: <ul>, joueurs: <table>).
On aura donc du code de ce type:
unParent.addEventListener('exemple', function(event){
if( /* c'est n'est pas l'élément descendant souhaité */ ) { return; }
});
Cette approche est très courante. En particulier, c'est le cas des programmes AJAX (qu'on verra plus tard) qui génèrent beaucoup de HTML en cours d’exécution.