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.
Each input field is encapsulated in a .editer
class element, which must be grouped in a class element .editer-groupe
. Until SPIP 3.0 these classes were respectively carried by html tags li
et ul
. From SPIP 3.1 onwards, the convention is to use simple div
to reduce the verbosity of the voice synthesis and improve the accessibility of forms.
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 embracing 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 must include two paragraphs to show 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 .editer
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
Each <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
In the case of radio buttons or checkboxes, we may not use the same structure, for example to have the button before the label, or to have 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;}