Exercices TP-4

  1. Bienvenue au TP-4
  2. Révisions
    1. Tableau
    2. Objets.
    3. Objet-2
    4. Tableaux
    5. Tableau
    6. Arbre jQuery
    7. arbre
  3. Cours : Fermetures
    1. Fermetures
    2. Fermetures
    3. Fermetures : facile ?
  4. Cours : événements
    1. Événements : bubbling
    2. Événements : bubbling
    3. Événements
  5. Gestionnaire d’événements
    1. Vocabulaire : Gestionnaire d’événements
    2. Gestionnaire d’événements : ordre
    3. Bubbling
    4. Bubbling 2
    5. Bubbling 3
    6. Bubbling 4
  6. Tableau joueurs : suite
    1. Joueurs : HTML, CSS, JS
    2. Tableau joueurs : validation
    3. Correction
    4. Tableau joueurs : effacer
    5. Correction
    6. Tableau joueurs : effacer suite
    7. Correction
    8. Correction : code complet
  7. Cours : Exemple popup
    1. Exemple : popup
    2. Exemple : HTML
    3. Exemple : liste
    4. Exemple : popup
    5. Exemple : CSS
    6. Exemple : .offset()
    7. Exemple : .offset()
    8. Exemple : fermer
    9. Exemple : JS
  8. Popup
    1. Popup: completer
    2. Correction
    3. Fermer les popups déjà ouverts
    4. Correction
    5. Ouvrir et fermer avec .hover()
    6. Correction
  9. Fin du TP

1. Bienvenue au TP-4

1.1 Bienvenue au TP-4

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 quelques révisions.

Révisions

2.2 Tableau

var parfums=XXXXX;

Que faut-il écrire à la place de XXXXX pour créer un tableau ayant les valeurs fraise, chocolat et vanille ?


Révisions

2.3 Objets.

var pos=XXXXX;

Que faut-il écrire à la place de XXXXX pour créer un objet ayant les propriétés top et left respectivement associées aux valeurs 100 et 200 ?


Révisions

2.4 Objet-2

var joueur={pseudo: "Joe"};
XXXXX

 
Que faut-il écrire à la place de XXXXX pour ajouter la propriété score à joueur associée à la valeur 100 ?

Révisions

2.5 Tableaux

var parfums=["fraise","chocolat","vanille"];
XXXXX
 
Que faut-il écrire à la place de XXXXX pour ajouter la valeur framboise à la fin du tableau parfums ?

Révisions

2.6 Tableau

var parfums=["fraise","chocolat","vanille"];
console.log(XXXXX);
 
Que faut-il écrire à la place de XXXXX pour afficher la taille du tableau dans la console ?

Révisions

2.7 Arbre jQuery


var divTop=$('#top');
XXXXX

Que faut-il écrire à la place de XXXXX pour cacher le <div> numéroté "3" ?

Indications:

Révisions

2.8 arbre


$('img').click(function(){ XXXXX });

Que faut-il écrire à la place de XXXXX pour que le <span> correspondant à l'image cliquée soit affiché en rouge (color, red) ?
C'est à dire:
Quand on clique sur 5, 4 est affiché en rouge.
Quand on clique sur 7, 6 est affiché en rouge

Indications:

3. Cours : Fermetures

3.1 Cours : Fermetures

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

Cours : Fermetures

3.2 Fermetures

Les fermetures existent dans d'autres langages, mais elles sont très utilisées en JavaScript.

Il s'agit tout simplement le fait de pouvoir utiliser des variables définies dans une fonction parent.

Ici la variable « x » est utilisée dans exemple2() alors qu'elle est définie dans exemple1().

Dans d'autres langages, une variable n'est accessible que dans la fonction qui la déclare.

Cours : Fermetures

3.3 Fermetures

Dans cet exemple la variable n est définie dans la 1ere fonction anonyme.

La variable n est utilisée (lue et modifiée) dans la fonction anonyme appelée par .each().

On a vu qu'en programmation événementielle on déclare souvent des fonctions à appeler « plus tard », quand un événement survient.

On se retrouve donc avec beaucoup de fonctions et on a besoin de partager des informations entre-elles. Les fermetures sont alors très pratiques.

Cours : Fermetures

3.4 Fermetures : facile ?

Les fermetures sont simples et intuitives à utiliser, mais en y regardant de plus près, il se passe des choses un peu bizarres.

Tout d'abord l'idée d'accéder à des variables locales déclarées dans une autre fonction est surprenante.

Ensuite, on se rend compte que ces variables sont utilisées alors que la fonction qui les déclare a déjà fini d’exécuter !

4. Cours : événements

4.1 Cours : événements

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

Dans cette partie, on va voir plus en détail la gestion d'événements.

Cours : événements

4.2 Événements : bubbling

Quand un utilisateur fait une action, un objet événement est créé. Il est successivement envoyé à :

- l'élément où il s'est produit.

- l'élément parent

- l'élément grand-parent

- ...

- ensuite est exécutée l'action par défaut

Exemples d'actions par défaut :

- "click" sur un lien : suivre le lien

- "keypress" dans un champs texte : afficher la lettre

- "click" sur un bouton : envoyer le formulaire

- "click" dans une boite à cocher : cocher

- "submit" pour un formulaire : envoyer formulaire

- ...

Cours : événements

4.3 Événements : bubbling

On peut ajouter un gestionnaire d'événement click à n'importe quel élément sur toute la chaîne. Ils seront tous appelés.

Par exemple, si on utilise un gestionnaire d'événement click sur "body", on récupère les clicks de tous les éléments de la page.

"this" est l'objet sur lequel se trouve le gestionnaire d’événement (notre fonction)

"e.target" est l'objet sur lequel s'est produit l'événement.

Cours : événements

4.4 Événements

L'action par défaut peut-être annulée avec:

e.preventDefault()

C'est très utilisé : quand on utilise un gestionnaire d'événement, on veut souvent remplacer la fonctionnalité par défaut par notre fonctionnalité,il faut donc utiliser preventDefault().

Exemples :

- "click" sur un lien : ne suit pas le lien

- "keypress" dans un champs texte : n'affiche pas la lettre

- ...

5. Gestionnaire d’événements

5.1 Gestionnaire d’événements

On va prendre un moment pour bien comprendre ce qui se passe quand on utilise un gestionnaire d'événements.


La fonction anonyme de la ligne 3 est exécuté lorsque l'utilisateur clique sur sur l'image... c'est à dire bien après la fin de l'exécution des lignes 2,3 et 8.

La fonction anonyme de la ligne 3 function(e){...} est appelée « gestionnaire d'événements » : son rôle est de réagir lorsqu'un événement survient.

$('img').click(function(){...})  n'exécute pas cette fonction. Il se contente d'ajouter ce gestionnaire d'événements à l'image, pour qu'il soit appelé plus tard... quand un utilisateur cliquera sur cette image.





Gestionnaire d’événements

5.2 Vocabulaire : Gestionnaire d’événements


$(document).ready(function()
{
console.log('Doc prêt');
$('img').click(function(e)
{
console.log('Image cliquée');
$(this).hide();
}
);
console.log("Fin mise en place");
});

Le gestionnaire d'événements  est le code en :

Gestionnaire d’événements

5.3 Gestionnaire d’événements : ordre


  $(document).ready(function()
{
0 console.log('Doc prêt');
1 $('img').click(function(e)
{
2 console.log('Image cliquée');
3 $(this).hide();
});
4 console.log("Fin mise en place");
});


Quel est l'ordre d'exécution ?

Gestionnaire d’événements

5.4 Bubbling


Quand un utilisateur fait une action, un objet événement est créé. Il est successivement envoyé à :

- l'élément où il s'est produit.

- l'élément parent

- l'élément grand-parent

- ...

------------------



$('span').click(function(e){...});

Sur quel(s) élément(s) peut-on cliquer pour provoquer l'appel de la fonction gestionnaire d'événements ?

Gestionnaire d’événements

5.5 Bubbling 2



$('img').click(function(e){...});

Sur quel(s) élément(s) peut-on cliquer pour provoquer l'appel de la fonction gestionnaire d'événements ?

Gestionnaire d’événements

5.6 Bubbling 3



$('h2').click(function(e){...});

Sur quel(s) élément(s) peut-on cliquer pour provoquer l'appel de la fonction gestionnaire d'événements ?

Gestionnaire d’événements

5.7 Bubbling 4


$('div').click(function(e){...});
Sur quel(s) élément(s) peut-on cliquer pour provoquer l'appel de la fonction gestionnaire d'événements ?

6. Tableau joueurs : suite

6.1 Tableau joueurs : suite

Suite de l'exercice du TP-3 « Tableau joueurs »

Il manque deux fonctionnalités au tableau de joueurs, qu'on va compléter, ensemble, dans les pages suivantes



Tableau joueurs : suite

6.2 Joueurs : HTML, CSS, JS

Reprenez votre code du TP-3, ou bien celui-ci:

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>

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

#joueurs .score
{
text-align: right;
}

#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");

$('#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());
$('#mediane').text(calculer_mediane());
trier();
});

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

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

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

Tableau joueurs : suite

6.3 Tableau joueurs : validation


Commençons par la validation.

Quand l'utilisateur clique sur le bouton "ajouter" faites les trois vérifications suivantes.

Dans chaque vérification, s'il y a un problème, affichez un alert() et n'ajoutez pas le joueur.

Tableau joueurs : suite

6.4 Correction

			if(joueur.nom.length===0){alert("Le nom ne doit pas être vide !");return;}			
if(/^[0-9]+$/.test(joueur.score)===false){alert("Score invalide");return;}
var existeDeja=false;
$('#joueurs tr').each(function()
{
if($(this).find('.nom').text()===joueur.nom){existeDeja=true;}
});
if(existeDeja){alert("Ce nom a déjà été rentré !");return;}

Tableau joueurs : suite

6.5 Tableau joueurs : effacer


On veut que l'utilisateur puisse effacer chaque ligne en cliquant sur une croix:


Image croix :

Modifiez le HTML, le CSS et écrivez un gestionnaire d'événement click sur la case effacer pour effacer toute la ligne du tableau.
Utilisez la fonction jQuery .remove() (voir doc)

Vérifiez que ca marche pour les lignes du tableau.

Ajoutez des lignes en utilisant le bouton ajouter.
Vous allez remarquer qu'effacer ne marche PAS sur les nouvelles lignes ajoutées.
Pourquoi ?

Tableau joueurs : suite

6.6 Correction

joueurs.html

...
<table id="joueurs">
<tr><td class="effacer"></td><td class="nom">Leïla</td><td class="score">121</td></tr>
<tr><td class="effacer"></td><td class="nom">Driss</td><td class="score">153</td></tr>
<tr><td class="effacer"></td><td class="nom">Lian</td><td class="score">210</td></tr>
<tr><td class="effacer"></td><td class="nom">Joe</td><td class="score"> 32</td></tr>
<tr><td class="effacer"></td><td class="nom">Naïma</td><td class="score">261</td></tr>
<tr><td class="effacer"></td><td class="nom">Karim</td><td class="score">183</td></tr>
<tr><td class="effacer"></td><td class="nom">Anon.</td><td class="score"> 0</td></tr>
</table>
...

joueurs.css

...
#joueurs .effacer
{
background-image: url(effacer.png);
background-repeat: no-repeat;
background-position: 4px center;
width: 25px;
height: 16px;
padding: 0;
cursor: pointer;
}

#joueurs .effacer:hover
{
background-color: #ff0;
}
...

joueurs.js

	$('#joueurs .effacer').click(function(event)
{
$(this).parent().remove();
});

Remarques :

On a choisi d'utiliser des images background CSS au lieu d'images HTML <img>.

Les deux choix sont possibles. Les images CSS ont l'avantage de laisser au graphiste plus de souplesse.
Dans un logiciel complèxe (ex. une grosse application PHP) le code HTML est plus lourd à modifier.

Tableau joueurs : suite

6.7 Tableau joueurs : effacer suite


Actuellement, dans notre programme, les gestionnaires d'événement "effacer" sont ajoutés au démarrage.

Ils fonctionnent bien pour les lignes présentes au démarrage.

Par contre, quand l'utilisateur crée un joueur avec le bouton ajouter, la case de la nouvelle ligne n'a pas de gestionnaire d'événement.

Deux solutions sont possibles:

La deuxième est plus élégante (moins de code).

Nous allons le faire nous mêmes à la main pour comprendre comment ca marche.
(Mais en pratique on utiliserait  la fonction jQuery .on() qui fait l'équivalent)

Regardez les transparents du cours sur le bubbling d'événements.

Au lieu d'installer le gestionnaire sur la case effacer, installez-le sur tout le tableau.

Dans ce gestionnaire vous récupérerez tous les clicks à l'intérieur du tableau ... y compris ceux qui viennent d'autres cases que la case "effacer".

Vous devez donc:

Indication : l'élément cliqué se trouve dans event.target

Tableau joueurs : suite

6.8 Correction

	$('#joueurs').click(function(event)
{
if($(event.target).hasClass('effacer'))
{
$(event.target).parent().remove();
$('#total' ).text(calculer_total());
$('#mediane').text(calculer_mediane());
}
});

Tableau joueurs : suite

6.9 Correction : code complet

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="effacer"></td><td class="nom">Leïla</td><td class="score">121</td></tr>
<tr><td class="effacer"></td><td class="nom">Driss</td><td class="score">153</td></tr>
<tr><td class="effacer"></td><td class="nom">Lian</td><td class="score">210</td></tr>
<tr><td class="effacer"></td><td class="nom">Joe</td><td class="score"> 32</td></tr>
<tr><td class="effacer"></td><td class="nom">Naïma</td><td class="score">261</td></tr>
<tr><td class="effacer"></td><td class="nom">Karim</td><td class="score">183</td></tr>
<tr><td class="effacer"></td><td class="nom">Anon.</td><td class="score"> 0</td></tr>
</table>
<p>
total : <span id="total" >960</span><br/>
médiane : <span id="mediane">153</span>
</p>

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

#joueurs .score
{
text-align: right;
}

#ajouter input[type='text']
{
width: 80px;
}

#ajout-nom
{
margin-right: 10px;
}

#joueurs .effacer
{
background-image: url(effacer.png);
background-repeat: no-repeat;
background-position: 4px center;
width: 25px;
height: 16px;
padding: 0;
cursor: pointer;
}

joueurs.js

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

trier();

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

if(joueur.nom.length===0){alert("Le nom ne doit pas être vide !");return;}
if(/^[0-9]+$/.test(joueur.score)===false){alert("Score invalide");return;}
var existeDeja=false;
$('#joueurs tr').each(function()
{
if($(this).find('.nom').text()===joueur.nom){existeDeja=true;}
});
if(existeDeja){alert("Ce nom a déjà été rentré !");return;}

ajouter_joueur(joueur);
$('#ajout-nom' ).val('');
$('#ajout-score').val('');

$('#total' ).text(calculer_total());
$('#mediane').text(calculer_mediane());
trier();
});

$('#joueurs').click(function(event)
{
if($(event.target).hasClass('effacer'))
{
$(event.target).parent().remove();
$('#total' ).text(calculer_total());
$('#mediane').text(calculer_mediane());
}
});

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

function ajouter_joueur(joueur)
{
var ligne=$('<tr><td class="effacer"></td><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;
}

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

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

7. Cours : Exemple popup

7.1 Cours : Exemple popup

Il est conseillé de (re)lire les pages du cours qui suivent.
Elles décrivent un exemple de popup.

On va ensuite travailler sur cet exemple.

Cours : Exemple popup

7.2 Exemple : popup

Dans cet exemple, l'utilisateur peut cliquer sur un nom pour afficher un popup dans lequel sont affichées des informations sur la personne.

Pour fermer le popup, il doit cliquer sur la croix située en haut à droite du popup.

Cours : Exemple popup

7.3 Exemple : HTML

Le HTML est composé de deux parties :

- La liste dans laquelle sont affichés les noms.

- Le popup et son contenu

Cours : Exemple popup

7.4 Exemple : liste

La liste n'a rien de particulier.

Les noms sont dans des <span> de classe "popup-mot" et ayant un attribut "data-popup" contenant un identifiant associé au nom.

La norme HTML 5 permet de créer des attributs dont le nom commence par "data-". On s'en sert ici pour stoker un identifiant qui nous permettra de trouver le popup correspondant à ce nom.

Cours : Exemple popup

7.5 Exemple : popup

On peut imaginer qu'il existe plusieurs popup, tous ayant la même structure.

Tous les popup ont class="popup".

Ils contiennent

- un <span> avec une croix pour les fermer.

- une image "triangle.png" qui représente le petit triangle blanc en bas du popup

- le contenu du popup (photo, titre, texte, liens)

Une classe (fermer, triangle, photo) nous permettra d'agir sur ces éléments dans le CSS et le JS.

Cours : Exemple popup

7.6 Exemple : CSS

Le popup a "position: absolute", ce qui permet de le déplacer n'importe où à l'aide de "left" et "top" (ce sera fait dans le JS)

Par ailleurs, "position: absolute" transforme le popup en un "containing block" : tous les éléments à l'intérieur du popup qui ont "position: absolute" sont positionnés par rapport au popup (et non pas par rapport à la page).

C'est pour ça que "top:0" positionne .fermer en haut du popup et pas en haut de la page.

De la même manière l'image .triangle est positionné en bas du popup (et pas en bas de la page). La valeur négative de bottom, fait sortir l'image en dehors de la région d'affichage de son parent (le popup). Ce n'est pas un problème, cette situation s'appelle un "overflow".

Cours : Exemple popup

7.7 Exemple : .offset()

Notre première tâche en JS est de placer le popup au-dessus du mot qui a été cliqué.

On utilise .offset() pour obtenir la position du mot cliqué. .offset() renvoie un objet avec deux propriétés (top, left).

On veut que le bas du triangle se trouve au même niveau que le mot. Pour trouver le haut de la fenêtre, il faut donc soustraire la hauteur du popup et du triangle.

.offset(pos) nous permet ensuite de positionner le popup.

Cours : Exemple popup

7.8 Exemple : .offset()

.offset({...}) fonctionne en modifiant la propriété "style" de l'élément HTML.

Il existe deux fonctions pour obtenir une position:

.offset() donne la position relative à la page

.position() donne la position relative à son "containing block"

.position() correspond donc tout simplement aux propriétés CSS left et top.

.offset() fait en interne un calcul, remontant tous les "containing blocks" jusque en haut de l'arbre DOM.

Cours : Exemple popup

7.9 Exemple : fermer

Dans la fonction gérant le click sur le <span class="fermer">, on a accès à "this". Mais "this" correspond au <span>, alors qu'on a besoin du <div class="popup"> pour fermer le popup. On utilise donc $(this).parent()

.fadeOut() permet de cacher un élément progressivement, avec une animation.

Cours : Exemple popup

7.10 Exemple : JS

Voici le JS complet.

Remarquez qu'on peut mettre les listes jQuery dans des variables. C'est plus lisible et plus rapide.

À partir de l'attribut "data-popup" du mot cliqué on construit le sélecteur '#popup-joe'.

Remarquez à la ligne 0 que $('.popup-mot') contient plusieurs mots. jQuery ajoute donc notre fonction gestionnaire d'événement à plusieurs éléments.

C'est aussi le cas pour .popup>.fermer (on peut imaginer qu'il y a plusieurs popups...)

8. Popup

8.1 Popup

Dans les pages suivantes on va reprendre l'exemple vu en cours.

 

Créez les fichiers suivants:

popup.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>popup</title>
<link type="text/css" rel="stylesheet" href="popup.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="popup.js"></script>
</head>
<body>
<div id="connectes">
<p>Connectés : </p>
<ul>
<li><span class="popup-mot" data-popup="joe" >Joe </span></li>
<li><span class="popup-mot" data-popup="marc">Marc</span></li>
<li><span class="popup-mot" data-popup="lian">Lian</span></li>
</ul>
</div>
<div id="popup-joe" class="popup">
<span class="fermer">X</span>
<img class="triangle" src="triangle.png" alt=""/>
<img src="et.png" alt="joe" class="photo"/>
<h2>Joe</h2>
<p>Célibataire, 22 ans.<br/>Aime les épinards.</p>
<p>
<a href="...">films</a> | <a href="...">page perso</a>
</p>
</div>
</body>

</html>

popup.css

body
{
font-family: sans;
background-image: url(texture-grise.jpg);
padding-top: 100px;
}

#connectes
{
background-color: #eee;
width: 150px;
padding: .5em;
}
#en-ligne p
{
margin: 0;
}


.popup-mot
{
font-weight: bold;
cursor: pointer;
}

.popup
{
position: absolute;
display: none;
width: 200px;
background-color: white;
padding: .7em;
box-shadow: 1px 1px 3px rgba(0,0,0,.4);
font-size: 12px;
}
.popup h2
{
margin-top: .2em;
}

.popup>.fermer
{
position: absolute;
top: 0;
right: 0;
padding: .5em;
padding-top: .1em;
}

.popup .photo
{
width: 80px;
height: auto;
float: right;
margin-left: .2em;
margin-bottom: .2em;
}

.popup>.triangle
{
position: absolute;
left: 10px;
bottom: -20px;
}

popup.js

$(document).ready(function()
{
$('.popup-mot').mousedown(function()
{
var mot=$(this);
var id="popup-"+mot.attr('data-popup');
var popup=$('#'+id);
var pos=mot.offset();
pos.top-=popup.outerHeight()+20;
popup.fadeIn();
popup.offset(pos);
});

$('.popup>.fermer').mousedown(function()
{
$(this).parent().fadeOut();
});


});

triangle.png : https://moodle.iutv.univ-paris13.fr/img/js/triangle.png

et.png: https://moodle.iutv.univ-paris13.fr/img/js/et.png

texture-grise.jpg:  https://moodle.iutv.univ-paris13.fr/img/js/texture-grise.jpg




Popup

8.2 Popup: completer


En modifiant uniquement le HTML, ajoutez les popup pour Marc et Lian.

Les images:

https://moodle.iutv.univ-paris13.fr/img/js/marc.png

https://moodle.iutv.univ-paris13.fr/img/js/lian.png


Popup

8.3 Correction

Il faut adapter le id des deux nouveaux popup.
Le JS utilise le nom qui se trouve dans data-popup en ajoutant "popup-" devant.

popup.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>popup</title>
<link type="text/css" rel="stylesheet" href="popup.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="popup.js"></script>
</head>
<body>
<div id="connectes">
<p>Connectés : </p>
<ul>
<li><span class="popup-mot" data-popup="joe" >Joe </span></li>
<li><span class="popup-mot" data-popup="marc">Marc</span></li>
<li><span class="popup-mot" data-popup="lian">Lian</span></li>
</ul>
</div>
<div id="popup-joe" class="popup">
<span class="fermer">X</span>
<img class="triangle" src="triangle.png" alt=""/>
<img src="et.png" alt="joe" class="photo"/>
<h2>Joe</h2>
<p>Célibataire, 22 ans.<br/>Aime les épinards.</p>
<p>
<a href="...">films</a> | <a href="...">page perso</a>
</p>
</div>
<div id="popup-marc" class="popup">
<span class="fermer">X</span>
<img class="triangle" src="triangle.png" alt=""/>
<img src="marc.png" alt="joe" class="photo"/>
<h2>Marc</h2>
<p>Marié, 29 ans.<br/>Aime les oranges.</p>
<p>
<a href="...">films</a> | <a href="...">page perso</a>
</p>
</div>
<div id="popup-lian" class="popup">
<span class="fermer">X</span>
<img class="triangle" src="triangle.png" alt=""/>
<img src="lian.png" alt="joe" class="photo"/>
<h2>Lian</h2>
<p>Joueur d'échecs, 24 ans.<br/>Aime les glaces.</p>
<p>
<a href="...">films</a> | <a href="...">page perso</a>
</p>
</div>
</body>

</html>

Popup

8.4 Fermer les popups déjà ouverts

Quand l'utilisateur ouvre un popup, on voudrait fermer ceux qui serait déjà ouverts.

Ajoutez le code nécessaire.

Popup

8.5 Correction

Astuce:
Pour éviter


popup.js:

$(document).ready(function()
{
$('.popup-mot').mousedown(function(e)
{
// Astuce: le .stop() permet d’arrêter l'animation fadeIn si elle est encore en cours
$('.popup').stop().fadeOut();
var mot=$(this);
var id="popup-"+mot.attr('data-popup');
var popup=$('#'+id);
var pos=mot.offset();
pos.top-=popup.outerHeight()+20;
popup.fadeIn();
popup.offset(pos);
});

$('.popup>.fermer').mousedown(function()
{
$(this).parent().fadeOut();
});

});


Popup

8.6 Ouvrir et fermer avec .hover()


Au lieu d'ouvrir et fermer en cliquant, on voudrait ouvrir et fermer les popups quand la souris passe pardessus le mot.

Donc, au lieu d'utiliser  .mousedown() (et le bouton fermer), on va utiliser utiliser la fonction jQuery .hover(), qui prend deux paramètres:

Réorganisez le programme pour obtenir le résultat souhaité.

Popup

8.7 Correction

popup.js

$(document).ready(function()
{
$('.popup-mot').hover(function(e)
{
var mot=$(this);
var id="popup-"+mot.attr('data-popup');
var popup=$('#'+id);
var pos=mot.offset();
pos.top-=popup.outerHeight()+20;
popup.fadeIn();
popup.offset(pos);
},
function(e)
{
$('.popup').stop().fadeOut();
});
});

9. Fin du TP

9.1 Fin du TP