Unobtrusive Javascript and form validation
UPDATE: 27/11/2006 (Comments n. 5 e 6)
Unobtrusive Javascript is not so complicated. In this article, inspired by the italian magazine Hacker Journal, we’re going to validate a simple login form before it’s posted to the server.
Some weeks ago, HJ’s CookBook survey reported an example of Javascript form validation code. The original example was a self-contained HTML file with a table layout and the Javascript code was inserted directly in the HTML (eg. <form onsubmit="return canSubmit(this)">). However the idea sounded interesting to me and with some make-up I came out with the following code.
You can see it in action online or you can download the full code.
Step 1: Component separation
The first thing to do is clean the page from unnecessary code and move all non-HTML code outside. Let’s start with an empty XHTML document and add links to the CSS and the Javascript code files.
<head>
<title>Form Validation Example</title>
<link type="text/css" rel="stylesheet" href="style.css" />
<script type="text/javascript" src="validation.js" ></script>
</head>
The CSS file is very simple. I used a hint by Kevin Hale to obtain something prettier than the default browser rendering.
Step 2: Creating the form
Then we create the form using standard XHTML markup. I used the <fieldset> tag to group the controls, the <legend> tag to title the group and the <label> tag to name text fields.
<form id="login" method="post" action="" enctype="text/plain" >
<fieldset>
<legend>Sign in to our account</legend>
<label for="username">User: </label>
<input class="text" type="text" name="username" id="username" size="15" tabindex="1" /><br />
<label for="password">Password: </label>
<input class="text" type="password" name="password" id="password" size="15" tabindex="2" /><br />
<input type="submit" value="Log in" name="send" tabindex="3" />
</fieldset>
</form>
The form’s action property is left blank, so the form is posted back to itself
UPDATE: 23/06/2008 1) As pointed out by Miki in comment n. 18, tag <label> binds to attribute id.
UPDATE: 23/06/2008 2) W3C Validator reminds me that attribute name is no more supported in XHTML 1.0 Strict.
Step 3: Attaching the events
As you can see, the form’s markup is just basic HTML code. All the Javascript code is inside the external file validation.js.
Initialization
The init() function is applied to the page loading event. The old HTML code <body onload="init()"> it’s been replaced with the unobtrusive code window.onload = init; within the external file.
function init() {
//Attaching the onSubmit event to the login form
loginForm = document.getElementById('login');
loginForm.onsubmit = function () {
return canSubmit(this);
}
//Setting focus to the user field
loginForm.username.focus();
}
Validation
The validation process is performed by the canSubmit function. The function returns true in case of success (the form is then sent to the server) or false otherwise (the form is not sent to the server).
In this example we only care that the text fields are not empty, but we can check for all other information such as text length or specific formatted text (eg. email addresses).
It’s easy, isn’t it?
This solution has two main advantages: independence from Javascript code and separation between content, presentation and behaviour.
The page is independent from Javascript. If a user’s agent is not JS enabled, the form is posted directly to the server and it’s processed by server-side validation code, which must be executed anyway.
Each component (the HTML page, the CSS file and the JS code) can be edited independently from the others.
Also, all the code is supported by standard-compliant browsers: it’s been tested with IE5.01, IE5.5, IE6 and Firefox 1.5.0.1 on Windows XP and with Safari, Camino 1.0, Firefox 1.5.0.1 and Opera 9 preview on Mac OS X Tiger.
9 May 2006, 20:20
It’s good to see standard compliant methods getting out, there are too many examples of bad javascript validation floating around now…
Anyone using this example in production should strongly consider using an addevent routine to push init into the onload event rather than using the straight assignment. Otherwise you may spend a few hours trying to figure out why your other onload events aren’t firing.
*
9 May 2006, 22:00
Thanks Toby.
In effect the first example I wrote used the Scott Andrew’s
addEventroutine, but I wanted to keep this first script straight and simple.However you’re right: in a production enviroment the best choice is an addEvent function.
5 July 2006, 15:00
Ciao molto bello il sistema di login,ma come funziona,cioeè come si fa ad inserire un user e una password che si colleghino poi alla pagina riservata. grazie anticipate a chi mi saprà rispondere!!!!!!(è urgente perche è da mesi che cerco un sistema di login….GRAZIE)
5 July 2006, 15:22
helmut: questo esempio è solo una parte del sistema di login. Per farlo funzionare devi collegare il form ad uno script lato server (PHP, perl, ecc) utilizzando l’attributo
action, per esempio<form method="post" action="validate_user.php">.Sarà lo script a controllare se i dati inseriti sono giusti secondo un metodo che decidi tu, tramite un database o altro sistema.
18 November 2006, 18:39
Veloce e compatto, lo ho trvato ottimo per svolgere lezioni di informatica a non esperti. Ottima la presentazione didattica.
24 November 2006, 17:51
Thanks for this, I’m new to JavaScript and want to learn the correct way from the beginning.
One question – why when you submit the form, you get the alert saying “please enter your user name”, but then the form submits anyway. It doesn’t seem to stop the form from submitting if you leave it blank. Shouldn’t the “return false;” bit after the “alert()” and “focus()” do that?
27 November 2006, 10:48
Thanks Stephen, you caught a little bug!
The code should be:
I’ll fix it soon
27 November 2006, 15:16
Excellent - thanks…
Think I’m starting to understand this now. I’m about half way though Jeremy Keith’s DOM Scripting book which is really easy to understand, just like this post.
Thanks again.
1 December 2006, 20:46
sei grande continua cosi
19 February 2007, 16:13
good article.
if (field.value == “” || field.value == null)
should be:
if (field.value == null || field.value == “”)
so you’ll never check the value of a null variable.
20 February 2007, 12:08
Thanks Palzo.
I did some test on recent browsers (IE6, Firefox 2 win/mac, and Safari) and they all catch only the ‘empty’ value.
In effect the ‘null test’ is there to take care of some unpredictable behaviour I experienced with old browsers and old versions of Javascript.
29 May 2007, 16:42
Salve. ho apprezzato molto il vostro articolo, e l’ho subito applicato a delle prove che sto effettuando per il mio futuro sito web. Avrei però alcune domande da fare.
Essendo agli inizi del Java Script, desidererei sapere come fare per inserire dei messaggi di avviso anche per delle selezioni e non solo campi di testo. E’ inoltre possibile validare il campo indirizzo mail?
Per entrambe le domande, quale codice devo inserire nel vostro esempio?
31 May 2007, 18:43
Ciao Giuseppe,
per le select puoi fare così (es. di una select provincia):
Per convalidare le email ci sono tantissimi esempi più o meno validi o complicati. Uno che mi piace molto è la funzione
checkEmail()a http://developer.apple.com/internet/webcontent/validation.htmlBuon lavoro
9 October 2007, 23:09
I know most people would probably disagree, but this is dumb, and here’s why…
I get why we want to do js unobtrusively. However, there is a certain point where the unobtrusive js becomes more intensive than simply inserting a return confirm() or something in the onsubmit. Why write/store/load up a whole new function with a whole new event handler just to attach a quick validator? I’m not saying this idea is bad. I have a custom ajax library that locates
<
form class=”ajax”> and dynamically attaches on submit that will serialize the form inputs into a string and post it with AJAX. Furthermore, it will check if that form object already has an onsubmit property. If so, it will run that function prior to submitting with ajax. This preserves the simplicity of doing something like…
<
form onsubmit=”return confirm(‘Are you sure?’);” class=”ajax”>
which basically means that it will confirm you want to send before submitting it with ajax. Could it be any easier? I just don’t see why you would want to write a whole new function and event handler just to do something like return canSubmit(). Unobtrusive js is great when you use it to increase efficiency, but a little one liner isn’t going to hurt anybody…
11 October 2007, 17:11
Hi JJMay,
I agree with you. My approach in this post is very simple, not the best solution for a medium web application. I recommend the use of a valid JS library instead and yours seems very interesting.
However in certain situations, where you need just two or three functions for your script to run, this is maybe better than including a 96Kb JS file.
There’s also a nice article by Dustin Diaz on this subject: http://www.dustindiaz.com/roll-out-your-own-interface/
Good work
26 March 2008, 13:37
hi, i’m pretty new with javascript and this is the sort of script i’ve been looking for. But i’ve read somewhere that you should try and avoid alert boxes. I was wondering if you could edit the script in which instead of alert prompts the script highlights the input boxes in red and show a message beside them. Is that possible ?
I’ll use this script now but would much appreciate any help on the above question …
thanx
22 April 2008, 14:33
Hi dev,
as an example, you can use the following code as a starting point to replace the alert statement.
It adds a CSS class to the username input field and adds a paragraph with class error containing a message.
Hope that helps
6 May 2008, 07:27
Complimenti, solo un appunto, il tag label con for va a puntare l’ID di un elemento e non l’attributo name.