Réalisation de sites web

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

Sommaire détaillé

Mentions légales.

Chapitres de cette page
Contenu  -> 

Page mise à jour le : 12-08-2015

Haut de la page

Présentation
L'objet 'XMLHttpRequest'
Principe de fonctionnement
Exemple
Plus simple
En savoir plus
A suivre...

Applications AJAX

Présentation

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

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...

Mode synchrone versus asynchrone

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

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)'.

L'objet 'XMLHttpRequest'

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.

Instanciation

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.

Propriétés

Voici les principales.

readyState

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

status

A la réception :' code d'état HTTP transmis par le serveur :

On devrait avoir la valeur 200.

responseText

Les données reçues depuis un document texte (format chaîne de caractères).

responseXml

Elément de données reçu depuis un document XML, Il faudra les extraire de cette information par une méthode du DOM.

onreadystatechange

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.

Méthodes

open(mode, url, type)

Ouvre la connexion avec le fichier de traitement.

send("donnees")

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).

 

Principe de fonctionnement

Côté client

Le client doit instancier l'objet "XMLHttpRequest".

En mode synchrone

Il suffit de créer une fonction gérant l'envoi des données au serveur et la réponse de celui-ci.

En mode asynchrone

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.

Côté serveur (version PHP et XML)

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.

 

Diagramme de déroulement version synchrone

Client

 

 

Initialisations :
Création de l’objet de type XMLHttpRequest.

  Serveur
   

Envoi :
Exécution de la séquence de fonctions :

                open 
              setRequestHeader
                send

1

Attente (suspension d’activité)

 

Récupération des informations par $_GET ou $_POST

 

Traitement

2

Génération du document XML

Le déroulement du script est repris :
La propriété status indique la nature de la réponse.
Celle-ci est obtenue dans responseXML

   

Diagramme de déroulement version asynchrone

Client

 

 

Initialisations :
Création de l’objet de type XMLHttpRequest.
Interception de l'événement onreadystatechange

  Serveur
   

Envoi :
Exécution de la séquence de fonctions :
                open 
                setRequestHeader
                send

3

Autres activités éventuelles….

 

Récupération des informations par $_GET ou $_POST

 

Traitement

4

Génération du document XML

La fonction onreadystatechange est activée.
Les propriétés readyState et status indiquent la nature de la réponse.
Celle-ci est obtenue dans responseXML

   

Conclusion

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.

Exemple d’application

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.

Pour tester les démonstrations, il faut que JavaScript soit activé !

Fichier de traitement (en PHP) sur le serveur

Partie principale

//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 :

<?xml version='1.0' encoding='UTF-8' ?>
<valeur>
...résultat...

</valeur>

 

La valeur de retour est générée par la fonction PHP 'recherche()'.

Fonction 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.

Fichier du client

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();

Corps HTML commun (synchrone ou asynchrone) du bas de la page

<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.

Fonction JavaScript, version synchrone

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.

Fonctions JavaScript, version asynchrone

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.

Quelques remarques pour faire plus simple

Utiliser la méthode « GET » au lieu de « POST »

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.

Réponse du serveur en texte (au lieu de XML)

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  :

/********* Document **********/
//En-tête
header('Content-type: text/html; charset=UTF-8');
//Corps
echo Recherche($valeur);
?>

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.

En savoir plus

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.

Spécification officielle du W3C

L’original en anglais
http://www.w3.org/TR/XMLHttpRequest/
La traduction en français
http://www.xul.fr/XMLHttpRequest.html

Tutoriel

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

A suivre...