Un formulaire intelligent avec AJAX

formulaire

Cet article a pour but de vous présenter comment créer un formulaire intelligent en utilisant la technologie AJAX.
Le formulaire est mis à jour en temps réel en fonction d’un fichier de configuration et les entrées de l’utilisateur.

Prérequis AJAX

Ce tutoriel fait appel à des connaissances en php et javascript.
Pour le fonctionnement d’AJAX, je vous renvoie vers cet excellent site: http://ajax.developpez.com/cours/.
Pour mémoire, AJAX permet à un site de récupérer des données sur un serveur de façon asynchrone et de les traiter ensuite grâce à du code javascript.
Cela donne un effet temps réel, il n’y a pas besoin de recharger la page pour voir les effets sur la page affichée.

Plantons le décor, une entreprise d’entretien de gazon vous propose différentes formules avec des prestations différentes.
Selon la prestation choisie et selon la superficie de votre terrain, le formulaire déterminera la facture en temps réel.

Le script est articulé autour de 6 fichiers:

  • commandes.xml : notre fichier de configuration, il contient l’ensemble des prestations, les tarifs…
  • script.js : le script javascript qui interagit avec le serveur, il affiche dynamiquement les résultats, les packs disponibles et participe à la validation du formulaire
  • calcul.php : le script php chargé d’analyser le fichier de configuration et de transmettre les données au fichier javascript
  • index.php : notre page d’affichage principal
  • style.css : la feuille de style pour gerer la mise en page
  • traitement.php : le script php qui permet l’envoi du fomulaire une fois rempli par mail

Nous n’étudierons pas la feuille de style et traitement.php.

Le fichier de configuration

On définit dans un fichier xml (comme l’illustre le modèle ci-dessous) des tranches de surface ainsi que les différents packs de prestations.

<?xml version="1.0" encoding="ISO-8859-1"?>
<commandes>
	<tranche id="1">
		<surface_inf>10</surface_inf>
		<surface_sup>100</surface_sup>
	</tranche>

	<tranche id="2">
		<surface_inf>101</surface_inf>
		<surface_sup>200</surface_sup>
	</tranche>

	<pack titre="Pack n°1">
		<intitule>Entretien courant</intitule>
		<nb_fi>0</nb_fi>
		<pc_fi>0</pc_fi>
		<tarif tranche="1">0.41</tarif>
		<tarif tranche="2">0.37</tarif>
		<tarif tranche="3">0.35</tarif>
		<tarif tranche="4">0.33</tarif>
	</pack>

	<pack titre="Pack n°2">
		<intitule>Entretien medium</intitule>
		<nb_fi>0</nb_fi>
		<pc_fi>0</pc_fi>
		<tarif tranche="1">0.99</tarif>
		<tarif tranche="2">0.9</tarif>
		<tarif tranche="3">0.78</tarif>
		<tarif tranche="4">0.71</tarif>
	</pack>

</commandes>

Le code HTML

Dans le fichier index.php, on déclare le formulaire et le champ d’entrée de la surface.

<form id="form_com" action="./traitement.php" method="post" name="form_com">
...
<label for="surface">Surface au sol de votre terrain (en m²) :</label>
<input id="surface" type="text" name="surface" maxlength="5" />

On affiche le choix des prestations et les caractéristiques, ici dans un tableau.

<table id="table_commande" border="1">
<tr>
	<th class="com_1">Choix du pack/kit</th>
	<th class="com_2">Intitulé</th>
	<th class="com_3">Quantité</th>
</tr>

<tr>
	<td id="select_pack"><select name="pack" id="pack"><option value="-1">Aucun</option></select></td>
	<td><label id="intitule"></label></td>
	<td><label id="quantite">1</label></td>
</tr>

<tr>
	<th class="com_4">Tarif ht/m²</th>
	<th class="com_5">Tarif ht</th>
	<th class="com_6">Montant T.V.A (19.6%)</th>
	<th class="com_7">Tarif TTC</th>
</tr>

<tr>
	<td><label id="tarif_ht_m"></label></td>
	<td><label id="tarif_ht"></label></td>
	<td><label id="tva"></label></td>
	<td><label id="tarif_ttc"></label></td>
	</tr>
</table>

Ici on affiche les montants calculés.

<div id="calculs">
  <p>
       <label>Nombre de factures intermediaires : </label>
       <span id="nb_factInt">0</span></p>
  <p>
       <label>Proportion de chaque facture intermediaire : </label>
       <span id="pc_factInt">0</span> % du tarif TTC</p>
  <p class="montant">
       <label>Montant de chaque facture intermediaire : </label>
       <span id="mt_factInt">0</span> &euro;</p>
  <p class="total">
       <label>Montant TTC du solde restant dû : </label>
       <span id="mt_restant">0</span> &euro;</p>
</div>

Des champs cachés contiennent les valeurs qui seront envoyées par mail.

<input type="hidden" id="intitule_hid"   name="intitule_hid"   value="" />
<input type="hidden" id="tarif_ht_m_hid" name="tarif_ht_m_hid" value="" />
<input type="hidden" id="tarif_ht_hid"   name="tarif_ht_hid"   value="" />
<input type="hidden" id="tva_hid"        name="tva_hid"        value="" />
<input type="hidden" id="tarif_ttc_hid"  name="tarif_ttc_hid"  value="" />
<input type="hidden" id="nb_factInt_hid" name="nb_factInt_hid" value="" />
<input type="hidden" id="pc_factInt_hid" name="pc_factInt_hid" value="" />
<input type="hidden" id="mt_factInt_hid" name="mt_factInt_hid" value="" />
<input type="hidden" id="mt_restant_hid" name="mt_restant_hid" value="" />

Le fichier calcul.php et le passage de paramètres

Ce fichier recevra certains paramètres du fichier javascript que nous verrons plus loin et lui retournera une chaine de caractère correspondant à sa requête.

Le fichier xml est chargé à l’aide de la classe SimpleXML dans $fichierXml. Cet objet sera utilisé ensuite pour extraire les données qui nous intéressent.

//**********   chargement du fichier xml
$fichierXml = file_get_contents('commandes.xml');
$objetSimpleXML=simplexml_load_string($fichierXml);

calcul.php reçoit les paramètres du fichier javascript par méthode post.

$load = $_POST['load'];

Passage de paramètres, contenu de la liste déroulante.

//**********   remplissage liste deroulante packs disponibles
if($load=='load_packs')
{
	echo '<select name="pack" id="pack">';
	echo '<option value="-1">Aucun</option>';

	foreach($objetSimpleXML->pack as $b)
	{
			echo '<option value="'.$b['titre'].'">';
			echo $b['titre'];
			echo "</option>";
	}
		foreach($objetSimpleXML->kit as $b)
	{
			echo '<option value="'.$b['titre'].'">';
			echo $b['titre'];
			echo "</option>";
	}
	echo '</select>';
	return;
}

Passage des paramètres en fonction du pack choisi et de la surface.

//************    preparation et calculs remplissage formulaire
if($load=='pack')
{
	if(!(isset($_POST['pack'])&&isset($_POST['surface'])))
	{
		return null;
	}

	$pack_id = $_POST['pack'];
	$surface = $_POST['surface'];

	$intitule = "";
	$nb_fi = "";
	$pc_fi = "";
	$tarif = "";
	$tranche = "";

	// determination de la tranche
	foreach($objetSimpleXML->tranche as $a)
	{
		$surface_inf = $a->surface_inf;
		$surface_sup = $a->surface_sup;
		if($surface>=$surface_inf)
		{
			if($surface<=$surface_sup)
			{
				$tranche = $a['id'];

			}
		}
	}

	//  determination du pack
	$increment = 1;
	foreach($objetSimpleXML->pack as $b)
	{
		if($increment == $pack_id)
		{
			$intitule = $b->intitule;
			$nb_fi = $b->nb_fi;
			$pc_fi = $b->pc_fi;
			foreach($b->tarif as $c)
			{
				$item = intval($c['tranche']);

				if($tranche == $item)
				{
					$tarif = $c;
				}
			}
		}
		$increment++;
	}

	echo $intitule.":".$nb_fi.":".$pc_fi.":".$tarif;
	return;
}

Le code javascript

Le fichier script.js coordonne l’ensemble des calculs et du formulaire.

Fonctions lancées au chargement de la page.

window.onload=function()
{
	// declaration des évènements
	load_pack();
	document.getElementById("cgv_accept").onclick = valid_Form;
	document.getElementById("surface").onchange = verif_surface;
	document.getElementById("pack").onchange = choix_pack;
	document.getElementById("form_com").onsubmit = formValid;
}

Envoi d’une requête synchrone à calcul.php afin de récupérer la liste des packs disponibles avant toute interaction possible de l’utilisateur.

function load_pack() {
//config et envoi d'une requete synchrone moteur ajax
	objetXHR = creationXHR();
	if(objetXHR==null)
	{
		alert('Votre navigateur ne prends pas en charge les objets ajax.\nVous ne pourrez pas utiliser ce formulaire.');
		return;
	}
	objetXHR.open("post","calcul.php",false);
	objetXHR.setRequestHeader("content-type","application/x-www-form-urlencoded");
	objetXHR.send("load=load_packs");
//retour serveur
	var liste_pack = objetXHR.responseText;
	document.getElementById("select_pack").innerHTML = liste_pack;
}

Si on change de pack, on vérifie la surface, qu’il y en ait une et qu’elle soit cohérente.
Si on change de surface, on vérifie cette nouvelle surface.
Si la surface est cohérente on lance la fonction de calcul.

function choix_pack() {
	verif_surface();
}

function verif_surface() {
	surface = Math.round(document.getElementById("surface").value);
	document.getElementById("surface").value = surface;
	if(!(surface>10&&surface<10000))
	{
		alert('La surface au sol de votre structure doit être comprise entre 10 et 10000 m²');
		document.getElementById("surface").value = 0;
		document.getElementById("pack").selectedIndex = 0;
	}
	if (document.getElementById("pack").selectedIndex != 0)
		calcul();
}

La fonction de calcul appelle, via le moteur ajax, le fichier calcul.php et lui transmet le nom du pack ainsi que la surface.
La fonction retour_calcul sera appelée au changement d’état du moteur ajax.

function calcul() {
//config et envoi d'une requete synchrone moteur ajax
	objetXHR = creationXHR();
	if(objetXHR==null)
	{
		alert('Votre navigateur ne prends pas en charge les objets ajax.\nVous ne pourrez pas utiliser ce formulaire.');
		return;
	}
	objetXHR.open("post","calcul.php",true);
	objetXHR.onreadystatechange = retour_calcul;
	objetXHR.setRequestHeader("content-type","application/x-www-form-urlencoded");
	var parametres = "load=pack&pack="+document.getElementById("pack").selectedIndex+"&surface="+document.getElementById("surface").value;
	objetXHR.send(parametres);
}

La fonction retour_calcul est appelée au changement d’état du moteur ajax et valide les résultats lorsque la réponse AJAX est complète.
On récupère l’intitulé du pack, le nombre de factures intermédiaires, le pourcentage de ces factures et le tarif au m².
On affiche alors les valeurs et les différents calculs dans le fichier index.php.

function retour_calcul() {
	if (objetXHR.readyState == 4)
	{
		if (objetXHR.status == 200)
		{
			// recuperation des données du moteur ajax
			var $resultat = objetXHR.responseText.split(":");
			$intitule = decodeURI($resultat[0]);
			$nb_fi = parseFloat($resultat[1]);
			$pc_fi = parseFloat($resultat[2]);
			$tarif = parseFloat($resultat[3]);

			$surface = document.getElementById("surface").value;			

// affectation des elements sans calculs dans la page, éléments affichés et éléments cachés
document.getElementById("intitule").innerHTML = $intitule;	            document.getElementById("intitule_hid").value = $intitule;	

document.getElementById("nb_factInt").innerHTML = $nb_fi;	document.getElementById("nb_factInt_hid").value = $nb_fi;

document.getElementById("pc_factInt").innerHTML = $pc_fi;	document.getElementById("pc_factInt_hid").value = $pc_fi;	

document.getElementById("tarif_ht_m").innerHTML = $tarif;	document.getElementById("tarif_ht_m_hid").value = $tarif;			

			// on determine le type de pack
			pack = document.getElementById("pack").value;
			pack_chaine = pack.indexOf('Kit');

			$tarif_ht = $surface*$tarif;

			$tarif_ttc = $tarif_ht*19.6/100+$tarif_ht;

			$mt_factInt = $tarif_ttc*$pc_fi/100;
			$tva = $tarif_ht*19.6/100;
			$mt_restant = $tarif_ttc-$nb_fi*$mt_factInt;

			// arrondissement des elements à 2 decimales
			$tarif_ht = Math.round($tarif_ht*100)/100;
			$tarif_ttc = Math.round($tarif_ttc*100)/100;
			$mt_factInt = Math.round($mt_factInt*100)/100;
			$tva = Math.round($tva*100)/100;
			$mt_restant = Math.round($mt_restant*100)/100;

// affectation des elements dans la page, éléments affichés et éléments cachés
document.getElementById("tarif_ht").innerHTML = $tarif_ht;		document.getElementById("tarif_ht_hid").value = $tarif_ht;

document.getElementById("tva").innerHTML = $tva;				document.getElementById("tva_hid").value = $tva;

document.getElementById("tarif_ttc").innerHTML = $tarif_ttc;	document.getElementById("tarif_ttc_hid").value = $tarif_ttc;

document.getElementById("mt_factInt").innerHTML = $mt_factInt;	document.getElementById("mt_factInt_hid").value = $mt_factInt;

document.getElementById("mt_restant").innerHTML = $mt_restant;	document.getElementById("mt_restant_hid").value = $mt_restant;			

		}
		else
		{
			alert('erreur lors de la reception des données du serveur');
		}
	}

}

Conclusion

Cet article vous aura présenté comment créer un formulaire intelligent grâce à AJAX.
Vous pouvez télécharger le script complet, il est pleinement fonctionnel.
N’ayez pas peur de me laisser un commentaire.

avatar

À propos de Rodolphe

Autodidacte passionné de la création web

Faites nous part de votre commentaire