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 du sujet précédent.
<div>
<h1>Hello</h1>
<p>Je m'appelle <span>Tom</span></p>
</div>
Écrivez, en une seule ligne, le HTML correspondant.
Vous pouvez inventer le contenu que vous voulez.
En JS, comment indique-t-on le début d'un commentaire qui ira jusqu'à la fin de la ligne ?
Écrivez, en une seule ligne, une boucle for sur la variable n qui affiche dans la console les nombres de 18 à 35 (35 compris) .
Rappel:
for(initialisation; condition pour continuer; code fin de chaque itération) {
...
}
Cette boucle est équivalente à :
initialisation
while(condition pour continuer){
...
code fin de chaque itération
}
En une seule ligne, déclarez une fonction appelée "somme", qui prend deux paramètres "x" et "y" et qui retourne la somme de x et de y.
En JS le retour se fait avec "return"
function exemple() { return 123; }
let a=???;
Que faut-il écrire à la place de ??? pour mettre dans "a" une référence à la fonction "exemple" ?
function exemple() { return 123; }
let b=???;
Que faut-il écrire à la place de ??? pour mettre dans "b" le résultat de l'appel de la fonction "exemple" ?
Dans le code suivant
document.querySelector('h1').addEventListener('click',xyz);
normalement, quel est le type de xyz ?
Indiquez les sélecteurs CSS:
Que renvoie la fonction querySelector ?
document.querySelector('.xyz');
<!DOCTYPE html>On voudrait que fonction_a_appeler soit appelée quand l'utilisateur clique sur le bouton (input).
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Bouton</title>
</head>
<body>
<input type="button" value="Appuyer"/>
<p>
Bonjour!
</p>
<script>
let bouton=document.querySelector('input');
bouton.ABC('click',DEF);
function fonction_a_appeler()
{
let paragraphe=document.querySelector('p');
paragraphe.style.color='red';
}
</script>
</body>
</html>
Que faut-il écrire à la place de ABC ?
Oui, addEventListener veut dire :
ajouter / enregistrer une fonction (appelée gestionnaire d'événements) qui doit être appelée lorsqu'un événement (click) survient.
<!DOCTYPE html>On voudrait que fonction_a_appeler soit appelée quand l'utilisateur clique sur le bouton (input).
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Bouton</title>
</head>
<body>
<input type="button" value="Appuyer"/>
<p>
Bonjour!
</p>
<script>
let bouton=document.querySelector('input');
bouton.addEventListener('click',DEF);
function fonction_a_appeler()
{
let paragraphe=document.querySelector('p');
paragraphe.style.color='red';
}
</script>
</body>
</html>
bouton.addEventListener('click',fonction_a_appeler() );Ceci appelle la fonction fonction_a_appeler avant d'appeler addEventListener. Le 2e paramètre que vous avez donné à addEventListener est la valeur de retour de la fonction fonction_a_appeler... qui n'est pas définie.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Bouton</title>
</head>
<body>
<input type="button" value="Appuyer"/>
<p>
Bonjour!
</p>
<script>
let bouton=document.querySelector('input');
bouton.addEventListener('click',fonction_a_appeler);
function fonction_a_appeler()
{
let paragraphe=document.querySelector('p');
paragraphe.style.color='red';
}
</script>
</body>
</html>
Dans les pages suivantes on va voir comment interagir avec des champs texte, dans des formulaires.
Créez le fichier texte.html suivant:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-nom"></span>!</p>
<script>
...
...
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
...
}
</script>
</body>
</html>
On voudrait que "Bonjour !" soit complété avec le nom tapé dans le champs texte, à chaque fois qu'on appuie sur une touche.
Pour y arriver, on va suivre la même idée que dans les programmes précédents:
Commençons par le début:
Que faut-il écrire pour créer une variable "inputNom" avec l'élément ayant l'id "nom" (utilisez le sélecteur pour l'id)
On a avancé !
<!DOCTYPE html>
<html lang="fr"><head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
ABC
function touche_nom_relachee(event)
{
console.log('Touche nom relachée');
...
}
</script>
</body>
</html>
Que faut-il écrire à la place de ABC pour dire au navigateur d'appeler la fonction touche_nom_relachee quand l'utilisateur relache une touche dans le champs inputNom ?
précision: le type d'événement "relâcher une touche" est "keyup"
( Avant de répondre ici, essayez dans votre navigateur en vérifiant la console)
On a maintenant:
<!DOCTYPE html>C'est à vous de finir le contenu de la fonction ...
<html lang="fr"><head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
...
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
}
</script>
</body>
</html>
<!DOCTYPE html>Complétez le programme pour que le prénom soit copié vers le span affiche-prenom
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
...
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
}
function touche_prenom_relachee(event)
{
console.log('Touche prénom relâchée');
...
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
let inputPrenom=document.querySelector('#prenom');
inputPrenom.addEventListener('keyup',touche_prenom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
}
function touche_prenom_relachee(event)
{
console.log('Touche prénom relâchée');
let affichePrenom=document.querySelector('#affiche-prenom');
affichePrenom.textContent=inputPrenom.value;
}
</script>
</body>
</html>
On voudrait afficher un message d'erreur "Vide ! " lorsque l'utilisateur n'a pas rempli un champs:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
<style>
.erreur{
color: red;
}
</style>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
<span class="erreur" id="erreur-nom">Vide !</span>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
let inputPrenom=document.querySelector('#prenom');
inputPrenom.addEventListener('keyup',touche_prenom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
...
}
function touche_prenom_relachee(event)
{
console.log('Touche prénom relâchée');
let affichePrenom=document.querySelector('#affiche-prenom');
affichePrenom.textContent=inputPrenom.value;
}
</script>
</body>
</html>
Quelques indices:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
<style>
.erreur{
color: red;
}
</style>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
<span class="erreur" id="erreur-nom">Vide !</span>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
let inputPrenom=document.querySelector('#prenom');
inputPrenom.addEventListener('keyup',touche_prenom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
let erreur=document.querySelector('#erreur-nom');
if(inputNom.value.length===0){erreur.style.opacity=1;}
else{erreur.style.opacity=0;}
}
function touche_prenom_relachee(event)
{
console.log('Touche prénom relâchée');
let affichePrenom=document.querySelector('#affiche-prenom');
affichePrenom.textContent=inputPrenom.value;
let erreur=document.querySelector('#erreur-prenom');
}
</script>
</body>
</html>
Dans les pages suivantes on va écrire un petit morpion en HTML, CSS et JavaScript
<!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>
...
</script>
</body>
</html>
Maintenant, réfléchissons au JS.
On voudrait réagir quand l'utilisateur clique sur chacune des 9 cases.
Pour ça, on pourrait ajouter un id à chacune des cases et utiliser querySelector pour chercher chacune.
Ce serait un peu long...
On va utiliser la fonction querySelectorAll(selecteur)
Dans la page avec votre tableau, tapez dans la console:
document.querySelectorAll('td')
Passez la souris sur les td affichés dans la console.
Quel est le type d'objet affiché ?
(No......)
Oui, un NodeList est une liste de Node.
let tds=document.querySelectorAll('td');
Ici, chaque Node est un élément "td".
On peut parcourir un NodeList comme un tableau. Sa longueur est donnée par length: tds.length
Écrivez une boucle for où une variable i va de 0 au nombre d'éléments du tableau.
(laissez le contenu de la boucle vide pour l'instant)
Presque!
Indice: vous rentrez une fois de trop dans la boucle
Rappel:
for(initialisation; condition pour continuer; code fin de chaque itération) {...}
let tds=document.querySelectorAll('td');Complétez cette boucle pour afficher ceci:
for(let i=0;i<tds.length;i++){
...
}
let tds=document.querySelectorAll('td');
for(let i=0;i<tds.length;i++)
{
tds[i].textContent=i;
}
Enlevez tds[i].textContent=i;
Maintenant, créez une fonction appelée "click_td" et faites en sorte qu'elle soit appelée quand l'utilisateur clique sur une case.
Vous pouvez vous inspirer d'autres fois où on a utilisé addEventListener
let tds=document.querySelectorAll('td');
for(let i=0;i<tds.length;i++)
{
tds[i].addEventListener('click',click_td);
}
function click_td(event)
{
console.log('Click!');
}
Il reste un problème pour le morpion. On veut écrire un 'X' sur le td cliqué.
La même fonction est appelée quelque soit le td cliqué.
Comment savoir de quel td il s'agit?
=> il existe une variable un peu particulière appelée "this" qui indique le td concerné
Finissez le programme, pour qu'un X soit affiché après le click
let tds=document.querySelectorAll('td');
for(let i=0;i<tds.length;i++)
{
tds[i].addEventListener('click',click_td);
}
function click_td(event)
{
console.log('Click');
this.textContent='X';
}
Ajoutons une variable appelée joueur.
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');
this.textContent=joueur;
...
}
Faîtes en sorte que joueur deviennent alternativement 'O' et 'X' à chaque click.
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');
this.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}
Maintenant, en utilisant textContent, vérifiez qu'une case est libre avant de la traiter.
<!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>
Jusqu'à là, on a utilisé des fonctions pour les événements comme ceci:
document.addEventListener('click', fonction_a_appeler);
function fonction_a_appeler() {
console.log('bonjour!');
...
}
En JavaScript il est possible de créer des fonctions sans nom, donc "anonymes":
function() {
console.log('bonjour!');
...
}
Mais alors, comment est-t-elle appelée ? A quoi sert-elle ?
On pourrait mettre une référence vers cette fonction dans une variable, puis appeler la variable:
let a=function() {
console.log('bonjour!');
...
}
// appel de la fonction:
a();
... mais c'est plus long que d'utiliser une fonction habituelle.
On pourrait aussi envoyer la fonction anonyme directement en paramètre à une fonction qui en a besoin... par exemple addEventListener:
document.addEventListener('click', function() {Remarquez bien les accolades et la parenthèse fermante.
console.log('bonjour!');
...
});
Parmi les codes suivants, lesquel(s) utilise(nt) des fonctions anonymes ?
Reprenez votre fichier morpion :
<!DOCTYPE html>et utilisez une fonction anonyme à la place de click_td
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Morpion</title>
<style>
#morpion
{
border-collapse: collapse;
}
#morpion td
{
border: 1px solid black;
width: 40px;
height: 40px;
font-size: 30px;
text-align: center;
cursor: pointer;
}
#morpion td:hover
{
background-color: #ffc;
}
</style>
</head>
<body>
<table id="morpion">
<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>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Morpion</title>
<style>
#morpion
{
border-collapse: collapse;
}
#morpion td
{
border: 1px solid black;
width: 40px;
height: 40px;
font-size: 30px;
text-align: center;
cursor: pointer;
}
#morpion td:hover
{
background-color: #ffc;
}
</style>
</head>
<body>
<table id="morpion">
<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', function(event) {
console.log('Click');
if(this.textContent!=''){return;}
this.textContent=joueur;
if(joueur==='X'){joueur='O';}else{joueur='X';}
});
}
let joueur='X';
</script>
</body>
</html>
Reprenons le formulaire. Utilisez des fonctions anonymes à la place des deux fonctions.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
<style>
.erreur{
color: red;
transition: opacity .3s;
}
</style>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
<span class="erreur" id="erreur-nom">Vide !</span>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
<span class="erreur" id="erreur-prenom">Vide !</span>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',touche_nom_relachee);
let inputPrenom=document.querySelector('#prenom');
inputPrenom.addEventListener('keyup',touche_prenom_relachee);
function touche_nom_relachee(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
let erreur=document.querySelector('#erreur-nom');
if(inputNom.value.length===0){erreur.style.opacity=1;}
else{erreur.style.opacity=0;}
}
function touche_prenom_relachee(event)
{
console.log('Touche prénom relâchée');
let affichePrenom=document.querySelector('#affiche-prenom');
affichePrenom.textContent=inputPrenom.value;
let erreur=document.querySelector('#erreur-prenom');
if(inputPrenom.value.length===0){erreur.style.opacity=1;}
else{erreur.style.opacity=0;}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Texte</title>
<style>
.erreur{
color: red;
transition: opacity .3s;
}
</style>
</head>
<body>
<form method="POST">
<p>
<label>Nom : <input id="nom" type="text"/></label>
<span class="erreur" id="erreur-nom">Vide !</span>
</p>
<p>
<label>Prénom : <input id="prenom" type="text"/></label>
<span class="erreur" id="erreur-prenom">Vide !</span>
</p>
</form>
<p>Bonjour <span id="affiche-prenom"></span> <span id="affiche-nom"></span>!</p>
<script>
let inputNom=document.querySelector('#nom');
inputNom.addEventListener('keyup',function(event)
{
console.log('Touche nom relâchée');
let afficheNom=document.querySelector('#affiche-nom');
afficheNom.textContent=inputNom.value;
let erreur=document.querySelector('#erreur-nom');
if(inputNom.value.length===0){erreur.style.opacity=1;}
else{erreur.style.opacity=0;}
});
let inputPrenom=document.querySelector('#prenom');
inputPrenom.addEventListener('keyup',function(event)
{
console.log('Touche prénom relâchée');
let affichePrenom=document.querySelector('#affiche-prenom');
affichePrenom.textContent=inputPrenom.value;
let erreur=document.querySelector('#erreur-prenom');
if(inputPrenom.value.length===0){erreur.style.opacity=1;}
else{erreur.style.opacity=0;}
});
</script>
</body>
</html>
L'attribut "class" est très utilisé en HTML, CSS et JS.
Ici, on va voir comment le manipuler en JS.
Exemple:
<p class="important">Lina a gagné !</p>
Il permet ensuite de spécifier la mise en forme dans le CSS:
.important {
color: red;
font-style: italic;
}
On peut avoir plusieurs classes pour un même élément. Elles sont séparées par des espaces:
<p class="important actu encart">Lina a gagné !</p>Elles sont bien vues par le CSS comme des classes différentes:
.important {
color: red;
font-style: italic;
}
.actu {
background-color: #ffe;
}
.encart {
border: 1px solid #aaa;
}
Un élément peut avoir à la fois des classes et un id:
<p id="para3" class="important actu encart">Lina a gagné !</p>
CSS:
#para3 {
margin-top: 1em;
}
.important {
color: red;
font-style: italic;
}
.actu {
background-color: #ffe;
}
.encart {
border: 1px solid #aaa;
}
Supposons qu'on veuille manipuler la classe de para3:
let p=document.querySelector('#para3');
<p id="para3" class="abc">Lina a gagné !</p>
<h1>Joueurs</h1>
<script>
let h=document.querySelector('h1');
XYZ
</script>
CSS:
.ok {
color: green;
}
Que faut-il écrire à la place de XYZ pour afficher le h1 en vert, en s'appuyant sur le CSS ?
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>className</title>
<style>
.selectionne
{
background-color: green;
color: white
}
</style>
</head>
<body>
<span>bonjour</span>
<script>
...
</script>
</body>
</html>
En utilisant le CSS fourni, faites en sorte que le bonjour devienne vert quand l'utilisateur clique dessus.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>className</title>
<style>
.selectionne
{
background-color: green;
color: white
}
</style>
</head>
<body>
<span>bonjour</span>
<script>
let s=document.querySelector('span');
s.addEventListener('click', function() {
s.className='selectionne';
});
</script>
</body>
</html>
<p id="para3" class="important actu encart">Lina a gagné !</p>Typiquement, on voudrait ajouter ou enlever une classe. On veut aussi savoir si une classe est présente.
classList permet de le faire :
let p=document.querySelector('#para3');
p.classList.add('abc');
<p id="para3" class="important actu encart abc">Lina a gagné !</p>
p.classList.remove('actu');on a maintenant:
<p id="para3" class="important encart abc">Lina a gagné !</p>
console.log(p.classList.contains('important'); => true
console.log(p.classList.contains('xyz')); => false
<h1 class="actu urgent">Joueurs</h1>En utilisant classList, que faut-il écrire à la place de XYZ transformer le h1 en :
<script>
let h=document.querySelector('h1');
XYZ
</script>
<h1 class="urgent">Joueurs</h1>
<h1 class="actu urgent">Joueurs</h1>En utilisant classList, que faut-il écrire à la place de XYZ transformer le h1 en :
<script>
let h=document.querySelector('h1');
XYZ
</script>
<h1 class="actu urgent news">Joueurs</h1>
On va prendre un moment pour revoir les sélecteurs CSS.
Ils seront très utiles non seulement pour la mise en page, mais aussi en JS (notamment dans querySelector...).
Un sélecteur CSS sert à dire « je veux appliquer ce style à tels éléments ».
Pour l'instant on a vu
Comment faire pour, par exemple, « appliquer ce style uniquement aux éléments <a> qui sont contenus dans un titre <h1> » ?
Prenons un autre exemple:
<ul id="liste1">
<li>abc</li>
<li>def</li>
</ul>
<ul id="liste2">
<li>xyz</li>
<li>rst</li>
</ul>
Supposons qu'on veuille changer uniquement la couleur des "li" de la deuxième liste.
li {color: red;}
ne marche pas, car elle change la couleur des "li" dans les deux listes.
On
peut utiliser un sélecteur composé de deux sélecteurs simples:
#liste2 li {color: red;}
L'espace entre "#liste2"
et "li" est très important: il veut dire "descendant de".
Donc: "#liste2
li" veut dire "tous les li qui sont descendants de #liste2
Remarquez: pour bien comprendre le sélecteur il faut le dire en français de droite à gauche.
Quel(s) élément(s) correspondent au sélecteur suivant?
li a
Quel(s) élément(s) correspondent au sélecteur suivant?
ul a
Quel(s) élément(s) correspondent au sélecteur suivant?
img p
Quel(s) élément(s) correspondent au sélecteur suivant?
.auth p img
Quel(s) élément(s) correspondent au sélecteur suivant?
#menu .actif
Quel(s) élément(s) correspondent au sélecteur suivant?
p>img
Quel(s) élément(s) correspondent au sélecteur suivant?
body>a
On peut aussi composer des sélecteurs en les accolant. Regardons ça sur un exemple:
<h1 class="actu">Mon titre</h1>
<p class="actu">
<strong class="actu">abc</strong> defg <a href="...">un lien </a>
</p>
Par exemple, imaginons qu'il y ait de nombreux types d'éléments (des "p" des "h1" ...) ayant tous une même classe "actu". On pourrait alors sélectionner uniquement les paragraphes ayant la classe "actu" comme ceci:
p.actu { color: red;}
(remarquez: il n'y a pas d'espace entre "p" et ".actu")
"p.actu" veut dire : les éléments à la fois de type "p" et appartenant à la classe "actu"
et ensuite on pourrait continuer, par exemple en spécifiant une relation de descendance:
p.actu a { color: red;}
qui veut dire : les éléments "a" contenus dans des paragraphes de classe "actu" seront en rouge
Ce genre d'approche est très utilisée en pratique.
On peut faire la même chose avec les id:
ul#menu { color: red;}
Comme il n'y a qu'un seul élément avec id="menu", ceci peut paraître redondant. Mais il y a des situations où c'est utile.
Quel(s) élément(s) correspondent au sélecteur suivant?
p.auth
Quel(s) élément(s) correspondent au sélecteur suivant?
ul#menu
Quel(s) élément(s) correspondent au sélecteur suivant?
.auth a.externe img
Quel(s) élément(s) correspondent au sélecteur suivant?
body.auth h2
Dans les exercices suivants on va voir comment des règles des style peuvent s'appliquer indirectement à des éléments et ce qu'il se passe lorsque plusieurs règles différentes s'appliquent à un même élément.
Pour résumer:
Supposons que les sélecteurs suivants s'appliquent tous sur un élément.
Classez-les par ordre de priorité (1= le plus prioritaire)
HTML:
<p id="intro">
Une jolie <a href="page.html" class="externe" id="lienpage">page</a>.
</p>
CSS:
#lienpage { color: red;}
a { color: green;}
.externe { color: blue;}
Quelle est la couleur du mot « page » ?
HTML:
<p id="intro">
Une jolie <a href="page.html" class="externe" id="lienpage">page</a>.
</p>
CSS:
a.externe { color: red;}
a { color: green;}
#intro a { color: blue;}
Quelle est la couleur du mot « page » ?
HTML:
<p id="intro">
Une jolie <a href="page.html" class="externe" id="lienpage">page</a>.
</p>
CSS:
#lienpage { color: red;}
#intro .externe { color: green;}
#intro a { color: blue;}
Quelle est la couleur du mot « page » ?
HTML:
<p id="intro">
Une jolie <a href="page.html" class="externe" id="lienpage">page</a>.
</p>
CSS:
#intro a { color: red;}
a.externe { color: green;}
#intro a .externe { color: blue;}
Quelle est la couleur du mot « page » ?
(attention piège, lisez attentivement)
Dans les pages suivantes on va réaliser, ensemble, les onglets de la figure de droite.
Si vous êtes en retard, il est préférable d'aller directement à la correction de la partie CSS, cette partie n'etant pas indispensable à l'apprentissage du JavaScript.
Commençons par le CSS.
Dans cette partie, le HTML est fixé. Vous ne devez pas le changer. Vous pouvez uniquement modifier le CSS.
Créez le fichier suivant:
onglets.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>onglets</title>
<link type="text/css" rel="stylesheet" href="onglets.css"/>
</head>
<body>
<!--------------------->
<ul id="onglets-menu">
<li>Présentation</li>
<li class="menu-actif">Règles</li>
<li>Personnages</li>
<li>Scores</li>
</ul>
<!--------------------->
<script src="onglets.js"></script>
</body>
</html>
Ouvrez aussi un fichier vide "onglets.css"
On va construire, ensemble, étape par étape ces onglets.
On veut d'abord obtenir exactement ceci:
Ajoutez l'image de fond suivante à body:
texture-grise.jpg :
Changez la couleur du texte des lignes de la liste en blanc.
Utilisez "display: flex, sur le ul pour que lignes s'affichent de gauche à droite (et pas de haut en bas)
Utilisez "list-style: none;" sur la liste pour enlever les puces.
On utilise une astuce un peu compliquée pour obtenir le coin coupé :
C'est un dégradé (gradient) penché à 220 degrés avec un passage très court entre transparent et rouge:
background: linear-gradient(220deg, transparent 10px, #ad1c1c 11px);
Dans chaque onglet, ajoutez un peu d'espace entre le texte et les bords de l'onglet.
Rappel:
onglets.css
body
{
background-image: url(texture-grise.jpg);
}
#onglets-menu
{
list-style: none;
display: flex;
}
#onglets-menu li
{
background: linear-gradient(220deg, transparent 10px, #ad1c1c 11px);
color: white;
padding: 11px 30px;
}
On veut maintenant obtenir exactement ceci:
Texte : Dans chaque onglet, utilisez la police suivante:
font-family: 'Lucida sans', Arial, Helvetica;
Mettez le texte en gras et ajustez sa taille à 12px.
Ajoutez une légère ombre sous le texte (text-shadow).
Relief : Pour l'effet de relief entre les onglets, ajoutez une ombre (voir box-shadow) semi-transparente rgba(0, 0, 0, .2) positionnée à gauche .
menu-actif: Faites en sorte que l'onglet ayant class="menu-actif" soit affiché en blanc.
(pour garder le coin coupé, reprenez la même idée que les autres onglets, en remplaçant la couleur dans le gradient par blanc)
La couleur du texte de l'onglet actif est #333 et il faut lui enlever l'ombre, avec : "text-shadow: none;"
:hover On veut changer légèrement la couleur d'un onglet quand la souris lui passe par-dessus.
Pour ça, on reprend la même idée que les coins coupés des autres onglets, en remplaçant la couleur dans le gradient par #c93434
onglets.css
body
{
background-image: url(texture-grise.jpg);
}
#onglets-menu
{
list-style: none;
display: flex;
}
#onglets-menu li
{
background: linear-gradient(220deg, transparent 10px, #ad1c1c 11px);
color: white;
padding: 11px 30px;
font-family: 'Lucida sans', Arial, Helvetica;
font-weight: bold;
font-size: 12px;
text-shadow: 0 1px 0 rgba(0,0,0,.5);
box-shadow: -4px 0 0 rgba(0, 0, 0, .2);
}
#onglets-menu li:hover
{
background: linear-gradient(220deg, transparent 10px, #c93434 11px);
}
#onglets-menu .menu-actif
{
background: linear-gradient(220deg, transparent 10px, white 11px);
color: #333;
text-shadow: none;
}
/* Forcer à rester blanc quand la souris passe sur le menu actif */
#onglets-menu .menu-actif:hover
{
background: linear-gradient(220deg, transparent 10px, white 11px);
}
On a fini la partie "menu" des onglets. Il nous reste à faire le contenu.
Utilisez cette nouvelle version du fichier onglets.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>onglets</title>
<link type="text/css" rel="stylesheet" href="onglets.css"/>
</head>
<body>
<!--------------------->
<div id="onglets">
<ul id="onglets-menu">
<li>Présentation</li>
<li class="menu-actif">Règles</li>
<li>Personnages</li>
<li>Scores</li>
</ul>
<div id="onglets-contenu">
<div>Martien est un nom générique qui désigne plusieurs types de créatures imaginaires censées vivre sur Mars. Selon la version la plus répandue, les martiens, également nommés « petits hommes verts », sont des êtres à l'apparence vaguement humanoïde et repoussante, minces, avec une grosse tête et des yeux globuleux, généralement animés de mauvaises intentions envers l'espèce humaine. Le nom de martien est souvent devenu, à tort, synonyme d'extraterrestre dans la culture populaire.</div>
<div class="contenu-actif"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. <p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div>
<div>Le chocolat [ ʃɔkɔla ], terme d'origine mésoaméricaine, est un aliment sucré produit à partir de la fève de cacao. Celle-ci est fermentée, torréfiée, broyée jusqu'à former une pâte de cacao liquide dont on extrait la matière grasse appelée beurre de cacao. Le chocolat est constitué du mélange, dans des proportions variables, de pâte de cacao, de beurre de cacao et de sucre ; on y ajoute éventuellement des épices, comme la vanille, ou des matières grasses végétales.</div>
<div><ul><li>Moi: beaucoup</li><li>Eux: pas tant que ça</li></ul></div>
</div>
</div>
<!--------------------->
<script src="onglets.js"></script>
</body>
</html>
(Dans les pages suivantes, le HTML est encore fixé. Vous ne devez pas le changer. Vous pouvez uniquement modifier le CSS.)
Regardons d'abord comment est structuré cet HTML :
<body>
<div id="onglets">
<ul id="onglets-menu">
<li>Présentation</li>
<li class="menu-actif">Règles</li>
<li>Personnages</li>
<li>Scores</li>
</ul>
<div id="onglets-contenu">
<div>Martien est un nom générique ...</div>
<div class="contenu-actif">Lorem ipsum dolor sit...</div>
<div>Le chocolat [ ʃɔkɔla ], terme d'origine...</div>
<div>...</div>
</div>
</div>
</body>
On veut obtenir ceci:
On veut réduire la largeur de l'ensemble et le centrer. Pour ça:
Fixez le width de <div id="onglets"> à 600 pixels.
Utilisez margin auto à gauche et à droite pour le centrer.
On veut que "onglets-contenu" soit blanc.
Remarquez que "onglets-menu" n'est pas collé à gauche.
En effet, par défaut un <ul> a du padding à gauche. Il faut l'enlever.
Dernière étape. On veut obtenir ceci:
Pour l'instant, tous les <div> dans "onglets-contenu" sont montrés en même temps.
On voudrait les cacher (display: none;) par défaut.
Ensuite, on voudrait montrer (display: block;) un seul, celui qui a class="contenu-actif" .
Complétez tout ce qu'il manque pour obtenir l'affichage ci-dessus.
/* Fortement inspiré de :
* http://red-team-design.com/css3-tabs-with-beveled-corners/
*/
body
{
background-image: url(texture-grise.jpg);
font-family : sans;
}
#onglets
{
width: 600px;
margin: 2em auto;
}
#onglets-menu
{
list-style: none;
padding: 0;
display: flex;
margin-bottom: 0;
}
#onglets-menu li
{
background: linear-gradient(220deg, transparent 10px, #ad1c1c 11px);
color: white;
padding: 11px 30px;
font-family: 'Lucida sans', Arial, Helvetica;
font-weight: bold;
font-size: 12px;
text-shadow: 0 1px 0 rgba(0,0,0,.5);
box-shadow: -4px 0 0 rgba(0, 0, 0, .2);
cursor: pointer;
}
#onglets-menu li:hover
{
background: linear-gradient(220deg, transparent 10px, #c93434 11px);
}
#onglets-menu .menu-actif
{
background: linear-gradient(220deg, transparent 10px, white 11px);
color: #333;
text-shadow: none;
}
/* Forcer à rester blanc quand la souris passe sur le menu actif */
#onglets-menu .menu-actif:hover
{
background: linear-gradient(220deg, transparent 10px, white 11px);
}
#onglets-contenu
{
clear: both;
background-color: white;
border-radius: 0 2px 2px 2px;
box-shadow: 0 2px 2px #000;
}
#onglets-contenu>div
{
display: none;
padding: 30px;
}
#onglets-contenu>.contenu-actif
{
display: block;
}
#onglets-contenu>div>*:first-child
{
margin-top: 0;
}
onglets.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>onglets</title>
<link type="text/css" rel="stylesheet" href="onglets.css"/>
</head>
<body>
<!--------------------->
<div id="onglets">
<ul id="onglets-menu">
<li>Présentation</li>
<li class="menu-actif">Règles</li>
<li>Personnages</li>
<li>Scores</li>
</ul>
<div id="onglets-contenu">
<div>Martien est un nom générique qui désigne plusieurs types de créatures imaginaires censées vivre sur Mars. Selon la version la plus répandue, les martiens, également nommés « petits hommes verts », sont des êtres à l'apparence vaguement humanoïde et repoussante, minces, avec une grosse tête et des yeux globuleux, généralement animés de mauvaises intentions envers l'espèce humaine. Le nom de martien est souvent devenu, à tort, synonyme d'extraterrestre dans la culture populaire.</div>
<div class="contenu-actif"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. <p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div>
<div>Le chocolat [ ʃɔkɔla ], terme d'origine mésoaméricaine, est un aliment sucré produit à partir de la fève de cacao. Celle-ci est fermentée, torréfiée, broyée jusqu'à former une pâte de cacao liquide dont on extrait la matière grasse appelée beurre de cacao. Le chocolat est constitué du mélange, dans des proportions variables, de pâte de cacao, de beurre de cacao et de sucre ; on y ajoute éventuellement des épices, comme la vanille, ou des matières grasses végétales.</div>
<div><ul><li>Moi: beaucoup</li><li>Eux: pas tant que ça</li></ul></div>
</div>
</div>
<!--------------------->
<script src="onglets.js"></script>
</body>
</html>
Nos onglets s'affichent bien. On ne va plus toucher aux fichiers HTML et CSS.
On veut maintenant passer d'un onglet à l'autre à l'aide d'un petit programme en JavaScript.
Dans les pages suivantes, on va le faire, ensemble, en deux étapes :
<script src="onglets.js"></script>Ceci permet de mettre le JS dans un fichier séparé onglets.js
let lis=document.querySelectorAll('#onglets-menu>li');
for(let i=0;i<lis.length;i++)
{
lis[i].addEventListener('mousedown',function(){
console.log('Click');
});
}
Lorsque l'utilisateur clique sur un onglet on doit:
Indications:
let lis=document.querySelectorAll('#onglets-menu>li');
for(let i=0;i<lis.length;i++)
{
lis[i].addEventListener('mousedown',function(){
console.log('Click');
document.querySelector('.menu-actif').className='';
this.className='menu-actif';
});
}
Quel est le sélecteur permettant d'obtenir tous les div directement contenus dans onglets-contenu ?
let lis=document.querySelectorAll('#onglets-menu>li');
for(let i=0;i<lis.length;i++)
{
let idx=i;
lis[i].addEventListener('mousedown',function(){
console.log('Click');
document.querySelector('.menu-actif').className='';
this.className='menu-actif';
...
});
}
Avec document.querySelectorAll, construisez une liste de tous div descendants directs de onglets-contenu.
Il vous reste deux choses à faire:
let contenus=document.querySelectorAll('#onglets-contenu>div');
let lis=document.querySelectorAll('#onglets-menu>li');
for(let i=0;i<lis.length;i++)
{
let idx=i;
lis[i].addEventListener('mousedown',function(){
console.log('Click');
document.querySelector('.menu-actif').className='';
this.className='menu-actif';
document.querySelector('.contenu-actif').className='';
contenus[idx].className='contenu-actif';
});
}