Exercices TP-3

  1. Bienvenue au TP-3
  2. Révisions
    1. JS text
    2. css
    3. console
    4. class
    5. hide
    6. input
    7. click
    8. Création élément jQuery
    9. Ajout paragraphe
  3. Cours : Objets et tableaux
    1. Pas de classe
    2. Créer un objet
    3. Propriétés dynamiques
    4. Objets et fonctions
    5. Objets et fonctions
    6. Objets et fonctions
    7. Tableaux
    8. Exemple : .animate()
  4. Exercice : .animate()
    1. .animate()
    2. .animate() : fin
    3. Correction
  5. Cours : window
    1. Rappel : objets DOM
    2. window
    3. window : objet global
    4. Fonctions window / JS
  6. Cours : Liste jQuery / arbre
    1. Fonction jQuery
    2. jQuery : listes
    3. .eq(n)
    4. .parent(), .children()
    5. .find()
    6. Enchaîner
    7. Effet sur toute la liste
    8. .each()
    9. .attr()
    10. Exemple : .parent()
    11. Exemple : .parent()
  7. Exercices listes jQuery
    1. Arbre jQuery
    2. Arbre jQuery
    3. Arbre jQuery
    4. Arbre jQuery
    5. Arbre jQuery
    6. Arbre jQuery
    7. Arbre jQuery
    8. Arbre jQuery
  8. Tableau joueurs - ajouter
    1. Fichiers
    2. Création d'objet
    3. Click - ajouter
    4. Correction: click
    5. ajouter_joueur
    6. Correction
    7. XSS
    8. Éviter XSS
    9. Correction
  9. Tableau joueurs : total et médiane
    1. Total : HTML
    2. calculer_total()
    3. calculer_total(), indications supplémentaires
    4. Correction
    5. Affichage total
    6. Correction
    7. Tableaux JS
    8. Ajout tableau JS
    9. calculer_mediane()
    10. Correction
    11. calculer_mediane(), suite
    12. Correction
    13. Trier le tableau HTML
    14. Correction
  10. Diaporama
    1. Diapos : défiler
    2. Diapos: décalage avec .css()
    3. Correction
    4. Diapos : améliorations
    5. Correction
    6. Diapos : défilement automatique
    7. Correction

1. Bienvenue au TP-3

1.1 Bienvenue au TP-3

Pour votre progression, c'est très important de finir le TP précédent avant de commencer celui-ci.

2. Révisions

2.1 Révisions

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

Révisions

2.2 JS text


<span>bonjour</span>

Que faut-il écrire en JS pour que ceci affiche "coucou" au lieu de "bonjour" ?

Révisions

2.3 css


<span>bonjour</span>
Que faut-il écrire en JS pour que ceci soit affiché en rouge ?

Révisions

2.4 console

Que faut-il écrire pour afficher, à partir d'un programme JS, "bonjour" dans la console ?

(c'est utilisé souvent pour débugger)

Révisions

2.5 class

Que faut-il écrire en JS pour transformer

<div class="important">

en

<div class="important urgent">

Révisions

2.6 hide

Que faut-il écrire en JS pour transformer

<h1>...</h1>

en

<h1 style="display: none">...</h1>

(en d'autres termes, ce ne sera plus affiché)

On demande une solution très simple et courte.
Indice : que fait visuellement "display :none" ?

Révisions

2.7 input


Un utilisateur vient de taper un mot dans un champs texte, comme celui-ci :

<input type="text" .../>

Que faut-il écrire pour afficher dans la console le mot tapé ?

Révisions

2.8 click


<span>cliquer ici</span>

function ma_fonction()
{
...
}
Quand un utilisateur clique sur le span, on veut que ma_fonction soit appelée. Que faut-il écrire ?

Révisions

2.9 Création élément jQuery

On veut ajouter un nouveau paragraphe dans le <body> d'un document.

<body>
<p>bonjour</p>
<p>bonjour</p>
(ajouter ici)
</body>
On a vu en cours, que l'on pouvait décomposer en deux étapes:

  1. créer le nouveau paragraphe
  2. l'insérer dans le document

Commençons par la première étape.
Que faut-il écrire en jQuery pour créer une liste contenant un nouveau paragraphe vide ?

(en cas de doute, relisez la fin du 1er cours)

Révisions

2.10 Ajout paragraphe

<body>
<p>bonjour</p>
<p>bonjour</p>
(ajouter ici)
</body>

On vient de créer un nouveau paragraphe vide avec

var n=$('<p></p>')

Que faut-il écrire pour ajouter n à l'endroit indiqué par "(ajouter ici)" ?

(en cas de doute, relisez la fin du 1er cours)

3. Cours : Objets et tableaux

3.1 Cours : Objets et tableaux

Si vous venez d'assister au cours magistral, passez à la section suivante.

Dans cette partie, on va apprendre à utiliser les objets et les tableaux.

Cours : Objets et tableaux

3.2 Pas de classe

En Java:

- on crée une classe

- on instancie un objet de cette classe (new)

- on accède à une propriété de l’objet

En JavaScript

- on crée directement un objet (ici, il est vide, mais il pourrait-être initialisé)

- on peut ajouter des propriétés simplement

Cours : Objets et tableaux

3.3 Créer un objet

En JavaScript, on peut créer un objet en utilisant les accolades "{", "}", et en spécifiant directement des propriétés et leurs valeurs.

Cette syntaxe est très utilisée en pratique.

Elle sert aussi comme un format d'échange de données appelé JSON. JSON est utilisé, entre autres, pour la communication entre le navigateur et le serveur. On étudiera JSON dans un autre cours.

Cours : Objets et tableaux

3.4 Propriétés dynamiques

En Java on ne peut pas utiliser une propriété qui n'a pas été déclarée dans la classe.

En JavaScript on peut ajouter des propriétés dynamiquement. Il n'y a pas de classe.

Cours : Objets et tableaux

3.5 Objets et fonctions

En JavaScript, les fonctions sont des valeurs comme les autres (number, String, object...). On peut les attribuer à des variables. On peut aussi les attribuer aux propriétés d'un objet.

Donc, pour créer une méthode, il suffit de créer une propriété dont la valeur est de type "function".

Le JS ne fait rien de spécial pour gérer la méthode. afficherNotes est juste une propriété de l'objet, dont la valeur se trouve être de type "function".

Cours : Objets et tableaux

3.6 Objets et fonctions

On peut aussi utiliser comme valeur une fonction anonyme directement dans l'initialisateur d'objet.

Cours : Objets et tableaux

3.7 Objets et fonctions

La fonction peut être créée ailleurs.

Contrairement au Java, la création d'une méthode en JavaScript est simplement une affectation à une propriété d'une valeur de type "function".

Cours : Objets et tableaux

3.8 Tableaux

Les tableaux JavaScript se déclarent avec des crochets [ ... ]. Les tableaux sont indexés par un entier et sont numérotés à partir de 0.

De nombreuses méthodes sont associées aux tableaux. Par exemple :

.push(v) permet d'ajouter une valeur à la fin d'un tableau.

.indexOf(v) renvoi l'indice de la première valeur v trouvée dans le tableau

Pour parcourir un tableau, utilisez une boucle numérique (comme en C).

.length permet d'obtenir la taille d'un tableau.

Cours : Objets et tableaux

3.9 Exemple : .animate()

Un exemple d'utilisation d'objet:

La fonction jQuery .animate() permet de changer progressivement les valeurs de propriétés CSS. Le premier argument « options » est un objet indiquant quelles propretés CSS doivent changer progressivement, et vers quelles valeurs elles doivent évoluer.

Ici on passe donc une série d'arguments à une fonction en utilisant un objet.

Cette approche est très utilisée dans jQuery.

Ici on a décomposé en deux étapes, mais en pratique, on définit souvent l'objet directement dans l'appel de la fonction:

$('#boite').animate({top: 100, ...},1000);

4. Exercice : .animate()

4.1 Exercice : .animate()

Après ces révisions, on va commencer par un exercice amusant :-)

Rappel du cours :

La fonction jQuery .animate() permet de faire évoluer dans le temps des propriétés CSS.
On fournit en argument un objet constitué des propriétés que l'on veut faire évoluer et la valeur destination.
.animate() peut uniquement faire évoluer des propriétés numériques (par exemple "width", mais pas "color")

Créez les 3 fichiers suivants:

animate.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>animate</title>
<link type="text/css" rel="stylesheet" href="animate.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="animate.js"></script>
</head>
<body>
<!--------------------->
<h1>Animate !</h1>
<!--------------------->
</body>
</html>

animate.css

h1
{
position: relative;
border: 2px solid black;
background-color: #eff;
width: 200px;
padding: 20px;
}

animate.js

$(document).ready(function()
{

});

Exercice : .animate()

4.2 .animate()

Complétez animate.js pour qu'une animation se lance quand l'utilisateur clique sur la boite.

Vérifiez que ca marche, puis essayez de faire évoluer les propriétés CSS suivantes:

left, top, width, padding, opacity (entre 0 et 1), "border-radius" (remarquez les guillemets), ...

Remarque: on peut faire évoluer une propriété à la fois, ou plusieurs en même temps.

Exercice : .animate()

4.3 .animate() : fin

.animate() peut prendre un 3eme argument : une fonction qui sera appelée à la fin de l'animation.

Essayez d'abord avec une fonction qui affiche juste un message dans la console.

Essayez ensuite  avec une fonction qui lance une deuxième animation ramenant tout à l'état initial.



Exercice : .animate()

4.4 Correction

$(document).ready(function()
{
$('h1').click(function()
{
var prop={left: 500,opacity: 0,"border-radius": 100,padding: 100};
$('h1').animate(prop,1000,function()
{
console.log('fin première anim');
$('h1').animate({left: 0,opacity: 1,"border-radius": 0, padding: 20},1000);
});
});
});


Remarque: pour faire certaines animations on peut aussi utiliser les transitions CSS.
Elles sont plus fluides (moins de CPU) .


5. Cours : window

5.1 Cours : window

Si vous venez d'assister au cours magistral, passez à la section suivante.

Cours : window

5.2 Rappel : objets DOM

Voici 3 types d'objets DOM importants:

- window : la fenêtre d'un document. S'il y a plusieurs onglets, chaque onglet a son window.

- document : à l'intérieur du window, contient l'arbre DOM issu du HTML.

- HTMLElement : la plupart des noeuds de l'arbre que nous manipulerons sont de type HTMLElement

Cours : window

5.3 window

window fournit de nombreuses propriétés et fonctions permettant de manipuler la page.

Par exemple, window.location permet de connaître l'URL de la page courante. On peut aussi changer window.location, dans ce cas le navigateur charge la nouvelle page.

Autres exemples: window.innerWidth donne la largeur de la fenêtre. window.scrollY permet de connaître le défilement vertical de la fenêtre (en pixels).

Cours : window

5.4 window : objet global

Les programmes JavaScript sont exécutés avec un « objet global». Dans un navigateur l'objet global est « window ».

Ça veut dire que si vous n'êtes pas dans une fonction, toutes les variables et fonctions que vous utilisez sont en réalité des propriétés de window.

Par exemple : écrire « a="bonjour" » c'est exactement la même chose que d'écrire « window.a="bonjour" ».

Donc, quand vous déclarez une variable globale, vous êtes en train d'ajouter une propriété à window.

Cours : window

5.5 Fonctions window / JS

document : l'arbre DOM

setInterval() : exécuter une fonction régulièrement

setTimeout() : exécuter une fonction dans x ms

...

6. Cours : Liste jQuery / arbre

6.1 Cours : Liste jQuery / arbre

Si vous venez d'assister au cours magistral, passez à la section suivante.

Dans cette partie, on va étudier plus en détail les listes jQuery et le parcours d'arbre.


Cours : Liste jQuery / arbre

6.2 Fonction jQuery

Depuis le début de ces cours on crée de nombreuses listes jQuery. Regardons en détail la syntaxe de création de ces listes.

Le "$" est en réalité un nom de fonction. Il se trouve que le "$" est un caractère valide pour un nom de fonction. C'est utilisé comme un raccourci pour la fonction aussi appelée "jQuery".

Ici, on passe à cette fonction une chaîne de caractères contenant un sélecteur CSS. La fonction jQuery reçoit cette chaîne de caractères et renvoi (return) un objet JS. Cet objet est la liste jQuery.

Cours : Liste jQuery / arbre

6.3 jQuery : listes

Comme on l'a vu $('.xyz') permet de créer une liste jQuery. Elle est constituée de tous les éléments désignes par le sélecteur .xyz.

Cette liste peut contenir de nombreux éléments. Elle peut aussi ne contenir qu'un seul élément, ou parfois même aucun. Sa taille est donnée par « .length ».

Ces listes sont le support de la majorité d'opérations faites en jQuery. Comme indiqué au 1er cours, il existe plus de 180 fonctions s'appliquant sur une liste jQuery.

On a souvent besoin de manipuler ces listes.

Cours : Liste jQuery / arbre

6.4 .eq(n)

La fonction jQuery .eq(n) renvoie une nouvelle liste jQUery contenant un seul élément déterminé par son indice n.

Remarquez comment on applique une fonction sur une liste pour en obtenir une autre liste.

Cours : Liste jQuery / arbre

6.5 .parent(), .children()

Le HTML est représenté par un arbre. On a donc souvent besoin de parcourir cet arbre.

Par exemple, avec .parent() on obtient l’élément situé au-dessus d'un autre dans l'arbre.

.children() permet d'obtenir tous les éléments contenus dans un autre (descendants directs).

Si on fournit un sélecteur en argument « .children('xyz') » , alors seuls les fils correspondant à ce sélecteur sont gardés dans la liste.

Cours : Liste jQuery / arbre

6.6 .find()

.children() retourne uniquement les descendants directs, alors que .find() retourne les descendants directs et indirects.

Cours : Liste jQuery / arbre

6.7 Enchaîner

Toutes les fonctions jQuery que nous venons de voir s'appliquent à une liste jQuery et retournent une liste jQuery. On peut donc appeler une fonction jQuery sur la nouvelle liste nouvelle jQuery. Ceci permet d'enchaîner des appels de fonctions jQuery.

C'est très pratique.

Cours : Liste jQuery / arbre

6.8 Effet sur toute la liste

En général (mais pas toujours), les fonctions jQuery ont un effet sur tous les éléments de la liste jQuery.

Par exemple .addClass('ex') ajoute la classe 'ex' à TOUS les éléments de la liste.

Rappel: en HTML un élément peut avoir plusieurs classes, on les sépare par des espaces:

<p class="xyz ex">

Ici il y a bien deux classes : "xyz" et "ex".

Cours : Liste jQuery / arbre

6.9 .each()

Comme les fonctions jQuery s'appliquent sur toute une liste, on peut souvent faire des opérations simples sur toute une liste, sans avoir à traiter chaque élément de la liste séparément.

Pour les opérations plus compliquées, jQuery fournit une sorte de « boucle ».

liste.each(ma_fonction) appelle ma_fonction pour chacun des éléments de la liste. Dans ma_fonction l'élément est accessible avec « this

».

Cours : Liste jQuery / arbre

6.10 .attr()

La fonction jQuery .attr() permet de lire et de modifier un attribut HTML.

Cours : Liste jQuery / arbre

6.11 Exemple : .parent()

Voici un exemple pour illustrer l'utilisation de .parent()

Dans un formulaire constitué de plusieurs lignes, on voudrait changer la couleur de la ligne que l'utilisateur est en train de modifier.

Cours : Liste jQuery / arbre

6.12 Exemple : .parent()

L'événement « focus » permet de savoir quand l'utilisateur commence à éditer un champ. L'événement « blur » permet de savoir quand il le quitte.

.focus est appelé sur le <input> donc "this" dans le gestionnaire d'événement correspond au <input>. On voudrait modifier la ligne <li> qui contient cet <input>. on utilise donc $(this).parent()

7. Exercices listes jQuery

7.1 Exercices listes jQuery

Les listes jQuery sont le fondement de la plupart des opérations jQuery.
C'est important de les comprendre et de savoir les manipuler.

Exercices listes jQuery

7.2 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('h2')

Exercices listes jQuery

7.3 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('h2').parent()

Exercices listes jQuery

7.4 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('p').eq(1)

Exercices listes jQuery

7.5 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('p').eq(1).children()

Exercices listes jQuery

7.6 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('#popup').children('a')

Exercices listes jQuery

7.7 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('#popup').find('a')

Exercices listes jQuery

7.8 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('#popup').children().eq(3)

Exercices listes jQuery

7.9 Arbre jQuery


Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :

$('a img').parent().eq(2)

(Attention: piège)

8. Tableau joueurs - ajouter

8.1 Tableau joueurs - ajouter

Dans les pages suivantes nous allons écrire ensemble un programme JavaScript permettant de gérer un tableau de joueurs.



Tableau joueurs - ajouter

8.2 Fichiers

Créez les fichiers suivants :

joueurs.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>joueurs</title>
<link type="text/css" rel="stylesheet" href="joueurs.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="joueurs.js"></script>
</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="ajout-bouton" type="button" value="ajouter"/>
</p>
<table id="joueurs">
<tr><td class="nom">Leïla</td><td class="score">121</td></tr>
<tr><td class="nom">Driss</td><td class="score">153</td></tr>
<tr><td class="nom">Lian </td><td class="score">210</td></tr>
</table>
<!--------------------->
</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

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");


console.log("La mise en place est finie. En attente d'événements...");
});

Vérifiez que l'affichage est correct.

Tableau joueurs - ajouter

8.3 Création d'objet

Dans les pages suivantes, on va écrire une fonction ajouter_joueur(joueur).
Elle prendra en argument un objet.
Avant, on va essayer de se rappeler comment créer un objet.

Dans la console, essayez de créer un objet ayant deux propriétés "nom" et "score" avec pour valeurs "Tom" et 100.

Que faut-il écrire pour créer cet objet ?



Tableau joueurs - ajouter

8.4 Click - ajouter

Quand l'utilisateur clique sur le bouton "ajouter", créez un objet { nom: ..., score: ...} avec les valeurs tapées dans les 2 champs texte.

Envoyez cet objet à une fonction ajouter_joueur(joueur).

Créez la fonction ajouter_joueur(joueur)
Pour l'instant elle doit seulement afficher dans la console l'objet reçu.

Tableau joueurs - ajouter

8.5 Correction: click

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

$('#ajout-bouton').click(function()
{
var joueur={ nom: $('#ajout-nom' ).val(),
score: $('#ajout-score').val()
};
ajouter_joueur(joueur);
});

console.log("La mise en place est finie. En attente d'événements...");
});

function ajouter_joueur(joueur)
{
console.log(joueur);
}

Tableau joueurs - ajouter

8.6 ajouter_joueur

Maintenant complétons ajouter_joueur().

On veut créer un nouvelle ligne et l'ajouter au tableau.
On a vu ce procédé plusieurs fois  (notamment à la fin du cours 1):

  1. on crée des élements avec jQuery
  2. on les ajoute dans l'arbre DOM

Pensez à créer une ligne complète (tr,td...) avec les classes nécessaires.

C'est à vous...

Tableau joueurs - ajouter

8.7 Correction

function ajouter_joueur(joueur)
{
// attention: solution simple, mais incorrecte
var ligne=$('<tr><td class="nom">'+joueur.nom+'</td><td class="score">'+joueur.score+'</td></tr>');
$('#joueurs').append(ligne);
}

Tableau joueurs - ajouter

8.8 XSS

La solution (correction) précédente semble marcher, mais pose de gros problèmes.

Essayez de taper dans le champ "nom" différentes balises HTML.

Que se passe-t-il ?

C'est embêtant ... l'utilisateur peut casser l'affichage...


Mais plus grave encore, ce genre d'erreur peut conduire à des failles de sécurité appelées XSS DOM.

Pour comprendre, tapez le "nom" suivant et appuyez sur "ajouter":

<script>alert('hacked!')</script>

L'utilisateur à réussi à exécuter un programme sur la page.
Ici, c'est dans son propre navigateur... donc ce n'est pas grave.
Mais ce genre de code JS peut conduire à exécuter du JS fourni par un tiers... qui peut alors prendre le contrôle de votre session.

Tableau joueurs - ajouter

8.9 Éviter XSS


Pour éviter les failles XSS, il faut éviter d'insérer du texte fourni par l'utilisateur directement en tant qu'HTML.

Dans notre programme, on va décomposer en deux étapes:

  1. créer une ligne vide (sans le nom et le score)
  2. utiliser la fonction jQuery .text() pour insérer le nom et prénom dans cette ligne.
function ajouter_joueur(joueur)
{
var ligne=$('<tr><td class="nom"></td><td class="score"></td></tr>');
/* ajoutez ici nom et score à l'aide de .text() */
...
$('#joueurs').append(ligne);
}

Attention: vous avez le <tr> dans la variable "ligne" mais vous voulez insérer le texte dans les cases <td>...
Il faut donc faire une petite manipulation jQuery... comme on a vu en cours.

Vérifiez que ca marche.

Essayez à nouveau de rentrer dans "nom" :

<script>alert('hacked!')</script>


Pensez à effacer les champs texte après avoir ajouté la ligne.


Tableau joueurs - ajouter

8.10 Correction

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

$('#ajout-bouton').click(function()
{
var joueur={ nom: $('#ajout-nom' ).val(),
score: $('#ajout-score').val()
};
ajouter_joueur(joueur);
$('#ajout-nom' ).val('');
$('#ajout-score').val('');
});

console.log("La mise en place est finie. En attente d'événements...");
});

function ajouter_joueur(joueur)
{
var ligne=$('<tr><td class="nom"></td><td class="score"></td></tr>');
ligne.find(".nom" ).text(joueur.nom );
ligne.find(".score").text(joueur.score);
$('#joueurs').append(ligne);
}

9. Tableau joueurs : total et médiane

9.1 Tableau joueurs : total et médiane

Dans les pages suivantes on va afficher le total des scores et, ensuite, le score médian.


Tableau joueurs : total et médiane

9.2 Total : HTML

Mettez à jour votre fichier joueurs.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>joueurs</title>
<link type="text/css" rel="stylesheet" href="joueurs.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="joueurs.js"></script>
</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="ajout-bouton" type="button" value="ajouter"/>
</p>
<table id="joueurs">
<tr><td class="nom">Leïla</td><td class="score">121</td></tr>
<tr><td class="nom">Driss</td><td class="score">153</td></tr>
<tr><td class="nom">Lian</td><td class="score">210</td></tr>
<tr><td class="nom">Joe</td><td class="score"> 32</td></tr>
<tr><td class="nom">Naïma</td><td class="score">261</td></tr>
<tr><td class="nom">Karim</td><td class="score">183</td></tr>
<tr><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>

<!--------------------->
</body>
</html>

(Par rapport au précédent, on a juste ajouté quelques joueurs et un paragraphe à la fin).

Tableau joueurs : total et médiane

9.3 calculer_total()

Écrivez une fonction calculer_total() qui retourne la somme des scores affichés dans le tableau.

Si calculer_total() est globale, vous pourrez l'appeler depuis la console.
C'est pratique pour faire des essais. Essayez.

Vous aurez besoin des fonction suivantes :

Vous utiliserez aussi une fermeture (mais vous ne vous en rendrez peut-être pas compte, tellement c'est simple et naturel...).

Essayez de le faire vous-mêmes, si vous avez des difficultés, vous trouverez plus d'indications à la page suivante.


Tableau joueurs : total et médiane

9.4 calculer_total(), indications supplémentaires

Rappel du cours:



Tableau joueurs : total et médiane

9.5 Correction



function calculer_total()
{
var total=0;
// Pour chaque ligne du tableau .each() appelle la fonction.
$('#joueurs tr').each(function()
{
// $(this) est la ligne (tr) ...
// on veut le texte dans la case avec le score
var score=parseInt($(this).find('.score').text());
// La variable "total" est définie dans la fonction calculer_total...
// mais on peut y accéder ici (fermeture)
total+=score;
});
return total;
}


Tableau joueurs : total et médiane

9.6 Affichage total

Quand un joueur est ajouté, mettez à jour le total affiché.


Tableau joueurs : total et médiane

9.7 Correction

joueurs.js

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

$('#ajout-bouton').click(function()
{
var joueur={ nom: $('#ajout-nom' ).val(),
score: $('#ajout-score').val()
};
ajouter_joueur(joueur);
$('#ajout-nom' ).val('');
$('#ajout-score').val('');

$('#total').text(calculer_total());
});

console.log("La mise en place est finie. En attente d'événements...");
});

function ajouter_joueur(joueur)
{
var ligne=$('<tr><td class="nom"></td><td class="score"></td></tr>');
ligne.find(".nom" ).text(joueur.nom );
ligne.find(".score").text(joueur.score);
$('#joueurs').append(ligne);
}

function calculer_total()
{
var total=0;
// Pour chaque ligne du tableau .each() appelle la fonction.
$('#joueurs tr').each(function()
{
// $(this) est la ligne (tr) ...
// on veut le texte dans la case avec le score
var score=parseInt($(this).find('.score').text());
// La variable "total" est définie dans la fonction calculer_total...
// mais on peut y accéder ici (fermeture)
total+=score;
});
return total;
}



Tableau joueurs : total et médiane

9.8 Tableaux JS

Nous avons vu dans le cours, comment créer des tableaux JS.

Que faut-il écrire pour créer un tableaux contenant les éléments "fraise", "chocolat" et "vanille" ?

Tableau joueurs : total et médiane

9.9 Ajout tableau JS

var tab=["fraise", "chocolat" , "vanille"];

Que faut-il écrire pour ajouter au tableau « tab » un élément "framboise" ?


Tableau joueurs : total et médiane

9.10 calculer_mediane()

On veut écrire une fonction calculer_mediane()

La médiane est la valeur qui se trouve à la moitié d'une série de valeurs triées.
Elle est souvent utilisée en statistiques. Elle a des propriétés intéressantes par rapport à la moyenne.

Pour calculer la médiane des scores on va, dans les pages suivantes :

  1. construire un tableau JS avec tous les scores
  2. le trier
  3. chercher la valeur qui se trouve au milieu du tableau

----

Etape 1.

On va commencer par 1. construire un tableau JS avec tous les scores

Créez la fonction calculer_mediane()  en commençant par l'étape 1
Affichez le tableau JS dans la console.
(vous pouvez vous inspirer de calculer_total() )
Indication: vous pouvez créer un tableau vide simplement avec [ ]

Tableau joueurs : total et médiane

9.11 Correction


function calculer_mediane()
{
var scores=[];
$('#joueurs tr').each(function()
{
var s=parseInt($(this).find('.score').text());
scores.push(s);
});
console.log(scores);
}


Tableau joueurs : total et médiane

9.12 calculer_mediane(), suite

Il nous reste à

Tri

.sort() permet de trier un tableau JS.

Par défaut .sort() trie par ordre "alphabetique".
Ici, nous voulons trier des nombres. Il faut donc passer une fonction de comparaison à sort:

scores.sort(function(a,b){return a-b;});

... non, il n'y a pas plus simple :-( 

Milieu du tableau

Indication: utilisez la fonction Math.floor() pour arrondir vers le bas.

Affichage

Affichez la nouvelle médiane quand l'utilisateur clique sur ajouter.

Tableau joueurs : total et médiane

9.13 Correction

function calculer_mediane()
{
var scores=[];
$('#joueurs tr').each(function()
{
var s=parseInt($(this).find('.score').text());
scores.push(s);
});
scores.sort(function(a,b){return a-b;});
return scores[Math.floor(scores.length/2)];
}

Tableau joueurs : total et médiane

9.14 Trier le tableau HTML

-----

Attention: exercice un peu difficile, passez le sauf si vous êtes en avance.

-----

On veut maintenant trier le tableau HTML, pour afficher en premier les joueurs ayant le plus grand score.

Dans calculer_mediane() on a trié un tableau JS de scores, mais ce tableau JS  trié ne peut pas nous servir pour réordonner le tableau HTML, car après le tri on ne sait pas de quelle ligne venait chaque score :

function calculer_mediane()
{
var scores=[];
$('#joueurs tr').each(function()
{
var s=parseInt($(this).find('.score').text());
scores.push(s);
});
scores.sort(function(a,b){return a-b;});
...
}

scores === [ 0, 32, 121, 153, 183, 210, 261]
(de quelle ligne HTML vient le 32 ?)


L'idée ici est de construire un tableau appelé "joueurs" (au lieu de "scores") qui contienne à la fois la ligne et le score correspondant:

joueurs === [ { ligne:<tr>, score:121},  { ligne:<tr>, score:153},  { ligne:<tr>, score:210},  { ligne:<tr>, score:32},  { ligne:<tr>, score:261},  { ligne:<tr>, score:183},  { ligne:<tr>, score:0} ]

C'est à dire, chaque élément du tableau est un objet contenant deux propriétés: ligne et score

Ensuite on le trie avec :

joueurs.sort(function(a,b){return b.score-a.score;});

et on obtient :
joueurs === [ { ligne:<tr>, score:261},  { ligne:<tr>, score:210},  { ligne:<tr>, score:183},  { ligne:<tr>, score:153},  { ligne:<tr>, score:121},  { ligne:<tr>, score:32},  { ligne:<tr>, score:0} ]

Maintenant, on n'a plus qu'à parcourir ce tableau JS joueurs en réinsérant les lignes avec .append() à la fin du tableau HTML.

(NB: quand une ligne existante est insérée, elle est en réalité déplacée)

Ouf... c'est un peu compliqué ... mais vous pouvez essayer !
Écrivez la fonction trier() en vous inspirant de calculer_mediane()


Tableau joueurs : total et médiane

9.15 Correction

function trier()
{
var joueurs=[];
$('#joueurs tr').each(function()
{
var s=parseInt($(this).find('.score').text());
var j=
{
ligne:$(this),
score:s
};
joueurs.push(j);
});
joueurs.sort(function(a,b){return b.score-a.score;});
for(var i=0;i<joueurs.length;i++)
{
var ligne=joueurs[i].ligne;
$('#joueurs').append(ligne);
}
}


10. Diaporama

10.1 Diaporama

On veut créer un affichage où plusieurs images peuvent défiler à l'aide de deux flèches, comme ceci:

Pour ça, on va utiliser le HTML et le CSS suivants:

diapos.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>diapos</title>
<link type="text/css" rel="stylesheet" href="diapos.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="diapos.js"></script>
</head>
<body>
<!--------------------->
<div id="dia">
<div id="dia-images">
<img src="http://moodle.iutv.univ-paris13.fr/img/js/montagne-small.jpg" />
<img src="http://moodle.iutv.univ-paris13.fr/img/js/oiseau-small.jpg" />
<img src="http://moodle.iutv.univ-paris13.fr/img/js/escargot-small.jpg" />
<img src="http://moodle.iutv.univ-paris13.fr/img/js/marmotte-small.jpg" />
</div>
<div id="dia-fleches">
<span id="dia-gauche">&lt;</span>
<span id="dia-droite">&gt;</span>
</div>
</div>
<!--------------------->
</body>
</html>

diapos.css

/* Le cadre principal. */
#dia
{
/* On le restreint exactement à la taille d'une seule image. */
width: 600px;
height: 450px;
/* Tout ce qui déborde est caché. Donc, une seule image est visible. */
overflow: hidden;
/* Ceci sert uniquement pour créer un containing block */
/* qui permet de positionner les flêches avec position: absolute */
position: relative;
}

/* Un div très très large */
/* Il contient toutes les images disposées horizontalement */
/* Il déborde de son parent */
#dia-images
{
width: 10000px;
/* Trés important: c'est ce qui permet de décaler ce div en JS avec "left: ...px;" */
position: relative;
/* Eviter les petits espaces entre les images */
font-size: 0;
/* initialisation à 0 (défaut "auto") : nécessaire sur Chrome */
left: 0;
}

/* Commun aux deux flêches */
#dia-fleches span
{
position: absolute;
top: 200px;
font-size: 30px;
font-family: sans;
background-color: rgba(0,0,0,.4);
color: #bbb;
padding: .1em;
/* Le pointeur de la souris */
cursor: pointer;
}
#dia-gauche
{
left: 0;
}
#dia-droite
{
right: 0;
}
#dia-fleches span:hover
{
color: #fff;
}


Vérifiez que ceci s'affiche bien et prenez le temps de comprendre en détail cette mise en page.

Lisez les commentaires du CSS.

Utilisez l'inspecteur (outils de développement) pour voir où sont les images.

On va ensuite voir ensemble comment faire fonctionner le défilement.

Diaporama

10.2 Diapos : défiler

<div id="dia"> est ajusté exactement à la taille d'une image (600x450).

<div id="dia-images"> contient toutes les images horizontalement. Il est beaucoup plus large que <div id="dia" >

Grâce à "overflow: hidden;"  tout ce qui déborde de <div id="dia"> est caché.

Grâce à "position: relative;"  on peut décaler <div id="dia-images"> à l'aide de "left: ...px;"

Donc pour faire défiler les images, il suffit de changer la propriété "left" de <div id="dia-images">

(Remarque: left peut être positif ou négatif)

Essayez d'enlever "overflow: hidden;" du CSS pour voir le résultat (puis remettez-le).
Faîtes quelques essais dans le fichier CSS avec "left" pour décaler <div id="dia-images">
Ensuite faîtes des essais dans la console, en utilisant jQuery et .css()

Que faut-il taper dans la console pour afficher exactement l'escargot ?
(essayez sur la console avant de répondre)

Diaporama

10.3 Diapos: décalage avec .css()

Pour afficher l'escargot on pouvait utiliser

$('#dia-images').css('left',-1200)
Écrivez maintenant le fichier JS permettant de passer d'une image à l'autre lorsqu'on clique sur les flèches.

Indications :

Avec la fonction .css() vous pouvez aussi récupérer la position actuelle:

$('#dia-images').css('left')

(remarquez qu'il n'y a qu'un seul argument donné dans ce cas à .css() )

Cette fonction renvoie une chaîne de caractères (par exemple : "-123px" ).
Pour la transformer en nombre utilisez la fonction parseInt()

N'oubliez pas d'empêcher l'utilisateur de dépasser à droite ou à gauche.

Diaporama

10.4 Correction

diapos.js

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

$('#dia-gauche').mousedown(function()
{
var position=parseInt($('#dia-images').css('left'));
position+=600;
if(position>0){return;}
$('#dia-images').css('left',position);
});

$('#dia-droite').mousedown(function()
{
var position=parseInt($('#dia-images').css('left'));
position-=600;
if(position<-600*3){return;}
$('#dia-images').css('left',position);
});
console.log("La mise en place est finie. En attente d'événements...");
});

Diaporama

10.5 Diapos : améliorations

On veut faire deux améliorations:

1) N'utiliser qu'un gestionnaire d'événements pour les deux flèches.
A l'intérieur de cette fonction vous pourrez distinguer les deux flèches en récupérant l'id de la flèche cliquée:

$(this).attr('id')

2) Défiler à l'aide d'une animation. Pour ça on va utiliser la fonction jQuery .animate() à la place de .css() :

Elle s'utilise comme ceci:

$('#dia-images').animate({left: "123px" });

(remplacez "123px" par la bonne valeur)

Attention: si l'utilisateur clique pendant l'animation il faut ignorer ce click.
Pour cela vérifiez que la position left actuelle est bien un multiple de 600.



Diaporama

10.6 Correction

diapos.js

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

$('#dia-fleches span').mousedown(function()
{
var position=parseInt($('#dia-images').css('left'));
if(position%600!==0){return;}
var flecheDroite=$(this).attr('id')==='dia-droite';
position+=(flecheDroite ? -600 : 600);
if(position<-600*3 || position>0){return;}
$('#dia-images').animate({left: position});
});

console.log("La mise en place est finie. En attente d'événements...");
});

Diaporama

10.7 Diapos : défilement automatique

On veut maintenant faire défiler automatiquement les images.

On peut utiliser la fonction setInterval() pour appeler une fonction de manière répétée, avec un certain délai fixé entre chaque appel.

Tapez le code suivant dans la console:

setInterval(function(){console.log('bonjour',Math.random());},2000);

Pour arrêter ce minuteur, il faut récupérer son numéro lors de la création, puis appeler clearInterval() 

var numero=setInterval(...);
clearInterval(numero)


Diaporama

10.8 Correction

diapos.js

console.log("Ce programme JS vient d'être chargé");
$(document).ready(function()
{
console.log("Le document est pret");

var minuteur=setInterval(function()
{
console.log("Appel par intervalles");
var position=parseInt($('#dia-images').css('left'));
if(position%600!==0){return;}
position-=600;
if(position<-600*3){position=0;}
$('#dia-images').animate({left: position});
},2000);

$('#dia-fleches span').mousedown(function()
{
console.log("Le bouton de la souris a été appuyé sur une flèche");
if(minuteur!==false)
{
clearInterval(minuteur);
minuteur=false;
}
var position=parseInt($('#dia-images').css('left'));
if(position%600!==0){return;}
var flecheDroite=$(this).attr('id')==='dia-droite';
position+=(flecheDroite ? -600 : 600);
if(position<-600*3 || position>0){return;}
$('#dia-images').animate({left: position});
});


console.log("La mise en place est finie. En attente d'événements...");
});