Tutoriel AJAX Chat Partie 5 : Javascript, envoi des messages, et changement de pseudo Envoi des messages Un aspect de coder une application avec AJAX est que l'on ne peut plus se passer de Javascript ensuite. Si vous avez l'intention de créer une application web dynamique en utilisant AJAX, des effets visuels, et des interfaces modernes et "funky", alors vous devrez simplement commencer à reconnaitre que Javascript va devenir un langage de programmation en premier plan pour vos applications. Une introduction à Javascript n'est pas le but de ce tutoriel, mais je vous préciserai les points important au long de ce tutoriel. Lancement d'une requête XHR XMLHttpRequest (Dorénavant surnommé "XHR") est un navigateur objet natif inclut dans la plupart des navigateurs modernes excepté Internet Explorer 6 où XHR est un objet ActiveX. Il permet à un langage de scripts comme Javascript de créer des connexions avec le serveur en arrière-plan qui évite le rechargement de la page web. Puisqu'accéder à XHR est un processus compliqué, je ne vous détaillerai pas tout afin de vous présenter Prototype. La classe Request cache ses détails derrière une interface simple. Utiliser AJAX avec Prototype est expliqué en détails sur http://www.sergiopereira.com/articles/prototype.js.html#usingajax. Avant de retourner à notre application de "chat" côté HTML, Ajax.Request permet d'utiliser XHR simplement. Vous créez une instance de l'objet, définissez l'url, les paramètres et options pour finalement créer une méthode qui traitera la réponse (dans notre cas, un tableau encodé avec JSON qui contiendra les nouveaux messages) qui sera ensuite affiché sur l'interface du "chat" HTML. Voici un exemple : var message = 'Hello World!'; var myajax = new Ajax.Request( 'controller/action', // relative uri to server method: 'get', parameters: 'message=' + encodeuricomponent(message) oncomplete: alertresponse ); function alertresponse(reply) // just print the JSON notation response in an alert message alert('json: ' + reply.responsetext); Dans cet exemple assez simple, nous créons une requête en utilisant la méthode GET avec le message comme paramètre (cad PHP récupèrera le message dans la variable $_GET['message']).
Quand nous recevons la réponse du serveur, l'objet Ajax.Request passera une instance de lui-même en paramètre pour la méthode - alertresponse() - que nous avons surnommé "reply". L'instance possède plusieurs propriétés, mais la principale que nous utiliserons est "responsetext" qui contient le texte brut équivalent au corps de réponse, cad nos données encodées avec JSON (supposez que nous avons utilisé Zend_Json pour encoder la réponse). Déclenchement d'une requête AJAX pour les nouveaux messages du "chat" Maintenant, nous sommes prêts à retourner au code côté client! Afin de déclencher une requête AJAX pour soumettre un nouveau message du "chat", nous ajouterons un évènement onclick au bouton "Say it!" dans notre gabarit HTML. L'évènement onclick permettra d'appeller une méthode surnommée sendmessage(). Voici la partie HTML mise-à-jour : <div id="control"> <p>your current username is: <?php echo $this->escape($this->screenname)?> </span>. Chat: <input type="text" value="" id="textmessage" size="50" maxlength="255" /> <input type="button" value="say it!" onclick="sendmessage()" /> <br /> <br /> Change Screen Name: <input type="text" value="" id="changename" size="15" maxlength="32" /> <input type="button" value="change!" /> </div> Ajouter savemessage() La méthode savemessage() sera placé dans notre fichier chat.js situé dans le dossier "/javascript" function sendmessage () var requesturl = 'index/message'; var message = $F('textmessage'); try var request = new Ajax.Request( requesturl, method: 'get', parameters: 'message=' + encodeuricomponent(message), oncomplete: handlerefresh ); catch (e) alert('error: ' + e.tostring());
Regardons cette méthode plus en détail. sendmessage() définit d'abord deux variables locales. requesturl contient l'url que la requête AJAX enverra. Dans notre cas, elle se dirige vers "index/message", cad la méthode MessageAction de la classe IndexController que nous avons défini plus tôt. La variable du message est définie comme valeur du message du "chat", que nous avons l'intention d'envoyer. Lorsque l'utilisateur a écrit dans le champ texte dont l'id est "textmessage", nous utilisons le raccourci vers la méthode Prototype $F() pour récupérer sa valeur. Puisque nous utilisons juste des champs textes pour récupérer leurs valeurs, et Javascript et XHR pour les soumettre, nous n'avons pas besoin d'un élément parent du formulaire. Nous lançons ensuite la requête AJAX en utilisant la classe Ajax.Request de Prototype. Nous avons écrit cette partie du code avec un bloc try/catch, ainsi aucune erreur n'est envoyée à l'utilisateur. Le traitement des erreurs n'est pas très détaillée - il l'est juste assez pour nous indiquer si quelque chose ne va pas. Une application complète implémente un traitement des erreurs beaucoup plus poussé. La classe Ajax.Request fonctionne comme nous l'avons évoqué dans l'introduction de notre XMLHttpRequest. Nous utilisons une méthode GET pour simplifier les choses (nous permettant de tester PHP côté serveur depuis un navigateur), en ajoutant le nouveau message comme paramètre, et définissant les méthodes oncomplete() et handlerefresh(). Normalement, l'application complète utilise la méthode POST (pour plus de sécurité). Ajouter handlerefresh() La méthode handlerefresh est aussi placée dans notre fichier chat.js. function handlerefresh (reply) $('textmessage').value = ''; var newmessages = eval('(' + reply.responsetext + ')'); var messagecount = newmessages.length; for (var i=0; i La première ligne vide le champ du texte de l'utilisateur. La seconde ligne place la réponse encodée avec JSON dans un tableau Javascript. Avec ce tableau, nous itérons ensuite tous ses éléments. Dans chaque itération, nous ajoutons un nouvel élément paragraphe avec comme id "chatpane" dans notre HTML. La méthode $() de Prototype est un simple raccourci pour utiliser : document.getelementbyid('chatpane') Finalement, nous nous assurons que l'interface du chat affiche en bas du chat la liste des messages à jour, en définissant la valeur de scrolltop à la valeur actuel de scrollheight. Au dessus, j'ai directement récupérer la réponse JSON. Pour une question de bonne pratique, il est généralement recommandé d'utiliser un "parser" JSON pour réduire le risque de réponses contenant du texte corrompu de l'utilisateur qui pourrait faire des ravages avec le client. Regardez : http://www.json.org/js.html. Est-ce que cela fonctionne?
Si vous rechargez l'application du "chat" dans le navigateur, vous pourrez alors envoyer des messages sous le pseudo NewUser. Bien sûr, nous ne pouvons pas être indéfiniment NewUser! Notre prochain but sera d'autoriser l'utilisateur à changer son pseudo. Changer son pseudo Si l'envoi de nouveaux messages via Javascript n'était pas trop intimidant pour vous, alors ce qui suit ne vous posera pas de problème. Notre première étape est d'ajouter un évènement onclick au bouton "Change!". Le code HTML mis-à-jour suit. <input type="text" value="" id="changename" size="15" maxlength="32" /> <input type="button" value="change!" onclick="changename()" /> Ajouter changename() Le nouvel évènement onclick appel une méthode Javascript changename(). Encore une fois, le code sera placé dans le fichier chat.js. function changename () var requesturl = 'index/name'; var newname = $F('changename'); try var request = new Ajax.Request( requesturl, method: 'get', parameters: 'name=' + encodeuricomponent(newname), oncomplete: handlechangename ); catch (e) alert('error: ' + e.tostring()); La méthode est toujours identique à sendmessage() avec quelques différences. Nous avons changé la variable requesturl en index/name, cad nous aurons besoin d'ajouter une méthode NameAction à la classe IndexController. Faisons ça maintenant. Un peu plus tard, nous regarderons plus en détails la méthode handlechangename(). Ajouter NameAction() à IndexController.php Ajoutez la méthode qui suit au fichier IndexController.php : public function NameAction() * Load the Zend Framework's Filter_Input class
require_once 'Zend/Filter/Input.php'; $get = new Zend_Filter_Input($_GET); * Ensure the new screen name is an expected value! * We assume it must contain the ASCII a-z0-9 * alphanumeric characters only * Error gets printed to screen instead of name. if(!$clean_name = $get->testalnum('name')) $this->getresponse()->setheader('content-type', 'text/plain'); $this->getresponse()->setbody('error: Invalid Screen Name'); return; Defense in Depth. The Zend Framework is likely * reliable - but you just never know. Escape all * potential output JIC (just in case). $escaped_clean_name = htmlentities($clean_name, ENT_QUOTES, 'utf-8'); * Update the user's session for the new screen name $_SESSION['chat_screenname'] = $escaped_clean_name; * To tell the client this request was successful echo * back the screen name as plain html. $this->getresponse()->setbody($escaped_clean_name); Comme nous l'avons remarqué plus tôt dans la méthode MessageAction(), le pseudo de l'utilisateur est stocké dans sa session. Dans cette méthode, nous présentons une nouvelle classe du Zend Framework appelée Zend_Filter_Input. Cette classe offre des méthodes de filtrage et de validation des données provenant des paramètres GET ou des formulaires. Nous allons supposer qu'un pseudo doit contenir uniquement des caractères alphanumériques, cad des lettres minuscules et majuscules entre a-z et des chiffres entre 0-9. Instancier un nouvel objet Zend_Filter_Input en passant des paramètres avec $_GET a un impact principal. L'objet va réécrire par dessus la superglobal $_GET forcant tous les accès aux variables GET à travers le nouvel objet. Ceci nous assure de filtrer/valider les valeurs avant leur utilisation. De plus, nous traiterons ces valeurs avec htmlentities() juste au cas où le Zend Framework échoue pour des raisons inconnues. Fortement peu probable, mais mieux vaut couvrir nos arrières ;). La méthode testalnum() retournera la valeur de "name" à notre script à moins qu'il ne soit pas de type alphanumérique, qui dans ce cas retournera un message d'erreur. En supposant que la valeur est valide, nous l'enregistrerons dans la session de l'utilisateur comme "chat_screenname". Cette variable de session est utiliser pour afficher "Votre pseudo est :" dans notre HTML.
Mettre à jour le document HTML pour les nouveaux pseudos De retour au côté client. Notre nouvelle méthode Javascript handlechangename() situé dans chat.js est très simple. function handlechangename (reply) $('changename').value = ''; $('screenname').innerhtml = reply.responsetext; Traduction réalisé par R-Benyacoub.