Pour votre progression, c'est très important de finir le TP précédent avant de commencer celui-ci.
Commençons ce TP par une rapide révision des notions du TP précédent.
<span>bonjour</span>
Que faut-il écrire en JS pour que ceci affiche "coucou" au lieu de "bonjour" ?
<span>bonjour</span>Que faut-il écrire en JS pour que ceci soit affiché en rouge ?
Que faut-il écrire pour afficher, à partir d'un programme JS, "bonjour" dans la console ?
(c'est utilisé souvent pour débugger)
Que faut-il écrire en JS pour transformer
<div class="important">
en
<div class="important urgent">
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" ?
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é ?
1) Vous confondez la fonction .text() avec une autre.
2) la question demande d'afficher la valeur trouvée dans la console.
<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 ?
{
...
}
On veut ajouter un nouveau paragraphe dans le <body> d'un document.
<body>On a vu en cours, que l'on pouvait décomposer en deux étapes:
<p>bonjour</p>
<p>bonjour</p>
(ajouter ici)
</body>
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)
<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)
Si vous venez d'assister au cours magistral, passez à la section suivante.
Dans cette partie, on va apprendre à utiliser les objets et les tableaux.
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
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.
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.
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".
On peut aussi utiliser comme valeur une fonction anonyme directement dans l'initialisateur d'objet.
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".
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.
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);
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()
{
});
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.
.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.
$(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) .
Si vous venez d'assister au cours magistral, passez à la section suivante.
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
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).
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.
document : l'arbre DOM
setInterval() : exécuter une fonction régulièrement
setTimeout() : exécuter une fonction dans x ms
...
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.
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.
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.
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.
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.
.children() retourne uniquement les descendants directs, alors que .find() retourne les descendants directs et indirects.
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.
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".
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
».
La fonction jQuery .attr() permet de lire et de modifier un attribut HTML.
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.
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()
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('h2')
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('h2').parent()
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('p').eq(1)
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('p').eq(1).children()
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('#popup').children('a')
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('#popup').find('a')
Quel(s) élément(s) sont contenus dans la liste jQuery générée par l'expression suivante :
$('#popup').children().eq(3)
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)
Dans les pages suivantes nous allons écrire ensemble un programme JavaScript permettant de gérer un tableau de joueurs.
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.
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 ?
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.
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);
}
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):
Pensez à créer une ligne complète (tr,td...) avec les classes nécessaires.
C'est à vous...
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);
}
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.
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:
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.
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);
}
Dans les pages suivantes on va afficher le total des scores et, ensuite, le score médian.
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).
É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.
Rappel du cours:
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;
}
Quand un joueur est ajouté, mettez à jour le total affiché.
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;
}
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" ?
var tab=["fraise", "chocolat" , "vanille"];
Que faut-il écrire pour ajouter au tableau « tab » un élément "framboise" ?
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 :
----
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 [ ]
function calculer_mediane()
{
var scores=[];
$('#joueurs tr').each(function()
{
var s=parseInt($(this).find('.score').text());
scores.push(s);
});
console.log(scores);
}
Il nous reste à
.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 :-(
Indication: utilisez la fonction Math.floor() pour arrondir vers le bas.
Affichez la nouvelle médiane quand l'utilisateur clique sur ajouter.
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)];
}
-----
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()
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);
}
}
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"><</span>
<span id="dia-droite">></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.
<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)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.
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.
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...");
});
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.
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...");
});
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)
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...");
});