Une interface de formulaire � base de tableaux dynamiques
Par cgo2, dimanche 18 septembre 2005 à 17:25 :: Les standards du web :: #50 :: rss
Premi�re �tape : construire la page
Tout d'abord, il faut faire la page web. Pour cela, on utilise du XHTML tout � fait classique, et on construit un tableau. Je vous invite � lire l'article Habillage de tableaux avec des CSS sur Openweb pour en savoir plus sur la mani�re de faire un tableau conforme aux standards.
Le tableau que j'ai choisi de dessiner est on-ne-peut-plus simple : il contient 4 colonnes contenants chacunes un champ de type "text", et une derni�re colonnes contenant les actions possibles. Pour l'instant, la seule action possible est la suppression d'une ligne.
Le code donne (vous pouvez consulter l'exemple 1) :
<table class="dTable"> <thead> <tr> <th>Colonne 1</th> <th>Colonne 2</th> <th>Colonne 3</th> <th>Colonne 4</th> <th>Actions</th> </tr> </thead> <tfoot> <tr> <th colspan="5"><a href="#">Ajouter une ligne</a></th> </tr> </tfoot> <tbody> <tr> <td><input type="text" name="champ1[]" /></td> <td><input type="text" name="champ2[]" /></td> <td><input type="text" name="champ3[]" /></td> <td><input type="text" name="champ4[]" /></td> <td><a href="#">Supp</a></td> </tr> </tbody> </table>
Les liens ont tous pour trajet (href
) la valeur #
. Cela revient � dire qu'ils n'ont pas d'effet... pour l'instant. J'ai appliqu� la classe dTable
au tableau (comme « Dynamic Table ») afin de pouvoir l'identifier parmis d'autres eventuels tableaux, qui, eux, ne seront pas dynamiques. Enfin, dernier d�tails, les champs input
ont tous un nom finissant par []
. Nous verrons dans la troisi�me partie � quoi �a va servir.
Deuxi�me �tape : rendre le tableau dynamique
Maintenant on rentre dans le vif du sujet. Pour rendre ce tableau dynamique, on va utiliser du Javascript et du DOM, en s'arrageant pour qu'il soit compatible Internet Explorer et Firefox.
Premi�re chose : inclure un script. Pour cela, on rajoute dans le header de la page html la ligne suivante (avec dtable.js
le nom du fichier script) :
<script type="text/javascript" src="dtable.js"></script>
Bien ensuite, un peu de conception... Comment allons nous proc�der ?
Ajout
Pour ajouter une ligne, le plus simple est d'utiliser la m�thode DOM cloneNode()
qui permet de dupliquer un noeud (par exemple un tr
, donc une ligne du tableau) et appendChild()
qui permet d'ajouter un noeud � un autre (par exemple le tr
clon� au tbody
, donc au corps du tableau). Cette m�thode est tr�s simple � condition d'avoir une ligne « de r�f�rence », c'est � dire une ligne vide que l'on pourra cloner pour simuler l'ajout de ligne. La premi�re ligne du tableau (la seule que j'ai saisis dans le code html ci-dessus) fera office de r�f�rence.
Nous allons faire une fonction addLigne
qui prend en param�tre l'�l�ment appellant (en l'occurence il s'agira d'un lien, donc d'un element A
). A partir du lien, il faudra retrouver le tableau en « remontant » dans l'arbre html � la recherche du parent s'appelant TABLE
. A partir du tableau, on pourra retrouver le TBODY
et la premi�re ligne, et effectuer l'ajout.
Pour retrouver le parent d'un �l�ment, j'utilise une fonction r�cursive, getParent(element, parentTagName)
, dont voici l'impl�mentation :
/* trouve le tag "parentTagName" parent de "element" */ function getParent(element, parentTagName) { if ( ! element ) return null; else if ( element.nodeType == 1 && element.tagName.toLowerCase() == parentTagName.toLowerCase() ) return element; else return getParent(element.parentNode, parentTagName); }
Le code pour ajouter une ligne devient :
/* ajoute une ligne */ function addLigne(link) { // 1. r�cuperer le node "TABLE" � manipuler var td = link.parentNode; var table = getParent(td,'TABLE'); // 2. on va manipuler le TBODY var tbody = table.tBodies[0]; // 3. on clone la ligne de reference var newTr = tbody.rows[0].cloneNode(true); tbody.appendChild(newTr); }
Pour appeller cette fonction, on peut transformer le lien « Ajouter une ligne » comme ceci :
<a href="#" onclick="addLigne(this); return false;">
Le return false;
permet de stopper le traitement normal du lien et donc de ne pas executer le href.
Suppression
L� encore, une fonction DOM nous mache tout le travail : removeChild()
. Il suffit de trouver le TR
� supprimer en remontant l'arbre html depuis le lien appellant, et de le retirer du TBODY
/* supprimer une ligne */ function delLigne(link) { // 1. r�cuperer le node "TABLE" � manipuler var td = link.parentNode; var table = getParent(td, 'TABLE'); // 2. r�cuperer le TBODY var tbody = table.tBodies[0]; // 3. Supprimer le TR tbody.removeChild(getParent(td, 'TR')); }
Pareil que pour l'ajout, on peut transformer les liens « Supp » comme ceci :
<a href="#" onclick="delLigne(this); return false;">
L'ajout et la suppression donnent l'exemple 2.
Prot�ger la premi�re ligne
Le probl�me de l'exemple 2, que vous avez peut-�tre remarqu� en testant, est que la premi�re ligne, la ligne de r�f�rence donc, est supprimable comme les autres. Et lorsqu'on supprime tous les lignes, il n'y en a plus aucune � cloner ! On va donc masquer la premi�re ligne avec la propri�t� CSS display="none"
et en ajoute une vide suppl�mentaire.
On ajoute au code :
window.onload = dtableInit; /* initialise le script */ function dtableInit() { var table = document.getElementsByTagName('TABLE'); for ( var i = 0; i < table.length; i++ ) { // on r�cup�re tous les tableaux dynamiques if ( table[i].className == 'dTable' ) { var tbody = table[i].tBodies[0]; var newTr = tbody.rows[0].cloneNode(true); // on masque la premi�re ligne du tbody (la ligne de reference) tbody.rows[0].style.display = 'none'; // on en ajoute une tbody.appendChild(newTr); } } }
Un dernier probl�me subsiste : lorsqu'on clone cette ligne, son style est clon� �galement. Toutes les lignes sont donc invisibles ! Il faut ajouter � la fin de addLigne
de quoi les remettres visibles :
if ( document.all ) newTr.style.display = "block"; // pour IE else newTr.style.display = "table-row"; // pour Gecko
L'utilisation de document.all
permet de d�tecter s'il s'agit d'IE ou pas. En effet, seul ce navigateur impl�mente cette propri�t� (non-standard).
Vous pouvez tester ce code dans l'exemple 3.
Troisi�me �tape : traiter les donn�es
Grace � leur nom finissant par []
, les valeurs des champs input
seront assembl�es dans un tableau lors du post du formulaire. R�sultat : on se retrouve avec 4 tableaux : champ1
, champ2
, champ3
et champ4
correspondants aux 4 colonnes du tableaux html. Les lignes de ces tableaux correspondent aux lignes du tableau html (en commen�ant par 0).
Imaginons qu'il faille mettre � jour une base, le plus rapide est de tout supprimer puis de r�ins�rer les donn�es directement ! Pas besoin de s'emb�ter � trouver ce qui a chang� puisque tout est renvoy�.
Derni�re chose : au moment de traiter ces donn�es, il ne faut pas oublier d'oublier l'index 0, qui correspond � la ligne de r�f�rence.
Vous pouvez tester le r�sultat renvoy� par le serveur grace � l'exemple 4.
Conclusion
Rajouter des fonctions � ce script est extrement simple : il suffit de veiller � ne pas toucher � la premi�re ligne. On peut par exemple imaginer des fonctions permettant de monter une ligne, de la descendre, de la dupliquer, etc. Bref, les possibilit�s de cr�er des interfaces web se rapprochant de celles des clients lourds sont de plus en plus nombreuses et de plus en plus simples � mettre en oeuvre grace notamment aux standards du W3C !
26 commentaires
1. Le lundi 19 septembre 2005 à 01:22, par bert
2. Le lundi 19 septembre 2005 à 22:19, par Celelibi
3. Le lundi 19 septembre 2005 à 22:33, par cgo2
4. Le mardi 20 septembre 2005 à 19:18, par Celelibi
5. Le mercredi 21 septembre 2005 à 15:02, par cgo2
6. Le samedi 24 septembre 2005 à 21:59, par Daniel
7. Le samedi 24 septembre 2005 à 22:29, par cgo2
8. Le dimanche 25 septembre 2005 à 16:57, par Daniel
9. Le dimanche 25 septembre 2005 à 17:06, par cgo2
10. Le dimanche 25 septembre 2005 à 17:56, par Daniel
11. Le dimanche 25 septembre 2005 à 18:17, par cgo2
12. Le lundi 26 septembre 2005 à 09:50, par Daniel
13. Le lundi 26 septembre 2005 à 18:35, par cgo2
14. Le dimanche 2 octobre 2005 à 15:38, par Jean
15. Le jeudi 20 octobre 2005 à 16:42, par lorenheit
16. Le jeudi 20 octobre 2005 à 17:05, par lorenheit
17. Le jeudi 20 octobre 2005 à 18:52, par cgo2
18. Le lundi 24 octobre 2005 à 19:15, par Sidaty
19. Le dimanche 20 novembre 2005 à 17:07, par Flo
20. Le jeudi 12 janvier 2006 à 15:41, par casse_bonbon
21. Le jeudi 2 mars 2006 à 15:08, par norm212
22. Le lundi 17 avril 2006 à 02:33, par C�dric
23. Le mercredi 19 avril 2006 à 16:51, par correction
24. Le mercredi 19 avril 2006 à 16:52, par correction
25. Le mercredi 26 avril 2006 à 23:04, par reinerg
26. Le jeudi 18 mai 2006 à 10:16, par inconnu
Ajouter un commentaire
Vous voulez lancer un d�bat ou poser des questions autour du sujet ? Dans ce cas, utilisez plut�t le forum !