Exercices TP-7

  1. Bienvenue au TP-7
  2. Cours : fonctions JS
    1. Fonctions : appel / valeur
    2. Fonctions : appel / valeur
    3. Gestionnaire d'événements
    4. Fonctions anonymes
    5. Gestionnaire d'événements
    6. Types en JavaScript
    7. undefined & typeof
    8. Fonctions : paramètres
  3. Exercices : fonctions JS
    1. Fonction dans une variable
    2. Fonction anonyme
    3. Closure
    4. Closure 2
    5. Closure 3
    6. Types (1)
    7. Types (2)
    8. Type (3)
    9. Types arg click
    10. Types (4)
    11. Type (5)
    12. Type l
    13. Type e
    14. Type (6)
    15. Type (7)
    16. Type s
    17. undefined
    18. passage par valeur
    19. passage par référence
  4. Cours : $(document).ready(...)
    1. $(document).ready()
    2. Ordre d’exécution
  5. Exercices : $(document).ready()
    1. Sans ready 1
    2. Sans ready 2
    3. Sans ready : 3
    4. Ordre affichage
    5. Requête Google
    6. Requête Google, suite
    7. Requête Google, avantages / inconvénients
  6. Exercice : chat
    1. Fichiers
    2. Explications
    3. Configurer et vérifier la connexion à la base de données
    4. GET ou POST ?
    5. Fournir un message suivant en JSON
    6. Requête SQL
    7. Correction requête SQL
    8. Envoi d'un objet JSON
    9. Correction
    10. Coté client : chercher le message
    11. Correction
    12. Coté client : afficher le message
    13. Correction
    14. Coté client : fin afficher le message
    15. Correction
    16. client + serveur : ajouter un message quand l'utilisateur appuie sur entrée
    17. Correction
    18. keyCode
    19. GET ou POST ?
    20. Ajouter le message
    21. Correction:
    22. Le nom
    23. Correction
    24. Derniers détails coté client
    25. Correction complète

1. Bienvenue au TP-7

1.1 Bienvenue au TP-7

2. Cours : fonctions JS

2.1 Cours : fonctions JS

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

Cours : fonctions JS

2.2 Fonctions : appel / valeur

Dans les cours et TP précédents on a surtout utilisé des fonctions anonymes. Un petit rappel sur sur les fonctions "normales" (non-anonymes) peut-être utile. La déclaration d'une fonction "normale" se fait comme en PHP.

C'est très important de distinguer exemple qui est la fonction et exemple() qui est l'appel de la fonction.

En JS les fonctions sont un type de valeur comme les autres. On peut affecter ce type à une variable. On peut ensuite appeler la fonction.

Cours : fonctions JS

2.3 Fonctions : appel / valeur

Voici un autre exemple où on manipule des fonctions dans une variable.

[1] Ici « x » reçoit la valeur « exemple » qui est de type « function ». Remarquez bien que la fonction « exemple » n'est pas appelée.

[2] « x » est ensuite passé en paramètre à la fonction « abcd ».

[3] Donc « f » dans « abcd » est bien la fonction « exemple ». Elle est appelée avec l'argument 10.

[4] « exemple » renvoie 20, donc abcd renvoie 20, donc « r » vaut 20.

C'est important de bien suivre l'ordre de l’exécution.

Cours : fonctions JS

2.4 Gestionnaire d'événements

Les exemples précédents pouvaient paraître « artificiels ». Mais en pratique on manipule souvent les fonctions de cette manière.

[1] Ici « exemple3 » est affecté à « x ». Remarquez bien que « exemple3 » n'est pas appelée.

[2] Ensuite « x » est passé en argument à .click(). Remarquez bien que « exemple3 » n'est pas non plus appelée.

[3,4] Le programme continue et rencontre la déclaration de « exemple3 ». Remarquez bien que « exemple3 » n'est pas non plus appelée.

Ensuite console.log("ok2") est appelé et le programme se termine.

[5] Après une attente l'utilisateur clique sur le paragraphe. Un événement est envoyé à celui-ci

[6] et la fonction «x » (donc exemple3) est appelée

Cours : fonctions JS

2.5 Fonctions anonymes

Depuis le début de ce cours on a souvent utilisé des fonctions anonymes.

C'est très pratique pour la programmation événementielle.

Ici on voit un exemple de fonction anonyme dans cadre non-événementiel.

On voit aussi les ressemblances avec la fonction non-anonyme « exemple ».

Remarquez bien que la fonction anonyme n'est pas appelée à la ligne [1]

Cours : fonctions JS

2.6 Gestionnaire d'événements

Un exemple pour montrer qu'on n'est pas obligé d'utiliser des fonctions anonymes comme gestionnaire d'événements.

C'est souvent pratique, mais parfois on peut vouloir séparer le code. Par exemple, si le gestionnaire d'événements devient trop long, il est parfois plus facile de lire le programme séparément.

Cours : fonctions JS

2.7 Types en JavaScript

JavaScript gère automatiquement les types. On n'a pas tout le temps besoin de s'en occuper, mais ... c'est important de bien les comprendre.

En JS, il existe uniquement 5 types primitifs (immuables) et le type Objet. Les tableaux ne sont qu'une forme d'Objet.

Pour connaître le type d'une expression on peut utiliser « typeof ».

Cours : fonctions JS

2.8 undefined & typeof

En JavaScript on peut passer moins d'arguments que prévu à une fonction. Les arguments manquants auront pour type undefined.

La seule manière toujours correcte de vérifier si une variable n'est pas définie est d'utiliser :

typeof a === "undefined"

Cours : fonctions JS

2.9 Fonctions : paramètres

Ici e et c sont des variables avec des types primitifs (number et string).

o est un objet.

On passe e,c et o en paramètre de la fonction exemple.

Dans la fonction exemple les paramètres correspondants (x,y et z) sont modifiés.

On remarque alors que e et c n'ont pas été modifiés (passage par valeur).

Par contre o a bien été modifié (passage par référence)

3. Exercices : fonctions JS

3.1 Exercices : fonctions JS

Exercices : fonctions JS

3.2 Fonction dans une variable


var u=XXXX;
console.log(u(5,10));

function somme(e,f) { return e+f; }


Que faut-il écrire à la place de XXXX pour que ce programme affiche 15 ?

Exercices : fonctions JS

3.3 Fonction anonyme


var u=function(a) { return 10+a; };
console.log(u(2));
Qu'affiche ce programme ?

Exercices : fonctions JS

3.4 Closure


var x=5;
var u=function(a) { return 10+a+x; };
console.log(u(2));
Qu'affiche ce programme ?

Exercices : fonctions JS

3.5 Closure 2


var x=5;
var u=function(a) { x=100;return 10+a+x; };
console.log(x);
Qu'affiche ce programme ?

Exercices : fonctions JS

3.6 Closure 3


var x=5;
var u=function(a) { x=100;return 10+a+x; };
u(0);
console.log(x);
Qu'affiche ce programme ?

Exercices : fonctions JS

3.7 Types (1)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (1) ?

Exercices : fonctions JS

3.8 Types (2)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (2) ?

Exercices : fonctions JS

3.9 Type (3)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (3) ?

Exercices : fonctions JS

3.10 Types arg click


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que l'argument de la fonction click ?

Exercices : fonctions JS

3.11 Types (4)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (4) ?

Exercices : fonctions JS

3.12 Type (5)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (5) ?

Exercices : fonctions JS

3.13 Type l


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que la variable l ?

Exercices : fonctions JS

3.14 Type e


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que la variable e ?

Exercices : fonctions JS

3.15 Type (6)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (6) ?

Exercices : fonctions JS

3.16 Type (7)


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que (7) ?

Exercices : fonctions JS

3.17 Type s


<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>


Qu'est-ce que la variable s ?

Exercices : fonctions JS

3.18 undefined

var x;
Quel est le type de x ?

Exercices : fonctions JS

3.19 passage par valeur


var a=10;
f(a);
console.log(a);

function f(x)
{
x=50;
}

Qu'affiche ce programme ?

Exercices : fonctions JS

3.20 passage par référence


var a={u:10};
f(a);
console.log(a.u);

function f(x)
{
x.u=50;
}

Qu'affiche ce programme ?

4. Cours : $(document).ready(...)

4.1 Cours : $(document).ready(...)

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

Cours : $(document).ready(...)

4.2 $(document).ready()

$(document).ready() figure dans tous nos programmes. On va prendre un moment pour essayer de comprendre.

$(document) est une liste jQuery contenant un seul élément : document.

document est l'objet DOM tout en haut de l'arbre DOM.

ready est un événement jQuery qui est appelé quand le DOM est prêt.

On est donc dans le même cadre d'utilisation que n'importe que autre gestionnaire d'événements (comme .click()). La différence est que .click() est un événement lié à une action de l'utilisateur alors que .ready() est un événement automatiquement déclenché par le navigateur (et jQuery).

Cours : $(document).ready(...)

4.3 Ordre d’exécution

Pourquoi $(document).ready() est-il nécessaire ?

Le navigateur construit l'arbre DOM progressivement.D'abord la partie verte [1]. Ensuite il arrive au programme exemple.js [2], qu'il exécute.

Important: remarquez que quand exemple.js est exécuté, l'arbre DOM partie bleue [6] n'existe pas encore !

[3] Le programme s’exécute

[4] Le gestionnaire d'événement ready est ajouté (mais pas encore appelé)

[5] Ici on construit la liste jQuery $('p'). Comme l'arbre DOM de la partie bleue n'existe pas encore, la liste jQuery est vide et il ne se passe rien !

[6] Le programme a fini. L'arbre DOM restant est construit.

[7] L'arbre DOM est prêt Le gestionnaire d'événements ready est appelée.

[8] $('p') contient bien le paragraphe.

5. Exercices : $(document).ready()

5.1 Exercices : $(document).ready()

Exercices : $(document).ready()

5.2 Sans ready 1

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>essai</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="essai.js"></script>
</head>
<body>
<!--------------------->
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
<!--------------------->
</body>
</html>

essai.js

$('#popup').css('background-color','red');


Que fait ce programme JS ?

(réfléchissez à la raison précise, avant de répondre)

Exercices : $(document).ready()

5.3 Sans ready 2

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>essai</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="essai.js"></script>
</head>
<body>
<!--------------------->
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
<!--------------------->
</body>
</html>

essai.js

$('html').css('background-color','red');


Que fait ce programme JS ?

(réfléchissez à la raison précise, avant de répondre)

Exercices : $(document).ready()

5.4 Sans ready : 3

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>essai</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<!--------------------->
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
<!--------------------->
<script src="essai.js"></script>
 </body>
</html>

essai.js

$('#popup').css('background-color','red');


Que fait ce programme JS ?

(réfléchissez à la raison précise, avant de répondre)

Exercices : $(document).ready()

5.5 Ordre affichage

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>essai</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="essai.js"></script>
</head>
<body>
<!--------------------->
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
<!--------------------->
 </body>
</html>

essai.js

console.log('A');
$(document).ready(function()
{
console.log('B');
});
console.log('C');

Dans quel ordre se fait l'affichage ?

Exercices : $(document).ready()

5.6 Requête Google

Créez les deux fichiers suivants :

essai.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>essai</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="essai.js"></script>
</head>
<body>
<!--------------------->
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
<!--------------------->
 </body>
</html>

essai.js

console.log('A');
$(document).ready(function()
{
console.log('B');
});
console.log('C');

Ouvrez Firebug et cliquez sur l'onglet « Réseau ».

Faîtes un rechargement complet de la page  :
Maintenez la touche maj appuyée et cliquez sur le bouton recharger:

Exercices : $(document).ready()

5.7 Requête Google, suite

Dans l'onglet réseau vous devez voir une requête vers ajax.googleapis.com

C'est normal, dans votre fichier essai.html vous avez:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

Ceci dit à votre navigateur « télécharge jquery.min.js à partir de ajax.googleapis.com

Vous pouvez aussi utiliser votre propre copie de jquery.min.js :

Téléchargez la dernière version de jQuery ici :
http://jquery.com/download/
(prenez la version compressé, de production)
et mettez le fichier dans le même répertoire que essai.html

Remplacez la ligne précédente par ceci (en adaptant au nom du fichier que vous avez téléchargé) :
<script src="jquery.????.min.js"></script>

Vérifiez que jQuery fonctionne bien.
Dans Firebug, vérifiez qu'il n'y a plus de requête sur ajax.googleapis.com

Exercices : $(document).ready()

5.8 Requête Google, avantages / inconvénients

Avantages de ajax.googleapis.com
Inconvénients de ajax.googleapis.com

6. Exercice : chat

6.1 Exercice : chat

Dans les pages suivantes, on va écrire, ensemble, un petit programme AJAX permettant de discuter avec d'autres personnes.

Coté serveur, le programme PHP accédera à une base de données, avec PDO.

Exercice : chat

6.2 Fichiers

Créez les fichiers suivants.

chat.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chat</title>
<link type="text/css" rel="stylesheet" href="chat.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="chat.js"></script>
</head>
<body>
<!--------------------->
<div id="principal">
<h2>Chat</h2>
<ul id="chat">
<li id="bienvenue"><span class="nom">bienvenue &gt; </span><span class="texte">Tapez votre message et appuyez sur entrée.</span></li>
</ul>
<input id="message" type="text"/>

<p><input id="rafraichir" type="submit" value="rafraichir à la main"/></p>

<a id="reinitialiser" href="chat-reinitialiser.php">réinitialiser</a>
</div>
<!--------------------->
</body>
</html>

chat.css

body
{
font-family: sans;
width: 600px;
margin-left: auto;
margin-right: auto;
background-color: #eee;
}
#principal
{
background-color: white;
padding: 10px;
}

#principal h2
{
margin: 0;
text-align: center;
font-size: 130%;
width: 400px;
}

#chat
{
width: 400px;
border: 1px solid #eee;
border-radius: 3px;
list-style: none;
padding: 3px;
height: 300px;
overflow: auto;
margin-top: 7px;
}

#message
{
width: 400px;
}

#bienvenue
{
color: #aaa;
font-style: italic;
}

#chat .nom
{
color: #00a;
font-weight: bold;
}

#reinitialiser
{
font-size: 10px;
float: right;
}

chat.js

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

});

chat-fonctions.php

<?php

// Ouvrire la connexion avec la base de données
// Si c'est la première fois, chat_initialiser_bdd() est aussi appelée.
function chat_connexion_bdd()
{
global $db;
// database user password
$db=new PDO('pgsql:host=aquabdd;dbname=1234567', '1234567', '???');
// Si la table messages n'existe pas encore, appeler chat_initialiser_bdd()
$result = $db->query("SELECT 1 FROM messages LIMIT 1");
if($result===false){chat_initialiser_bdd();}
// Afficher les messages d'erreur
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
}

// Supprime l'ancienne table "messages" et la recrée à nouveau.
// Rempli la table avec quelques messages.
function chat_initialiser_bdd()
{
global $db;
// Supprimer la table messages si elle existe déjà
$db->exec('DROP TABLE IF EXISTS messages');
// Créer la table messages
$db->exec('CREATE TABLE messages(
id SERIAL PRIMARY KEY,
nom TEXT NOT NULL,
texte TEXT NOT NULL
);');

// Remplir la table messages avec 3 messages
$req=$db->prepare("INSERT INTO messages(nom, texte) VALUES(:nom, :texte)");
$req->execute(array('nom'=>"Joe",'texte'=>'Salut tout le monde.'));
$req->execute(array('nom'=>"Joe",'texte'=>"Ya quelqu'un ?"));
$req->execute(array('nom'=>"Leïla",'texte'=>'Salut.'));
}

chat-ajouter.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

chat-message-suivant.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

chat-reinitialiser.php
<?php
require_once 'chat-fonctions.php';
chat_connexion_bdd();
chat_initialiser_bdd();
echo "La base de donnees a ete reinitialisee";

Exercice : chat

6.3 Explications

Les grandes lignes:

Les messages sont affichés dans une liste <ul id="chat">
Chaque message est un <li>
Le HTML souhaité pour un message ressemble à ceci

<li><span class="nom">Leïla &gt; </span><span class="texte">Salut.</span></li>

Quand l'utilisateur tape un message et appuie sur la touche entrée, le message est envoyé au serveur avec une requête AJAX.

Régulièrement (toutes les deux secondes) une requête est envoyée au serveur pour chercher un nouveau message (s'il y en a).

Étapes
Dans les pages suivantes, on va voir, ensemble, les étapes suivantes:


Exercice : chat

6.4 Configurer et vérifier la connexion à la base de données

Étapes

----------

Modifiez les paramètres de connexion dans chat-fonctions.php : chat_connexion_bdd()

Ouvrez http://localhost/~1234567/.../chat.html dans le navigateur

Cliquez sur le lien réinitialiser et vérifiez qu'il n'y ait pas d'erreur.

Dans votre terminal, ouvrez une console postgres

psql -h aquabdd ...

vérifiez le contenu de la table messages

Exercice : chat

6.5 GET ou POST ?

Étapes

----------

Fonctionnement de chat-message-suivant.php :

On veut fournir à chat-message-suivant.php une information appelée idDernierMessage. Cette information lui indique le numéro (id) du dernier message déjà affiché.
Il doit alors chercher le message suivant (un seul), ayant un id supérieur à idDernierMessage
Il doit nous afficher (en JSON) le message.

Commençons par la question récurrente : Quelle méthode faut-il utiliser ?

Exercice : chat

6.6 Fournir un message suivant en JSON

On veut donc fournir un argument GET appelé idDernierMessage, indiquant le numéro (id) du dernier message déjà affiché.
chat-message-suivant.php cherchera le prochain suivant (un seul)

Commençons par l'URL:

Quelle URL (complète) faut-il taper dans votre navigateur pour chercher le message après le numéro 2

Exercice : chat

6.7 Requête SQL

Il faut maintenant réfléchir à une requête SQL permettant de chercher tous les champs du premier message dont le ID est supérieur à idDernierMessage.

Indications :

Réfléchissez bien à votre requête. Faîtes des essais dans la console psql:  psql -h aquabdd ...

(correction SQL à la page suivante)

Exercice : chat

6.8 Correction requête SQL

Correction

SELECT * FROM messages WHERE id>? ORDER BY id ASC LIMIT 1


Exercice : chat

6.9 Envoi d'un objet JSON

Complétez chat-message-suivant.php pour qu'il renvoie un objet JSON contenant tous les champs du message.

S'il n'y pas de message correspondant, renvoyez juste false.

Inspirez-vous de ce qui a été fait dans les TP précédents (JSON...).
Inspirez-vous aussi de vos TP en PHP/PDO.

Exercice : chat

6.10 Correction

chat-message-suivant.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

$idDernierMessage=(int)$_GET['idDernierMessage'];
$req=$db->prepare("SELECT * FROM messages WHERE id>? ORDER BY id ASC LIMIT 1");
$req->execute(array($idDernierMessage));
$message=$req->fetch(PDO::FETCH_ASSOC);

header('Content-Type: application/json; charset=utf-8');
echo json_encode($message);

Exercice : chat

6.11 Coté client : chercher le message

Étapes

----------

Ouvrez chat.html dans votre navigateur.

On va dans un premier temps utiliser le bouton "rafraîchir à la main" pour chercher le message suivant à partir du serveur.
Plus tard, une fois que tout fonctionnera, on pourra enlever ce bouton le remplacer par un rafraîchissement automatique toutes les 2 secondes.

Écrivez le JS pour que :

quand l'utilisateur appuie sur le bouton "rafraîchir à la main", une requête AJAX soit faîte sur chat-message-suivant.php pour chercher un message.
Pour l'instant affichez uniquement la réponse du serveur avec console.log()
Pour l'instant, utilisez la valeur 0 pour idDernierMessage


Exercice : chat

6.12 Correction

chat.js

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

// Chercher le message suivant à partir du serveur
$('#rafraichir').click(function()
{
$.get('http://localhost/~1234567/.../tp-7/chat-message-suivant.php',
{idDernierMessage: 0},
function(reponse)
{
console.log('reponse:',reponse);
});
};
});

Exercice : chat

6.13 Coté client : afficher le message

On veut maintenant afficher le message reçu.
On a reçu un objet réponse du serveur.
On veut construire du html ressemblant à ceci:

<li><span class="nom">Leïla &gt; </span><span class="texte">Salut.</span></li>

On a vu au cours-1 et à l'exercice "tableau joueurs" comment créer et ajouter ces éléments dans l'arbre DOM.

(pour l'instant on utilise toujours la valeur 0 pour idDernierMessage)

C'est à vous.

Exercice : chat

6.14 Correction

chat.js

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

// Chercher le message suivant à partir du serveur
$('#rafraichir').click(function()
{
$.get('http://localhost/~1234567/.../tp-7/chat-message-suivant.php',
{idDernierMessage: 0},
function(reponse)
{
console.log('reponse:',reponse);
var ligne=$('<li><span class="nom"></span><span class="texte"></span></li>');
ligne.find('.nom').text(reponse.nom+" > ");
ligne.find('.texte').text(reponse.texte);
$('#chat').append(ligne);
});
};
});

Exercice : chat

6.15 Coté client : fin afficher le message

Pour terminer cette étape vous devez régler deux points:

1) Gérer idDernierMessage
remarquez que la réponse du serveur contient le id du message reçu.

2) Le défilement
Quand on ajoute beaucoup de messages, ils dépassent le bas du cadre prévu.
Il faut donc  faire défiler vers le bas le <ul id="chat"> avec :

                  $("#chat").scrollTop($("#chat")[0].scrollHeight);


Exercice : chat

6.16 Correction

chat.js

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

// Chercher le message suivant à partir du serveur
$('#rafraichir').click(function()
{
$.get('http://localhost/~1234567/.../tp-7/chat-message-suivant.php',
{idDernierMessage: idDernierMessage},
function(reponse)
{
console.log('reponse:',reponse);
var ligne=$('<li><span class="nom"></span><span class="texte"></span></li>');
ligne.find('.nom').text(reponse.nom+" > ");
ligne.find('.texte').text(reponse.texte);
$('#chat').append(ligne);
$("#chat").scrollTop($("#chat")[0].scrollHeight);
idDernierMessage=reponse.id;

});
};
});

Exercice : chat

6.17 client + serveur : ajouter un message quand l'utilisateur appuie sur entrée

Étapes

----------

On est arrivé à la dernière étape.

Commençons par la gestions de la touche entrée dans le champs texte.
Écrivez un gestionnaire d'événement "keypress"  qui ne fait qu'afficher avec console.log() le champs keyCode de l'événement.


Exercice : chat

6.18 Correction


...
$('#message').keypress(function(e)
{
console.log("Une touche a été appuyée:",e.keyCode);
}
...


Exercice : chat

6.19 keyCode

Faîtes des essais.

Quel est le keyCode correspondant à la touche entrée.

Exercice : chat

6.20 GET ou POST ?

Quand l'utilisateur appuie sur la touche entrée, on veut envoyer au serveur le message qu'il vient de taper.

Quelle méthode faut-il utiliser ?

Exercice : chat

6.21 Ajouter le message

Coté client

Quand l'utilisateur appuie sur entrée, faîtes une requête .post() vers chat-ajouter.php, envoyant uniquement le texte se trouvant dans le champs texte.

Coté serveur

Dans chat-ajouter.php faites la requête SQL qui permet d'insérer un nouveau message dans la table "messages".
Pour l'instant utilisez un nom fixe (Par exemple, "Joe").

Vérifiez que tout marche bien.

Pour débugger, n'hésitez pas à utiliser la ligne de commande "psql -h auquanux" .
Dans le navigateur, appuyez sur "rafraîchir à la main" pour vérifier que le nouveau message est bien ajouté.

Exercice : chat

6.22 Correction:


chat.js

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

// Chercher le message suivant à partir du serveur
$('#rafraichir').click(function()
{
$.get('http://localhost/~12345567/.../tp-7/chat-message-suivant.php',
{idDernierMessage: idDernierMessage},
function(reponse)
{
console.log('reponse:',reponse);
if(reponse===false){return; }
var ligne=$('<li><span class="nom"></span><span class="texte"></span></li>');
ligne.find('.nom').text(reponse.nom+" > ");
ligne.find('.texte').text(reponse.texte);
$('#chat').append(ligne);
$("#chat").scrollTop($("#chat")[0].scrollHeight);
idDernierMessage=reponse.id;
});
}
);

// Quand la touche entrée est appuyée, envoyer un message au serveur
$('#message').keypress(function(e)
{
console.log("Une touche a été appuyée:",e.keyCode);
if(e.keyCode!==13){return;}
var message=$('#message').val();
$.post('http://localhost/~12345567/.../tp-7/chat-ajouter.php',
{texte: message},
function(reponse)
{

});
});

});

chat-ajouter.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();


$req=$db->prepare("INSERT INTO messages (nom, texte) VALUES (:nom,:texte)");
$req->execute(array('nom'=>'Joe',
'texte'=>$_POST['texte']));


echo "ok";

Exercice : chat

6.23 Le nom


En PHP la variable $_SESSION permet de conserver des informations pour un utilisateur.

On peut donc enregistrer le nom de l'utilisateur dans $_SESSION['nom'].

Utilisez isset()  pour voir si un nom existe déjà. S'il n'y en a pas, ajoutez le nom 'anonyme'.

Si un utilisateur tape un message commençant par '#nom ' alors il faut remplacer son nom dans $_SESSION['nom']
Par exemple s'il tape "#nom Tom" son nom sera 'Tom'.

(vous pouvez utiliser preg_match() ou bien substr() )

Exercice : chat

6.24 Correction

chat-ajouter.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

if(!isset($_SESSION['nom'])){$_SESSION['nom']='anonyme';}
if(preg_match('/^#nom (.{1,15})$/',$_POST['texte'],$match)){$_SESSION['nom']=$match[1];}



$req=$db->prepare("INSERT INTO messages (nom, texte) VALUES (:nom,:texte)");
$req->execute(array('nom'=>$_SESSION['nom'],
'texte'=>$_POST['texte']));

echo "ok";

Exercice : chat

6.25 Derniers détails coté client

Il ne reste plus que deux détails à régler coté client.

1) Quand le message a bien été envoyé au serveur, il faut effacer le champs texte.

2) Supprimer le bouton "rafraichir à la main" et faire un rafraichissement automatique à l'aide de window.setInterval()
(on a utilisé window.setInterval au TP2)
Faîtes un rafraîchissement toutes les 2000 ms pour éviter de surcharger le serveur.


Essayez votre programme avec deux navigateurs différents en même temps.
Demandez à votre voisin d'utiliser votre programme (http://localhost/~1234556/.../chat.html)

Exercice : chat

6.26 Correction complète

chat.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chat</title>
<link type="text/css" rel="stylesheet" href="chat.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="chat.js"></script>
</head>
<body>
<!--------------------->
<div id="principal">
<h2>Chat</h2>
<ul id="chat">
<li id="bienvenue"><span class="nom">bienvenue &gt; </span><span class="texte">Tapez votre message et appuyez sur entrée.</span></li>
</ul>
<input id="message" type="text"/>

<a id="reinitialiser" href="chat-reinitialiser.php">réinitialiser</a>
</div>
<!--------------------->
</body>
</html>

chat.css

body
{
font-family: sans;
width: 600px;
margin-left: auto;
margin-right: auto;
background-color: #eee;
}
#principal
{
background-color: white;
padding: 10px;
}

#principal h2
{
margin: 0;
text-align: center;
font-size: 130%;
width: 400px;
}

#chat
{
width: 400px;
border: 1px solid #eee;
border-radius: 3px;
list-style: none;
padding: 3px;
height: 300px;
overflow: auto;
margin-top: 7px;
}

#message
{
width: 400px;
}

#bienvenue
{
color: #aaa;
font-style: italic;
}

#chat .nom
{
color: #00a;
font-weight: bold;
}

#reinitialiser
{
font-size: 10px;
float: right;
}

chat.js

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

// Chercher le message suivant à partir du serveur
window.setInterval(function()
{
$.get('http://localhost/~1234567/.../tp-7/chat-message-suivant.php',
{idDernierMessage: idDernierMessage},
function(reponse)
{
console.log('reponse:',reponse);
if(reponse===false){return; }
var ligne=$('<li><span class="nom"></span><span class="texte"></span></li>');
ligne.find('.nom').text(reponse.nom+" > ");
ligne.find('.texte').text(reponse.texte);
$('#chat').append(ligne);
$("#chat").scrollTop($("#chat")[0].scrollHeight);
idDernierMessage=reponse.id;
});
}
,2000);

// Quand la touche entrée est appuyée, envoyer un message au serveur
$('#message').keypress(function(e)
{
console.log("Une touche a été appuyée:",e.keyCode);
if(e.keyCode!==13){return;}
var message=$('#message').val();
$.post('http://localhost/~1234567/.../tp-7/chat-ajouter.php',
{texte: message},
function(reponse)
{
$('#message').val('');
});
});

});

chat-fonctions.php

<?php

// Ouvrire la connexion avec la base de données
// Si c'est la première fois, chat_initialiser_bdd() est aussi appelée.
function chat_connexion_bdd()
{
global $db;
// database user password
$db=new PDO('pgsql:host=aquabdd;dbname=1234567', '1234567', '???');
// Si la table messages n'existe pas encore, appeler chat_initialiser_bdd()
$result = $db->query("SELECT 1 FROM messages LIMIT 1");
if($result===false){chat_initialiser_bdd();}
// Afficher les messages d'erreur
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
}

// Supprime l'ancienne table "messages" et la recrée à nouveau.
// Rempli la table avec quelques messages.
function chat_initialiser_bdd()
{
global $db;
// Supprimer la table messages si elle existe déjà
$db->exec('DROP TABLE IF EXISTS messages');
// Créer la table messages
$db->exec('CREATE TABLE messages(
id SERIAL PRIMARY KEY,
nom TEXT NOT NULL,
texte TEXT NOT NULL
);');

// Remplir la table messages avec 3 messages
$req=$db->prepare("INSERT INTO messages(nom, texte) VALUES(:nom, :texte)");
$req->execute(array('nom'=>"Joe",'texte'=>'Salut tout le monde.'));
$req->execute(array('nom'=>"Joe",'texte'=>"Ya quelqu'un ?"));
$req->execute(array('nom'=>"Leïla",'texte'=>'Salut.'));
}

chat-ajouter.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

if(!isset($_SESSION['nom'])){$_SESSION['nom']='anonyme';}
if(preg_match('/^#nom (.{1,15})$/',$_POST['texte'],$match)){$_SESSION['nom']=$match[1];}

$req=$db->prepare("INSERT INTO messages (nom, texte) VALUES (:nom,:texte)");
$req->execute(array('nom'=>$_SESSION['nom'],
'texte'=>$_POST['texte']));

echo "ok";

chat-message-suivant.php

<?php

session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();

$idDernierMessage=(int)$_GET['idDernierMessage'];
$req=$db->prepare("SELECT * FROM messages WHERE id>? ORDER BY id ASC LIMIT 1");
$req->execute(array($idDernierMessage));
$message=$req->fetch(PDO::FETCH_ASSOC);

header('Content-Type: application/json; charset=utf-8');
echo json_encode($message);