Javascript et Formulaires HTML

Jean-Marc Lecarpentier
Université de Caen
Partie HTML adaptée du cours d'Alexandre Niveau

Formulaires HTML

Le langage HTML fournit une interface permettant aux internautes de communiquer des informations au serveur web : les formulaires

Ils sont principalement utiles pour envoyer des données (par la méthode POST du protocole HTTP) : poster un commentaire, s'authentifier sur un site…

Mais ils permettent aussi de spécifier des paramètres pour une page : champ de recherche, contrôle de l'affichage du contenu (ordre, filtrage), etc. (par la méthode GET du protocole HTTP)

Ils fonctionnent exactement de la même manière pour les deux usages : des widgets (éléments d'interface) permettent à l'internaute de choisir des valeurs pour des « variables » spécifiées dans le code

Base d'un formulaire

L'élément représentant un formulaire est form

On peut mettre des éléments classiques à l'intérieur (comme du texte, des paragraphes, des div…), mais surtout des widgets

La plupart des widgets sont créés avec l'élément input, qui donne des résultats très différents en fonction de son attribut type :
<form>
   <input type="text" />
   <input type="checkbox" />
   <input type="radio" />
</form>

Labels

Les légendes des champs du formulaires doivent être placés dans des éléments label (étiquettes)

Les labels doivent être explicitement associés à leurs champs : extrêmement important pour l'accessibilité et pour l'ergonomie !

Pour associer un label à un champ, le plus simple est de mettre le champ dans le label :
<form>
  <label>Ville : <input type="text" /></label>
  <label>Capitale : <input type="checkbox" /></label>
</form>
(Cliquer sur les labels !)

Autre solution pour associer un label à un champ

Si on ne veut pas mettre le champ dans le label, on peut aussi relier le label au champ grâce à l'attribut for, qui fait référence à l'id du champ. En général, la solution précédente suffit, est plus rapide à écrire et donne un code plus lisible.
<form>
  <div>
    <label for="ville">Ville :</label>
    <input type="text" id="ville" />
  </div>
  <div>
    <label for="cap">Capitale</label>
    <input type="checkbox" id="cap" />
  </div>
</form>
(Cliquer sur les labels !)

Bouton de soumission

Un formulaire est inutile si on ne peut pas le soumettre

Élément button
<form action="demo/recup.php">
   <input type="text" value="Texte par défaut"/>
   <button type="submit">Envoyer !</button>
</form>
Trois types de bouton :
  • submit envoie les données
  • reset remet tous les champs du formulaire à leur valeur par défaut
  • button ne fait rien ! Utile pour les scripts côté client

Noms des paramètres

Les données entrées sur les widgets servent à donner des valeurs à des variables

Il faut donner des noms à ces variables, pour que le serveur sache à quoi sert chaque donnée !

Jamais d'espace ou de caractère accentué dans le nom

La plupart des widgets utilisent l'attribut name pour cela
<form action="demo/recup.php">
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

Attention au comportement des checkbox

Ne pas confondre les attributs name et id

Utilisation des données comme paramètres d'une page

Pour renvoyer vers une autre page, il faut donner l'URL dans l'attribut action de l'élément form

Le navigateur a ajouté des paramètres d'URL, construits à partir des noms des widgets et des valeurs fournies par l'internaute

Dans cet exemple on renvoie vers une page qui fait quelque chose avec les paramètres :

<form action="demo/recup.php">
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

Envoi des données

Les paramètres d'URL ne conviennent pas à toutes les situations

On a souvent besoin d'envoyer des données au serveur

Dans ce cas, on peut spécifier que le navigateur doit utiliser la méthode POST de HTTP, en écrivant method="POST" comme attribut de l'élément form (la valeur par défaut de method est GET ⇒ construit une URL paramétrée)

<form action="demo/recup.php" method="POST">
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

Traitement des données côté serveur

La récupération des données côté serveur sort largement du cadre des cours TW1 et TW2. Cependant il est bon de comprendre dès maintenant la différence d'utilisation GET/POST

Dans les deux cas, cliquer sur le bouton submit construit les couples (clef, valeur) et les communique au serveur

N'importe quel programme peut être utilisé pour les récupérer : il suffit qu'il comprenne le protocole HTTP, ou qu'il puisse être lancé par le serveur lorsqu'un client demande l'URL en question (ex. : script PHP)

NB : une simple page HTML ne sait rien faire avec les paramètres d'URL, c'est le serveur qui va analyser les paramètres et modifier le HTML envoyé en fonction.

La récupération et l'utilisation des données envoyées au serveur est faite par un programme exécuté sur le serveur.

Module TW3 le Licence 3e année (S5)

Boutons radio

Les boutons radio n'ont d'intérêt qu'en groupe : un seul peut être sélectionné

C'est l'attribut name qui les groupe

Le paramètre prendra la valeur du bouton sélectionné : cette valeur correspond à l'attribut value
<form action="demo/recup.php" method="POST">
  Les formulaires HTML, vous êtes :
  <label><input type="radio" value="oui" name="fan" /> Fan</label>
  <label><input type="radio" value="non" name="fan" /> Pas fan</label>
  <label><input type="radio" value="?" name="fan" /> NSPP</label>
  <button type=submit>Envoyer !</button>
</form>
Les formulaires HTML, vous êtes :

Grouper des champs

L'élément fieldset permet de grouper des champs qui ont un rapport logique entre eux et de leur associer un label commun avec legend

Utile notamment pour les cases à cocher et les boutons radio
<form action="demo/recup.php" method="POST">
    <fieldset>
      <legend>Les formulaires HTML, vous êtes :</legend>
      <label><input type="radio" value="oui" name="fan" /> Fan</label>
      <label><input type="radio" value="non" name="fan" /> Pas fan</label>
      <label><input type="radio" value="?" name="fan" /> NSPP</label>
    </fieldset>
    <button type=submit>Envoyer !</button>
</form>
Les formulaires HTML, vous êtes :

Texte multi-lignes

On utilise l'élément textarea pour du texte sur plusieurs lignes
<form action="demo/recup.php" method="POST">
  <textarea cols="30" rows="5" name="multi">Mettre du texte ici !</textarea>
  <button type="submit">Go</button>
</form>

Propriété CSS resize pour que l'internaute puisse modifier la taille (valeurs : horizontal, vertical, both)

Attention, contrairement à input, textarea a une balise ouvrante et une balise fermante (le contenu est utilisé comme valeur par défaut)

Valeur par défaut et placeholder

Dans les champs texte, on peut mettre une valeur par défaut :
<form action="demo/recup.php" method="POST">
    <label>Prénom<br>
  <input type="text" size="10" name="prenom" value="Prénom" /></label>
  <label>Commentaire<br>
  <textarea cols="10" rows="5" name="comm">Votre commentaire…</textarea></label>
  <button type="submit">Envoyer</button>
</form>

L'internaute doit effacer le contenu avant de taper

En règle générale, c'est plutôt une sorte de « mode d'emploi » qu'on voudrait

Il faut utiliser l'attribut placeholder :
<form action="demo/recup.php" method="POST">
<label>Prénom<br>
  <input type="text" size="10" name="prenom" placeholder="Prénom" /></label>
    <label>Commentaire<br>
  <textarea cols="10" rows="5" name="comm" placeholder="Votre commentaire…"></textarea></label>
  <button type="submit">Envoyer</button>
</form>

Menu déroulant

Le menu déroulant s'obtient avec l'élément select, qui contient plusieurs éléments option

La valeur du paramètre est le contenu de l'attribut value de chaque option
<form action="demo/recup.php" method="GET">
  <select name="fruit">
    <option value="fraise">Fraise</option>
    <option value="pomme">Pomme</option>
    <option value="raison">Raisin</option>
  </select>
  <button type="submit">Go</button>
</form>

Groupes d'options dans un menu

On peut grouper les options d'un menu déroulant avec l'élément optgroup
<form action="demo/recup.php" method="GET">
  <select name="instrument">
    <optgroup label="Bois">
      <option value="clarinette">Clarinette (si♭)</option>
      <option value="basson">Basson (ut)</option>
      <option value="sax">Saxophone (mi♭)</option>
    </optgroup>
    <optgroup label="Cuivres">
      <option value="trompette">Trompette (si♭)</option>
      <option value="trombone">Trombone (ut)</option>
      <option value="tuba">Tuba (fa)</option>
    </optgroup>
  </select>
  <button type="submit">Go</button>
</form>

remarquer l'utilisation de value (on n'utilise pas les noms « compliqués » des instruments dans le code)

Améliore aussi l'accessibilité

Style des formulaires

Tout n'est pas modifiable par CSS dans les formulaires, notamment les menus déroulants…

Pour sélectionner un type d'input : utiliser les sélecteurs par attribut
input[type=text] {
	border: 2px dotted green;
}
Nombreuses pseudo-classes utiles pour les éléments de formulaire
  • :focus, sélectionne les éléments qui ont le focus, très utile pour les champs texte
  • :checked sélectionne les cases cochées, les boutons radio sélectionnés, et les options choisies dans un menu déroulant (peut être détourné, un peu comme :target, pour rendre les pages un peu dynamiques !)
  • :default sélectionne les éléments qui sont dans leur état par défaut (ex.: cases à cocher)
  • :valid et :invalid, pour styler les champs dont la validation est correcte ou non
  • :disabled et :enabled sélectionnent les éléments désactivés ou non par l'attribut HTML disabled
  • :required et :optional sélectionnent les élements obligatoires ou non (attribut HTML required)

Attention à width : les widgets ont chacun leur propre interprétation. Préciser box-sizing: border-box; pour être tranquille

Tous les détails sur le tutoriel de MDN

Javascript et formulaires

Le traitement des données envoyées (programmation côté serveur) est hors programme en L1

Mais pas le traitement des données avant leur envoi
<form id="form-1" action="demo/recup.php" method="GET">
  <label>Votre mot <input type="text" name="texte" id="texte" value="Texte par défaut"></label>
  <button type="submit">Go</button>
</form>
<script>
document.getElementById("form-1").addEventListener("submit", affiche);
function affiche(event) {
    let texte = document.getElementById("texte").value;
    alert(texte.toUpperCase());   
}
</script>

Le alert bloque l'exécution

Mais ensuite les données sont envoyées

C'est bien si on veut continuer avec le traitement côté serveur

Mais c'est un problème si on veut continuer à travailler sur la page

Bloquer l'envoi du formulaire

Applications client : tout doit être exécuté dans le navigateur

Bloquer l'envoi du formulaire avec l'évènement submit
<form id="form-2" action="demo/recup.php" method="GET">
  <label>Votre mot <input type="text" name="texte" id="texte" value="Texte par défaut"></label>
  <button type="submit">Go</button>
</form>
<script>
document.getElementById("form-2").addEventListener("submit", affiche);
function affiche(event) {
    alert("Bloquer la soumission du formulaire avec l'évènement submit et event.preventDefault()");   
    event.preventDefault();
}
</script>

Attention capter le clic sur le bouton "Envoyer" ne suffit pas !

Objet Form

Propriétés

method : méthode (POST/GET) utilisée

action : valeur de l'attribut action

elements : tableau non modifiable des éléments widgets du formulaire

Méthodes

submit() : faire envoyer les données du formulaire

reset() : remettre à zéro les champs du formulaire

Évènements

reset est déclenché quand le formulaire est réinitialisé

submit est déclenché au moment de l'envoi des données

Champs du formulaire

Propriété elements de l'objet Form contient la liste des champs du formulaire

Accès à l'objet JS de chaque champ par son nom càd attribut name

Chaque champ est un objet JS dont la nature dépend du type de champ, par ex. HTMLInputElement pour les éléments input

Accès à la valeur du champ en temps réel avec sa propriété value (en lecture/écriture)

Exemple
<form id="form-3" action="demo/recup.php" method="GET">
  <label>Votre mot <input type="text" name="saisie" value="Texte par défaut"></label>
  <button type="submit">Go</button>
</form>
<script>
document.getElementById("form-3").addEventListener("submit", affiche);
function affiche(event) {
    event.preventDefault();
    let formulaire = document.getElementById("form-3");
    // syntaxe 1
    let champ = formulaire.elements.saisie;
    alert(champ.value);
    
    // syntaxe 2
    let champ2 = formulaire.elements['saisie'];
    alert(champ2.value);
}
</script>

Objets JS de champ de formulaire

  • Chaque champ est un objet JS dont la nature dépend du type de champ
  • Propriétés communes à tous les types :
    • form l'objet Form dans lequel se trouve le champ
    • value la valeur du champ en temps réel
  • Méthodes communes à tous les types :
    • focus() donner le focus au champ
    • blur() enlever le focus au champ
  • Évènements communs à tous les types :
    • focus et blur déclenché quand le champ reçoit/perd le focus
    • input déclenché à chaque changement du champ (assez récent, attention ne marche pas avec les vieux navigateurs pour les select et boutons radio/checkbox)
    • change déclenché quand un élément perd le focus et a changé de valeur
  • Détails pour chaque type de champ

Exemple

Regarder en console pour avoir les messages

<form id="form-4" action="demo/recup.php" method="GET">
  <label>Votre mot <input type="text" name="saisie" value="Texte par défaut"></label>
      <fieldset>
      <legend>Vos langages préférés</legend>
      <label><input type="checkbox" value="HTML" name="prog" /> HTML</label>
      <label><input type="checkbox" value="javascript" name="prog" /> Javascript</label>
      <label><input type="checkbox" value="python" name="prog" /> Python</label>
      <label><input type="checkbox" value="c" name="prog" /> C</label>
      <label><input type="checkbox" value="java" name="prog" /> Java</label>
      <label><input type="checkbox" value="swift" name="prog" /> Swift</label>
      <label><input type="checkbox" value="cobol" name="prog" /> Cobol</label>
      <br>
      <button type="button" id="tout">Tout sélectionner</button>
    </fieldset>
  <button type="submit">Go</button>
</form>
<script>
let form4 = document.getElementById("form-4");
// le input texte capte le focus
form4.elements.saisie.addEventListener("focus", inputFocus);
function inputFocus(event) {
    console.log("Le input a maintenant le focus");
}

// le input texte capte le blur
form4.elements.saisie.addEventListener("blur", inputBlur);
function inputBlur(event) {
    console.log("Le input a perdu le focus");
}

// cocher tous les checkox
document.getElementById("tout").addEventListener("click", toutCocher);
function toutCocher(event) {
    let cases = form4.elements.prog;
    for (let i = 0; i < cases.length; i++) {
        cases[i].checked = true;
    }
}

// empêcher le submit et afficher les données du formulaire
form4.addEventListener("submit", demo);
function demo(event) {
    event.preventDefault();
    let texte = form4.elements.saisie.value;
    console.log("Texte saisi : " + texte);
    let checkboxes = form4.elements.prog;
    let langages = "";
    for (let i = 0; i < checkboxes.length; i++) {
        if (checkboxes[i].checked) {
            langages += checkboxes[i].value + " ";
        }
    }
    console.log("Vous aimez les langages suivants : " + langages);
}
</script>
Vos langages préférés

Conclusion

Essentiel bien comprendre event.preventDefault() pour empêcher l'envoi des données et rester sur la page

DOM et Javascript fournissent tous les outils pour manipuler les formulaires et les données saisies

Il n'y a plus qu'à construire les applications !