Imbriquer plusieurs formulaires dans un même tableau

Vu le nombre de sites traitant des standards du Web, du HTML au XHTML en passant par les CSS, on a tendance à dire que les tableaux doivent être utilisés uniquement afin de présenter des données dites tabulaires. Évidemment. Même s'il fut difficile pour les webmasters qui codaient à l'ancienne (utilisation massive des tableaux pour la mise en page), nous allons voir que dans certains cas, l'utilisation des tableaux est impossible. Impossible en gardant une page grammaticalement valide.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Imbriquer plusieurs formulaires dans un même tableau

Le sens premier des tableaux peut parfois être détourné pour contenir et aligner des éléments de formulaire : champs de type texte, listes déroulantes ou encore cases à cocher… Le sens n'en est pas pour autant changé, la sémantique est toutefois respectée : les en-têtes du tableau jouent le rôle d'étiquettes, et les cellules contiennent les éléments de formulaire. Voyons un exemple de tableau monoligne contenant un formulaire. Le résultat du code ci-dessous peut être consulté sur cette page.

 
Sélectionnez
<form method="get" action="#">
 <fieldset>
  <legend>Insertion d'une personne</legend>
  <table border="1">
   <tr>
    <th><label for="nom">Nom</label></th>
    <td><input type="text" name="nom" id="nom" /></td>
   </tr>
   <tr>
    <th><label for="prenom">Prénom</label></th>
    <td><input type="text" name="prenom" id="prenom" /></td>
   </tr>
   <tr>
    <th><label for="dateNaissance">Date de naissance</label></th>
    <td><input type="text" name="dateNaissance" id="dateNaissance" /></td>
   </tr>
   <tr>
    <th>Sexe</th>
    <td>
    <input type="radio" name="sexe" id="sexeM" value="M" /><label for="sexeM">M</label><br />
    <input type="radio" name="sexe" id="sexeF" value="F" /><label for="sexeF">F</label>
    </td>
   </tr>
  </table>
  <p><input type="submit" value="Valider" /></p>
 </fieldset>
</form>

L'utilisation des formulaires mêlés aux tableaux reste extrêmement limitée. Supposons que nous ayons une liste de personnes, chacune étant caractérisée par un nom, prénom, date de naissance et sexe. On souhaite proposer une interface permettant à la fois de consulter la liste de toutes les personnes et de pouvoir modifier les informations d'une personne. Il s'agit ici de données tabulaires, donc cela nécessite un tableau qui sera présenté de manière verticale. Pour modifier les informations, nous aurons besoin d'un formulaire par ligne : on doit pouvoir identifier précisément quelle personne est mise à jour. Le formulaire servira à la fois pour l'affichage et pour la modification des données. Pour notre tableau on utilise la balise th pour nommer la colonne, et la balise td pour les cellules du tableau. Pour que les cellules d'en-tête gardent tout leur sens, chaque élément du formulaire devra être placé dans la colonne appropriée. Mais si vous voulez que votre page soit grammaticalement valide (HTML ou XHTML), vous allez vous trouver devant le problème suivant : un formulaire par ligne ? Où doit-on placer les balises form ? Comment imbriquer tout cet amas de balises ? Et bien, il n'y a pas de solution en utilisant les tableaux… Plusieurs hypothèses :

Imbrication dans l'ordre table form tr td

 
Sélectionnez
<table>
 <form method="post" action="execute.php">
  <tr>
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </tr>
 </form>
 <form method="post" action="execute.php">
  <tr>
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </tr>
 </form>
 <form method="post" action="execute.php">
  <tr>
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </tr>
 </form>
</table>

Ce type d'imbrication n'est pas permis. Le validateur vous indiquera que l'élément table ne peut pas contenir d'élément form qui lui-même ne peut contenir d'élément tr.

Imbrication dans l'ordre table tr form td

 
Sélectionnez
<table>
 <tr>
  <form method="post" action="execute.php">
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </form>
 </tr>
 <tr>
  <form method="post" action="execute.php">
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </form>
 </tr>
 <tr>
  <form method="post" action="execute.php">
   <td><input type="text" name="nom" /></td>
   <td><input type="text" name="prenom" /></td>
   <td><input type="submit" value="OK" /></td>
  </form>
 </tr>
</table>

Ce type d'imbrication n'est pas permis. Le validateur vous indiquera que l'élément tr ne peut pas contenir d'élément form qui lui-même ne peut contenir d'élément td.

Après avoir réfléchi un instant, la solution n'existe pas. Enfin, pas avec l'élément table. Nous allons donc voir comment simuler un tableau à l'aide de balises span principalement. L'apparence doit rester celle d'un tableau. Sans utilisation des CSS, le rendu n'est pas trop abîmé : les cellules d'en-tête ne sont pas alignées avec le reste du tableau, mais l'aspect général reste celui d'un tableau.

Nous aurons d'abord besoin d'une balise div à laquelle nous donnerons comme nom de classe : tableau. Sémantiquement, cela délimitera le début et la fin dudit tableau, mais visuellement, c'est grâce à elle que nous pourrons définir une bordure, ou un arrière-plan… À l'intérieur de cette balise, nous utiliserons un autre élément div auquel nous donnerons comme nom de classe : entete et un autre de classe : corps. Afin que le pseudotableau soit correctement lisible sans feuille de style, nous devons utiliser pour les cellules, une balise de type inline afin de ne pas provoquer de retour à la ligne. Les éléments br ne doivent d'ailleurs surtout pas être utilisés pour cette application sous peine de déformer complètement l'apparence du tableau. Le div de classe entete est de type block, de ce fait, un retour à la ligne sera fait avant et après. Nous avons bien une ligne de cellules d'en-tête. N'oublions pas nos formulaires, ils sont eux aussi de type block, profitons-en pour s'en servir comme délimiteur de ligne (équivalent à tr). Il faudra bien veiller à interposer un élément p entre le formulaire et les éléments en ligne span sinon la page ne sera pas valide. Voici un premier aperçu de la structure de notre pseudotableau :

 
Sélectionnez
 <div class="tableau">
  <div class="entete">
   <p>
    <span class="nom">Nom</span>
    <span class="prenom">Prénom</span>
    <span class="dateNaissance">Date de naissance</span>
    <span class="sexe">Sexe</span>
    <span class="action">Action</span>
   </p>
  </div>
  <div class="corps">
   <form method="get" action="modifier.php">
    <p>
     <span class="nom"><input type="text" name="nom" value="" maxlength="" /></span>
     <span class="prenom"><input type="text" name="prenom" value="" maxlength="" /></span>
     <span class="dateNaissance"><input type="text" name="dateNaissance" value="" maxlength="" /></span>
     <span class="sexe">
     <input type="radio" name="sexe" id="sexeF_1" value="F" /><label for="sexeF_1">F</label>
     <input type="radio" name="sexe" id="sexeM_1" value="M" /><label for="sexeM_1">M</label>
     </span>
     <span class="action"><input type="hidden" name="idPersonne" value="1" />
     <input type="submit" name="modif" value="Modifier" /></span>
    </p>
   </form>
   <form method="get" action="modifier.php">
    <p>
     <span class="nom"><input type="text" name="nom" value="" maxlength="" /></span>
     <span class="prenom"><input type="text" name="prenom" value="" maxlength="" /></span>
     <span class="dateNaissance"><input type="text" name="dateNaissance" value="" maxlength="" /></span>
     <span class="sexe">
     <input type="radio" name="sexe" id="sexeF_2" value="F" /><label for="sexeF_2">F</label>
     <input type="radio" name="sexe" id="sexeM_2" value="M" /><label for="sexeM_2">M</label>
     </span>
     <span class="action"><input type="hidden" name="idPersonne" value="2" />
     <input type="submit" name="modif" value="Modifier" /></span>
    </p>
   </form>
   <form method="get" action="modifier.php">
    <p>
     <span class="nom"><input type="text" name="nom" value="" maxlength="" /></span>
     <span class="prenom"><input type="text" name="prenom" value="" maxlength="" /></span>
     <span class="dateNaissance"><input type="text" name="dateNaissance" value="" maxlength="" /></span>
     <span class="sexe">
     <input type="radio" name="sexe" id="sexeF_3" value="F" /><label for="sexeF_3">F</label>
     <input type="radio" name="sexe" id="sexeM_3" value="M" /><label for="sexeM_3">M</label>
     </span>
     <span class="action"><input type="hidden" name="idPersonne" value="3" />
     <input type="submit" name="modif" value="Modifier" /></span>
    </p>
   </form>
   <form method="get" action="modifier.php">
    <p>
     <span class="nom"><input type="text" name="nom" value="" maxlength="" /></span>
     <span class="prenom"><input type="text" name="prenom" value="" maxlength="" /></span>
     <span class="dateNaissance"><input type="text" name="dateNaissance" value="" maxlength="" /></span>
     <span class="sexe">
     <input type="radio" name="sexe" id="sexeF_4" value="F" /><label for="sexeF_4">F</label>
     <input type="radio" name="sexe" id="sexeM_4" value="M" /><label for="sexeM_4">M</label>
     </span>
     <span class="action"><input type="hidden" name="idPersonne" value="4" />
     <input type="submit" name="modif" value="Modifier" /></span>
    </p>
   </form>
   <form method="get" action="modifier.php">
    <p>
     <span class="nom"><input type="text" name="nom" value="" maxlength="" /></span>
     <span class="prenom"><input type="text" name="prenom" value="" maxlength="" /></span>
     <span class="dateNaissance"><input type="text" name="dateNaissance" value="" maxlength="" /></span>
     <span class="sexe">
     <input type="radio" name="sexe" id="sexeF_5" value="F" /><label for="sexeF_5">F</label>
     <input type="radio" name="sexe" id="sexeM_5" value="M" /><label for="sexeM_5">M</label>
     </span>
     <span class="action"><input type="hidden" name="idPersonne" value="5" />
     <input type="submit" name="modif" value="Modifier" /></span>
    </p>
   </form>
   <span class="clear"></span>
  </div>
 </div>

Notez que le champ de type hidden contient l'identifiant de la personne, c'est la seule manière fiable pour savoir sur qui porte la modification. Bien sûr, tout ceci relève de la programmation côté serveur, les champs de formulaire devraient contenir des noms, prénoms, dates de naissance et sexes. Les étiquettes label doivent pointer sur l'identifiant d'un champ, cet identifiant doit être unique, une bonne méthode consiste à ajouter à l'attribut id un numéro unique (ici, il s'agit du numéro de la personne). Mais on ne parlera que de la mise en forme du tableau et pas des techniques de programmation pour extraire des données d'une base… Le résultat du code ci-dessus peut être consulté sur cette page.

Le reste de l'exercice se fera à l'aide d'une feuille de style. Nous allons procéder par étape. La première étape consiste à donner une bordure au tableau, et une bordure à chaque cellule pour voir le comportement des différents éléments. Le résultat du code ci-dessous peut être consulté sur cette page.

 
Sélectionnez
div.tableau {
  border:1px solid black;
}
  
.corps form span, .entete span {
  border:1px solid red;
}

Le problème qui se pose est la largeur des cellules. Il faudrait pouvoir préciser une largeur pour chaque colonne et que, quelle que soit la taille des caractères, les cellules aient toujours la même largeur. Pour pouvoir les dimensionner, il faut que les éléments soient de type block. Pour ne pas que la taille des cellules varie, et donc que l'alignement soit toujours assuré, nous utiliserons la propriété overflow à la valeur auto ; de cette manière, si le contenu des cellules augmente, la taille des cellules ne changera pas et des barres de défilement apparaîtront en cas de nécessité. Étant donné que les éléments sont maintenant de type block, il va falloir les mettre en flottant à gauche, sinon ils seront positionnés les uns en dessous des autres. On utilise pour cela la propriété float:left;. Afin que le retour à la ligne s'effectue bien, nous aurons besoin d'annuler le flottement à chaque nouvelle ligne à l'aide de la propriété clear:both; que nous intégrerons à l'élément jouant le rôle de conteneur de la ligne : ici, la balise form. Le résultat du code ci-dessous peut être consulté sur cette page.

 
Sélectionnez
div.tableau {
  border:1px solid black;
}
 
.corps form span, .entete span {
  display:block;
  float:left;
  width:100px;
  height:50px;
  overflow:auto;
  border:1px solid red;
}
 
.corps form {
  clear:both;
}

Vous remarquerez que la bordure du pseudotableau n'englobe pas la dernière ligne. C'est parce que le flottement n'a pas été annulé, vu qu'il n'y a pas de balise form à la suite. Pour cela, on va ajouter une règle pour l'élément <span class="clear"></span>, eh oui, elle n'était pas là par hasard cette balise ; certains d'entre vous tenteront peut-être de la remplacer par un élément hr plus approprié, mais comme d'habitude, Internet Explorer est là pour nous mettre de bonne humeur, en effet le hr provoque un saut de ligne trop épais, ce qui insère un espace disgracieux entre la dernière ligne de cellules et la bordure du tableau. Le résultat du code ci-dessous peut être consulté sur cette page.

 
Sélectionnez
div.tableau {
  border:1px solid black;
}
  
.corps form span, .entete span {
  display:block;
  float:left;
  width:100px;
  height:50px;
  overflow:auto;
  border:1px solid red;
}

.corps form {
  clear:both;
}

.clear {
  display:block;
  clear:both;
  visibility:hidden;
}

Vous pouvez essayer d'augmenter ou de diminuer la taille du texte, l'alignement des cellules doit être conservé. Si le texte devient trop grand pour tenir entièrement dans la cellule, celle-ci n'est pas redimensionnée, mais des ascenseurs apparaissent. Voyez l'allure de ce pseudotableau avec une feuille de style un peu plus élaborée.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2005 Matthieu PETIOT. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.