Une fonction ajax simple, compatible et prête à l’emploi

L’ajax (Asynchronous Javascript And Xml), c’est bien ! Cette technologie permet d’alléger le trafic web et d’accroître l’ergonomie et l’expérience utilisateur.

Pourtant, le concept de transfert asynchrone n’est pas simple à aborder et les tutoriels sur le sujet sont parfois très longs.

Voici une fonction ajax prête à l’emploi, simple à utiliser, compatible avec tous les navigateurs et indépendante (aucune librairie javascript n’est requise).

Un peu d’histoire

Cette fonction a été initialement créée par Sutekidane en 2005 : l’article et la fonction brute d’époque.

Les fonctions (en réalité il y en a deux : XHRConnection et chargeFichier) ont été modifiées principalement pour permettre l’appel d’une fonction après le chargement de l’ajax (un callback), si ce dernier a réussi.

D’autres bugs mineurs ont été corrigés (comme l’erreur lors d’une requête de type POST).

Fonctions et documentation

Voici les deux fonctions, à placer dans un fichier JS ou dans une balise <script> [téléchargement direct] :

function XHRConnection()
{
	// + ----------------------------------------------------------------------------------
	var conn = false;
	var debug = true;
	var datas = new String();
	var areaId = new String();
	// Objet XML
	var xmlObj;
	// Type de comportement au chargement du XML
	var xmlLoad;

	// + ----------------------------------------------------------------------------------
	try {
		conn = new XMLHttpRequest();		
	}
	catch (error) {
		if (debug) { alert('Erreur lors de la tentative de création de l\'objet \nnew XMLHttpRequest()\n\n' + error); }
		try {
			conn = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (error) {
			if (debug) { alert('Erreur lors de la tentative de création de l\'objet \nnew ActiveXObject("Microsoft.XMLHTTP")\n\n' + error); }
			try {
				conn = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch (error) {
				if (debug) { alert('Erreur lors de la tentative de création de l\'objet \nnew ActiveXObject("Msxml2.XMLHTTP")\n\n' + error); }
				conn = false;
			}
		}
	}

	// + ----------------------------------------------------------------------------------
	// + setDebugOff
	// + Désactive l'affichage des exceptions
	// + ----------------------------------------------------------------------------------
	this.setDebugOff = function() {
		debug = false;
	};

	// + ----------------------------------------------------------------------------------
	// + setDebugOn
	// + Active l'affichage des exceptions
	// + ----------------------------------------------------------------------------------
	this.setDebugOn = function() {
		debug = true;
	};

	// + ----------------------------------------------------------------------------------
	// + resetData
	// + Permet de vider la pile des données
	// + ----------------------------------------------------------------------------------
	this.resetData = function() {
		datas = new String();
		datas = '';
	};

	// + ----------------------------------------------------------------------------------
	// + appendData
	// + Permet d'empiler des données afin de les envoyer
	// + ----------------------------------------------------------------------------------
	this.appendData = function(pfield, pvalue) {
		datas += (datas.length == 0) ? pfield+ "=" + escape(pvalue) : "&" + pfield + "=" + escape(pvalue);
	};

	// + ----------------------------------------------------------------------------------
	// + setRefreshArea
	// + Indique quel elment identifié par id est valoris lorsque l'objet XHR reoit une réponse
	// + ----------------------------------------------------------------------------------
	this.setRefreshArea = function(id) {
		areaId = id;
	};

	// + ----------------------------------------------------------------------------------
	// + createXMLObject
	// + Méthode permettant de créer un objet DOM, retourne la réfrence
	// + Inspiré de: http://www.quirksmode.org/dom/importxml.html
	// + ----------------------------------------------------------------------------------
	this.createXMLObject = function() {
		try {
			 	xmlDoc = document.implementation.createDocument("", "", null);
				xmlLoad = 'onload';
		}
		catch (error) {
			try {
				xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
				xmlLoad = 'onreadystatechange ';
			}
			catch (error) {
				if (debug) { alert('Erreur lors de la tentative de création de l\'objet XML\n\n'); }
				return false;
			}
		}
		return xmlDoc;
	}

	// + ----------------------------------------------------------------------------------
	// + Permet de définir l'objet XML qui doit être valorisé lorsque l'objet XHR reoit une réponse
	// + ----------------------------------------------------------------------------------
	this.setXMLObject = function(obj) {
		if (obj == undefined) {
				if (debug) { alert('Paramètre manquant lors de l\'appel de la méthode setXMLObject'); }
				return false;
		}
		try {
			//xmlObj = this.createXMLObject();
			xmlObj = obj;
		}
		catch (error) {
				if (debug) { alert('Erreur lors de l\'affectation de l\'objet XML dans la méthode setXMLObject'); }
		}
	}

	// + ----------------------------------------------------------------------------------
	// + loadXML
	// + Charge un fichier XML
	// + Entrées
	// + 	xml			String		Le fichier XML à charger
	// + ----------------------------------------------------------------------------------
	this.loadXML = function(xml, callBack) {
		if (!conn) return false;
		// Chargement pour alimenter un objet DOM
		if (xmlObj && xml) {
			if (typeof callBack == "function") {
				if (xmlLoad == 'onload') {
					xmlObj.onload = function() {
						callBack(xmlObj);
					}
				}
				else {
					xmlObj.onreadystatechange = function() {
						if (xmlObj.readyState == 4) callBack(xmlObj)
					}
				}
			}
			xmlObj.load(xml);
			return;
		}		
	}

	// + ----------------------------------------------------------------------------------
	// + sendAndLoad
	// + Connexion à la page désirée avec envoie des données, puis mise en attente de la réponse
	// + Entrées
	// + 	Url			String		L'url de la page à laquelle l'objet doit se connecter
	// + 	httpMode		String		La méthode de communication HTTP : GET, HEAD ou POST
	// + 	callBack		Objet		Le nom de la fonction de callback
	// + ----------------------------------------------------------------------------------
	this.sendAndLoad = function(Url, httpMode, callBack) {
		httpMode = httpMode.toUpperCase();
		conn.onreadystatechange = function() {
			if (conn.readyState == 4 && conn.status == 200) {
				// Si une fonction de callBack a été définie
				// Si une zone destinée à récupérer le résultat a été définie
				if (areaId.length > 0){
					try {
						document.getElementById(areaId).innerHTML = conn.responseText;
					}
					catch(error) {
						if (debug) { alert('Echec, ' + areaId + ' n\'est pas un objet valide'); }
						return false;
					}
					if (typeof callBack == "function") {
						callBack();
					}
					return;
				}
			}
		};
		switch(httpMode) {
			case "GET":
				try {
					Url = (datas.length > 0) ? Url + "?" + datas : Url;
					conn.open("GET", Url);
					conn.send(null);
				}
				catch(error) {
					if (debug) { alert('Echec lors de la transaction avec ' + Url + ' via la méthode GET'); }
					return false;
				}
			break;
			case "POST":
				try {
					tab_url = Url.split('?');
					nom_fichier = tab_url[0];
					datas = tab_url[1];
					conn.open("POST", nom_fichier);
					conn.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					conn.send(datas);
				}
				catch(error) {
					if (debug) { alert('Echec lors de la transaction avec ' + Url + ' via la mthode POST'); }
					return false;
				}
			break;
			default :
				return false;
			break;
		}
		return true;
	};
	return this;
}

function chargeFichier(fichier, zone, methode, callback)
{
	if (methode == undefined) { methode = "GET"; }
	if (callback == undefined) { callback = "void()"; }
	callback = new Function("callback", callback + ";");

	var XHR = new XHRConnection();

	XHR.setRefreshArea(zone);

	XHR.sendAndLoad(fichier + "&time=" + new Date().getTime(), methode, callback );
	return true;
}

La fonction XHRConnection permet de créer l’objet XML en fonction du navigateur. De votre côté vous utiliserez chargeFichier ainsi :

chargeFichier(fichier, zone, methode, callback);

Voici comment utiliser les paramètres :

  • Fichier : fichier à charger et ses paramètres, par exemple : page2.php?id=3&login=xxx
  • Zone : Identifiant (attribut id) de l’élément HTML à utiliser : un div, un td, un span…
  • Méthode : GET ou POST au choix. La méthode GET sera soumise aux problèmes d’encodage des caractères dans les url.
  • Callback : Une fonction JS à appeler à la fin du chargement ajax, si ce dernier à réussi, ce paramètre peut être vide.

Warning_iconDans le cas d’une requête POST (recommandé), les paramètres doivent être renseignés comme pour une requête GET, sous la forme page.php?parametre=1&utilisateur=2.

Quelques exemples

Requête POST sur page2.php, appel de la fonction postajax() après chargement :

chargeFichier("page.php?parametre=valeur", "div_ajax", "POST", "postajax()");

Requête GET sur page2.php, sans fonction de callback :

chargeFichier("page2.php?parametre=valeur", "span_ajax", "GET", "");

N’hésitez pas à me donner vos retours quant à l’utilisation de la fonction.

Réalisé et rédigé avec Julien TAUBENHAUS dans le cadre de son projet SUPINFO.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Êtes-vous humain ? *