Démarrer avec Ajax et le PHP: exemple d’application
Préparation à l’ajout des utilitaires Ajax
On veut donc ajouter des outils interactifs à notre application, sans la modifier outre mesure. Pour cela, on va ajouter dans le div « bandeau » un div « menuOutils », dans lequel on mettra un menu d’utilitaires, puis les « include » de nos outils.
<div class= »menuOutils »>
<span id= »ouvreOutil1″ class= »ouvreOutil »>outil1</span> <? include ‘outil1.php’; ?>
<span id= »ouvreOutil2″ class= »ouvreOutil »>outil2</span> <? include ‘outil2.php’; ?>
<span id= »ouvreOutil3″ class= »ouvreOutil »>outil3</span> <? include ‘outil3.php’; ?>
</div>
Remarquons que l’on a introduit des « id » dans les « span » d’affichage des menus. Nous aurons en effet besoin d’agir lorsque l’on cliquera sur ces faux boutons. On va également modifier le style bandeau h1 pour ne prendre que la moitié du bandeau (width: 50%;), pour laisser la place aux menus des outils. En cliquant sur le libellé de l’outil, on pourra l’ouvrir et l’utiliser; on va donc créer une classe « ouvreOutil ». L’outil comprendra un bouton de fermeture, nous créons donc une classe « fermeOutil ». Ces deux classes vont simuler des boutons sur lesquels on va cliquer, donc on définira « text-decoration: underline » et « cursor: pointer ».
.ouvreOutil {
margin: 10%;
background-color: #DFFFF4;
text-decoration: underline;
cursor: pointer;
}
.fermeOutil {
position: relative;
margin: 0;
top:0;
left:33em;
width: 7em;
height: 1,5em;
font-size:1em;
font-weight:bold;
background-color: #DFFFF4;
opacity:0.8;
text-decoration: underline;
cursor: pointer;
}
Il faudra aussi rendre ces faux boutons actifs, on le verra plus tard.
Les fenêtres des utilitaires:
Nous avons préparer les menus des outils, nous allons maintenant préparer les fenêtres contenant nos outils. Ici, j’ai choisi d’ouvrir des fenêtres identiques pour chaque outil, positionnées directement sous le menu outil et prenant sa largeur. Pour cela, les outils utiliseront une classe « outil », définie ci-dessous:
.outil {
position: absolute;
top: 100%;
left: 0;
Démarrer avec Ajax et le php: exemple d’application 4/23
width: 100%;
padding:0;
margin: 0;
background-color:lightgreen;
opacity: 0.8;
display: none;
}
Le « display: none; » permet de cacher les outils au chargement de la page. On l’enlèvera pour la mise au point des fenêtres des outils. Opacity permet de rendre plus ou moins transparente la fenêtre, permettant pour les tests de voir ce qui est dessous (ça fonctionne différemment sous IE, et on le supprimera éventuellement).
Nous allons créer pour l’instant des outils « vides », simplement pour leur donner une structure et remarquer que l’on donne des « id » aux « div » containers et aux boutons de fermeture des outils, justement afin de pouvoir gérer l’affichage de chaque outil.
<?
// outil vide echo ‘
<div id= »outil1″ class= »outil »> <fieldset>
<legend>Outil vide</legend>
<span>Cet outil ne fait rien!!!</span> </fieldset>
<div id= »fermeOutil1″ class= »fermeOutil »> <p>fermeture X</p>
</div>
</div>
‘;
?>
Notre site se présente maintenant ainsi:
Gestion des évènements
Il faut pouvoir faire apparaître et disparaître les outils, et il sera nécessaire pour déclencher nos actions Ajax de savoir gérer les évènements. Je vais donc insister un peu sur cette gestion d’évènement, bien que cela ne soit pas directement lié à Ajax; cela permettra également d’apprendre à gérer les évènements « proprement », c’est à dire indépendamment du contenu des pages, comme on le fait encore trop peu à l’heure actuelle. Tous les évènements et les actions Ajax seront réalisés par des scripts Javascript qu’il faut donc charger dans la page; on le fera d’une manière « propre », c’est à dire dans l’entête, et on les décomposera en modules:
● commun.js: comprendra toutes les fonctions générales et/ou communes à l’ensemble de l’application
● outil1, outil2, outil3.js comprendront respectivement les fonction liés aux fonctionnement de l’outil correspondant
● init.js comprendra les opérations d’initialisation de l’application.
On ajoutera donc après la référence à la feuille de style style.css
<script type= »text/javascript » src= »commun.js »></script> <script type= »text/javascript » src= »outil1.js »></script> <script type= »text/javascript » src= »outil2.js »></script> <script type= »text/javascript » src= »outil3.js »></script> <script type= »text/javascript » src= »init.js »></script>
Tout d’abord, il faut pouvoir faire apparaître et disparaître les outils. Pour cela, on va donc éviter d’utiliser la syntaxe encore répandu « onclick= »fonction() » positionné dans la balise du champ, pour utiliser des gestionnaires d’évènements qui vont prendre en charge les clics sur les boutons d’ouverture et de fermeture des outils. On aura donc l’enchaînement suivant:
● lors du chargement du script, un gestionnaire d’évènement (listener) est activé qui se déclenchera à la fin de chargement de la page (« onload »), provoquant ainsi l’appel de la fonction « init ».
● la fonction « init » permettra de créer les gestionnaires d’évènement qui seront déclenchés par les clics sur les boutons. Du fait que cette fonction « init » sera appelé à la fin du chargement de la page (par le déclenchement du listener « onload », on est sûr que tous les éléments concernés seront déjà chargés dans le DOM (Document Object Model) de la page.
● les gestionnaires appelleront les fonctions permettant l’ouverture et la fermeture des outils
On trouvera dans le fichier commun.js les fonctions addListener de création de gestionnaires d’évènements, trouveIdDeclencheur permettant de trouver l’ID de l’élément déclencheur de l’évènement, et la fonction existeChamp permettant de tester l’existence d’un champ, puis les fonctions spécifiques à notre application permettant d’ouvrir et de fermer les outils, en manipulant la propriété « display » des éléments « div » contenant les outils:
// ajoute listener
// compatible IE + mozilla & co
function addListener(element, action, fonction) { if (element.addEventListener)
element.addEventListener(action, fonction, false); else if (element.attachEvent)
element.attachEvent(‘on’ + action, fonction); } // addListener
function trouveIdDeclencheur(e) {
// quel id a declenche l’evenement ?
// compatible IE + mozilla & co
if (window.event) {
var id=window.event.srcElement.id;
} else {
var id=e.target.id;
}
return(id);
}
function existeChamp(id) {
// retourne true si le champ d’id id existe, false sinon return (document.getElementById(id))? true: false;
}
function ofOutil(e) {
//
var id=trouveIdDeclencheur(e);
if (id.substr(0,10)==’ouvreOutil’) ouvreOutil(id); if (id.substr(0,10)==’fermeOutil’) fermeOutil(id);
}
function ouvreOutil(id) {
switch (id) {
case ‘ouvreOutil1′:
var idO=’outil1’;
fermeOutil(‘outil2’);
fermeOutil(‘outil3’);
break;
case ‘ouvreOutil2′:
var idO=’outil2’;
fermeOutil(‘outil1’);
fermeOutil(‘outil3’);
break;
case ‘ouvreOutil3′:
var idO=’outil3’;
fermeOutil(‘outil1’);
fermeOutil(‘outil2′);
break;
}
if(existeChamp(idO)) document.getElementById(idO).style.display=’inline’;
}
function fermeOutil(id) {
switch (id) {
case ‘fermeOutil1′:
var idF=’outil1’;
break;
case ‘fermeOutil2′:
var idF=’outil2’;
break;
case ‘fermeOutil3′:
var idF=’outil3′;
break;
default:
var idF=id;
}
if(existeChamp(idF)) document.getElementById(idF).style.display=’none’;
}
Dans le fichier init.js, on trouvera la création des « listeners » nécessaires:
function init() {
// les listeners lance la fonction ofOutil (ouvrefermeOutil)
// listeners pour ecoute click ouverture outil addListener(document.getElementById(‘ouvreOutil1′),’click’,ofOutil); addListener(document.getElementById(‘ouvreOutil2′),’click’,ofOutil); addListener(document.getElementById(‘ouvreOutil3′),’click’,ofOutil);
// listeners pour ecoute click fermeture outil addListener(document.getElementById(‘fermeOutil1′),’click’,ofOutil); addListener(document.getElementById(‘fermeOutil2′),’click’,ofOutil); addListener(document.getElementById(‘fermeOutil3′),’click’,ofOutil);
}
addListener(window,’load’,init);
Détaillons le fonctionnement de cette partie:
● lors du chargement du script init.js (chargé en dernier, de façon à ce toutes les fonctions soient déjà définies), on crée un gestionnaire, qui lors de la fin de chargement de la page (il y a des querelles d’experts sur l’adéquation de cette fonction, mais passons…), va déclencher l’exécution de la fonction « init ». A noter qu’on fait dans la définition du gestionnaire une référence à la fonction et non un appel (d’où pas de parenthèses).
● la fonction « init » va à son tour définir les autres gestionnaires, avec l’avantage comme je l’ai souligné plus-haut, d’être sur à ce moment de l’existence des éléments utilisés. On fait références aux éléments de la page par leurs Id, en utilisant la fonction getElementById appliquée au document courant, et l’évènement « click » (et non pas onclick!) de la norme DOM. Tous les gestionnaires lanceront la fonction ofOutil lors d’un click sur l’élément voulu.
● la fonction addListener(element,action,fonction) permet de créer le gestionnaire de manière compatible aux navigateurs IE et compatibles DOM. Je passe sur le paramètre mis à false, qui gère le mode d’interception des évènements qui sera d’office le bouillonnement (bouillonnement ou Event bubbling en anglais, par rapport à la capture (Event capture), qui n’est d’ailleurs pas géré par IE, voir la littérature ou les spécifications DOM pour les curieux).
● à noter: lors du déclenchement d’un évènement, un objet « évènement » est passé en argument à la fonction de traitement (DOM) ou un objet windows.event est créé et accessible, ce qui permet à la fonction trouveIdDeclencheur(e) de trouveer l’Id de l’élément ayant déclenché l’action.
● les fonctions ofOutil, ouvreOutil et fermeOutil sont appelées selon l’ID déclenchant, pour ouvrir l’outil correspondant et fermer les autres, ou fermer un outil particulier.
Les outils
Il faut maintenant créer nos fichiers outil1.php, outil2.php, outil3.php, qui contiendront les outils Ajax que nous voulons pouvoir utiliser. Pour cela, j’ai opté pour des « include », comme pour les actions, ce qui permet facilement de développer ces modules sans (trop d’) interaction avec le programme principal.
Comme exemple d’outils, j’ai choisi une mini-calculatrice, un bloc-notes et un outil de consultation de base de données, ce qui donnera un éventail assez divers déjà de ce qu’on peut faire avec Ajax. Ces outils seront donc disponibles dans n’importe quelle page de l’application, puisque indépendants des actions.
Outil1: calculette
L’outil 1 sera donc une mini-calculatrice sans touche, il suffira de taper une expression pour connaître le résultat. Évidemment, cela n’offre aucun intérêt si les calculs sont simples, on pourrait le faire directement en local en Javascript, mais si on doit faire appel à des ressources complexes, ou disponibles uniquement sur le serveur, l’approche Ajax peut se justifier.
<?
echo ‘
<div id= »outil1″ class= »outil »>
<fieldset>
<legend>Mini Calculatrice sans touche</legend>
<span>Il suffit de taper une expression de calcul valide et de faire return</span>
<form id= »outil1_form » action= » » >
<table>
<tbody>
<tr><td>Calcul à faire</td><td><input type= »text » size= »50″ /></td></tr> <tr><td>Résultat</td><td><input type= »text » size= »50″ disabled= »disabled »
/></td></tr>
</body>
</table>
</form>
</fieldset>
<div class= »fermeOutil »>
<p id= »fermeOutil1″>fermeture X</p>
</div>
</div>
‘;
?>
On voit que cet outil comporte uniquement un formulaire avec le champ permettant de saisir l’expression à calculer, et un champ réceptacle du résultat renvoyé par le serveur. A noter que le formulaire ne définit pas d’action (l’attribut action n’est là que pour la conformité avec la norme XHTML strict) ni de méthode, car ce formulaire ne sera pas soumis, et n’existe que pour assurer la cohérence avec des champs de formulaire.
Le résultat du calcul sera mis dans un champ input désactivé, c’est souvent ce qui est utilisé car le plus simple à gérer, avec les fonctions Javascript déjà connus (document.getElementById(id).value= resultat).
Outil2: bloc-notes
L’outil 2 sera donc un bloc-notes permettant d’enregistrer ce que l’utilisateur note sans intervention de sa part, et de ré-utiliser ce contenu dans une autre page. Pour cela, on va simplement utiliser un « textarea ». On va aussi récupérer le contenu de la variable de session $_SESSION[‘bloc_notes’], qui sera initialisée dans le script php appelé par Ajax, ce qui permettra par exemple de garder le contenu du bloc_notes entre les différentes pages de l’application, voir de garder le contenu d’une session à l’autre, si l’utilisateur dispose d’un compte sur le serveur, etc…