facebook google plus twitter
Webucator's Free JavaScript Tutorial

Lesson: JavaScript Form Validation

Welcome to our free JavaScript tutorial. This tutorial is based on Webucator's Introduction to JavaScript Training course.

In this lesson, you will learn about form validation.

Lesson Goals

  • Learn to access data entered by users in forms.
  • Learn to validate text fields and passwords.
  • Learn to validate radio buttons.
  • Learn to validate check boxes.
  • Learn to validate select menus.
  • Learn to validate textareas.
  • Learn to write clean, reusable validation functions.
  • Learn to catch focus, blur, and change events.

Accessing Form Data

All forms on a web page are stored in the document.forms[] array. The first form on a page is document.forms[0], the second form is document.forms[1], and so on. However, it is usually easier to reference forms via their id attribute and refer to them that way - especially as we may add, remove, or move around form elements. For example, a form with id LoginForm can be referenced as document.getElementById('LoginForm'). The major advantage of referencing forms by id is that the forms can be repositioned on the page without affecting the JavaScript.

Elements within a form are properties of that form and can be referenced as follows:

Syntax

document.formName.elementName

But we can access form elements by their ids, too, just as we can forms - it's concise, simple, and clear.

Text fields and passwords have a value property that holds the text value of the field. The following example shows how JavaScript can access user-entered text:

Code Sample:

FormValidation/Demos/FormFields.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Form Fields</title>
<script>
function changeBg(){
		var userName = document.getElementById("userName").value;
		var backgroundClr = document.getElementById("color").value;
		
		document.body.style.backgroundColor = backgroundClr;
		alert(userName + ", the background color is " + backgroundClr + ".");
	}


	window.onload = function() {
		document.getElementById("changebutton").addEventListener("click", function(){
	    	changeBg();
		});
	}
</script>
</head>
<body>
<h1>Change Background Color</h1>
<form name="colorForm">
	Your Name: <input type="text" name="userName" id="userName"><br>
	Background Color: <input type="text" name="color" id="color"><br>
	<input type="button" value="Change Background" id="changebutton">
</form>
</body>
</html>

Code Explanation

Some things to notice:

  1. When the user clicks on the "Change Background" button, the changeBg() function is called. Note how we added a click handler via the addEventListener() method: whereas earlier in the course we used the onclick attribute on the button itself to call a JavaScript function, we now use addEventListener() to call the function. Separating the event handler from the element makes for cleaner, more-easily-maintainable code. Similarly, we call the onload method using window.onload(), rather than (as we had done previously) adding an attribute to the body tag.
  2. The values entered into the userName and color fields are stored in variables (userName and backgroundClr).
  3. We reference the two fields directly via their ids.

Textfield to Textfield

Duration: 15 to 25 minutes.

In this exercise, you will write a function that bases the value of one text field on the value of another.

  1. Open FormValidation/Exercises/TextfieldToTextField.html for editing.
  2. Write a function called getMonth() that passes the month number entered by the user to the monthAsString() function in DateUDFs.js and writes the result in the monthName field.

Code Sample:

FormValidation/Exercises/TextfieldToTextField.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Textfield to Textfield</title>
<script src="DateUDFs.js"></script>
<script>
/*
		Write a function called getMonth() that passes the
		month number entered by the user to the monthAsString()
		function in DateUDFs.js and writes the result in
		the monthName field.
	*/
</script>
</head>
<body>
<h1>Month Check</h1>
<form name="dateForm">
	Month Number: <input type="text" name="MonthNumber" id="MonthNumber" size="2">
	<input type="button" value="Get Month" id="getmonthbutton"><br>
	Month Name: <input type="text" name="monthName" id="monthName" size="10">
</form>
</body>
</html>

Code Explanation

Challenge

  1. If the user enters a number less than 1 or greater than 12 or a non-number, have the function write "Bad Number" in the monthName field.
  2. If the user enters a decimal between 1 and 12 (inclusive), strip the decimal portion of the number.

Solution:

FormValidation/Solutions/TextfieldToTextField.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Textfield to Textfield</title>
<script src="DateUDFs.js"></script>
<script>
function getMonth(){
		var elemMonthNumber = document.getElementById("monthNumber");
		var elemMonthName = document.getElementById("monthName");
		var month = monthAsString(elemMonthNumber.value);
		
		elemMonthName.value = month;
	}

	window.onload = function() {
		document.getElementById("getMonthButton").addEventListener("click", function(){
	    	getMonth();
		});
	}
</script>
</head>
<body>
<h1>Month Check</h1>
<form name="dateForm">
	Month Number: <input type="text" name="monthNumber" id="monthNumber" size="2">
	<input type="button" value="Get Month" id="getMonthButton"><br>
	Month Name: <input type="text" name="monthName" id="monthName" size="10">
</form>
</body>
</html>

Code Explanation

Challenge Solution:

FormValidation/Solutions/TextfieldToTextField-challenge.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Textfield to Textfield</title>
<script src="DateUDFs.js"></script>
<script>
	function getMonth(){
		var elemMonthNumber = document.getElementById("monthNumber");
		var elemMonthName = document.getElementById("monthName");
		var monthNum = parseInt(elemMonthNumber.value);
		
		var month = (monthNum >= 1 && monthNum <= 12) ? monthAsString(monthNum) : "Bad Number";
				
		elemMonthName.value = month;
	}

	window.onload = function() {
		document.getElementById("getMonthButton").addEventListener("click", function(){
	    	getMonth();
		});
	}
</script>
</head>
<body>
<h1>Month Check</h1>
<form name="dateForm">
	Month Number: <input type="text" name="monthNumber" id="monthNumber" size="2">
	<input type="button" value="Get Month" id="getMonthButton"><br>
	Month Name: <input type="text" name="monthName" id="monthName" size="10">
</form>
</body>
</html>

Code Explanation

Notice the use of the ternary operator.

Basics of Form Validation

When the user clicks on a submit button or presses the return/enter key while in a form field, an event occurs that can be caught with the form's onsubmit event handler. Unless JavaScript is used to explicitly cancel the submit event, the form will be submitted. The return false; statement explicitly cancels the submit event. For example, the following form will never be submitted:

<form action="Process.html" onsubmit="return false;">
	<!--Code for form fields would go here-->
	<input type="submit" value="Submit Form">
</form>

Note that, for brevity, we here use the onsubmit attribute to listen for the submit event; we'll generally listen for the submit event (and other events) with addEventListener() to keep our JavaScript separate from our HTML markup.

Of course, when validating a form, we only want the form not to submit if something is wrong. We can use the preventDefault() method to stop the form from submitting if the data entered by the user doesn't match what we expect. Let's look at an example

Code Sample:

FormValidation/Demos/Login.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
<script>
function validate(e){
	var userName = document.getElementById("Username").value;
	var password = document.getElementById("Password").value;

	if (userName.length === 0) {
		alert("You must enter a username.");
		e.preventDefault();
		return;
	}

	if (password.length === 0) {
		alert("You must enter a password.");
		e.preventDefault();
		return;
	}
}

window.onload = function() {
	document.getElementById("logInForm").addEventListener("submit", function(e){
    	validate(e);
	});
}
</script>
</head>
<body>
<h1>Login Form</h1>
<form method="post" action="Process.html" id="logInForm">

	Username: <input type="text" name="Username" id="Username" size="10"><br>
	Password: <input type="password" name="password" id="Password" size="10"><br>

	<input type="submit" value="Submit">
	<input type="reset" value="Reset Form">
</form>
</body>
</html>

Code Explanation

  1. When the user submits the form, the addEventListener event handler captures the submit event and calls the validate() function, passing in the event object ("e").
  2. The values entered into the Username and Password fields are stored in variables (userName and password).
  3. An if condition is used to check if userName is an empty string. If it is, an alert pops up explaining the problem and we use preventDefault() to prevent the form from submitting. We use return to halt the function - the function does not check for any additional validation errors.
  4. An if condition is used to check that password is an empty string. If it is, an alert pops up explaining the problem and we use preventDefault() to prevent the form from submitting. We use return to halt the function - the function does not check for any additional validation errors.
  5. If neither if condition catches a problem, then there is no call to preventDefault() and the form submits.

Cleaner Validation

There are a few improvements we can make on the last example.

One problem is that the validate() function only checks for one problem at a time. That is, if it finds and error, it reports it immediately and does not check for additional errors. Why not just tell the user all the mistakes that need to be corrected, so (s)he doesn't have to keep submitting the form to find each subsequent error?

Another problem is that the code is not written in a way that makes it easily reusable. For example, checking for the length of user-entered values is a common thing to do, so it would be nice to have a ready-made function to handle this.

These improvements are made in the example below.

Code Sample:

FormValidation/Demos/Login2.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
<script>
function validate(e){
	var userName = document.getElementById("Username").value;
	var password = document.getElementById("Password").value;
	var errors = [];

	if (!checkLength(userName,1,100)) {
		errors[errors.length] = "You must enter a username.";
	}

	if (!checkLength(password,1,100)) {
		errors[errors.length] = "You must enter a password.";
	}

	if (errors.length > 0) {
		reportErrors(errors);
		e.preventDefault();
	}
}

function checkLength(text, min, max){

	if (text.length < min || text.length > max) {
		return false;
	}
	return true;
}

function reportErrors(errors){
	var msg = "There were some problems...\n";
	var numError;
	for (var i=0; i<errors.length; i++) {
		numError = i + 1;
		msg += "\n" + numError + ". " + errors[i];
	}
	alert(msg);
}

window.onload = function() {
	document.getElementById("logInForm").addEventListener("submit", function(e){
    	validate(e);
	});
}
</script>
</head>
<body>
<h1>Login Form</h1>
<form method="post" action="Process.html" id="logInForm">

	Username: <input type="text" name="Username" id="Username" size="10"><br>
	Password: <input type="password" name="Password" id="Password" size="10"><br>

	<input type="submit" value="Submit">
	<input type="reset" value="Reset Form">
</form>
</body>
</html>

Code Explanation

Some things to notice:

  1. Two additional functions are created: checkLength() and reportErrors().
    • The checkLength() function takes three arguments, the text to examine, the required minimum length, and the required maximum length.
    • The reportErrors() function takes one argument, an array holding the errors. It loops through the errors array creating an error message and then it pops up an alert with a message. The \n is an escape character for a newline.
  2. In the main validate() function, a new array, errors, is created to hold any errors that are found.
  3. userName and password are passed to checkLength() for validation.
    • If errors are found, they are appended to errors.
  4. If there are any errors in errors (i.e., if its length is greater than zero), then errors is passed to reportErrors(), which pops up an alert letting the user know where the errors are. The validate() function then uses e.preventDefault() to prevent the form from submiting.

By modularizing the code in this way, it makes it easy to add new validation functions. In the next examples we will move the reusable validation functions into a separate JavaScript file called FormValidation.js.

Validating a Registration Form

Duration: 25 to 40 minutes.

In this exercise, you will write code to validate a registration form. You may find it useful to use the Common String Methods table as a reference.

  1. Open FormValidation/Exercises/FormValidation.js for editing.
    • Create a function called compareValues() that takes two arguments: val1 and val2. The function should return:
      • 0 if the two values are equal
      • -1 if val1 is greater than val2
      • 1 if val2 is greater than val1
    • Create a function called checkEmail() that takes one argument: email. The function should return:
      • false if email has fewer than 6 characters
      • false if email does not contain an @ symbol
      • false if email does not contain a period (.)
      • true otherwise
  2. Open FormValidation/Exercises/Register.html for editing.
    • Add code so that the functions in FormValidation.js are accessible from this page.
    • Create a validate() function that does the following:
      • Checks that the FirstName, LastName, City, Country, UserName, and Password1 fields are filled out.
      • Checks that the middle initial is a single character.
      • Checks that the state is exactly two characters.
      • Checks that the email is a valid email address.
      • Checks that the values entered into Password1 and Password2 are the same.
      • If there are errors, passes reportErrors() the errors array and use e.preventDefault(); to prevent the form from submitting.
  3. Test your solution in a browser.

In FormValidation/Exercises/FormValidation.js, modify the checkEmail() function so that it also checks to see that the final period (.) is after the final @ symbol. The solution is included in FormValidation/Solutions/FormValidation.js.

Solution:

FormValidation/Solutions/FormValidation.js
/*
	Function Name: checkLength
	Arguments: text,min?,max?
	Returns:
		false if text has fewer than min characters
		false if text has more than max characters
		true otherwise
*/
function checkLength(text, min, max){

	if (text.length < min || text.length > max) {
		return false;
	}
	return true;
}
/*
	Function Name: compareValues
	Arguments: val1, val2
	Returns:
		0 if two values are equal
		-1 if val1 is greater than val2
		1 if val2 is greater than val1
*/
function compareValues(val1, val2){
	if (val1 > val2) {
		return -1;
	} else if(val2 > val1) {
		return 1;
	} else {
		return 0;
	}
}

/*
	Function Name: checkEmail
	Arguments: email
	Returns:
		false if email has fewer than 6 characters
		false if email does not contain @ symbol 
		false if email does not contain a period (.)
		true otherwise
*/
function checkEmail(email){
	if (!checkLength(email, 6)) {
		return false;
	} else if (email.indexOf("@") == -1) {
		return false;
	} else if (email.indexOf(".") == -1) {
		return false;
	}
	/* THIS LAST ELSE IF FROM CHALLENGE */
	else if (email.lastIndexOf(".") < email.lastIndexOf("@")) {
		return false;
	}
	return true;}
            

Solution:

FormValidation/Solutions/Register.html
---- C O D E   O M I T T E D ----

<script src="FormValidation.js"></script>
<script>
function validate(e){
	var firstName = document.getElementById("FirstName").value;
	var midInit = document.getElementById("MidInit").value;
	var lastName = document.getElementById("LastName").value;
	var city = document.getElementById("City").value;
	var state = document.getElementById("State").value;
	var country = document.getElementById("Country").value;
	var zipCode = document.getElementById("Zip").value;
	var email = document.getElementById("Email").value;
	var userName = document.getElementById("Username").value;
	var password1 = document.getElementById("Password1").value;
	var password2 = document.getElementById("Password2").value;
	var errors = [];
	
	if (!checkLength(firstName,1,100)) {
		errors[errors.length] = "You must enter a first name.";
	}

	if (!checkLength(midInit, 1, 1)) {
		errors[errors.length] = "You must enter a one-letter middle initial.";
	}

	if (!checkLength(lastName,1,100)) {
		errors[errors.length] = "You must enter a last name.";
	}

	if (!checkLength(city,1,100)) {
		errors[errors.length] = "You must enter a city.";
	}

	if (!checkLength(state, 2, 2)) {
		errors[errors.length] = "You must enter a state abbreviation.";
	}

	if (!checkLength(country,1,100)) {
		errors[errors.length] = "You must enter a country.";
	}

	if (!checkLength(zipCode, 5, 10)) {
		errors[errors.length] = "You must enter a valid zip code.";
	}
	if (!checkEmail(email)) {
		errors[errors.length] = "You must enter a valid email address.";
	}

	if (!checkLength(userName,1,100)) {
		errors[errors.length] = "You must enter a username.";
	}
	
	if (!checkLength(password1,1,100)) {
		errors[errors.length] = "You must enter a password.";
	} else if (compareValues(password1, password2) !== 0) {
		errors[errors.length] = "Passwords don't match.";
	}

	if (errors.length > 0) {
		reportErrors(errors);
		e.preventDefault();
	}
}function reportErrors(errors){
	var msg = "There were some problems...\n";
	var numError;
	for (var i=0; i<errors.length; i++) {
		numError = i + 1;
		msg += "\n" + numError + ". " + errors[i];
	}
	alert(msg);
}

window.onload = function() {
  document.getElementById("registrationform").addEventListener("submit", function(e){
      validate(e);
  });
}
</script>
---- C O D E   O M I T T E D ----

Validating Radio Buttons

Radio buttons that have the same name are grouped as arrays. Generally, the goal in validating a radio button array is to make sure that the user has checked one of the options. Individual radio buttons have the checked property, which is true if the button is checked and false if it is not. The example below shows a simple function for checking radio button arrays.

Code Sample:

FormValidation/Demos/RadioArrays.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Radio Arrays</title>
<script>
function validate(e){
	var errors = [];
	var f = e.currentTarget;
		
	              if (!checkRadioArray(f.container) ) {
		errors[errors.length] = "You must choose a cup or cone.";
	}
	
	if (errors.length > 0) {
		reportErrors(errors);
		e.preventDefault();
	}
}

function checkRadioArray(radioButtons){
	for (var i=0; i < radioButtons.length; i++) {
		if (radioButtons[i].checked) {
			return true;
		}
	}
	return false;
}

function reportErrors(errors){
	var msg = "There were some problems...\n";
	var numError;
	for (var i=0; i<errors.length; i++) {
		numError = i + 1;
		msg += "\n" + numError + ". " + errors[i];
	}
	alert(msg);
}

window.onload = function() {
	document.getElementById("IceCreamForm").addEventListener("submit", function(e){
    	validate(e);
	});
}

</script>
</head>
<body>
<h1>Ice Cream Form</h1>
<form method="post" action="Process.html" id="IceCreamForm">
	<strong>Cup or Cone?</strong>
	<input type="radio" name="container" id="Container_Cup" value="cup"> Cup
	<input type="radio" name="container" id="Container_Plaincone" value="plainCone"> Plain cone
	<input type="radio" name="container" id="Container_Sugarcone" value="sugarCone"> Sugar cone
	<input type="radio" name="container" id="Container_Wafflecone" value="waffleCone"> Waffle cone
	<br><br>
	<input type="submit" value="Place Order">
</form>

</body>
</html>

Code Explanation

The checkRadioArray() function takes a radio button array as an argument, loops through each radio button in the array, and returns true as soon as it finds one that is checked. Since it is only possible for one option to be checked, there is no reason to continue looking once a checked button has been found. If none of the buttons are checked, the function returns false.

Note that we get the form from the event object e with e.currentTarget, store the form as JavaScript variable f, and then get the radio button set by name (f.container). While not needed in this example, we adopt the common practice of giving radio buttons unique ids, where each id is the shared name, underscore, then unique value, like container_cup. This is useful if we need to refer to a specific radio button.

Validating Check Boxes

Like radio buttons, check boxes have the checked property, which is true if the button is checked and false if it is not. However, unlike radio buttons, check boxes are not stored as arrays. The example below shows a simple function for checking to make sure a check box is checked.

Code Sample:

FormValidation/Demos/CheckBoxes.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Checkboxes</title>
<script>
function validate(e){
	var errors = [];
	
	if ( !checkCheckBox(document.getElementById("terms")) ) {
		errors[errors.length] = "You must agree to the terms.";
	}
	
	if (errors.length > 0) {
		reportErrors(errors);
		e.preventDefault();
	}

}function checkCheckBox(cb){
	return cb.checked;
}

function reportErrors(errors){
	var msg = "There were some problems...\n";
	var numError;
	for (var i = 0; i<errors.length; i++) {
		numError = i + 1;
		msg += "\n" + numError + ". " + errors[i];
	}
	alert(msg);
}

window.onload = function() {
	document.getElementById("noicecreamform").addEventListener("submit", function(e){
    	validate(e);
	});
}
</script>
</head>
<body>
<h1>Ice Cream Form</h1>
<form method="post" action="Process.html" id="noicecreamform">
	<input type="checkbox" name="terms" id="terms">
	I understand that I'm really not going to get any ice cream.
	<br><br>
	<input type="submit" value="Place Order">
</form>

</body>
</html>

Code Explanation

Validating Select Menus

Select menus contain an array of options. The selectedIndex property of a select menu contains the index of the option that is selected. Often the first option of a select menu is something meaningless like "Please choose an option..." The checkSelect() function in the example below makes sure that the first option is not selected.

Code Sample:

FormValidation/Demos/SelectMenus.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Select Menus</title>
<script>
function validate(e){
	var errors = [];
	
	if (!checkSelect(document.getElementById("flavor")) ) {
		errors[errors.length] = "You must choose a flavor.";
	}
	
	if (errors.length > 0) {
		reportErrors(errors);
		e.preventDefault();
	}

}

function checkSelect(select){
	return (select.selectedIndex > 0);
}
function reportErrors(errors){
	var msg = "There were some problems...\n";
	var numError;
	for (var i=0; i<errors.length; i++) {
		numError = i + 1;
		msg += "\n" + numError + ". " + errors[i];
	}
	alert(msg);
}

window.onload = function() {
	document.getElementById("flavorform").addEventListener("submit", function(e){
    	validate(e);
	});
}
</script>
</head>
<body>
<h1>Ice Cream Form</h1>
<form method="post" action="Process.html" id="flavorform">
	<strong>Flavor:</strong>
	<select name="flavor" id="flavor">
		<option value="0" selected></option>
		<option value="choc">Chocolate</option>
		<option value="straw">Strawberry</option>
		<option value="van">Vanilla</option>
	</select>
	<br><br>
	<input type="submit" value="Place Order">
</form>
</body>
</html>

Focus, Blur, and Change Events

Focus, blur and change events can be used to improve the user experience.

Focus and Blur

Focus and blur events are caught with the onfocus and onblur event handlers. These events have corresponding focus() and blur() methods. The example below shows

  1. how to set focus on a field.
  2. how to capture when a user leaves a field.
  3. how to prevent focus on a field.

Code Sample:

FormValidation/Demos/FocusAndBlur.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Focus and Blur</title>
<script src="DateUDFs.js"></script>
<script>
function getMonth(){
	var elemMonthNumber = document.DateForm.MonthNumber;
	var monthNumber = elemMonthNumber.value;
	
	var elemMonthName = document.DateForm.MonthName;
	var month = monthAsString(elemMonthNumber.value);
	
	elemMonthName.value = (monthNumber > 0 && monthNumber <=12) ? month : "Bad Number";
}

window.onload = function() {
	document.getElementById("MonthNumber").focus();

	document.getElementById("MonthNumber").addEventListener("blur", function(e){
		getMonth();
	});

	document.getElementById("MonthName").addEventListener("focus", function(e){
		this.blur();
	});
}
</script>
</head>
<body>
<h1>Month Check</h1>
<form name="DateForm" id="DateForm">
	Month Number: 
	<input type="text" name="MonthNumber" id="MonthNumber" size="2">
	Month Name:
	<input type="text" name="MonthName" id="MonthName" size="10">
</form>
</body>
</html>

Code Explanation

Things to notice:

  1. When the document is loaded, we call focus() on the MonthNumber element, making that field active for the user to start typing.
  2. When focus leaves the MonthNumber field, we capture the blur event and call the getMonth() function.
  3. The onfocus event handler of the MonthName element triggers a call to the blur() method of this (the MonthName element itself) to prevent the user from focusing on the MonthName element.

Change

Change events are caught when the value of a text element changes or when the selected index of a select element changes. The example below shows how to capture a change event.

Code Sample:

FormValidation/Demos/Change.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Change</title>
<script src="DateUDFs.js"></script>
<script>
function getMonth(){
	var elemMonthNumber = document.DateForm.MonthNumber;
	var i = elemMonthNumber.selectedIndex;
	var monthNumber = elemMonthNumber[i].value;
	
	var elemMonthName = document.DateForm.MonthName;
	var month = monthAsString(monthNumber);
	
	elemMonthName.value = (i === 0) ? "" : month;
}

window.onload = function() {
	document.getElementById("MonthNumber").focus();

	document.getElementById("MonthNumber").addEventListener("change", function(e){
		getMonth();
	});

	document.getElementById("MonthName").addEventListener("focus", function(e){
		this.blur();
	});
}
</script>
</head>
<body>
<h1>Month Check</h1>
<form name="DateForm">
	Month Number: 
	<select name="MonthNumber" id="MonthNumber">
		<option>--Choose--</option>
		<option value="1">1</option>
		<option value="2">2</option>
		<option value="3">3</option>
		<option value="4">4</option>
		<option value="5">5</option>
		<option value="6">6</option>
		<option value="7">7</option>
		<option value="8">8</option>
		<option value="9">9</option>
		<option value="10">10</option>
		<option value="11">11</option>
		<option value="12">12</option>
	</select><br>
	Month Name: <input type="text" name="MonthName" id="MonthName" size="10">
</form>
</body>
</html>

Code Explanation

This is similar to the last example. The only major difference is that MonthNumber is a select menu instead of a text field and that the getMonth() function is called when a different option is selected - that is, when the select menu changes.

Validating Textareas

Textareas can be validated the same way that text fields are by using the checkLength() function shown earlier. However, because textareas generally allow for many more characters, it's often difficult for the user to know if he's exceeded the limit. It could be helpful to let the user know if there's a problem as soon as focus leaves the textarea. The example below, which contains a more complete form for ordering ice cream, includes a function that alerts the user if there are too many characters in a textarea.

Code Sample:

FormValidation/Demos/IceCreamForm.html
---- C O D E   O M I T T E D ----

function checkLength(text, min=1, max=10000){
	if (text.length < min || text.length > max) {
		return false;
	}
	return true;
}
function checkTextArea(textArea, max){
	var numChars, chopped, message;
	if (!checkLength(textArea.value, 0, max)) {
		numChars = textArea.value.length;
		chopped = textArea.value.substr(0, max);
		message = 'You typed ' + numChars + ' characters.\n';
		message += 'The limit is ' + max + '.';
		message += 'Your entry will be shortened to:\n\n' + chopped;
		alert(message);
		textArea.value = chopped;
	}
}


---- C O D E   O M I T T E D ----

	<p>
	<strong>Special Requests:</strong><br>
	<textarea name="requests" id="requests" cols="40" rows="6" wrap="virtual"></textarea>
	</p>
	
---- C O D E   O M I T T E D ----

Improving the Registration Form

Duration: 15 to 25 minutes.

In this exercise, you will make some improvements to the registration form from the last exercise.

  1. Open FormValidation/Exercises/FormValidation2.js in your editor. You will see that the functions discussed above have been added: checkRadioArray(), checkCheckBox(), checkSelect(), and checkTextArea().
  2. Open FormValidation/Exercises/Register2.html for editing.
    • Notice that the following changes have been made to the form:
      • State has been changed from a textfield to a select menu. The first option is meaningless. The next 51 options are U.S. states. The rest of the options are Canadian provinces.
      • Country has been changed to a radio array.
      • A Comments field has been added.
      • A Terms check box has been added.
    • Write code that:
      • Checks that a country is selected.
      • Checks that the country and state selection are in sync.
      • Checks that the terms have been accepted.
    • Add an event handler for the Comments textarea (as you saw in our earlier demo) that alerts the user if the comment is too long.
  3. Test your solution in a browser.

Solution:

FormValidation/Solutions/Register2.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Registration Form</title>
<script src="FormValidation2.js"></script>
<script>
	function validate(e){
		var f = e.currentTarget;
		var firstName = document.getElementById("FirstName").value;
		var midInit = document.getElementById("MidInit").value;
		var lastName = document.getElementById("LastName").value;
		var city = document.getElementById("City").value;
		var state = document.getElementById("State").value;
		var zipCode = document.getElementById("Zip").value;
		var email = document.getElementById("Email").value;
		var userName = document.getElementById("Username").value;
		var password1 = document.getElementById("Password1").value;
		var password2 = document.getElementById("Password2").value;
		var errors = [];

		if (!checkLength(firstName,1,100)) {
			errors[errors.length] = "You must enter a first name.";
		}

		if (!checkLength(midInit, 1, 1)) {
			errors[errors.length] = "You must enter a one-letter middle initial.";
		}

		if (!checkLength(lastName,1,100)) {
			errors[errors.length] = "You must enter a last name.";
		}

		if (!checkLength(city,1,100)) {
			errors[errors.length] = "You must enter a city.";
		}

		if (!checkLength(zipCode, 5, 10)) {
			errors[errors.length] = "You must enter a valid zip code.";
		}
		if (!checkEmail(email)) {
			errors[errors.length] = "You must enter a valid email address.";
		}

		if (!checkLength(userName,1,100)) {
			errors[errors.length] = "You must enter a username.";
		}

		if (!checkLength(password1,1,100)) {
			errors[errors.length] = "You must enter a password.";
		} else if (compareValues(password1, password2) !== 0) {
			errors[errors.length] = "Passwords don't match.";
		}

		if (!checkRadioArray(f.Country)) {
			errors[errors.length] = "You must select a country.";
		} else if ((!document.getElementById("Country_Other").checked && f.State.selectedIndex === 0)
			|| (document.getElementById("Country_USA").checked && f.State.selectedIndex > 51)
			|| (document.getElementById("Country_CA").checked && f.State.selectedIndex <= 51)
			|| (document.getElementById("Country_Other").checked && f.State.selectedIndex > 0)) {

			errors[errors.length] = "Country and State don't match.";
		}

		if (!checkCheckBox(document.getElementById("Terms")) ) {
			errors[errors.length] = "You must agree to the terms.";
		}

		if (errors.length > 0) {
			reportErrors(errors);
			e.preventDefault();
		}

	}

	function reportErrors(errors){
		var msg = "There were some problems...\n";
		var numError;
		for (var i=0; i<errors.length; i++) {
			numError = i + 1;
			msg += "\n" + numError + ". " + errors[i];
		}
		alert(msg);
	}

	window.onload = function() {
	  	document.getElementById("registrationform").addEventListener("submit", function(e){
	    	validate(e);
	  	});

	  	document.getElementById("Comments").addEventListener("blur", function(){
			checkTextArea(this, 100);
		});
	}
</script>
</head>
<body>
<h1>Registration Form</h1>
<form method="post" id="registrationform" action="Process.html">
<table border="0" cellspacing="2" cellpadding="2">
<tr>
	<td>First Name:</td>
	<td><input type="text" name="FirstName" id="FirstName" size="20"></td>
</tr>
<tr>
	<td>Middle Initial:</td>
	<td><input type="text" name="MidInit" id="MidInit" size="2"></td>
</tr>
<tr>
	<td> Last Name:</td>
	<td><input type="text" name="LastName" id="LastName" size="20"></td>
</tr>
<tr>
	<td>City: </td>
	<td><input type="text" name="City" id="City" size="20"></td>
</tr>
<tr>
	<td>State/Province: </td>
	<td>
		<select name="State" id="State">
			<option value="0">Please Choose...</option>
			<option value="AL">Alabama</option>
			<option value="AK">Alaska</option>
			<option value="AZ">Arizona</option>
			<option value="AR">Arkansas</option>
			<option value="CA">California</option>
			<option value="CO">Colorado</option>
			<option value="CT">Connecticut</option>
			<option value="DE">Delaware</option>
			<option value="DC">District of Columbia</option>
			<option value="FL">Florida</option>
			<option value="GA">Georgia</option>
			<option value="HI">Hawaii</option>
			<option value="ID">Idaho</option>
			<option value="IL">Illinois</option>
			<option value="IN">Indiana</option>
			<option value="IA">Iowa</option>
			<option value="KS">Kansas</option>
			<option value="KY">Kentucky</option>
			<option value="LA">Louisiana</option>
			<option value="ME">Maine</option>
			<option value="MD">Maryland</option>
			<option value="MA">Massachusetts</option>
			<option value="MI">Michigan</option>
			<option value="MN">Minnesota</option>
			<option value="MS">Mississippi</option>
			<option value="MO">Missouri</option>
			<option value="MT">Montana</option>
			<option value="NE">Nebraska</option>
			<option value="NV">Nevada</option>
			<option value="NH">New Hampshire</option>
			<option value="NJ">New Jersey</option>
			<option value="NM">New Mexico</option>
			<option value="NY">New York</option>
			<option value="NC">North Carolina</option>
			<option value="ND">North Dakota</option>
			<option value="OH">Ohio</option>
			<option value="OK">Oklahoma</option>
			<option value="OR">Oregon</option>
			<option value="PA">Pennsylvania</option>
			<option value="RI">Rhode Island</option>
			<option value="SC">South Carolina</option>
			<option value="SD">South Dakota</option>
			<option value="TN">Tennessee</option>
			<option value="TX">Texas</option>
			<option value="UT">Utah</option>
			<option value="VT">Vermont</option>
			<option value="VA">Virginia</option>
			<option value="WA">Washington</option>
			<option value="WV">West Virginia</option>
			<option value="WI">Wisconsin</option>
			<option value="WY">Wyoming</option>
			<option value="AB">Alberta</option>
			<option value="BC">British Columbia</option>
			<option value="MB">Manitoba</option>
			<option value="NB">New Brunswick</option>
			<option value="NF">Newfoundland</option>
			<option value="NS">Nova Scotia</option>
			<option value="ON">Ontario</option>
			<option value="PE">Prince Edward Island</option>
			<option value="QC">Quebec</option>
			<option value="SK">Saskatchewan</option>
		</select>
	</td>
</tr>
<tr valign="top">
	<td>Country:</td>
	<td>
		<input type="radio" name="Country" id="Country_USA" value="USA"> United States<br>
		<input type="radio" name="Country" id="Country_CA" value="CA"> Canada<br>
		<input type="radio" name="Country" id="Country_Other" value="Other"> Other
	</td>
</tr>
<tr>
	<td>Zip: </td>
	<td><input type="text" name="Zip" id="Zip" size="10"></td>
</tr>
<tr>
	<td>Email: </td>
	<td><input type="text" name="Email" id="Email" size="30"></td>
</tr>
<tr>
	<td>Username:</td>
	<td><input type="text" name="Username" id="Username" size="10"></td>
</tr>
<tr>
	<td>Password:</td>
	<td><input type="password" name="Password1" id="Password1" size="10"></td>
</tr>
<tr>
	<td>Repeat Password: </td>
	<td><input type="password" name="Password2" id="Password2" size="10"></td>
</tr>
<tr valign="top">
	<td>Comments: </td>
	<td>
		<textarea name="Comments" id="Comments" cols="30" rows="3" wrap="virtual"></textarea>
	</td>
</tr>
<tr>
	<td colspan="2">
		<input type="checkbox" name="Terms" id="Terms" value="checkbox">
		I agree to the site terms.
	</td>
</tr>
<tr>
	<td colspan="2" align="center">
		<input name="submit" type="submit" value="Submit">
		<input name="reset" type="reset" value="Reset Form">
	</td>
</tr>
</table>
</form>
</body>
</html>

Code Explanation