Asynchronous – JavaScript - XML
Transcription
Asynchronous – JavaScript - XML
AJAX Asynchronous – JavaScript - XML Rédacteur Version Date : Morel Alexandre : 1.2 : 08 novembre 2005 Alexandre Morel Ajax Tables des matières Introduction _________________________________________ 3 L'objet XMLHttpRequest ____________________________________ 3 Qu'est-ce qu'AJAX ? _______________________________________ 3 Utilisation ___________________________________________ 4 Étape 1 - Lancement d'une requête http _______________________ 4 Étape 2 - Gestion de la réponse du serveur _____________________ 7 Étape 3 - Utilisation de la réponse du serveur ___________________ 8 Étape 4 - Un exemple simple ________________________________ 9 Étape 5 - Travailler avec des réponses XML ____________________ 12 Conclusions _________________________________________ 13 Avantages______________________________________________ 13 Inconvénients___________________________________________ 13 Annexes ___________________________________________ 14 Propriétés et méthodes ___________________________________ 14 Propriétés _______________________________________________________ 14 Méthodes ________________________________________________________ 14 Code d'état http _________________________________________ 16 2/16 Alexandre Morel Ajax Introduction L'objet XMLHttpRequest Créé par Microsoft pour Internet Explorer, l'objet XMLHttpRequest a été adopté par les navigateurs Mozilla, Konqueror, Safari et récemment Opéra. Bien que largement implémentée dans les navigateurs récents, cette technologie n'est pas un standard du W3C , lequel propose des fonctionnalités similaires à travers la recommandation Document Object Model (DOM) Level 3 Load and Save Specification. Cet objet permet de faire des requêtes HTTP afin de récupérer des données au format XML qui pourront être intégrées à un document. Cela peut être très utile pour mettre à jour des données sans pour autant recharger la page. Qu'est-ce qu'AJAX ? L'utilisation de XMLHttpRequest fait immédiatement penser à AJAX, c'est un nouveau terme inventé récemment pour désigner deux puissantes fonctionnalités du JavaScript qui existent depuis plusieurs années, mais qui sont restées inaperçues de nombreux développeurs Web jusqu'il y a peu. Depuis, des applications comme Gmail, Google suggest et Google Maps sont devenues monnaie courante. Ces deux fonctionnalités de JavaScript sont les possibilités de : • • Faire des requêtes vers le serveur sans avoir à recharger la page. Parcourir et travailler avec des documents XML ou autres. Le terme AJAX est un acronyme en anglais. Le A est pour « asynchronous » (asynchrone), ce qui signifie que vous pouvez faire une requête HTTP vers le serveur et faire d'autres choses en attendant que la réponse arrive. JA est pour « JavaScript » et X est pour « XML ». Cette architecture client/serveur consiste en effet à découper une application web de la façon suivante : • • • • • une présentation utilisant XHTML et CSS. la manipulation dynamique des pages à travers DOM. la manipulation des données avec XML et XSLT. l'échange des données de manière asynchrone avec XMLHttpRequest. le tout étant assemblé avec du Javascript. Les éléments clés de cette architecture sont la séparation en couches distinctes des éléments du client à l'aide de technologies standardisées et les échanges asynchrones de données au format XML. 3/16 Alexandre Morel Ajax Utilisation Étape 1 - Lancement d'une requête http Afin de faire une requête HTTP vers le serveur à l'aide de JavaScript, il faut disposer d'une instance d'une classe fournissant cette fonctionnalité. Une telle classe a d'abord été introduite dans Internet Explorer sous la forme d'un objet ActiveX appelé XMLHTTP. Par la suite, Mozilla, Safari et d'autres navigateurs ont suivi en implémentant une classe XMLHttpRequest qui fournit les mêmes méthodes et propriétés que l'objet ActiveX original de Microsoft. Par conséquent, pour créer une instance de la classe (un objet) fonctionnant sur plusieurs navigateurs, vous pouvez utiliser : /* On crée l’instance de l’objet XMLHTTPRequest */ var mon_objet = new object ; /* Si c’est Mozilla/Firefox/Nescape/opera/safari */ if(window.XMLHttpRequest) mon_objet = new XMLHttpRequest(); /* Si c’est Internet Explorer */ else if(window.ActiveXObject) mon_objet = new ActiveXObject("Microsoft.XMLHTTP"); /* Si aucun navigateur compatible avec XMLHttpRequest, on le signal */ else { alert("Votre navigateur ne supporte pas les objet XMLHTTPRequest…"); return; } Certaines versions de certains navigateurs Mozilla ne fonctionneront pas correctement si la réponse du serveur n'a pas un en-tête de type MIME XML. Pour les satisfaire, vous pouvez utiliser un appel de fonction supplémentaire pour écraser l'en-tête envoyé par le serveur, juste au cas où il ne s'agit pas de text/xml, comme ceci : mon_objet.overrideMimeType("text/xml"); La chose suivante à faire est de décider ce que vous voulez faire après avoir reçu la réponse du serveur. À ce stade, vous devez juste dire à l'objet de requête HTTP quelle fonction JavaScript devra effectuer le travail d'analyse de la réponse. Cela se réalise en assignant à la propriété onreadystatechange de l'objet le nom de la fonction JavaScript que vous envisagez d'utiliser, comme ceci : 4/16 Alexandre Morel Ajax mon_objet.onreadystatechange = nomDeLaFonction; Notez qu'il n'y a pas de parenthèses après le nom de la fonction, ni de paramètres fournis. Par ailleurs, au lieu de donner un nom de fonction, vous pouvez également utiliser la technique JavaScript de définition de fonctions au vol, et spécifier directement les actions à effectuer sur la réponse, comme ceci : mon_objet.onreadystatechange = function() { /* instructions de traitement de la réponse */ }; Ensuite, après avoir déclaré ce qui se passera lorsque la réponse sera reçue, il s'agit de lancer effectivement la requête. Il faut pour cela appeler les méthodes open() et send() de la classe de requête HTTP, comme ceci : /* on spécifie la méthode de transmission des données, l'URL et le mode de transmission de la requête */ mon_objet.open("GET", "ma_page.php", true); mon_objet.send(null); Le premier paramètre de l'appel à open() est la méthode de requête HTTP – GET, POST, HEAD ou toute autre méthode que vous voulez utiliser et est gérée par le serveur. Laissez le nom de la méthode en majuscules comme spécifié par la norme HTTP , autrement certains navigateurs (comme Firefox) peuvent ne pas procéder à la requête. Le second paramètre est l'URL de la page dont vous faites la requête. Pour des raisons de sécurité, il n'est pas possible d'appeler des pages se situant sur un autre domaine. Le troisième paramètre précise si la requête est asynchrone. Si, mis à TRUE, l'exécution de la fonction JavaScript se poursuivra en attendant l'arrivée de la réponse du serveur. 5/16 Alexandre Morel Ajax Le paramètre de la méthode send() peut être n'importe quelle donnée que vous voulez envoyer au serveur en cas d'utilisation de la méthode POST. Les données doivent être sous la forme d'une chaîne de requête, comme : /* Variable qui contient les données */ var donnee = "variable1=valeur1?variable2=valeur2"; /* On envoit la requête avec les données */ mon_objet.send(donnee); Exemple avec GET : /* Variable qui contient les données */ var donnee = "variable1=valeur1?variable2=valeur2"; /* les données à transmettre sont concaténées à l'URL */ mon_objet.open("GET", "ma_page.php?"+donnee, true); /* On envoie la requête */ mon_objet.send(null); Exemple avec POST : /* Variable qui contient les données */ var donnee = "variable1=valeur1?variable2=valeur2"; mon_objet.open("POST", "ma_page.php", true); /* On précise l'encodage en spécifiant l'en-tête adéquat (seulement avec POST) */ mon_objet.setRequestHeader("Content-type","application/x-www-form-urlencoded"); /* On envoie la requête avec les données */ mon_objet.send(donnee); 6/16 Alexandre Morel Ajax Étape 2 - Gestion de la réponse du serveur Souvenez-vous que lors de l'envoi de la requête, vous aviez fourni le nom d'une fonction JavaScript conçue pour traiter la réponse. Voyons maintenant ce que cette fonction doit faire. Tout d'abord, elle doit vérifier l'état de la requête. Si cet état a une valeur de 4, cela signifie que la réponse du serveur a été reçue dans son intégralité et qu'elle peut maintenant être traitée. if (mon_objet.readyState == 4) { /* tout va bien, la réponse a été reçue */ } else { /* pas encore prête */ } Voici la liste complète des valeurs de readyState : 0 (non initialisée) 1 (en cours de chargement) 2 (chargée) 3 (en cours d'interaction) 4 (terminée) La seconde chose à vérifier est le code d'état HTTP de la réponse du serveur. Tous les codes possibles sont listés en annexe. Cela nous permet de gérer les différentes erreurs possible. Exmple avec une réponse 404 (page non trouvée). if (mon_objet.readyState == 4) { /* tout va bien, la réponse a été reçue */ } else { if (mon_objet.status == 404) { /* la page n'a pas été trouvé */ } } 7/16 Alexandre Morel Ajax Étape 3 - Utilisation de la réponse du serveur Maintenant que vous avez vérifié l'état de la requête et le code d'état HTTP de la réponse, vous pouvez faire ce que vous voulez des données envoyées par le serveur. Il existe deux manières d'accéder à ces données : http_request.responseText – renvoie la réponse du serveur sous la forme d'une chaîne de texte, Exemple : /* Variable qui contient la commande */ var donnee = "commande=1&type=veste&couleur=rouge&taille=XL"; mon_objet.open("POST", "creation_facture.php", true); /* On spécifie la fonction à exécuter */ mon_objet.onreadystatechange = function() { if (mon_objet.readyState == 4) { var facture = mon_objet.reponseText; /* on affiche la facture */ alert(facture); } } /* On précise l'encodage en spécifiant l'en-tête adéquat (seulement avec POST) */ mon_objet.setRequestHeader("Content-type","application/x-www-form-urlencoded"); /* On envoit la requête avec les données */ mon_objet.send(donnee); http_request.responseXML – renvoie la réponse sous la forme d'un objet XMLDocument que vous pouvez parcourir à l'aide des fonctions DOM de JavaScript (nous verrons cela plus tard). 8/16 Alexandre Morel Ajax Étape 4 - Un exemple simple Mettons tout cela ensemble et effectuons une requête HTTP simple. Notre JavaScript demandera une reponse php, personne.php, qui contiendra le texte« Nom: et Prenom:», et nous afficherons le contenu dans une case d'un tableau html avec innerHTML). Fichier HTML (index.html) : <html> <head> <title>Personnes</title> <script LANGUAGE="Javascript1 1.2" src="javascript.js"></script> <head> <body> <table> <tr> <td name="reponse"><a href="javascript:mapage("AM")">AM</a></td> </tr> </table> </body> </html> Fichier javascript (javascript.js) /* On crée l’instance de l’objet XMLHTTPRequest */ var mon_objet = null; /* Si c’est Mozilla/Firefox/Nescape/opera/safari */ if(window.XMLHttpRequest) mon_objet = new XMLHttpRequest(); /* Si c’est Internet Explorer */ else if(window.ActiveXObject) mon_objet = new ActiveXObject("Microsoft.XMLHTTP"); /* Si aucun navigateur compatible avec XMLHttpRequest, on le signal */ else { alert("Votre navigateur ne supporte pas les objet XMLHTTPRequest…"); return; } /* Fonction à executer quand on clique sur le lien AM */ function mapage(ma_valeur) { mon_objet.open("POST", "personne.php", true); /* On spécifie la fonction à exécuter */ mon_objet.onreadystatechange = function() { if (mon_objet.readyState == 4) 9/16 Alexandre Morel Ajax { /* On exécute la fonction avec paramètre réponse */ affiche(mon_objet.reponseText); } } /* On précise l'encodage en spécifiant l'en-tête adéquat (seulement avec POST) */ mon_objet.setRequestHeader("Content-type","application/x-www-form-urlencoded"); /* On définit les variables a envoyer */ if (ma_variable=="AM") var donnee = "nom=Morel&prenom=Alexandre"; else var donnee = "nom=Inconnu&prenom=Inconnu"; /* On envoie la requête avec les données */ mon_objet.send(donnee); } /* Pour remplacer le texte dans le document */ function affiche(texte) { /* on cherche la version du navigateur */ var ns4 = (document.layers)? true:false; /* Nescape 4 */ var ie4 = (document.all)? true:false; /* Internet Eplorer 4 */ var dom = (document.getElementById)? true:false; /* Nescape 6 ou Internet Eplorer 6 */ if(dom) { document.getElementById("reponse").innerHTML = texte; return; } else if(ie4) { document.all["reponse"].innerHTML = texte; return; } else if(ns4) { with (eval('document.'+"reponse"+'.document')) { open(); write(texte); close(); } return; } } 10/16 Alexandre Morel Ajax Fichier php (personne.php) /* On défini le type de fichier */ Header("Content-type: text/html; charset=iso-8859-1"); /* on affiche le nom */ echo 'Nom : '.$_POST['nom']; /* on affiche le prénom */ echo 'Prénom : '.$_POST['prenom']; Dans cet exemple : L'utilisateur clique sur le lien « AM » dans le navigateur. ceci appelle la fonction mapage() avec en paramètre les initiales (AM) cela exécute le fichier personne.php. qui renvoie le texte mis en forme. quand on reçoit la réponse, on exécute affiche() qui remplace la case lien « AM » par le résultat de reponseText 11/16 Alexandre Morel Ajax Étape 5 - Travailler avec des réponses XML Dans l'exemple précédent, après que la réponse à la requête HTTP ait été reçue, nous avons utilisé la propriété reponseText de l'objet de requête, et celle-ci renvoyait le contenu du fichier. Essayons maintenant la propriété reponseXML. Tout d'abord, créons un document XML valide qui sera l'objet de la requête. Le document (test.xml) contient ce qui suit : <?xml version="1.0" ?> <root> Je suis un test. </root> Dans le script, il est juste nécessaire de remplacer la ligne de requête par : ... onclick="makeRequest('test.xml')"> ... Ensuite, dans alertContents(), il faut remplacer la ligne affichant un message alert(mon_objet.responseText), par : /* on crée un objet qui contiendra le document XML */ var DocXml = http_request.responseXML; /* on crée une variable qui contiendra le noeud root */ var noeud = DocXml.getElementsByTagName('root').item(0); /* on affiche le premier noeud root trouver */ alert(noeud.firstChild.data); De cette façon, nous avons pris l'objet XMLDocument donné par responseXML et nous avons utilisé des méthodes DOM pour accéder à certaines données contenues dans le document XML. 12/16 Alexandre Morel Ajax Conclusions Avantages • • • Diminution de la bande passante : seules les données sont chargées et non plus tout le document. Interactivité accrue : plus de rechargement de la page. Rationnalisation du code : des routines (de vérification par exemple) n'ont plus à être écrites et maintenues dans deux langages (côté client et côté serveur). Inconvénients • • • • • Ne fonctionne pas sans Javascript, ni dans les navigateurs les plus anciens. Ne fonctionne qu'avec HTTP : il est impossible de récupérer des données sur un disque local (ce qui est normal). Impossible d’envoyer un fichier en utilisant AJAX, défini pour des raisons de sécurité évidente (On pourrai prendre un fichier sans prévenir utilisateur,…) Les requêtes en dehors du domaine provoquent un avertissement de sécurité. Peut empêcher des comportements habituels du navigateur : o Marques-pages et liens vers la page. o Enregistrement des pages. o Bouton retour. o Difficulté de référencement 13/16 Alexandre Morel Ajax Annexes Propriétés et méthodes Cette section n'est pas exhaustive. Elle présente les propriétés et méthodes les plus utiles, même s'il est vrai que cette notion est assez subjective. Pour une liste complète, je vous invite à consulter la MSDN http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmobjpmeserverxmlhttp.asp Propriétés .onreadystatechange : Spécifie la fonction à appeler lorsque la propriéte readyState varie. Lecture/Ecriture .readyState : Représente l'état d'avancement de la requête. Lecture seule .responseText : Chaîne de caractères contenant la réponse à la requête. Lecture seule .responseXML : Objet XML contenant la réponse à la requête. Lecture seule .status : Représente le code HTTP retourné par la requête. Lecture seule . statusText : message accompagnant le code de réponse. Lecture seule Méthodes .abort() : Annule la requête courante. . getAllResponseHeaders() : Retourne les noms et les valeurs de tous les en-têtes HTTP sous forme d'une chaîne. . getResponseHeader(headerName) : Récupère la valeur d'un certain en-tête HTTP (headerName) sous forme d'une chaîne. .open(method, url[, asynchrone[, user[, password]]]) : Initialise une requête en spécifiant la méthode (method), l'URL (url), si le mode est asynchrone (asyncFlag vaut true ou false) et en indiquant d'éventuelles informations d'identification (user et password). .send(data) : Envoie la requête HTTP au serveur en transmettant éventuellement des données (data doit alors être différent de null) sous forme d'une « postable string » (je suis preneur pour une traduction) ou sous forme d'un objet DOM. 14/16 Alexandre Morel Ajax .setTimeouts(timeout) : Spécifie la durée maximale (timeout) accordée à une requête pour quelle s'effectue complètement. . setRequestHeader(headerName, headerValue) : Spécifie un en-tête HTTP (headerName et headerValue) à envoyer avec la requête. eval(mon_object.responseText); Permet d’exécuter la réponse si elle est sous forme javascript 15/16 Alexandre Morel Ajax Code d'état http 100 101 200 201 202 203 204 205 206 300 301 302 303 304 305 307 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 500 501 502 503 504 505 Continue Switching protocols OK Created Accepted Non-Authoritative Information No Content Reset Content Partial Content Multiple Choices Moved Permanently Found See Other Not Modified Use Proxy Temporary Redirect Bad Request Unauthorized Payment Required Forbidden Not Found Method Not Allowed Not Acceptable Proxy Authentication Required Request Timeout Conflict Gone Length Required Precondition Failed Request Entity Too Large Request-URI Too Long Unsupported Media Type Requested Range Not Suitable Expectation Failed Internal Server Error Not Implemented Bad Gateway Service Unavailable Gateway Timeout HTTP Version Not Supported 16/16