Développement Web 2 Ajax (Asynchronous JavaScript and XML
Transcription
Développement Web 2 Ajax (Asynchronous JavaScript and XML
Communication client/serveur AJAX Ajax (Asynchronous JavaScript and XML) Ajax est un acronyme pour Asynchronous JavaScript and XML. Développement Web 2 Il est un ensemble de technologies libres couramment utilisées : Bertrand Estellon Aix-Marseille Université April 1, 2014 .. Bertrand Estellon (AMU) . .. . .. . Développement Web 2 Communication client/serveur . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. ▶ HTML (ou XHTML) pour la structure sémantique des informations; ▶ CSS pour la présentation des informations; ▶ DOM et javaScript pour interagir avec l’information présentée; ▶ l’objet XMLHttpRequest pour échanger l’information avec le serveur; ▶ XML (parfois JSON) pour le format des données informatives. . .. 1 / 436 Bertrand Estellon (AMU) L’objet XMLHttpRequest Communication client/serveur . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. Développement Web 2 AJAX XMLHttpRequest : Les méthodes et propriétés Une fonction Javascript permettant de créer un objet XMLHttpRequest : Description de l’objet XMLHttpRequest : .. . .. . .. . interface XMLHttpRequest { function createXhrObject() { if (window.XMLHttpRequest) return new XMLHttpRequest(); /* requête */ void open(DOMString method, DOMString url); void open(DOMString method, DOMString url, boolean async); /* ... */ void setRequestHeader(DOMString header, DOMString value); void send(); void send(Document data); /* ... */ void abort(); if (window.ActiveXObject) { var names = [ "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP", "Microsoft.XMLHTTP" ]; for(var i in names) { try{ return new ActiveXObject(names[i]); } catch(e){} } } window.alert("pas de XMLHTTPRequest."); return null; /* réponse */ readonly attribute unsigned short status; readonly attribute DOMString statusText; DOMString getResponseHeader(DOMString header); DOMString getAllResponseHeaders(); readonly attribute DOMString responseText; readonly attribute Document responseXML; } .. Développement Web 2 . 240 / 436 L’objet XMLHttpRequest XMLHttpRequest : Création Bertrand Estellon (AMU) . .. April 1, 2014 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 241 / 436 . } .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 242 / 436 . Communication client/serveur AJAX L’objet XMLHttpRequest Communication client/serveur XMLHttpRequest : Les méthodes et propriétés AJAX L’objet XMLHttpRequest XMLHttpRequest : Les états Suite de la descrition de l’objet XMLHttpRequest : interface XMLHttpRequest { Les différents états de XMLHttpRequest : /* ... */ /* gestionnaire d'événement */ attribute Function onreadystatechange; /* états */ const unsigned short UNSENT = 0; const unsigned short OPENED = 1; const unsigned short HEADERS_RECEIVED = 2; const unsigned short LOADING = 3; const unsigned short DONE = 4; readonly attribute unsigned short readyState; ▶ UNSENT (0) : L’objet a été construit. ▶ OPENED (1) : La méthode open a été invoquée avec succès. Le header de la requête peut être modifié avec la méthode setRequestHeader. ▶ HEADERS_RECEIVED (2) : Le header HTTP de la réponse a été reçu. ▶ LOADING (3) : Le corps de la réponse est en cours de téléchargement. ▶ DONE (4) : Le transfert des données est terminé (ou erreur !). }; .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. Développement Web 2 . .. April 1, 2014 AJAX . .. . .. . .. . .. 243 / 436 Bertrand Estellon (AMU) Les reqêtes asynchrones Communication client/serveur XMLHttpRequest : Requête asynchrone GET . .. . .. . Développement Web 2 . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 244 / 436 Les reqêtes asynchrones XMLHttpRequest : Requête asynchrone POST Exemple de requête POST : Exemple de requête GET : xhr = createXhrObject(); xhr = createXhrObject(); xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) alert(xhr.responseText); else alert("Error : "+xhr.status); } }; xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) alert(xhr.responseText); else alert("Error : "+xhr.status); } }; .. Bertrand Estellon (AMU) Développement Web 2 xhr.open("POST", "server.php", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("a=12&b=13"); true); xhr.open("GET", "server.php?a=12&b=13", xhr.send(null); . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 245 / 436 . .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 246 / 436 . Communication client/serveur AJAX Les reqêtes asynchrones Communication client/serveur AJAX et jQuery AJAX Sans serveur dynamique Un exemple sans serveur dynamique : la problématique Nous souhaitons réaliser le site suivant : Exemple de requête POST : $.ajax({ type: "POST", url: "toto.php", data: {numero : "123", nom : "bob"} }).done(function( msg ) { alert( msg ); }) .fail(function() { alert("erreur"); }) .always(function() { alert("fini"); }); Exemple de requête GET : $.get("test.php", { 'choices[]': ["Jon", "Susan"]} ); .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . Développement Web 2 . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . .. 247 / 436 Bertrand Estellon (AMU) Sans serveur dynamique Communication client/serveur Un exemple sans serveur dynamique : les données . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 248 / 436 Sans serveur dynamique Nous avons également les images associés aux auteurs dans un répertoire image du serveur. De plus, pour chaque auteur, nous avons un fichier de la forme suivante : [ { { "name" : "Victor Hugo", "description" : "Victor Hugo, né le 26 février 1802 à Besançon et mort le 22 mai 1885 à Paris, est un poète, dramaturge et prosateur romantique considéré comme l’un des plus importants écrivains de langue française. [wikipedia]", "born" : "26 février 1802, Besançon", "died" : "22 mai 1885, Paris" } "name" : "Simone de Beauvoir", "picture" : "beauvoir.jpg", "description" : "beauvoir.json" }, { "name" : "Agatha Christie", "picture" : "christie.jpg", "description" : "christie.json" }, /* ... */ ] .. Développement Web 2 . .. Un exemple sans serveur dynamique : les données Nous avons sur notre serveur le fichier authors.json suivant : Bertrand Estellon (AMU) . .. Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 249 / 436 . Le nom du fichier est donné par les propriétés description associées à chaque auteur dans le fichier authors.json. .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 250 / 436 . Communication client/serveur AJAX Sans serveur dynamique Communication client/serveur AJAX Sans serveur dynamique Un exemple sans serveur dynamique : index.html Un exemple sans serveur dynamique : index.js Nous allons remplir dynamiquement la structure de document suivante : function displayAuthorsList(authors) { $("#list").html(""); for (var i = 0; i < authors.length; i++) { var author = authors[i]; var line = '<tr onclick="showAuthor(\''+author.description+'\');">'; line += '<td><strong>'+author.name+'</strong></td>'; line += '<td><img src="resources/images/'+author.picture+'"></td>'; line += '</tr>'; $("#list").append(line); } } <!DOCTYPE html> <html> <head> <script src="index.js"></script><!--- et bootstrap et jquery ---> </head> <body> <div class="container"><div class="fluid-row"> <table id="list" class="table table-bordered span3 offset2"></table> <div id="author" class="span4 well hide"> <h2 id="author_name"></h2> <span id="author_description"></span><br><br> <strong>Naissance : </strong><span id="author_born"></span><br> <strong>Décès : </strong><span id="author_died"></span><br> </div> </div></div> </body> </html> .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. Développement Web 2 . .. April 1, 2014 AJAX . .. . .. . .. . function displayAuthor(author) { $("#author").removeClass("hide"); $("#author_name").text(author.name); $("#author_description").text(author.description); $("#author_born").text(author.born); $("#author_died").text(author.died); } . . . .. 251 / 436 Bertrand Estellon (AMU) Sans serveur dynamique Communication client/serveur jQuery, AJAX, JSON et PHP function requestAuthorsList(callback) { $.ajax({ url : "resources/authors.json", type : "GET", dataType : "json", success : callback }); } Côté serveur : . .. April 1, 2014 . .. . .. . .. . 252 / 436 Avec un serveur écrit en PHP header('Content-type: application/json'); $a = array('nom'=>$_POST['nom'], 'maj'=>strtoupper($_POST['nom'])); echo json_encode($a); function requestAuthor(ressource, callback) { $.ajax({ url : "resources/"+ressource, type : "GET", dataType : "json", success : callback }); } Côté client : $.ajax({ type: "post", url: "server.php", data: { nom : "bob" } }).done(function( msg ) { alert( msg['nom']+"=>"+msg['maj'] ); }); function showList() { requestAuthorsList(displayAuthorsList); } function showAuthor(resource) { requestAuthor(resource, displayAuthor); } $(document).ready(function() { showList(); }); .. Développement Web 2 . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. AJAX Un exemple sans serveur dynamique : index.js Bertrand Estellon (AMU) .. Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 253 / 436 . .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 254 / 436 . Communication client/serveur AJAX Avec un serveur écrit en PHP Communication client/serveur Exemple : autocompletion AJAX Avec un serveur écrit en PHP Exemple : autocompletion – index.html Autocomplétion sur les mots du français : <!DOCTYPE html> <html> <head> <link href="bootstrap-combined.min.css" rel="stylesheet"> <script src="jquery.min.js"></script> <script src="bootstrap.min.js"></script> <script src="index.js"></script> </head> <body> <input id="input" type="text" data-provide="typeahead"> </body> </html> Nous allons utiliser : ▶ coté client : jQuery et Bootstrap; ▶ coté serveur : PHP. .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. Développement Web 2 . .. April 1, 2014 AJAX . .. . .. . .. . .. 255 / 436 Bertrand Estellon (AMU) Avec un serveur écrit en PHP Communication client/serveur Exemple : autocompletion – index.js . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 256 / 436 Avec un serveur écrit en PHP <? function getWords(&$query) { if (empty($query)) return array(); $file = fopen("francais.txt","r"); $words = array(); while (($word = fgets($file, 255))!==false) { if (strpos($word, $query) === 0) $words[] = $word; if (count($words) > 8) break; } return $words; } function getWords(query, callback) { $.ajax({ url : "server.php", method : "post", dataType : "JSON", data : { query : query }, success : callback }); } $(document).ready(function() { $("#input").typeahead({ source : getWords }); }); .. Développement Web 2 . .. Exemple : autocompletion – server.php Avec Bootstrap, il est très facile de mettre en place l’autocompletion : Bertrand Estellon (AMU) . .. Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 257 / 436 . $query = &$_POST['query']; $words = getWords($query); echo json_encode($words); ?> Bertrand Estellon (AMU) Développement Web 2 .. . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 258 / 436 . Communication client/serveur AJAX Avec un serveur écrit en PHP Communication client/serveur Exemple : autocompletion – déroulement d’une requête <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar-inner"><div class="container"> <form id="signin_form" action="#" class="navbar-form pull-right"> <input id="signin_nickname" class="span2" type="text"> <input id="signin_password" class="span2" type="password"> <button id="signin_button" type="submit" class="btn">Sign In</button> </form> <form id="logout_form" action="#" class="navbar-form pull-right hide"> <button id="logout_button" type="submit" class="btn">Logout</button> </form> </div></div> </div> <div class="container"> <div id="message" class="hide alert alert-error span6 offset2"></div> </div> </body> réponse du serveur '["manganate", ... ]' Serveur $.ajax({...}) : post server.php avec query="mang" json_encode(array("manganate", ...)) getWords("mang") .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . Développement Web 2 . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . .. 259 / 436 Bertrand Estellon (AMU) Avec un serveur écrit en PHP Communication client/serveur Exemple : authentification – server.php function getSessionNickname() { $nickname = &$_SESSION["nickname"]; return isset($nickname)?$nickname:null; } ?> .. . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 260 / 436 Avec un serveur écrit en PHP Exécution de l’action demandée par le client : <? function runServerAction(&$action) { if (!isset($action) || !(in_array($action, array("signin", "logout", "init")))) return array("action"=>"error", "msg"=>"Invalid action."); return $action(); } <? function setSessionNickname($nickname) { $_SESSION["nickname"] = $nickname; } Développement Web 2 . .. Développement Web 2 Exemple : authentification – server.php Fonctions pour maintenir le pseudonyme de l’utilisateur dans la session : Bertrand Estellon (AMU) Avec un serveur écrit en PHP Exemple : authentification – index.html getWords("mang", callback) callback(["manganate", ... ]) AJAX . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 261 / 436 . session_start(); $action = &$_GET['action']; $result = runServerAction($action); echo json_encode($result); ?> Il est également possible (et souhaitable) de mettre place une architecture similaire à celle du premier projet ou utiliser un framework PHP. .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 262 / 436 . Communication client/serveur AJAX Avec un serveur écrit en PHP Communication client/serveur AJAX Avec un serveur écrit en PHP Exemple : authentification – server.php Exemple : authentification – server.php Les actions du serveur : Les actions du serveur : <? function signin() { $nickname = &$_POST['nickname']; $password = &$_POST['password']; if (empty($nickname) || empty($password)) return array("action"=>"error", "msg"=>"Empty nickname or password."); if ($nickname !== "toto" || $password !== "toto") return array("action"=>"error", "msg"=>"Invalid nickname or password."); setSessionNickname($nickname); return array("action"=>"signin", "nickname"=>$nickname); } ?> <? function logout() { setSessionNickname(null); return array("action"=>"logout"); } .. Bertrand Estellon (AMU) Communication client/serveur . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. Développement Web 2 . .. April 1, 2014 AJAX . .. function init() { $nickname = getSessionNickname(); if ($nickname!==null) return array("action"=>"signin", "nickname"=>$nickname); else return array("action"=>"logout"); } ?> . .. . .. . .. 263 / 436 Bertrand Estellon (AMU) Avec un serveur écrit en PHP Communication client/serveur Exemple : authentification – index.js function signin() { $("#message").addClass("hide"); runServerAction("signin", { nickname : $("#signin_nickname").val(), password : $("#signin_password").val() }); } function logout() { $("#message").addClass("hide"); runServerAction("logout", { }); } function switch case case case } } Bertrand Estellon (AMU) Développement Web 2 .. . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 265 / 436 . . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX Exemple : authentification – index.js $(document).ready(function() { $("#signin_button").click(signin); $("#logout_button").click(logout); runServerAction("init", { }); }); . .. Développement Web 2 . .. . .. . .. . 264 / 436 Avec un serveur écrit en PHP runClientAction(data) { (data.action) { "error" : runErrorAction(data); break; "signin" : runSigninAction(data); break; "logout" : runlogoutAction(data); break; function runServerAction(actionName, data) { $.ajax({ url : "server.php?action="+actionName, method : "post", dataType : "JSON", data : data, success : runClientAction }); } .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 266 / 436 . Communication client/serveur AJAX Avec un serveur écrit en PHP Communication client/serveur Exemple : authentification – index.js AJAX Projet AJAX Projet 2 (PHP et AJAX) Vous devez réaliser un jeu client/serveur. function runErrorAction(data) { $("#message").text(data.msg); $("#message").removeClass("hide"); } function runSigninAction(data) { $("#signin_form").addClass("hide"); $("#logout_form").removeClass("hide"); } function runlogoutAction(data) { $("#signin_form").removeClass("hide"); $("#logout_form").addClass("hide"); } .. Bertrand Estellon (AMU) . .. . .. . Développement Web 2 Communication client/serveur . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . .. 267 / 436 Bertrand Estellon (AMU) Projet AJAX . .. . .. . Développement Web 2 Communication client/serveur . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. Projet 2 (PHP et AJAX) Déroulement de la partie : Première partie du projet : Vous devez réaliser le projet en utilisant uniquement PHP en vous basant sur l’organisation mise à place dans le projet ”Sondages”. Les joueurs doivent pouvoir : La grille est vide et le serveur choisit un mot à faire deviner au joueur. ▶ Le joueur tape un mot de 8 lettres dans la zone de texte puis appuie sur la touche entrée pour soumettre le mot au serveur. Le serveur associe alors une couleur à chaque lettre du mot : ▶ ▶ ▶ ▶ ▶ ▶ ▶ ▶ ▶ La couleur rouge est associée aux lettres bien placées. La couleur jaune est associée aux lettres mal placées mais présentes dans le mot à trouver. ▶ ▶ Les couleurs associées à chaque lettre sont envoyées au client. La partie s’arrête une des deux conditions est vérifiées : ▶ ▶ Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . créer un compte; s’authentifier; changer de mot de passe; commencer une nouvelle partie; jouer; afficher le tableau des scores. Deuxième partie du projet : Utiliser la technologie AJAX pour réduire la quantité de données envoyées par le serveur. Le but est d’obtenir une version où toutes les actions de l’utilisateur se font en utilisant AJAX. Le joueur a trouvé le mot → gagné; Le joueur a rempli toutes les lignes de la grille → perdu; .. . .. Projet AJAX Projet 2 (PHP et AJAX) ▶ . .. 268 / 436 Librairies : jQuery et Bootstrap. . .. . .. . .. . .. 269 / 436 . .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 270 / 436 . Communication client/serveur AJAX Projet AJAX Communication client/serveur Projet 2 (PHP et AJAX) . .. . .. . Développement Web 2 Communication client/serveur . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . .. 271 / 436 Bertrand Estellon (AMU) Projet AJAX . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 272 / 436 Projet AJAX Projet 2 (PHP et AJAX) .. Développement Web 2 . .. Développement Web 2 Communication client/serveur Projet 2 (PHP et AJAX) Bertrand Estellon (AMU) Projet AJAX Projet 2 (PHP et AJAX) .. Bertrand Estellon (AMU) AJAX . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 273 / 436 . .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 274 / 436 . Communication client/serveur AJAX Projet AJAX Communication client/serveur Projet 2 (PHP et AJAX) . .. . .. . Développement Web 2 Communication client/serveur . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . .. 275 / 436 Bertrand Estellon (AMU) Projet AJAX . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. . .. April 1, 2014 AJAX . .. . .. . .. . 276 / 436 Projet AJAX Projet 2 (PHP et AJAX) .. Développement Web 2 . .. Développement Web 2 Communication client/serveur Projet 2 (PHP et AJAX) Bertrand Estellon (AMU) Projet AJAX Projet 2 (PHP et AJAX) .. Bertrand Estellon (AMU) AJAX . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 277 / 436 . .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 278 / 436 . Communication client/serveur AJAX Projet AJAX Projet 2 (PHP et AJAX) .. Bertrand Estellon (AMU) Développement Web 2 . .. . .. . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. April 1, 2014 . .. . .. . .. . .. 279 / 436 .