img

FONDAMENTI: 15).I Moduli, creazione di form e controlli utente

Form e Controlli

I form o moduli sono lo strumento essenziale utilizzato nel Web per inviare dei dati a un server al fine di effettuare delle operazioni di elaborazione predefinite. Esempi comuni sono dati dai moduli che compiliamo per inviare informazioni di accesso alla nostra banca o a un negozio di commercio elettronico (in pratica il login) e così via, in un elenco pressoché infinito.

Essi si creano mediante l'utilizzo del tag <form>, che ha i seguenti principali attributi.

- action: indica l'URL di destinazione dei dati inviati con il form. Generalmente punta a un file su un server web scritto in una qualche tecnologia lato server come PHP, ASP.NET, JEE e così via che è in grado di "leggere" e interpretare le informazioni ottenute e di elaborarle in un modo stabilito restituendo il risultato, spesso sotto forma di una completa pagina HTML adeguatamente formattata.

- method: indica il metodo o comando HTTP da usare quando si effettua il submit del form, che determina come sono inviati i dati alla risorsa indicata dall'attributo

- action. Può avere il valore GET (utilizzato di default se l'attributo non è indicato o se è scritto senza alcuna specificazione), e allora i dati sono inviati via URL come una query string nella forma precedentemente esaminata, oppure il valore
- POST, e allora i dati sono inviati come parte della richiesta nel corpo del messaggio dopo gli header (e non sono quindi visibili nell'URL).

- target: indica dove visualizzare la risposta che si è ricevuta a seguito del submit del form. Può assumere i valori
_blank, _self, _parent, _top e _iframename.

- autocomplete: indica se, per i campi di un form, devono essere memorizzati i valori precedentemente inseriti al fine di consentire, durante future digitazioni, la visualizzazione di un'area rettangolare (suggestion box) entro la quale appariranno i valori memorizzati che sono coerenti con quello che si sta digitando. Se l'attributo è omesso allora il suo stato sarà su on, mentre, se si vuole evitare l'autocompletamento, bisognerà specificare l'attributo con il valore off.

- novalidate: indica, se presente, che i dati inseriti nei relativi campi di input non devono essere validati quando si effettuerà il submit del form.

Get e Post

Nello scegliere se utilizzare il metodo GET o il metodo POST per inviare i dati di un form considerate quanto segue:
per il metodo GET.

- Produce una stringa che è visibile nella barra degli indirizzi del browser.
- La stringa è limitata a un massimo di caratteri che è dipendente dal browser in uso (per esempio, in Internet Explorer è di 2083 caratteri).
- La stringa è mandata in chiaro e pertanto non bisogna mai utilizzarla per il passaggio di informazioni sensibili (per esempio le password).
- Non può essere usato per l'inoltro di dati binari (per esempio le immagini).
- Non dovrebbe essere usato per modificare dei dati ma solo per ottenere delle risorse come avviene, per esempio, nelle query di ricerca che si inoltrano tramite i form dei motori di ricerca. In questo contesto si dice che il metodo GET è di tipo idempotente, ossia non dovrebbe mai causare sul server degli effetti collaterali.
- Può essere conservato come segnalibro in quanto parte del relativo URL.
- Le risposte possono essere memorizzate nella cache.

Per il metodo POST bisogna invece considerare quanto segue.

- Non ha alcuna restrizione sulla quantità di dati da inviare.
- Può inviare anche dati binari.
- Non può essere conservato come segnalibro.
- I dati, così come per il metodo GET, sono mandati in chiaro e pertanto non bisogna mai utilizzarlo per il passaggio di informazioni sensibili (per esempio le password). Non bisogna commettere l'errore di pensare che, anche se i dati non sono visibili nell'URL, essi non siano intercettabili. Infatti, tramite uno sniffer di rete è sempre possibile leggere il "dialogo" che avviene sul protocollo HTTP tra un client e un server.
- Dovrebbe essere usato per effettuare modifiche sul server.
- Le risposte non sono memorizzabili nella cache a meno che esse includano gli appropriati header Cache-Control o Expires.

Un form, al fine di essere utile e di poter trasmettere delle informazioni a un server, deve poter contenere una serie di controlli grafici di interfaccia (definiti anche widget) attraverso cui inserire del testo, compiere delle scelte e così via.

In HTML5 possiamo utilizzare come widget quelli definibili mediante i seguenti tag e attributi.

Controlli input

<input type="text">: con esso si crea una casella rettangolare a riga singola (casella o campo di testo) dove l'utente può inserire del testo.

<input type="password">: con esso si crea una casella rettangolare a riga singola dove l'utente può inserire i caratteri di una password che non sono mostrati in chiaro ma sono sostituiti dal carattere asterisco(*) o da un simbolo di un cerchietto pieno nero(•)

<input type="button">: con esso si crea un comune pulsante con un'etichetta testuale cui può essere associato, di solito tramite JavaScript, del codice da eseguire quando si fa clic su di esso. Se non è indicata un'etichetta (attraverso il valore dell'attributo value), il pulsante non avrà alcuna etichetta di default.

<input type="submit">: con esso si crea un comune pulsante con un'etichetta testuale che, quando attivato, consente di effettuare l'invio dei dati del relativo form. Se non è indicata un'etichetta, il pulsante avrà come etichetta di default un valore analogo a Invia.

<input type="reset">: con esso si crea un comune pulsante con un'etichetta testuale che, quando attivato, consente di cancellare gli eventuali dati inseriti in tutti i campi di testo del form. Se non è indicata un'etichetta, il pulsante avrà come etichetta di default un valore analogo a Ripristina o Reimposta.

<input type="checkbox">: con esso si crea una casella di controllo la cui interazione causa l'apposizione o la rimozione di un segno di spunta che ne indica lo stato, rispettivamente, di attivato/disattivato. È utile per creare un widget a due stati che consente di decidere se una determinata operazione, azione, domanda e così via deve essere considerata affermativa (il segno di spunta indicherà lo stato di ) oppure non affermativa (la mancanza di un segno di spunta indicherà lo stato no).

<input type="radio">: con esso si crea un pulsante di opzione la cui interazione causa l'apposizione di un simbolo di selezione (un cerchietto nero all'interno di un cerchio esterno bianco) sul pulsante selezionato e la contestuale deselezione con la rimozione dello stesso simbolo da un altro pulsante precedentemente selezionato. Questo controllo consente di creare dei pulsanti mutualmente esclusivi appartenenti a un medesimo gruppo: solo uno per volta può essere selezionato. Per un pulsante di opzione, si decide l'appartenenza a un gruppo indicando un nome, che dovrà chiaramente essere uguale anche per gli altri, nell'attributo name.

<input type="file">: con esso si crea un controllo formato da una casella di testo a riga singola e un pulsante (di norma con valore Sfoglia) laddove l'attivazione di quest'ultimo farà apparire una finestra di selezione di uno o più file (se presente l'attributo multiple) che sarà possibile gestire per operazioni come, per esempio, l'upload verso un server. Dopo aver scelto i file, un path completo degli stessi apparirà nella relativa casella di testo (tranne che per il browser Chrome, che presenterà solo un'etichetta riepilogativa).

<input type="number">: con esso si crea un controllo formato da una casella di testo a riga singola con a fianco due pulsanti: uno con il simbolo di freccia rivolta verso l'alto e uno con il simbolo di freccia rivolta verso il basso denominati comunemente spinner o spin box. Questi pulsanti consentono di visualizzare all'interno della casella di testo dei valori numerici. Non è consentito inserire valori di un altro tipo (per esempio stringhe di lettere), se ciò avviene e si fa il submit del form il browser non invia alcun valore.

<input type="range">: con esso si crea un controllo, denominato slider, formato da una barra orizzontale o verticale con un cursore (indicatore) il cui spostamento permette di selezionare dei valori di tipo numerico (rappresentato in alcuni browser da piccole tacche).

<input type="color">: con esso si crea un controllo che consente di scegliere, tramite un classico selettore, un colore che è espresso in esadecimale nella forma RGB #RRGGBB.

<input type="image">: con esso si crea un comune pulsante che è renderizzato con un'immagine specificata.

<input type="email">: con esso si crea una casella rettangolare a riga singola dove l'utente può inserire del testo che dovrebbe conformarsi al pattern utilizzato per esprimere un indirizzo di posta elettronica (per esempio nome@dominio).

<input type="url">: con esso si crea una casella rettangolare a riga singola dove l'utente può inserire del testo che dovrebbe conformarsi al pattern utilizzato per esprimere un URL assoluto (per esempio http://www.indirizzoweb.it).

<input type="search">: con esso si crea una casella rettangolare a riga singola dove l'utente può inserire del testo per effettuare delle ricerche. Un browser dovrebbe renderizzare questo campo in modo che abbia uno stile differente da una comune casella di testo evidenziando il fatto che esso è deputato alle operazioni di ricerca. In Chrome, per esempio, non appena si inizia a digitare del testo, appare all'interno della relativa casella un simbolo x che consente di cancellare quanto appena inserito.

<input type="tel">: con esso si crea una casella rettangolare a riga singola dove l'utente può inserire del testo che dovrebbe rappresentare un numero telefonico. Anche in questo caso il browser potrebbe aiutare l'utente nell'inserimento di un numero telefonico, magari visualizzando il programma predefinito di rubrica.

<input type="datetime">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere una data e un orario, espresso secondo l'ora di riferimento internazionale Coordinated Universal Time (UTC). Per la data, il widget potrebbe essere renderizzato come un comune calendario, mentre per l'orario potrebbe apparire come uno spin box laddove la sua attivazione consentirebbe di inserire valori validi, per l'ora da 0 a 23, per i minuti da 0 a 59 e così via. In ogni caso, elenchiamo il formato completo per una data e un orario secondo quanto indicato dalla specifica di HTML5, considerando che alcune parti possono essere omesse, se non presenti (per esempio le frazioni di secondo): YYYY-MM-DDTHH:MM:SS.FFFtimezone dove la lettera T separa la parte data dalla parte oraria, le lettere FFF indicano le frazioni di secondo, timezone indica l'offset del fuso orario che può essere espresso con la lettera Z (per Zulu time, il fuso orario con offset pari a 0 come quello di Londra, Parigi, Madrid e così via), oppure con + o , cui fanno seguito le ore e i minuti, rappresentanti un offset di zona oraria, separati dal carattere :.

<input type="datetime-local">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere una data e un orario locale, senza considerare quindi il fuso orario ( time zone).

<input type="date">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere solamente una data senza, però, un orario nel formato anno-mese-giorno ( YYYY-MM-DD).

<input type="month">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere solamente una data espressa nel formato anno-mese ( YYYY-MM).

<input type="week">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere solamente una data espressa nel formato anno-settimana nell'anno ( YYYY-Www).

<input type="time">: con esso si crea un controllo attraverso il quale è possibile selezionare e scegliere solamente un orario espresso nel formato ore-minuti-secondi e frazioni di secondi ( HH:MM:SS.FFF).

<textarea>: con esso si crea un box rettangolare formato da più righe ( multiline textfield) dove l'utente può inserire del testo.

<select>: con esso si crea un controllo definito drop-down list, formato da una combinazione di due elementi grafici, dove il primo è un rettangolo a riga singola (casella di testo) con a lato un simbolo di freccia e il secondo è un altro rettangolo, che appare se l'utente fa clic sul simbolo della freccia o sulla casella di testo. Al suo interno è presente una lista di voci ( item), definibili mediante il tag <option>, che può essere a scelta singola o multipla (se è impostato l'attributo multiple). Inoltre, se impostiamo l'attributo size con un valore maggiore di 1, l'elemento select sarà renderizzato come una list box, ossia come un unico rettangolo al cui interno è presente una lista di voci che sono selezionabili secondo uno dei seguenti criteri: a singola selezione, possiamo selezionare solo una voce alla volta; a selezione d'intervallo multiplo, possiamo selezionare più voci in più intervalli di item. La selezione è attuabile facendo clic su una voce per aprire l'intervallo e quindi, tenendo premuto il tasto Shift, facendo clic su un'altra voce per concludere l'intervallo. È anche possibile utilizzare il tasto Ctrl che permette di selezionare voci "a scacchiera".

<datalist>: con esso si crea una sorta di list box che contiene una serie di voci (tag <option>) mostrate come suggerimento quando un utente inizia a digitare del testo in una casella ottenuta da un elemento input, per il quale l'attributo list è impostato con il valore dell'attributo id dell'elemento datalist. In pratica tale tag consente di definire un controllo di tipo autocomplete applicabile a un elemento di tipo text input.

<keygen>: con esso si crea un controllo che consente di generare delle chiavi per un sistema crittografico. Infatti, un browser che supporta tale widget crea una coppia di chiavi: quella pubblica è inviata al server unitamente agli altri dati del form, mentre quella privata rimane memorizzata nel browser. Successivamente allo scambio di tali chiavi, quella pubblica può essere impiegata per generare un certificato per il client da utilizzare, in futuro, per l'autenticazione di un utente. Allo stato attuale è supportato solo il sistema crittografico detto RSA, e un browser renderizza il relativo controllo mediante un menu a tendina dal quale è possibile scegliere la lunghezza della chiave espressa in bit e dunque il suo grado di sicurezza.


Il tag <button>

Tramite il tag <button> è possibile creare un pulsante di tipo:
button, submit o reset
analogamente a quanto visto per il tag <input>.
Tuttavia tra i due esiste l'importante differenza che il tag <button> consente di aggiungere al suo interno, come contenuto, altri elementi HTML.
Ciò permette, per esempio, di creare un pulsante di tipo button con un'immagine al suo interno che ne stabilisce, dunque, una forma personalizzata.

Widget

Abbiamo inoltre i seguenti tag che, anche se non sono direttamente collegati a un form perché il suo submit non invia i relativi valori, possono essere considerati come dei widget.

<progress>: con esso si crea una barra di avanzamento o progress bar, che viene progressivamente riempita con un colore fino al compimento di una determinata operazione. L'avanzamento è tracciato attraverso il valore numerico dell'attributo value. Inoltre l'attributo max permette, con un valore numerico, di definire la scala. Omettendo value è anche possibile creare una barra di avanzamento di tipo indeterminato, ossia che non indica lo stato di avanzamento dell'operazione ma segnala, semplicemente, che il sistema è in attesa del suo completamento.

<meter>: con esso si crea una barra di avanzamento che indica un determinato ammontare riguardante la misurazione della tipologia di oggetto che intende rappresentare (per esempio quantità di utilizzo di un hard disk, percentuale di rilevanza di un risultato di ricerca e così via). Ancora una volta l'avanzamento è definito da value e max.

<menu>: con esso si crea una struttura a menu per una lista di comandi. Può definire: se è impostato l'attributo type con il valore context, un menu contestuale; se è impostato l'attributo type con il valore toolbar, una barra degli strumenti; l'assenza dell'attributo type, uno "stato" di list ossia una lista di comandi.

<command>: con esso si crea una sorta di "azione" che può essere svolta da un utente. Può essere parte di un menu oppure può essere inserita ovunque all'interno del documento HTML per rappresentare una scelta rapida da tastiera.


Il tag <output>

Nella specifica HTML5 è stato definito il nuovo tag <output> che funziona come una sorta di segnaposto per il risultato di un calcolo. In un certo senso, possiamo dire, che esso è complementare a degli elementi input che forniscono i valori della computazione. Tali elementi di input possono essere riferiti dall'elemento output mediante l'indicazione nel suo attributo for dei valori degli attributi id degli input, separati da un solo carattere di spazio (per esempio <output for="id1 id2">). È bene sottolineare che l'elemento output ha la sola funzione di visualizzare il risultato di un calcolo, sia esso una somma, una moltiplicazione, una sottrazione o un'espressione complessa. La definizione del calcolo da svolgere è invece delegata a un linguaggio di programmazione tipo JavaScript.

Altri Attributi

Infine, i nuovi attributi utilizzabili nei controlli.

required: con esso si indica che il valore di un elemento di tipo input, select o textarea è obbligatoriamente richiesto per il corretto submit del form. Inoltre, se l'utente non soddisfa tale richiesta, dopo che avrà premuto il pulsante di submit del form, il browser visualizzerà un breve messaggio (una sorta di tooltip) che indicherà l'obbligatorietà delle compilazione del relativo controllo e interromperà l'invio del dati al server.

formnovalidate: con esso si indica che si intende evitare il controllo di validazione sui campi di un form. Generalmente tale attributo si assegna ai pulsanti di tipo submit.

pattern: con esso si indica un'espressione regolare che determina il corretto formato del valore da inserire in un campo di input. Se il campo è a inserimento obbligatorio e l'utente non rispetta quanto espresso dall'espressione regolare non avverrà il submit del form.

placeholder: con esso è possibile mostrare un testo, generalmente in grigio chiaro, all'interno di una casella di testo. Il testo viene nascosto quando la casella riceve un focus e diviene attiva. È importante dire che, se si esce dal controllo senza aver inserito del testo, sarà nuovamente visibile il testo definito come segnaposto. Questo attributo è utilizzabile per fornire un breve suggerimento all'utente sotto forma di esempio di valore da inserire o su come lo stesso debba essere formattato.

autocomplete: con esso è possibile decidere, per un singolo campo di testo, se la caratteristica di autocompletamento del testo deve essere attiva (valore on) oppure no (valore off).

autofocus: con esso è possibile assegnare a un controllo un focus automatico, che gli viene fornito quando la pagina è stata caricata. Tale attributo consente, di fatto, di rendere subito disponibile per un utente il controllo principale di un form, permettendogli di iniziare subito a digitare i relativi dati senza doversi preoccupare di selezionarlo manualmente.

spellcheck: con esso si indica (valore true o false) se un campo di testo o, più in generale, un elemento editabile, deve avere o meno un controllo ortografico. Nei browser che supportano tale attributo, se si digita del testo con errori di ortografia o con del testo senza senso lo stesso sarà renderizzato con una linea orizzontale rossa tratteggiata o ondulata ( red squiggle) posta sotto di esso.

multiple: con esso si indica la possibilità per un controllo di tipo input o select di specificare più di un valore. Ciò può essere utile, per esempio, quando si utilizza un elemento di input di tipo email per indicare più mittenti o destinatari di un messaggio di posta (che devono essere separati dal carattere di virgola) oppure per un elemento di input di tipo file per indicare più file di cui effettuare l'upload.

min, max e step: con essi si indica un valore minimo, massimo e di step (un valore che segnala di quante unità alla volta deve essere incrementato o decrementato il valore principale) da poter utilizzare all'interno di elementi di input del tipo number, date, month, week, time, range e in controlli quali progress (solo max) e meter (solo min e max). Così, per esempio, se abbiamo un campo di testo di tipo numerico con gli attributi scritti come min=4, max=25, step=3 i valori accettati saranno nell'intervallo 4-25 con i limiti inclusi a intervalli di 3 ( 4, 7, 10, 13, , 25).

form: con esso si imposta per elementi come button, input, keygen, output, select e textarea il form di appartenenza tramite la specifica del suo id come valore. Questo attributo è utile perché permette di associare uno degli elementi succitati a prescindere dal fatto che siano innestati direttamente all'interno di un form.

formaction, formenctype, formmethod, formtarget: con essi si imposta direttamente per gli elementi input o button di tipo submit i relativi attributi action, enctype, method e target, generalmente specificati all'interno del tag <form>, in modo da sovrascriverli.

height e width: specificano, rispettivamente e in pixel, l'altezza e la larghezza di un elemento input di tipo image. Prima dell'avvento di HTML5 questo attributo non era definibile per tali elementi ma solo per gli elementi img, iframe, object e così via.

L'attributo contenteditable

È interessante accennare al nuovo attributo HTML5 denominato contenteditable, perché, anche se non direttamente collegato ai controlli di un form, consente di dotare un elemento HTML della caratteristica della modificabilità o meno del suo contenuto (valore true o false) e, dunque, lo fa divenire una sorta di "widget editabile". Per esempio, se definiamo un elemento td di una tabella che contiene del testo con l'attributo contenteditable="true", successivamente potremo fare clic all'interno della medesima cella per far apparire il classico caret ( ^) che ci indica che siamo in modalità di editing e che, dunque, possiamo compiere tutte le consuete operazioni di inserimento, modifica e cancellazione del relativo testo.


Vediamo ora un esempio che mostra come definire un form che raccoglie una serie di informazioni sull'utente che lo compila.


<!DOCTYPE html>
<html>
<head>
 <title>Form e controlli utente</title>
 <meta name="keywords" content="web, html5, javascript, css"
charset="utf-8">
</head>
<body>
 <form autocomplete="off">
  <fieldset>
   <legend>Dettagli:</legend>
   <table>
    <tr>
     <td>
      <label for="nome">Nome: </label>
     </td>
     <td>
      <input type="text" name="nome" id="nome" autofocus required size="20" />
     </td>
    </tr>
    <tr>
     <td>
      <label for="cognome">Cognome: </label>
     </td>
     <td>
      <input type="text" name="cognome" id="cognome" required size="20" />
     </td>
    </tr>
    <tr>
     <td>
      <label for="pwd">Password: </label>
     </td>
     <td>
      <input type="password" name="password" id="pwd" required size="20"/>
     </td>
    </tr>
    <tr>
     <td>
      <label for="data">Data di nascita: </label>
     </td>
     <td>
      <input type="date" name="data" id="data" required/>
     </td>
    </tr>
    <tr>
     <td>
      Sesso: 
     </td>
     <td>
      <input type="radio" name="sesso" id="maschio" value="maschio"/>
      <label for="maschio">Maschio: </label>
      <input type="radio" name="sesso" id="femmina" value="femmina"/>
      <label for="femmina">Femmina: </label>
     </td>
    </tr>
    <tr>
     <td>
      <label for="mail">Email: </label>
     </td>
     <td>
      <input type="email" name="mail" id="mail" multiple required size="20"
      placeholder="nome.utente@gmail.com" />
     </td>
    </tr>
    <tr>
     <td>
      <label for="i_web">Indirizzo Web: </label>
     </td>
     <td>
      <input type="url" name="i_web" id="i_web" size="20"
      placeholder="http://www.indirizzoweb.it"/>
     </td>
    </tr>
    <tr>
     <td>Materie preferite:</td>
     <td>
      <input type="checkbox" name="storia" id="storia" value="STO"/>
      <label for="storia">Storia: </label>        
      <input type="checkbox" name="matematica" id="matematica" value="MAT"/>
      <label for="matematica">Matematica: </label>   
      <input type="checkbox" name="geografia" id="geografia" value="GEO"/>
      <label for="geografia">Geografia </label>   
      <input type="checkbox" name="fisica" id="fisica" value="FIS"/>
      <label for="fisica">Fisica: </label>   
     </td>
    </tr>
    <tr>
     <td>
      <label for="nr_libri">Quanti libri leggi all'anno? </label>
     </td>
     <td>
      <input type="number" name="nr_libri" id="nr_libri" value="1" />
     </td>
    </tr>
    <tr>
     <td>
      <label for="libri">Ogni quanti mesi compri un libro? </label>
     </td>
     <td>
     <input type="range" name="libri" id="libri" min="1" step="1" max="12" value="1"/>
     </td>
    </tr>
    <tr>
     <td>
      <label for="colore">Il tuo colore preferito? </label>
     </td>
     <td>
      <input type="color" name="colore" id="colore" />
     </td>
    </tr>
    <tr>
     <td>
       Seleziona un sistema operativo: 
     </td>
     <td>
      <select name="so">
        <optgroup label="Famiglia BSD">
         <option value="fbsd">FreeBSD</option>
         <option value="obsd">OpenBSD</option>
         <option value="nbsd">NetBSD</option>
        </optgroup>
        <optgroup label="Famiglia Windows">
         <option value="windows_8">Windows 8</option>
         <option value="windows_7">Windows 7</option>
         <option value="windows_xp">Windows XP</option>
        </optgroup>
       </select>
     </td>
    </tr>
    <tr>
     <td>
      <label for="lp">Scegli un linguaggio di programmazione: </label>
     </td>
     <td>
      <datalist id="lp_datasource">
       <option value="Java"></option>
       <option value="C#"></option>
       <option value="C++"></option>
       <option value="PHP"></option>
       <option value="JavaScript"></option>
       <option value="Python"></option>
       </datalist>
       <input type="text" name="lp" id="lp" list="lp_datasource"/>
      </td>
    </tr>
    <tr>
     <td>
      <label for="note">Note: </label>
     </td>
     <td>
     <textarea name="note" id="note" rows="10"
     cols="20" maxlength="2000" wrap="soft"
     spellcheck="true"></textarea>
      </td>
      </tr>
      <tr>
      <td>
       &nbsp;
      </td>
      <td>
       <button type="submit" id="ok"> Salva i dati <img src="apply.png" /></button>
       <button type="reset" id="reset"> Ripristina <img src="refresh.png" /></button>
      </td>
      </tr>
      </table>
     </fieldset>
    </form>
</body>
</html>


Alcune considerazioni: I controlli di tipo testo input type="text", che hanno l'attributo required rende obbligatorio,
inserire un contenuto (es. nome e un cognome).

E questo è il risultato del FORM:

Dettagli:
Sesso:
Materie preferite:
Seleziona un sistema operativo: