11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour à toutes et à tous,

Context: je suis en train de développer une sorte de groupware pour mon équipe de travail chez Alcatel-Lucent, et j'ai la volonté d'utiliser AJAX pour la convivialité que cette technique apportera à mon outils web.

Toute mon appli est codée en objet PHP, et retourne un flux xml bien construit. Depuis ma page, lorsque je clique sur un bouton, j'appelle mon script PHP qui instantie un objet PHP, puis fait un header("Content-Type: text/xml"); puis un simple echo de mon flux XML. Du côté client, dans mon javascript, je voudrais récupérer le flux de retour sous forme d'objet DOM puisque c'est du XML que je retourne.

Problème: sous FF, j'ai bien un objet, et j'arrive à le parser sans aucun souci. Sous IE, en revanche, j'ai null qui est retourné Smiley decu Du coup... je ne peux rien parser. ça plante et rien ne s'affiche ! Smiley decu


J'ai cru voir sur developpez.net qu'il faut nettoyer son XML car les espaces et les retours chariot dans le flux XML sont traité comme des noeuds par l'un et pas par l'autre. Du coup, j'ai tenté d'utiliser le script qu'ils fournissaient et ça marche bien sous FF.... mais j'ai toujours null sous IE.

Est-ce que quelqu'un aurait de bons tuyaux ?


merci beaucoup par avance Smiley cligne
Modifié par Tanhys Kellhio (30 Mar 2007 - 17:13)
Bonjour Tanhys Kellhio,

Pourrais-tu nous donner la portion de code qui crée ton objet XMLHttpRequest ainsi que sa fonction callback.

Une des erreurs communes est de loader une page et d'envoyer les paramètres post avant de spécifier la fonction de callback, comme ceci :


xhr = getXHR(); // une fonction facade de création d'objets XMLHttpRequest
xhr.open('POST', 'mapage.ext', true);
xhr.send('params');
xhr.onreadystatechange = func_callback; // mauvaise position, doit être déclarée avant la méthode send.


Peut-être qu'on pourra t'aider avec un peu plus d'indications sur ton code.

@plouche.
Oui, bien entendu !! Smiley ravi

Alors, j'ai simplifié tout ça, parce que si j'vous donnais le code au stade où j'en suis actuellement, vous ne comprendriez rien.

structure: index.html qui contient ceci:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>New document</title>
<script src="ajax.js" language="Javascript"></script>
</head>
<body>
<input type="text" id="text_to_send" value="Nicolas">
<input type="button" value="get server content" onclick="javascript:test();">
<div id="content">
</div>
</body>
</html>


donc qui contient le fichier ajax.js qui contient ceci:
var pickRecentProgID = function (idList){
	// found progID flag
    var bFound = false;
    for(var i=0; i < idList.length && !bFound; i++){
        try{
            var oDoc = new ActiveXObject(idList[i]);
            o2Store = idList[i];
            bFound = true;
        }catch (objException){
            // trap; try next progID
        };
    };
    if (!bFound)
		throw ("Aucun ActiveXObject n'est valide sur votre ordinateur, pensez à mettre à jour votre navigateur");
    idList = null;
    return o2Store;
}

// Retourne un nouvel objet XmlHttpRequest
var GetXmlHttpRequest_AXO=null
var GetXmlHttpRequest=function () {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest()
	}
	else if (window.ActiveXObject)
    {

		if (!GetXmlHttpRequest_AXO) {
			GetXmlHttpRequest_AXO=pickRecentProgID(["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
		}
		return new ActiveXObject(GetXmlHttpRequest_AXO)
	}
	return false;
}


getXhr=GetXmlHttpRequest;
/**
 *
 * @access public
 * @return void
 **/
function test()
{

    var requete = getXhr();
    requete.open('post','server.php',true);
    data = '';
    data += "data="+document.getElementById("text_to_send").value;



    requete.onreadystatechange = function()
    {
    	if(requete.readyState == 4)
    	{
    	   if(navigator.appName == "Microsoft Internet Explorer")
    	   {

                var xmlDocument = new ActiveXObject("Microsoft.XMLDOM");

                xmlDocument.loadXML(requete.responseText);



        	}
        	else
        	{

        	   var xmlDocument = requete.responseXML;
        	}

        	var x=xmlDocument.documentElement.childNodes;
            alert(x.length)

            for (i=0;i<x.length;i++)
            {
                node = x[i];
                alert(node.childNodes[1].textContent);
            }
    	}
    }
    requete.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    

    requete.send(data);

}


et enfin, le fichier server.php qui génère un flux xml:
<?php
header("Content-Type: text/xml");

echo "<response>";
echo "<context>";
echo "<locked>true</locked>";
echo "<update>false</update>";
echo "</context>";
echo "<site>";
echo "<update>true</update>";
echo "<content><![CDATA[";
echo "Vous <b>avez</b> <i>envoyé</i> ".$_POST["data"];
echo "]]></content>";
echo "</site>";
echo "</response>";
?>



Bon, comme dit plus haut, sous Firefox, j'arrive bien à récupérer mon objet XML et à la parser normalement. Mais pas sous IE, il est là le souchi ![/i][/i][/i]
Il y a un petit souci dans ta fonction de création d'objet activex à cette ligne :

var oDoc = new ActiveXObject(idList);

Ce ne serait pas plutot :

var oDoc = new ActiveXObject(idList[ i ]);

Ensuite, je ne sais pas exactement pourquoi tu crées un activex xml pour loader le responseText puisqu'IE interprete déjà le responseXML comme un objet activex. La vérification de l'agent est donc inutile.

il te suffit simplement de mettre :

var xmlDocument = requete.responseXML;

Je pense que ça pourra t'avancer un peu

@plouche
Modifié par Ze Nenex (16 Mar 2007 - 18:50)
Ah oui j'oubliais,

l'objet documentElement est problématique sous IE, je te conseille d'utiliser les fonctions du DOM directement sur ton objet responseXML


responseXML.getElementsByTagName('response').item(...


@plouche
Pour finir avec ça et si tu veux vraiment utiliser un loader XML depuis le responseText, la synchro de ton activex xml doit être false (oblige l'xml a être totalement chargé avant de continuer) :


var xmlDocument = new ActiveXObject("Microsoft.XMLDOM");
xmlDocument.async="false";
xmlDocument.loadXML(requete.responseText);
alert(xmlDocument.getElementsByTagName('content')[0].firstChild.nodeValue);


Tiens nous au courrant,
@plouche.
Modifié par Ze Nenex (16 Mar 2007 - 19:13)
Bon, alors ça y est, j'ai réussi à faire ce que je voulais. Smiley biggrin

Déjà, finalement et heureusement, j'ai bien pu récupérer mon objet DOM grâce à l'objet marequete.responseXML, dans IE et dans FF. Le truc qui, visiblement, coinçait, c'est la manière de récupérer le content d'une balise xml. Je me suis aperçu que sous IE, il fallait mettre XMLDoc.documentElement.childNodes[0].childNodes[0].text alors que sous FF, il fallait mettre XMLDoc.documentElement.childNodes[0].childNodes[0].textContent.

En ce qui concerne le "fameux" nettoyage de ma réponse XML à cause des retours chariots etc. Je n'ai pas eu ce problème car ma réponse XML est formée dynamiquement par mes objets PHP côté serveur.


Donc, pour ceux qui, comme moi, se demandent comment on récupère en Javascript les différents éléments d'une réponse XML générée depuis le serveur, voici un exemple de ce que je suis parvenu à accomplir:

voici ma réponse XML renvoyée par mon serveur:
<?xml version="1.0"?><response><context><locked>false</locked><update>true</update>
</context><site><update>true</update><content><![CDATA[ <table width="800px" border="1"><tr><td class="news_tlc"></td><td class="news_t"></td><td class="news_trc"></td></tr><tr><td class="news_l"></td><td><table width="100%" border ="1"><tr><td><h3>News publique</h3><div class="comment">Published on 2007-02-20 13:23:02 by 1</div><br><div class="text">News publique créée par Nicolas</div></td><td class="news_edition_options"><a href="#" onclick="javascript:updateSite('edit', 'comp_news', 1, 'editNews', 'DB_IDENTIFIER=>1', 'comp_news_1_view');" title="Edit">E</a><br /></td></tr></table></td><td class="news_r"></td></tr><tr><td class="news_blc"></td><td class="news_b"></td><td class="news_brc"></td></tr></table>]]></content></site></response>





et le code javascript qui arrive à parser et à faire ce qu'il faut avec cette réponse XML:
function handleHTTPResponse(XMLMessage, tbu_object)
{
	var contextNode = XMLMessage.documentElement.childNodes[0];
	var siteNode = XMLMessage.documentElement.childNodes[1];
	
	if(navigator.appName == "Microsoft Internet Explorer")
	{
		var doLockContext = contextNode.childNodes[0].text;
		var doUpdateContext = contextNode.childNodes[1].text;

		var doUpdateSite = siteNode.childNodes[0].text;
		var siteUpdateContent = siteNode.childNodes[1].text;
	}
	else
	{
		var doLockContext = contextNode.childNodes[0].textContent;
		var doUpdateContext = contextNode.childNodes[1].textContent;

		var doUpdateSite = siteNode.childNodes[0].textContent;
		var siteUpdateContent = siteNode.childNodes[1].textContent;
	}
	getObj("context_locked").value = doLockContext;

	if(doUpdateSite = "true")
	{
		getObj(tbu_object).innerHTML = siteUpdateContent
	}
	else
	{
	}
}
tbu_object est l'identifiant HTML de l'objet dont le contenu doit être mis à jour, et la méthode getObj() n'est rien d'autre qu'un raccourci vers le code javascript document.getElementById Smiley ravi


Voilà, j'espère que tout ceci aidera quelqu'un d'autre que moi s'il ou elle tombe dessus.

En tout cas, je te remercie Ze Nenex Smiley cligne