HTML structure
A basic form is structured as follows:
<div class="formulaire_spip formulaire_editer formulaire_editer_nomformulaire" id="formulaire_editer_nomformulaire-id">
<a id="nomformulaire" name="nomformulaire"></a>
<form action="#" method="post">
<fieldset>
<legend>Une légende</legend>
<p class="explication">Un texte d'explication</p>
<div class="editer-groupe">
<div class="editer editer_nomlabel obligatoire erreur">
<label for="nomlabel">Courriel</label>
<em class="aide">#AIDER{arttitre}</em>
<p class="explication"> Explication du label</p>
<span class="erreur_message">Message d'erreur</span>
<input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
</div>
</div>
</fieldset>
</form>
</div>
The surrounding div is assigned the generic class formulaire_spip. Data entry forms in the private zone are additionally assigned the class formulaire_editer, indicating that we’re dealing with a database data entry form.
The first fieldset being optional, we could also code it without the fieldset and without the optional paragraphs:
<div class="formulaire_spip formulaire_editer formulaire_editer_nomformulaire formulaire_editer_nomformulaire-id">
<a id="nomformulaire" name="nomformulaire"></a>
<form action="#" method="post">
<div class="editer-groupe">
<div class="editer editer_nomlabel obligatoire">
<label for="nomlabel">Courriel</label>
<input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
</div>
</div>
</form>
</div>
The special classes
- "explication": to indicate an explanatory message (which applies either to all of the fields, or to just one step). Example:
<p class="explication">
. - "attention": to display a message concerning a essential entry field. Example:
<em class="attention"><:text_login_warning:></em>
. - "obligatoire": to indicate a compulsory field to be applied to the parent list element. Example:
<li class="obligatoire">
. - "erreur": to indicate a step causing an error, to be applied to the parent list element. Example:
<li class="erreur">
. Each error uses an explanatory message tagged with the class "erreur_message":<span class="erreur_message">
.
The surrounding frame
This form may optionally be included within a cadre-formulaire-editer (entry form frame), and can also therefore contain a entete-formulaire (form header):
<div class="cadre-formulaire-editer">
<div class="entete-formulaire"></div>
<div class="formulaire_editer formulaire_editer_site formulaire_editer_site-#ENV{id_site,nouveau}"></div>
</div>
Managing the success/error messages
Global messages
A form absolutely must include two paragraphs enabling the display of the global success and error messages which may arise after submitting the form. The environment variables message_ok and message_erreur are the parameters returned by SPIP (using the CVT forms).
<div class="formulaire_editer formulaire_editer_site formulaire_editer_site-#ENV{id_site,nouveau}">
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
</div>
Special messages
Each field on the form, wrapped within an li, can receive a special error message. This is contained in the ’erreurs’ environment table array and can be retrieved as follows:
[(#ENV**{erreurs}|table_valeur{field_name})]
We can assign the ’erreur’ class to the li and display a special error if there is one as shown below:
<div class="editer editer_descriptif[ (#ENV**{erreurs}|table_valeur{descriptif}|oui)erreur]">
<label for="descriptif"><:texte_descriptif_rapide:></label>
[<span class='erreur_message'>(#ENV**{erreurs}|table_valeur{desctiptif})</span>]
<textarea name='descriptif' id='descriptif' rows='2' cols='40'>[(#ENV**{descriptif})]</textarea>
</div>
Particularities for CSS styling
Input fields
Every <input />
that is not hidden must have a class identical to its type (in order to remediate a deficiency in Internet Explorer):
<input type="text" class="text" name="titre" id="titre" value="[(#ENV**{titre})]" />
Submit buttons
The submit buttons are included in a .boutons box (which can accept several buttons):
<p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
radio/checkbox
For radio buttons or checkboxes, we are permitted to not follow exactly the same structure, for example having the button before the label, or having radio buttons displayed horizontally.
Each (radio + label) entry may therefore be framed within a .choix block:
<div class="editer editer_syndication">
<div class="choix">
<input type='radio' class="radio" name='syndication' value='non' id='syndication_non'[ (#ENV{syndication}|=={non}|?{'checked="checked"'})] />
<label for='syndication_non'><:bouton_radio_non_syndication:></label>
</div>
<div class="choix">
<input type='radio' class="radio" name='syndication' value='oui' id='syndication_oui'[ (#ENV{syndication}|=={oui}|?{'checked="checked"'})] />
<label for='syndication_oui'><:bouton_radio_syndication:><em>#AIDER{rubsyn}</em></label>
</div>
</div>
By default, the list is displayed vertically. To make the list horizontal, you only need to specify that the .champ (field) in question is an inline type:
.formulaire_editer .editer_syndication .choix {display:inline;}