Glossaire et XMLHttpRequest, second round

Nouvelle bidouille javascript : j'ai enfin trouvé le moyen d'afficher les définitions tirées du glossaire de manière satisfaisante (ou presque) avec l'objet XMLHttpRequest.

Résumé des épisodes précédents :

  1. La première version des liens définition ouvrait une fenêtre popup dés plus classique avec la page du glossaire n'affichant que la définition demandée.
  2. La deuxième version faisait appel à un objet XMLHttpRequest pour effectuer une requête HTTP afin de récupérer les données de la page glossaire (la définition) ; la réponse était ensuite insérée dans le document courant.

Problème : cette réponse était récupérée avec la propriété responseText. L'objet DOM retourné était donc considéré comme une simple chaîne de caractères ; c'était suffisant pour les définitions sans aucune balise HTML mais pas pour celles qui contiennent un lien ou tout autre balise. La propriété responseXML permettait, elle, de récupérer des données xml, tenant compte donc des éventuels noeuds qu'elles contiennent, mais sa mise en pratique s'était heurtée à des difficultés que je n'avais pas réussi à identifier.

Après quelques heures d'errance sur la toile, j'ai finalement trouver les raisons de cet échec : la page glossaire n'est pas un fichier xml mais un document xhtml généré en PHP (oui, je sais, c'est une découverte extraordinaire !). Pour que la propriété responseXML fonctionne, il fallait donc :

  • Lui fournir un document xml correctement formé et avec le bon en-tête HTTP, c'est-à-dire Content-Type: text/xml ou Content-Type: application/xml, et non Content-Type: text/html par défaut.
  • Définir un espace de nommage (xmlns) qui permette ensuite d'insérer les données xml dans un document xhtml.

Une fois le code PHP modifié pour répondre à ces contraintes, la page glossaire devenait un fichier xml de la forme :

<?xml version="1.0" encoding="UTF-8"?>
<p xmlns="http://www.w3.org/1999/xhtml">
  Définition avec des <em>balises</em>.
</p>
1. Code retourné par la page glossaire.php?def=definition

La propriété responseXML récupère ainsi les données sous forme de fragment dom que l'on peut manipuler et insérer dans le document web comme n'importe quel autre objet.

var defId = 'definition';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4) {
    if (xmlhttp.status == 200) {
      // Récupération des données
      var def = xmlhttp.responseXML;
      // Récupération du noeud portant la définition
      var Popup = def.getElementsByTagName("p")[0];
      // insérer le popup dans la page web
      document.body.appendChild(Popup);
    }
  }
}
xmlhttp.open("GET", "/glossaire.php?def="+defId,true); 
xmlhttp.send(null);
2. Version simplifiée de la requête XMLHttpRequest en utilisant la propriété responseXML.

Cette nouvelle version a été testée avec succès sur les navigateurs web Firefox 1.5.0.2 et Opera 8.51. Par contre, impossible de faire fonctionner le script sous Internet Explorer ! J'ai donc mis en place une petite astuce javascript qui se contente de recopier le texte de la définition comme s'il s'agissait d'une chaîne de caractère simple.

Une alternative au système serait d'utiliser une fonction PHP pour (1) repérer tous les liens définition d'une page, (2) aller chercher les définitions dans le glossaire et (3) les placer dans la page. Plus besoin de XMLHttpRequest pour récupérer les données et les définitions nécessaires se retrouveraient directement dans la page web, utile lors de l'impression par exemple.

Encore une piste à explorer.

Ressources :

BRAY, T. ; HOLLANDER, D. ; LAYMAN, A.. Namespaces in XML. W3C, . Tout savoir sur les espaces de nommage pour les fichiers xml.

COLLECTIF. AJAX : Premiers pas. Mozilla Developper Center, . Tutoriel fort pratique pour comprendre comment utiliser l'objet XMLHttpRequest.

HONNEN, M.. Re: Copy responseXML DOM fragment to the document. Thescript.com, javascript forum, . Réponse de Martin Honnen au problème d'un internaute sensiblement identique au mien.

SVAY, M.. L'objet XMLHttpRequest. OpenWeb, . Comment utiliser l'objet xmlhttprequest.