Pour votre progression, c'est très important de finir le TP précédent avant de commencer celui-ci.
Si vous venez d'assister au cours magistral, passez à la section suivante.
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.
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.
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
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]
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.
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 ».
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"
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)
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 ?
var u=function(a) { return 10+a; };Qu'affiche ce programme ?
console.log(u(2));
var x=5;Qu'affiche ce programme ?
var u=function(a) { return 10+a+x; };
console.log(u(2));
var x=5;Qu'affiche ce programme ?
var u=function(a) { x=100;return 10+a+x; };
console.log(x);
var x=5;Qu'affiche ce programme ?
var u=function(a) { x=100;return 10+a+x; };
u(0);
console.log(x);
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (1) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (2) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (3) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que l'argument de la fonction click ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (4) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (5) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que la variable l ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que la variable e ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (6) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que (7) ?
<div id="popup">
<span class="nom">Tom</span>
<span class="score">20</span>
</div>
Qu'est-ce que la variable s ?
var x;Quel est le type de x ?
var a=10;
f(a);
console.log(a);
function f(x)
{
x=50;
}
Qu'affiche ce programme ?
var a={u:10};Qu'affiche ce programme ?
f(a);
console.log(a.u);
function f(x)
{
x.u=50;
}
Si vous venez d'assister au cours magistral, passez à la section suivante.
$(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).
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.
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)
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)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)
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 ?
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:
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 :<script src="jquery.????.min.js"></script>
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.
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 > </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
<?phpchat-reinitialiser.php
session_start();
require_once 'chat-fonctions.php';
chat_connexion_bdd();
<?php
require_once 'chat-fonctions.php';
chat_connexion_bdd();
chat_initialiser_bdd();
echo "La base de donnees a ete reinitialisee";
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 > </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).
----------
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
----------
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 ?
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
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.
Réfléchissez bien à votre requête. Faîtes des essais dans la console psql: psql -h aquabdd ...
(correction SQL à la page suivante)
Correction
SELECT * FROM messages WHERE id>? ORDER BY id ASC LIMIT 1
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.
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);
----------
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
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);
});
};
});
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 > </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.
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);
});
};
});
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);
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;
});
};
});
----------
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.
...
$('#message').keypress(function(e)
{
console.log("Une touche a été appuyée:",e.keyCode);
}
...
Faîtes des essais.
Quel est le keyCode correspondant à la touche entrée.
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.
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é.
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";
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() )
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";
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)
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 > </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);