I. Introduction

Dans cet article, je vais vous présenter la mise en oeuvre des requêtes XMLHttp à l'aide d'une petite partie de la librairie Yahoo User Interface.

Cette partie, le Connection Manager, fournit le nécessaire pour invoquer une requête XMLHttp.

Comme vous le verrez, l'implémentation du Connection Manager de la YUI ne représente qu'une petite partie du tutoriel, le reste étant dévolu à la réflexion et à la mise en oeuvre.

J'ai voulu cet article assez détaillé (vous y trouverez de nombreuses copies d'écran) et le plus didactique possible.

J'estime le niveau demandé à intermédiaire. Il est donc nécessaire d'avoir quelques connaissances en Html, en Php (ou le langage côté serveur choisi) et un niveau correct en javascript. Si l'exemple abordé est simple, je déconseille toutefois aux débutants de se lancer dans l'aventure.

Bonne lecture ;=)

I-A. Remerciements

Je tiens à remercier Denis Cabasson, responsable de la rubrique Javascript, qui a relu attentivement ce document.

J'adresse également un grand merci à ma soeur, Marie Pommereau, qui a largement participé à l'amélioration de cet article.

I-B. Le web aujourd'hui

Aujourd'hui, les sites web utilisent massivement les technologies Ajax.

La révolution du "web 2.0" (bien que je n'aime pas trop ce terme parfois emprunt de pipologie) a changé la donne avec le partage de contenu, le rechargement partiel des pages, l'ergonomie et bien d'autres choses encore.

En effet, il faut désormais compter avec ces technologies coûteuses en temps et en connaissances. Au passage, on notera un coût (financier) de développement bien plus important : fini le temps du webmestre qui ne fait que du Html.

Plus le temps passe et plus nos pages web, théoriquement déconnectées (modèle originel du web), doivent se comporter comme une application fenêtrée.

Dans ce modèle pseudo-connecté, l'un des aspects le plus important réside dans le dialogue entre le navigateur (le client) et un serveur web (le serveur), le tout sans rechargement de page.

C'est ce que nous allons voir dans cet article ;=).

I-C. Pourquoi la Yahoo User Library ?

Tout d'abord, sachez que la YUI ne s'impose pas nécessairement dans le cadre d'une simple requête XMLHttp.

Pour ce cas en particulier, on aurait pu utiliser d'autres librairies plus légères telles que prototype ou jquery.

Quel est l'intérêt d'utiliser la YUI ?

La YUI, contrairement à d'autres librairies, propose un bon nombre de composants visuels comme : datatable, autocomplete, treeview, tabview qui se reposent sur d'autres composants non visuels comme le connection manager. A mon sens, cela fait de cette librairie un choix de framework javascript tout à fait crédible dans le cadre d'un projet d'application web.

Ce qui fait, d'après moi, la force de YUI :

  • Un nombre très important de composants visuels et non visuels
  • Une licence attractive (licence BSD)
  • Une importante communauté
  • Un projet très dynamique (des compsants sont régulièrement publiés)
  • Une documentation complète (A.P.I.), des exemples détaillés pour chaque composant

Quelques inconvénients :

  • La taille et le nombre des fichiers à inclure
  • La difficulté de mise en oeuvre de certains composants

II. Les outils

Avant d'attaquer, attardons-nous sur les outils dont nous avons besoin pour mettre en oeuvre notre cas pratique.

Même si cela peut paraître secondaire, il est important d'être bien "outillé" avant de commencer à développer. Mieux vaut donc prendre tout de suite de bonnes habitudes.

Bien sur, il ne s'agit ici que de recommandations, libre à vous de choisir les outils qui vous conviennent.

II-A. Serveur web

Concernant le serveur web qui prendra en charge la requête XMLHttp, le choix se portera sur la technologie que vous utilisez côté serveur.

Dans cet article, j'ai choisi d'écrire les exemples en Php, le serveur web utilisé est Apache. (package Wamp)

Ici encore, à vous de choisir le serveur web (tomcat, apache, IIS ...) et la technologie côté serveur (Php, Asp 3.0, Asp.Net ...) qui vous conviennent.

II-B. Firefox

Firefox est indéniablement le navigateur le plus adapté au développement web.

La profusion d'extensions "orientées développement" en fait, en effet, un outil incontournable.

Voici, pour information, quelques extensions dont vous pourriez avoir besoin (ici, celle que j'aime le plus) :

Nom Description
Firebug Outil de développement complet pour vos pages web. Edition et debugage des feuilles CSS, des pages Html et du javascript.
Web Developer Barre d'outils de développement web
ColorZilla Permet de sélectionner une couleur et d'obtenir sa représentation rgb, hexadécimale...
MeasureIt Mesurer une zone dans le navigateur
Live HTTP Headers Les en-têtes Http en live.

Ces extensions peuvent être téléchargées à l'adresse suivante : Extensions Firefox

II-C. L'extension Firebug

Firebug est une extension du navigateur Firefox.

Particulièrement riche en fonctionnalités, cette extension permet notamment :

  • L'inspection du code d'une page web en survolant les éléments affichés
  • La vérification de la réussite de l'inclusion de scripts javascript
  • La visualisation aisée des erreurs javascript
  • L'accès rapide aux différentes feuilles de styles et aux scripts javascript d'une page
  • Le traçage en temps réel des requêtes XMLHttp

Bien d'autres fonctionnalités sont disponibles. Voyez donc le site de l'auteur de l'extension : Site de l'auteur

II-D. Un éditeur de texte

Concernant l'éditeur de texte, je n'ai pas de conseil particulier à donner.

Toutefois, dans notre cas, le choix devrait se porter sur un éditeur capable de coloriser correctement le html, le javascript et le langage que vous aurez choisi pour la partie serveur.

Pour ma part j'utilise html-kit, notepad++ ou pspad. Pour Php, je vous recommande un éditeur spécialisé comme zend studio ou bien le plugin PDT d'Eclipse.

III. Cas pratique

Nous allons voir un exemple pratique de requête XMLHttp.

Ce cas pratique a été testé avec succès avec les navigateurs suivants :
  • Internet Explorer 6
  • Internet Explorer 7
  • Firefox 2
  • Safari 3

Soit un formulaire Html contenant 2 champs (balise input de type text) dont un champ est destiné au prénom et l'autre à l'année de naissance.

Attention, cet exemple ne constitue qu'un cas d'école. Il est inutile en soi mais représente bien le processus Ajax pour l'invocation d'une requête XMLHttp.

Image non disponible

Un bouton déclenche l'envoi des données du formulaire au serveur.

Par la suite, le serveur traite ces données et retourne le prénom en majuscules et l'âge supposé de la personne (par soustraction de l'année courante à l'année de naissance).

Image non disponible

III-A. Réfléchir avant d'agir...

Derrière ce simple formulaire se cache un processus qui est certainement moins évident qu'il n'y paraît.

Voici un petit schéma qui illustre la cinématique de cet exemple de requête XMLHttp.

Image non disponible
  1. Saisie des données et clic sur le bouton
  2. Envoi des données via une requête XMLHttp initiée par le framework YUI
  3. Traitement et réponse du serveur Web
  4. Injection de la réponse par déclenchement d'un évènement de la YUI

III-B. Mise en oeuvre

Maintenant que l'on a identifié tout le processus, reste à faire le plus plaisant : coder... ;)

III-B-1. Côté serveur

Commençons par la partie serveur. Comme on l'a vu plus haut, le traitement est on ne peut plus simple.

Dans l'exemple le fichier créé est nommé : simpleRequest.php

 
Sélectionnez
<?php
	if (isset($_REQUEST['annee_naissance']) && $_REQUEST['annee_naissance'] != '' ) {
		// Calculer l'age (année courante - année de naissance)
		$age = date('Y') - $_REQUEST['annee_naissance'];

		// Affichage du résultat
		echo "1. Traitement dans <b>simpleRequest.php</b><br />";
		echo '2. ' . strtoupper($_REQUEST['prenom']) . ' tu as ' . $age . ' ans';
	}else {
		// Cas d'erreur, retourne une erreur 404
		//echo 'Erreur';
		header("HTTP/1.0 404 Not Found");
	}
?>

Au lieu de se lancer à corps perdu dans la partie client, nous allons d'abord prendre le temps de vérifier que notre traitement côté serveur fonctionne convenablement.

Pour cela nous allons tout simplement invoquer notre page simpleRequest.php avec les bons paramètres dans l'url (annee_naissance et prenom).

Image non disponible
Adresse entrée dans la barre d'adresse du navigateur
Image non disponible
... le résultat

En Php, l'utilisation de la variable "superglobale" $_REQUEST permet d'utiliser indifférement la méthode GET ou la méthode POST lors de l'invocation du script.

III-B-2. Html

Une fois la partie serveur effectuée, on crée la partie client, à savoir le squelette de notre page html. Cela ne présente pas de difficulté particulière :

 
Sélectionnez
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8">
		<title>Yahoo! User Interface Library par l'exemple : utilisation du connection manager </title>
	</head>
	<body>
		<form name="formulaire">
			<fieldset>
				<legend>Exemple simple de r&eacute;cup&eacute;ration de donn&eacute;e par AJAX</legend>
				Ton pr&eacute;nom : <input type="text" name="prenom" value="" /><br />
				Ann&eacute;e de naissance : <input type="text" name="annee_naissance" value="" />
			</fieldset>		
			<br />
			<input type="button" value="GO !!" onclick="lanceLaRequete()" />
		</form>
		<br />
		<div id="conteneur" style="color:navy;border:1px solid black;width:250px;height:100px;"></div>
	</body>
</html>

Ce fichier sera placé dans un répertoire dédié du serveur web, il s'agit du même répertoire que le fichier php chargé de renvoyer de la réponse.

Attention, la plupart des navigateurs comme Firefox ou Internet Explorer ne permettent pas d'effectuer des requêtes XMLHttp sur d'autres domaines que la page qui est à l'origine de cette requête. Par exemple, ma page http://eric_pommereau.dvp.com/test.html ne peut invoquer la page http://rico.free.fr/test_ajax.php. On parle alors de restriction cross-domain. Pour les exemples, nous travaillons sur le domaine "localhost" donc pas de soucis.

Il faut ensuite installer la librairie YUI. En fait, il suffit de créer un répertoire et d'y déposer les fichiers téléchargés. Dans notre exemple, j'ai créé un répertoire yui_2.4 dans lequel j'ai placé fichiers et répertoires.

On incorpore alors les inclusions javascript qui font appel à la YUI :

 
Sélectionnez
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8">
		<title>Yahoo! User Interface Library par l'exemple : utilisation du connection manager </title>
		
		<script type="text/javascript" src="../../yui_2.4/build/yahoo/yahoo.js"></script>
		<script type="text/javascript" src="../../yui_2.4/build/event/event.js"></script>
		<script type="text/javascript" src="../../yui_2.4/build/connection/connection.js"></script>
		
	</head>
...

Quelques précisions sur les fichiers javascript de la YUI que nous avons inclus :

  • Le fichier yahoo.js est le coeur de la YUI, il est indispensable.
  • Le fichier event.js prend en charge la gestion des événements.
  • Le fichier connection.js est nécessaire pour la mise en oeuvre de la requête XMLHttp.

La difficulté ici est de trouver le bon chemin des sources de la YUI, c'est là qu'intervient l'extension firebug.

En effet, rien de plus simple avec cette extension que de vérifier la réussite de l'inclusion d'un fichier externe :

En cliquant sur le bouton All et sur l'onglet Net, Firebug affiche l'ensemble des ressources externes à la page html telles que css, javascripts, images...

Chaque fichier effectivement inclus est affiché en noir, alors que ceux qui n'ont pas été inclus sont siglés en rouge. Dans la copie d'écran suivante une erreur est signalée lors de l'inclusion du fichier connectio.js (qui n'existe pas).

Image non disponible

Revenons sur l'interface afin d'identifier clairement les éléments que l'on retrouve dans le code source :

Image non disponible

La partie 1 est le formulaire constitué d'un champ prenom et d'un champ annee_naissance.

La partie 2 est le bouton qui déclenche la requête XMLHttp sur l'évènement javascript onclick().

La partie 3 est l'élément Html <div> destiné à afficher le texte généré par le serveur en cas de réussite ou bien, en cas d'échec, un message d'erreur.
Par ailleurs, nous changerons l'apparence de ce conteneur en fonction de la réussite ou de l'échec de la requête XMLHttp.

III-B-3. Javascript

Une fois les inclusions de javascript faites et vérifiées, nous pouvons nous pencher sur la mise en oeuvre de notre requête XMLHttp avec la librairie YUI.

Pour cela, nous allons créer un bloc javascript à la fin de notre page qui va contenir les éléments suivants :

  1. Une variable pointant sur le conteneur chargé d'afficher le résultat,
  2. une fonction qui provoque le lancement de la requête XMLHttp,
  3. une fonction qui exécute du code javascript en cas de succès de la requête,
  4. une fonction qui exécute du code javascript en cas d'échec de la requête,

Cela donne le code suivant :

 
Sélectionnez
...
<div id="conteneur" style="color:navy;border:1px solid black;width:250px;height:100px;"></div>
<script type="text/javascript" >
	// Récupération du conteneur 
	var oConteneurDiv = document.getElementById('conteneur');

	// Lancement de la requête
	function lanceLaRequete() {
		var prenom = document.forms['formulaire'].elements['prenom'].value;
		var dtnais = document.forms['formulaire'].elements['annee_naissance'].value;
		var url = 'simpleRequest.php?' + 'prenom=' + prenom + '&annee_naissance=' +  dtnais;
		
		YAHOO.util.Connect.asyncRequest(
			'GET', 
			url, 
			{
				success:maRequeteFonctionne, 
				failure:maRequeteEchoue
			}
		);
		}
	
	// En cas de succès de la requête
	function maRequeteFonctionne (o) {
		// Remplir le div
		oConteneurDiv.innerHTML = o.responseText;
		oConteneurDiv.style.backgroundColor = '#ECF5FA';
		oConteneurDiv.style.border = '1px solid blue';
	}
	
	// En cas d'échec
	function maRequeteEchoue (o) {
		oConteneurDiv.innerHTML = 'Echec de la requête';
		oConteneurDiv.style.backgroundColor = '#FAECED';
		oConteneurDiv.style.border = '1px solid red';
	}
</script>

...

Nous avons ajouté notre script sous le conteneur pour pouvoir faire facilement référence à ce dernier (le conteneur).

Voyons en détail la cinématique de la requête XLMHttp :

D'abord, la fonction lanceLaRequete() est déclenchée par le clic sur le bouton.

Lancement de la requête : déclenché par clic du bouton
Sélectionnez
	// Lancement de la requête
function lanceLaRequete() {
	var prenom = document.forms['formulaire'].elements['prenom'].value;
	var dtnais = document.forms['formulaire'].elements['annee_naissance'].value;
	var url = 'simpleRequest.php?' + 'prenom=' + prenom + '&annee_naissance=' +  dtnais;
		
	YAHOO.util.Connect.asyncRequest(
		'GET', 
		url, 
		{
			success:maRequeteFonctionne, 
			failure:maRequeteEchoue
		}
	);
}

Puis, les deux valeurs des champs sont récupérées pour recomposer l'url qui sera invoquée par la requête.

Nous en arrivons, maintenant, au coeur de métier du module connection manager de la YUI, à savoir l'invocation de la requête XMLHttp. Pour laquelle on utilise une méthode statique de la librairie à savoir : YAHOO.util.Connect.asyncRequest(...)

Cet méthode prend 3 arguments :

  • La méthode utilisée (GET ou POST) de type chaîne de caractères
  • L'url invoquée par la requête de type chaîne de caractères
  • Les évènements que l'on souhaite prendre en charge de type tableau (Array()). A chaque évènement correspond une fonction définie plus bas.

En cas de succès, la fonction de callback maRequeteFonctionne() est exécutée :

Succès de la requête
Sélectionnez
// En cas de succès de la requête
function maRequeteFonctionne (o) {
	// Remplir le div
	oConteneurDiv.innerHTML = o.responseText;
	oConteneurDiv.style.backgroundColor = '#ECF5FA';
	oConteneurDiv.style.border = '1px solid blue';
}

On remarquera l'argument o qui est en fait l'instance de la requête. Grâce à cet objet on peut récupérer le texte renvoyé par le serveur en utilisant la propriété responseText.

Les deux dernières lignes de code permettent, en outre, de modifier l'apparence du conteneur.

Nous avons fait le choix de retourner une erreur 404 (page non trouvée) en cas d'erreur dans les paramètres (par exemple une année de naissance vide).

Une erreur 404 est considérée par la requête XMLHttp comme un échec (failure).

En cas d'échec, la fonction de callback maRequeteEchoue est exécutée :

Echec de la requête
Sélectionnez
// En cas d'échec
function maRequeteEchoue (o) {
	oConteneurDiv.innerHTML = 'Echec de la requête';
	oConteneurDiv.style.backgroundColor = '#FAECED';
	oConteneurDiv.style.border = '1px solid red';
}

Dans cette fonction, on se contente d'afficher un message d'erreur et de modifier l'apparence du conteneur.

Cette façon de gérer une erreur de traitement côté serveur n'est pas idéale. En effet, de cette manière, il est impossible de retourner un message informant de la source de l'erreur (date invalide ou absence de valeur...). Dans le cas d'une gestion d'erreur plus fine, on le ferait en javascript via la valeur de retour de la requête XMLHttp.

IV. Résultat

Maintenant que le plus gros du travail est fait, voyons ce que cela donne.

Si les deux paramètres ont été correctement entrés, le serveur retourne une chaîne de caractères après le traitement : mise en capitales du prénom et calcul de l'âge.

Image non disponible

Si l'on ne renseigne pas le champ "année de naissance", le serveur retourne une erreur.

Image non disponible

V. Résoudre des problèmes avec Firebug

La mise en oeuvre des techniques Ajax provoque bien souvent des erreurs dont il n'est pas évident d'identifier la source. Le fait que tout se passe côté client (en javascript) ne nous facilite pas la tâche : la remontée claire et explicite des erreurs n'est pas le fort des navigateurs.

Firebug permet là encore de nous faciliter cette tâche ingrate qu'est la résolution de ces problèmes.

V-A. Identifier les erreurs javascript

Dans Firebug, l'onglet console (il s'agit de l'écran par défaut) affiche les erreurs javascript éventuelles de votre script.

Pour l'exemple, j'ai volontairement mal nommé le conteneur en changeant son identifiant.

 
Sélectionnez
<!-- id changé en 'conteneu' au lieu de 'conteneur' -->
<div id="conteneu" style="color:navy;border:1px solid black;width:250px;height:100px;"></div>
	<script type="text/javascript" >
		// Récupération du conteneur (echec puisque l'élément n'est pas trouvé)
		var oConteneurDiv = document.getElementById('conteneur'); 
...

Ce qui donne dans Firebug :

Image non disponible

V-B. Inspecter le html

Avec Firebug vous pouvez également inspecter le Html de votre page de deux manières.

Soit en survolant l'élément de votre page comme ici :

Image non disponible

Ou bien en parcourant directement l'inspecteur Html de Firebug :

Image non disponible

Cette facilité à naviguer dans le code source fait gagner un temps considérable par rapport aux outils disponibles jusqu'ici (simple visualisation du code source au format texte). Visualiser aussi confortablement vos éléments vous permettra de savoir si un élément est mal nommé ou si une balise n'est pas à sa place.

V-C. Visualiser les requêtes XMLHttp

Firebug permet aussi de visualiser en temps réel les requêtes XMlHttp.

Pour ce faire il faut sélectionner l'onglet Net puis le bouton XHR comme cela est indiqué dans la capture d'écran suivante :

Image non disponible

Ensuite, il ne reste plus qu'à tester notre petit exemple, et l'on voit apparaître comme par magie les requêtes XMLHttp comportant le nom du script invoqué ainsi que le domaine concerné :

Image non disponible

L'exploration de la requête va beaucoup plus loin, en effet, si l'on déplie la zone en cliquant sur le +, on découvre plusieurs onglets dont voici quelques copies d'écran qui parlent d'elles-mêmes :

Image non disponible
Onglet params
Image non disponible
Les en-têtes Http : la requête du navigateur et la réponse du serveur web
Image non disponible
La réponse du serveur web

Lorsque le serveur retourne une erreur, Firebug affiche le nom et le domaine du script invoqué en rouge avec le motif de l'erreur retournée (404, 403 ...).

Image non disponible

Avec ces quelques éléments vous voilà paré pour affronter quelques problèmes courants.

VI. Conclusion

Ainsi s'achève "Ajax avec la Yahoo User Interface library : les requêtes XMLHttp". Ce tutoriel devrait être un prélude à d'autres publications sur le riche framework Yahoo User Interface library.

J'espère que vous avez eu plaisir à me lire et que cet article vous a aidé à progresser dans le monde étrange et merveilleux d'Ajax.

Vous pouvez télécharger les deux fichiers utilisés dans notre exemple ici.

Quelques liens developpez.com :

Quelques liens externes :