Sujet 2

  1. Bienvenue au 2e sujet
  2. Révisions
    1. Révision arbre 1
    2. Révision arbre 2
    3. Syntaxe: commentaires
    4. Boucle for
    5. Déclaration fonction
    6. fonction dans une variable
    7. appel d'une fonction
    8. addEventListener
    9. Sélecteurs CSS
    10. querySelector
    11. Gestionnaire d'événements
    12. addEventListener 2
    13. Appel
  3. Champs texte
    1. texte.html
    2. querySelector
    3. addEventListener
    4. Copie du texte
    5. Correction
    6. Prénom
    7. Correction
    8. Champs vide
    9. Correction
  4. Jeu Morpion
    1. Correction HTML CSS
    2. querySelectorAll
    3. NodeList
    4. Boucle, suite
    5. Correction boucle
    6. Correction addEventListener
    7. Correction click
    8. Changer de joueur
    9. Correction joueur
    10. Correction Morpion
  5. Fonctions anonymes
    1. anonyme vs non anonyme
    2. Fonction anonyme : morpion
    3. Correction: Fonction anonyme : morpion
    4. Fonction anonyme : formulaire
    5. Correction: Fonction anonyme : formulaire
  6. Class
    1. className
    2. exercice
    3. Correction: exercice
    4. classList
    5. exo classList
    6. exo classList 2
  7. Rappels : sélecteurs CSS
    1. Rappel : arbre des éléments HTML
    2. Sélecteur de descendants
    3. Descendants - 1
    4. Descendants - 2
    5. Descendants
    6. Descendants
    7. Descendants
    8. Descendants
    9. Descendants directs
    10. Descendants directs
    11. Descendants directs
  8. Compositions de sélecteurs
    1. Composition
    2. Composition
    3. Composition
    4. Composition
    5. Composition
    6. Composition
  9. Priorité des sélecteurs
    1. Priorité des sélecteurs
    2. Priorités CSS : exercice
    3. Priorités CSS : exercice
    4. Priorités CSS : exercice
    5. Priorités CSS : exercice
  10. Onglets
  11. Onglets : HTML/CSS
    1. Onglets CSS 1
    2. Correction
    3. Onglets CSS 2
    4. Correction
    5. Onglets complets
    6. Onglets: arbre
    7. Onglets contenu : CSS
    8. Onglets contenu : CSS fin
    9. Correction : fin onglets.css
  12. Onglets : JS
    1. Sélecteur onglets menu
    2. Onglets JS : menu
    3. Correction: onglets click
    4. Onglets: partie du haut
    5. Correction: partie du haut
    6. Sélecteur contenu
    7. Onglets: contenu
    8. Correction: onglets

1. Bienvenue au 2e sujet

1.1 Bienvenue au 2e sujet

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.


2. Révisions

2.1 Révisions

Commençons par une rapide révision des notions du sujet précédent.

Révisions

2.2 Révision arbre 1


<div>
<h1>Hello</h1>
<p>Je m&apos;appelle <span>Tom</span></p>
</div>



Révisions

2.3 Révision arbre 2

Écrivez, en une seule ligne, le HTML correspondant.
Vous pouvez inventer le contenu que vous voulez.

Révisions

2.4 Syntaxe: commentaires

En JS, comment indique-t-on le début d'un commentaire qui ira jusqu'à la fin de la ligne ?

Révisions

2.5 Boucle for

É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
}

Révisions

2.6 Déclaration fonction

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"

Révisions

2.7 fonction dans une variable

function exemple() { return 123; }
let a=???;

Que faut-il écrire à la place de ??? pour mettre dans "a" une référence à la fonction "exemple" ?

Révisions

2.8 appel d'une fonction

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" ?

Révisions

2.9 addEventListener

Dans le code suivant

 document.querySelector('h1').addEventListener('click',xyz);

normalement, quel est le type de xyz ?

Révisions

2.10 Sélecteurs CSS

Indiquez les sélecteurs CSS:

Révisions

2.11 querySelector

Que renvoie la fonction  querySelector ?

document.querySelector('.xyz');

Révisions

2.12 Gestionnaire d'événements

<!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.ABC('click',DEF);
function fonction_a_appeler()
{
let paragraphe=document.querySelector('p');
paragraphe.style.color='red';
}
</script>
</body>
</html>
On voudrait que fonction_a_appeler soit appelée quand l'utilisateur clique sur le bouton (input).
Il faut compléter ABC, puis DEF.

Que faut-il écrire à la place de ABC ?

Révisions

2.13 addEventListener 2

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>
<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>
On voudrait que fonction_a_appeler soit appelée quand l'utilisateur clique sur le bouton (input).

Que faut-il écrire à la place de DEF ?

Révisions

2.14 Appel


<!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 ce programme, quand sont appelées les fonctions suivantes ?


3. Champs texte

3.1 Champs texte

Dans les pages suivantes on va voir comment interagir avec des champs texte, dans des formulaires.


Champs texte

3.2 texte.html

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>


Champs texte

3.3 querySelector


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)

Champs texte

3.4 addEventListener

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)

Champs texte

3.5 Copie du texte

On a maintenant:

<!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');
...
}
</script>
</body>
</html>
C'est à vous de finir le contenu de la fonction ...
Vous devez copier le texte qui se trouve dans inputNom vers le span affiche-nom.
Indices:

Champs texte

3.6 Correction


<!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>


Champs texte

3.7 Prénom

Maintenant, ajoutons un champs prénom:


<!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);
...
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>
Complétez le programme pour que le prénom soit copié vers le span affiche-prenom
(Le nom doit continuer à être copié vers le span affiche-nom)


Champs texte

3.8 Correction


<!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>

Champs texte

3.9 Champs vide

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:

Champs texte

3.10 Correction


<!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>


4. Jeu Morpion

4.1 Jeu Morpion

Dans les pages suivantes on va écrire un petit morpion en HTML, CSS et JavaScript

Commençons par le HTML et le CSS uniquement.


Jeu Morpion

4.2 Correction HTML CSS


<!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>

Jeu Morpion

4.3 querySelectorAll

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......)

Jeu Morpion

4.4 ¤ NodeList

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)

Jeu Morpion

4.5 Boucle, suite


let tds=document.querySelectorAll('td');
for(let i=0;i<tds.length;i++){
...
}
Complétez cette boucle pour afficher ceci:
Indice:
  • utilisez textContent
  • tds se comporte comme un tableau. On peut faire tds[...]

Jeu Morpion

4.6 Correction boucle

            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

Jeu Morpion

4.7 Correction 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

Jeu Morpion

4.8 Correction 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';
}


Jeu Morpion

4.9 Changer de joueur

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.

Jeu Morpion

4.10 Correction 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;
if(joueur==='X'){joueur='O';}else{joueur='X';}
}

Maintenant, en utilisant textContent, vérifiez qu'une case est libre avant de la traiter.


Jeu Morpion

4.11 Correction Morpion


<!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>


5. Fonctions anonymes

5.1 ¤ Fonctions anonymes

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() {
   console.log('bonjour!');
   ...
});
Remarquez bien les accolades et la parenthèse fermante.
On vient de faire la même chose qu'au début, mais sans avoir à donner un nom à la fonction. Par ailleurs, cette écriture est plus courte. On n'a plus à gérer la fonction à deux endroits séparés.
En pratique, les fonctions anonymes sont très utilisées. Pour addEventListener, on utilisera le plus souvent une fonction anonyme. On n'utilisera des fonctions avec un nom que quand elles sont trop longues ou que la fonction doit être réutilisée à un deuxième endroit.



Fonctions anonymes

5.2 anonyme vs non anonyme

Parmi les codes suivants, lesquel(s) utilise(nt) des fonctions anonymes ?

Fonctions anonymes

5.3 Fonction anonyme : morpion

Reprenez votre fichier morpion :

<!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',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>
et utilisez une fonction anonyme à la place de click_td
Vérifiez que tout fonctionne bien.

Fonctions anonymes

5.4 Correction: Fonction anonyme : morpion


<!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>


Fonctions anonymes

5.5 Fonction anonyme : formulaire

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>


Fonctions anonymes

5.6 Correction: Fonction anonyme : formulaire


<!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>


6. Class

6.1 ¤ Class

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;
}

Manipulation en JS

Supposons qu'on veuille manipuler la classe de para3:

let p=document.querySelector('#para3');
Attention: pour accéder à "class" on ne peut pas utiliser p.class
car "class" est un mot clé en JS. On doit donc utiliser p.className

  • On peut lire className :  console.log(p.className) => "important actu encart"
  • On peut écrire dans className :  p.className="abc". Ceci change tout l'attribut class:
<p id="para3" class="abc">Lina a gagné !</p>


Class

6.2 className


<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 ?

Class

6.3 exercice

<!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.

Class

6.4 Correction: exercice

<!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>

Class

6.5 ¤ classList

Quand on doit gérer plusieurs classes, className devient pénible à utiliser.
<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');
on a maintenant:

<p id="para3" class="important actu encart abc">Lina a gagné !</p>
Essayons remove():

p.classList.remove('actu');
on a maintenant:

<p id="para3" class="important encart abc">Lina a gagné !</p>
Avec contains() on peut interroger:

console.log(p.classList.contains('important'); => true
console.log(p.classList.contains('xyz')); => false

Class

6.6 exo classList

<h1 class="actu urgent">Joueurs</h1>
<script>
let h=document.querySelector('h1');
XYZ
</script>
En utilisant classList, que faut-il écrire à la place de XYZ transformer le h1 en :

<h1 class="urgent">Joueurs</h1>

Class

6.7 exo classList 2

<h1 class="actu urgent">Joueurs</h1>
<script>
let h=document.querySelector('h1');
XYZ
</script>
En utilisant classList, que faut-il écrire à la place de XYZ transformer le h1 en :

<h1 class="actu urgent news">Joueurs</h1>

7. Rappels : sélecteurs CSS

7.1 Rappels : sélecteurs CSS

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...).

http://moodle.iutv.univ-paris13.fr/img/web/webs1-cm-3-2-1.png

http://moodle.iutv.univ-paris13.fr/img/web/webs1-tp-1-16.png

http://moodle.iutv.univ-paris13.fr/img/web/webs1-cm-1-17-1.png

Rappels : sélecteurs CSS

7.2 Rappel : arbre des éléments HTML

La notion d'arbre (avec des ancêtres et des descendants) est très utilisée dans les sélecteurs CSS.
Pour comprendre cette notion il faut raisonner sur l'arbre formé par les éléments HTML d'un document.

Voici un exemple d'arbre:

x
Le <a> à gauche est fils (descendant direct) de <h1>
Le <a> à droite est descendant (indirect) de ul.

Rappels : sélecteurs CSS

7.3 ¤ Sélecteur de descendants

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> » ?

r

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.



Rappels : sélecteurs CSS

7.4 Descendants - 1

s

Quel(s) élément(s) correspondent au sélecteur suivant?
li a

Rappels : sélecteurs CSS

7.5 Descendants - 2

s
Quel(s) élément(s) correspondent au sélecteur suivant?
ul a

Rappels : sélecteurs CSS

7.6 Descendants

s
Quel(s) élément(s) correspondent au sélecteur suivant?
#grostitre a

Rappels : sélecteurs CSS

7.7 Descendants

s
Quel(s) élément(s) correspondent au sélecteur suivant?
img p

Rappels : sélecteurs CSS

7.8 Descendants

s
Quel(s) élément(s) correspondent au sélecteur suivant?
.auth p img

Rappels : sélecteurs CSS

7.9 Descendants

s
Quel(s) élément(s) correspondent au sélecteur suivant?
#menu .actif

Rappels : sélecteurs CSS

7.10 ¤ Descendants directs

descendant direct

Le sélecteur " " (espace) sélectionne les descendants directs et indirects.
Par contre le sélecteur ">" sélectionne uniquement les descendants directs.

Rappels : sélecteurs CSS

7.11 Descendants directs

s
Quel(s) élément(s) correspondent au sélecteur suivant?

p>img

Rappels : sélecteurs CSS

7.12 Descendants directs

s
Quel(s) élément(s) correspondent au sélecteur suivant?

body>a

8. Compositions de sélecteurs

8.1 ¤ Compositions de sélecteurs

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.

r

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.

Compositions de sélecteurs

8.2 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
a.actif

Compositions de sélecteurs

8.3 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
ul.actif

Compositions de sélecteurs

8.4 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
p.auth

Compositions de sélecteurs

8.5 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
ul#menu

Compositions de sélecteurs

8.6 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
.auth a.externe img

Compositions de sélecteurs

8.7 Composition

s
Quel(s) élément(s) correspondent au sélecteur suivant?
body.auth h2

9. Priorité des sélecteurs

9.1 ¤ Priorité des sélecteurs

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:

Priorité des sélecteurs

9.2 Priorité des sélecteurs

Supposons que les sélecteurs suivants s'appliquent tous sur un élément.
Classez-les par ordre de priorité (1= le plus prioritaire)

Priorité des sélecteurs

9.3 Priorités CSS : exercice

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 » ?

Priorité des sélecteurs

9.4 Priorités CSS : exercice

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 » ?

Priorité des sélecteurs

9.5 Priorités CSS : exercice

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 » ?

Priorité des sélecteurs

9.6 Priorités CSS : exercice

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)

10. Onglets

10.1 Onglets

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.

11. Onglets : HTML/CSS

11.1 Onglets : HTML/CSS

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.

Onglets : HTML/CSS

11.2 Onglets CSS 1

On veut d'abord obtenir exactement ceci:

Indications :

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:

http://moodle.iutv.univ-paris13.fr/img/web/webs1-tp-1-19.png

Onglets : HTML/CSS

11.3 Correction

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;
}

Onglets : HTML/CSS

11.4 Onglets CSS 2

On veut maintenant obtenir exactement ceci:

Indications :

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 : HTML/CSS

11.5 Correction

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);
}

Onglets : HTML/CSS

11.6 Onglets complets

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.)


Onglets : HTML/CSS

11.7 Onglets: arbre

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>



Onglets : HTML/CSS

11.8 Onglets contenu : CSS

On veut obtenir ceci:

Indications

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.


Onglets : HTML/CSS

11.9 Onglets contenu : CSS fin

Dernière étape. On veut obtenir ceci:

http://moodle.iutv.univ-paris13.fr/img/js/onglets.png


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.




Onglets : HTML/CSS

11.10 Correction : fin onglets.css

onglets.css

/* 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>

12. Onglets : JS

12.1 Onglets : JS

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 :

JS externe
Vous avez remarqué ceci dans le HTML:
        <script src="onglets.js"></script>
Ceci permet de mettre le JS dans un fichier séparé onglets.js
Quand, le JS et le HTML sont courts, c'est pratique de tout mettre dans le même fichier HTML.
Quand ce n'est plus le cas, c'est plus propre d'utiliser un fichier séparé.

Onglets : JS

12.2 Sélecteur onglets menu

Voici l'arbre du code HTML onglets.html
Quel sélecteur CSS permet d'indiquer tous les li dans onglets-menu ?

Onglets : JS

12.3 Onglets JS : menu

En vous inspirant du morpion qu'on a fait, affichez "Click" dans la console chaque fois que l'utilisateur clique sur un onglet.
Indications:
  • le sélecteur vu précédemment peut vous servir
  • comme dans morpion où il y avait plusieurs td, ici il y a plusieurs li... il faut donc une boucle

Onglets : JS

12.4 Correction: onglets click


let lis=document.querySelectorAll('#onglets-menu>li');
for(let i=0;i<lis.length;i++)
{
lis[i].addEventListener('mousedown',function(){
console.log('Click');
});
}


Onglets : JS

12.5 Onglets: partie du haut

Lorsque l'utilisateur clique sur un onglet on doit:

Indications:


Onglets : JS

12.6 Correction: partie du haut


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';
});
}


Onglets : JS

12.7 Sélecteur contenu

Quel est le sélecteur permettant d'obtenir tous les div directement contenus dans onglets-contenu ?

Onglets : JS

12.8 Onglets: contenu

Le sélecteur est: #onglets-contenu>div

Pour savoir dans quel onglet on se trouve, on voudrait utiliser la variable i
Pour des raisons un peu compliquées, à l'intérieur de la fonction anonyme, la valeur de la variable i ne sera pas celle qu'on veut.
On va donc créer une copie locale appelée "idx", comme ceci:

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:


Onglets : JS

12.9 Correction: onglets


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';
});
}