Sommaire du site
Présentation
Comment apprendre
L'équipement
La page web
Styles et CSS
HTML, structure de la page
HTML, éléments du corps
Le langage JavaScript
JavaScript, objets "core"
JavaScript, DOM, les bases
JavaScript, DOM, node
JavaScript, compléments
Le langage PHP, les bases
PHP, fonctions utiles
PHP pour le web
PHP, compléments
SQL, introduction
MySQL et PHP pour le web
MySQL, plus loin...
Applications AJAX
Annexes utiles
Fichier .htaccess
Sécurité des sites web
Conception d'un site web
Référencement,
syndication
Page mise à jour le : 12-08-2015
Afin d’obtenir une bonne interactivité dans les pages web, il peut-être intéressant d’obtenir des données depuis un serveur sans changer de page.
En effet, on a vu qu'une fois la page chargée, du code JavaScript peut être exécuté, en particulier par intervention de l'utilisateur. Or, à priori le JavaScript ne peut manipuler que les données présentes dans la page ou qui viennent d'être fournies par l'utilisateur. Notamment, il ne semble pas possible d'exécuter du code PHP ni d'accéder aux informations d'une base de données.
Pour combler cette lacune un objet JavaScript "XMLHttpRequest" a été défini.
Ses propriétés et méthodes permettent d'établir un dialogue entre le JavaScript de la page en cours et une application située sur un serveur distant.
Il s'agit donc d'une utilisation particulière du JavaScript. Or on sait que certains utilisateurs désactivent le JavaScript et que la plupart des robots de moteurs de recherche ne l'utilisent pas.
Par conséquent, cette limitation doit être prise en compte et que, sauf cas particuliers, il ne faut pas faire reposer le site sur ce type d'application, surtout en ce qui concerne les possibilités de navigation.
AJAX est l'acronyme de "Asynchronous JavaScript and XML". Il s'agit d'une technique de communication asynchrone entre le JavaScript et un document XML. Cette communication se fait par l'objet "XMLHttpRequest".
On verra, dans cette page, que si le JavaScript est indispensable pour profiter de cette communication, il est aussi possible de la réaliser en mode synchrone et que l'on peut obtenir les informations depuis un document qui n'est pas en XML.
Ce ne sera alors pas du "vrai AJAX" et l'on perdra quelques unes des possibilités intéressantes. Mais ce sera un peu plus simple à réaliser...
Le mode synchrone est le mode traditionnel de la programmation : le programme appelle une fonction (mot pris ici au sens large), celle-ci s'exécute et le programme appelant reprend alors son exécution. La fonction peut mettre du temps à s'exécuter et durant ce moment le programme appelant ne peut rien faire d'autre.
Dans le mode asynchrone le programme appelant continue son exécution dès l'appel de la fonction et la poursuit durant l'exécution de la fonction. Si celle-ci produit des résultats, il faudra tout de même les gérer. Pour cela, la fonction à la fin de son exécution doit déclencher un événement. Il suffit de l'intercepter pour obtenir les résultats de la fonction et les gérer.
XML (eXtensible Markup Language) est un langage de description structurée de données. Il repose sur un système de balisage (Markup) semblable à celui du HTML
Les documents XML sont en texte. Voici un document XML qui décrit une liste de livres :
<?xml version="1.0" encoding="UTF-8"?>
<liste_livres>
<ouvrage>
<titre>Les Misérables</titre>
<auteur>Victor Hugo</auteur>
</ouvrage>
<ouvrage>
<titre>La mare au diable </titre>
<auteur>George Sand </auteur>
</ouvrage>
<liste_livres>
On voit que les documents XML suivent le modèle DOM que l'on a rencontré en JavaScript pour l'HTML. On pourra donc depuis le JavaScript utiliser des méthodes telles que :
'getElementsByTagName(nom_element)'.
Il s'agit d'un objet au sens du JavaScript. Il sera nécessaire de l'instancier (avec quelques particularités pour Internet Explorer).
Une fois une instance de cet objet créée, on pourra utiliser ses propriétés et méthodes.
Internet Explorer 5.0 a été le premier navigateur à disposer de cet objet. Microsoft l'a implémenté comme ActiveX. Les autres navigateurs l'implantent comme objet JavaScript. Cela fait que l'instanciation est un peu complexe. En général on crée une fonction qui la réalise.
//Source : Wikipedia http://fr.wikipedia.org/wiki/XMLHttpRequest 22-04-2010 function CreeXHR() {
if (window.XMLHttpRequest) //Mozilla & co.
return new XMLHttpRequest();
if (window.ActiveXObject) { //IE
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("Votre navigateur ne prend pas en charge l'objet XMLHTTPRequest.");
return null; // non supporté
}
Cette fonction "CreeXHR" renvoie une instance de l'objet 'XMLHttpRequest' ou 'null' si échec.
On remarquera, dans ce listing, la structure d'essais-erreurs : 'try / catch' pour essayer les différentes versions en ActiveX.
Voici les principales.
Code d'état, il est surtout utilisé lors de la réception et a une des valeurs suivantes :
Ce dernier état est celui que l'on attend pour utiliser les données
A la réception :' code d'état HTTP transmis par le serveur :
On devrait avoir la valeur 200.
Les données reçues depuis un document texte (format chaîne de caractères).
Elément de données reçu depuis un document XML, Il faudra les extraire de cette information par une méthode du DOM.
Evénement survenant aux changements d'état de l'objet. Cet événement doit être intercepté par la fonction de traitement des données reçues.
Ouvre la connexion avec le fichier de traitement.
Pour le mode 'POST' envoi les données passées en paramètre.
Pour le mode 'GET' le paramètre est ignoré (on le met à 'null' ou à une chaîne vide).
Le client doit instancier l'objet "XMLHttpRequest".
Il suffit de créer une fonction gérant l'envoi des données au serveur et la réponse de celui-ci.
Il faut associer à l'événement 'onreadystatechange' une fonction de récupération des données transmises par le serveur.
Et créer une fonction d'envoi des données au serveur.
Le serveur recevra les demandes du client par les tableaux PHP « $_GET » ou « $_POST » comme pour les formulaires.
Bien que ce ne soit pas obligatoire mais conforme à la signification d’AJAX, le serveur renverra les informations en construisant un document XML.
La mise au point du script du serveur n'est pas facile. En effet si des erreurs se produisent les messages ne sont pas transmis au client et on n'est pas informé de ce qui s'y passe.
Pour des applications complexes, il est judicieux de créer un client de test, hors AJAX, qui envoie les données au programme du serveur par une gestion traditionnelle de formulaire.
Client |
|
|
Initialisations : |
Serveur | |
Envoi : open |
||
Attente (suspension d’activité) |
Récupération des informations par $_GET ou $_POST |
|
Traitement |
||
Génération du document XML |
||
Le déroulement du script est repris : |
Client |
|
|
Initialisations : |
Serveur | |
Envoi : |
||
Autres activités éventuelles…. |
Récupération des informations par $_GET ou $_POST |
|
Traitement |
||
Génération du document XML |
||
La fonction onreadystatechange est activée. |
Il parait donc préférable de réaliser la version asynchrone car elle permet au client de réaliser des actions durant le travail du serveur.
Cependant, il faut prendre en compte deux conséquences :
Dans ce dernier cas, il peut être utile de vérifier que le serveur a accompli son travail avant de lui envoyer une nouvelle demande.
Le nombre de requêtes "simultanées" gérables dépend du navigateur. C'est pourquoi, si l'on ne les limite pas on peut avoir une application qui fonctionne bien sur certaines machines clientes et mal sur d'autres.
L'utilisateur est invité à entrer les lettres d'un prénom. Au fur et à mesure de la frappe la partie saisie est recherchée par le serveur dans une base de donnée en vue d'afficher le plus tôt possible le nom complet et l'adresse correspondant à ce prénom.
//Initialise
if (isset($_POST['n']))
$valeur= $_POST['n'];
else
$valeur= "?";
//En-têtes
header('Content-Type: text/xml;charset=UTF-8');
echo "<?xml version='1.0' encoding='UTF-8' ?>";
//Corps
echo "<valeur>";
echo Recherche($valeur);
echo "</valeur>";
On notera l'utilisation de la fonction PHP 'header()' qui indique le type de document.
Il s'agit donc d'une production de document XML. Il sera de la forme :
La valeur de retour est générée par la fonction PHP 'recherche()'.
function Recherche($v) { $requete= "SELECT nom, adresse FROM adherents WHERE nom LIKE '$v%' ORDER BY nom"; $res= mysql_query($requete); if ($res) { $n= mysql_num_rows($res); switch ($n) { case 0: return "$v : INCONNU"; case 1: $inf= mysql_fetch_row($res); return $inf[0]." : ".$inf[1]; default: return "$v..."; } } return "ERREUR"; }
La recherche dans la table est faite sur la correspondance du paramètre passé avec les premiers caractères du champ 'nom' de la table.
Selon le nombre de résultats obtenus, une information de contrôle ou le nom et l'adresse sont renvoyés.
La fonction d'instanciation de l'objet 'XMLHttpRequest' n'est pas vue ici car c'est la même que celle présenté plus haut dans cette page. Cet objet est créé simplement en début de page par :
xhr= CreeXHR();
<body style="font-family: Arial,Helvetica,sans-serif;" onload="document.formulaire.nom.focus()">
<h1>
Démonstration AJAX synchrone</h1>
<p>Rechercher l'adresse d'un adhérent de l'association </p>
<form action="javascript: Envoie()" name="formulaire" id="formulaire">
<table border="0" cellpadding="2" cellspacing="2" width="100%">
<tbody>
<tr>
<td align="right">
Prénom : </td>
<td align="left" valign="undefined">
<input name="nom" value="" autocomplete="off" onkeyup="Envoie()">
</td>
</tr>
<tr>
<td></td>
<td align="left">
prendre un de ces prénoms : Jean, Marie, Charles, Sarah, Laurent, Laure<br>
(mettre un espace après Laure)
</td>
</tr>
<tr>
<td align="right">
Adresse :
</td>
<td align="left">
<input name="result" value="" size="40" maxlength="40" readonly="readonly">
</td>
</tr>
</tbody>
</table>
</form>
</body>
Il s'agit d'un simple formulaire HTML, mais avec trois particularités.
Dans cette version, l'unique fonction 'Envoie()' gère aussi la réception.
function Envoie () {//Fonction d'envoi et reception
n= document.formulaire.nom.value;
xhr.open("POST", "ajax_srv.php", false);
xhr.setRequestHeader(
"Content-Type", "application/x-www-form-urlencoded"
);
xhr.send("n="+n);
if(xhr.status == 200) {// Réponse OK
rep= xhr.responseXML;
document.formulaire.result.value= rep.getElementsByTagName('valeur')[0].firstChild.data;
}
else
document.formulaire.result.value="Erreur " + xhr.status;
}
On rappelle que 'xhr' est l'instanciation de l'objet 'XMLHttpRequest'.
La saisie du formulaire est récupérée dans la variable 'n'.
L'envoi est fait par la succession des appels 'open', 'setRequestHeader' et 'send'; On notera le dernier paramètre de 'open' à 'false' indiquant la version synchrone. Les données sont envoyées par 'send' conformément au mode 'POST'.
Cette fonction 'send' est bloquante (version synchrone). Par conséquent il est inutile de vérifier la propriété 'readyState'. On continue lorsque le serveur a répondu.
Le test de 'status' permet de s'assure que la réponse est valide. Dans ce cas, on récupère l'élément d'information depuis la propriété 'responseXML' et on extrait l'information avec la méthode DOM 'getElementsByTagName'. Celle-ci est placée directement dans le champ 'result" du formulaire.
Là il nous faut distinguer les fonctions d'envoi et de réception.
On rappelle que 'xhr' est l'instanciation de l'objet 'XMLHttpRequest'.
Envoi
function Envoie () {
if(xhr.readyState != 0 && xhr.readyState != 4) return;
n= document.formulaire.nom.value;
xhr.open("POST", "ajax_srv.php", true);
xhr.setRequestHeader(
"Content-Type", "application/x-www-form-urlencoded"
);
xhr.send("n="+n);
}
Elle est plus courte puisqu'elle ne fait que l'envoi.
Un test est fait au début pour éviter les bourrages éventuels (peut être facultatif).
La seule différence avec l'envoi synchrone est dans le dernier paramètre de 'open' qui ici vaut 'true'.
Réception
En revanche un peu plus complexe qu'en synchrone.
xhr.onreadystatechange=function() {
if(xhr.readyState == 4) { // Prêt
if(xhr.status == 200) {// Réponse OK
rep= xhr.responseXML;
document.formulaire.result.value=
rep.getElementsByTagName('valeur')[0].firstChild.data;
}
else
document.formulaire.result.value=
"Erreur " + xhr.status;
}
}
Cette fonction de réception (anonyme) est directement reliée à l'événement 'onreadystatechange'. Elle est donc appelée lors de tout changement d'état de 'xhr'.
On doit donc commencer par tester la propriété 'readyState' pour être sûr de traiter uniquement le cas de réception des données.
Le reste est identique à la partie réception synchrone.
Elle transmet les données dans l’URL du serveur de la fonction « open ». On aurait écrit :
xhr.open("GET", "calcule.php?n="+n, false);
Dans ce cas, il est inutile d’appeler «xhr.setRequestHeader» et, comme les données sont déjà transmises, on aurait eu :
xhr.send("");
La méthode 'GET' n'est pas adaptée pour un volume de données important.
Cette possibilité est adaptée à une réponse unique.
Le code côté serveur est un peu plus simple : une production de texte en PHP. La partie principale de notre exemple devient :
On remarque que le 'header' n'est plus le même.
Et du côté client on remplace « responseXML» par « responseText» :
rep= xhr.responseText;
On n'a plus à extraire les données puisqu'elles sont fournies directement.
On trouve facilement sur le web un grand nombre de pages qui traitent de AJAX et de 'XMLHttpRequest'. Mais le plus souvent on obtiendra les mêmes exemples et les modes synchrone et 'GET' sont peu abordés.
Voici une petite sélection de pages qui semblent être parmi les plus pertinentes.
L’original en anglais
http://www.w3.org/TR/XMLHttpRequest/
La traduction en français
http://www.xul.fr/XMLHttpRequest.html
En français
http://www.xul.fr/xml-ajax.html
ou
http://www.siteduzero.com/tutoriel-3-4745-ajax-et-l-echange-de-donnees-en-javascript.html