Form Handling

Exclusive offer: get 50% off this eBook here
jQuery 2.0 Development Cookbook

jQuery 2.0 Development Cookbook — Save 50%

Over 90 recipes providing modern solutions to web development problems with real-world examples with this book and ebook

£16.99    £8.50
by Leon Revill | February 2014 | Open Source Web Development

In this article written by Leon Revill, the author of the book jQuery 2.0 Development Cookbook, we will look at how to create robust and attractive web forms with animation, validation, and user feedback. We will cover:

  • Implementing basic form validation
  • Adding number validation
  • Adding credit card number validation
  • Adding date validation
  • Adding e-mail address validation
  • Implementing live form validation
  • Adding a password strength indicator
  • Adding anti-spam measures
  • Implementing input character restrictions

(For more resources related to this topic, see here.)

Collecting user data is a basic function of many websites and web applications, from simple data collection techniques such as registration or login information, to more complex scenarios such as payment or billing information. It is important that only relevant and complete information is collected from the user. To ensure this, the web developer must enforce validation on all data input. It is also important to provide a good user experience while enforcing this data integrity. This can be done by providing useful feedback to the user regarding any validation errors their data may have caused. This article will show you how to create an attractive web form that enforces data integrity while keeping a high-quality user experience.

A very important point to note is that any JavaScript or jQuery validation is open to manipulation by the user. JavaScript and jQuery resides within the web browser, so a user with little knowledge can easily modify the code to bypass any client-side validation techniques. This means that client-side validation cannot be totally relied on to prevent the user from submitting invalid data. Any validation done within the client side must be replicated on the server, which is not open for manipulation by the user.

We use client-side validation to improve the user experience. Because of this, the user does not need to wait for a server response.

Implementing basic form validation

At the most basic level of form validation, you will need to be able to prevent the user from submitting empty values. This recipe will provide the HTML and CSS code for a web form that will be used for recipes 1 through 8 of this article.

Getting ready

Using your favorite text editor or IDE, create a blank HTML page in an easily accessible location and save this file as recipe-1.html. Ensure that you have the latest version of jQuery downloaded to the same location as this HTML file.

This HTML page will form the basis of most of this article, so remember to keep it after you have completed this recipe.

How to do it…

Learn how to implement basic form validation with jQuery by performing the following steps:

  1. Add the following HTML code to index.html. Be sure to change the source location of the JavaScript included for the jQuery library, pointing it to where the latest version of jQuery is downloaded on your computer.

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <head>    <title>Chapter 5 :: Recipe 1</title>    <link type="text/css" media="screen" rel="stylesheet" href="styles.css" />    <script src = "jquery.min.js"></script>    <script src = "validation.js"></script> </head> <body>    <form id="webForm" method="POST">       <div class="header">          <h1>Register</h1>       </div>       <div class="input-frame">          <label for="firstName">First Name:</label>          <input name="firstName" id="firstName" type="text"             class="required" />       </div>       <div class="input-frame">          <label for="lastName">Last Name:</label>          <input name="lastName" id="lastName" type="text"             class="required" />       </div>       <div class="input-frame">          <label for="email">Email:</label>          <input name="email" id="email" type="text"             class="required email" />       </div>       <div class="input-frame">          <label for="number">Telephone:</label>          <input name="number" id="number" type="text"             class="number" />       </div>       <div class="input-frame">          <label for="dob">Date of Birth:</label>          <input name="dob" id="dob" type="text"             class="required date"             placeholder="DD/MM/YYYY"/>       </div>       <div class="input-frame">          <label for="creditCard">Credit Card #:</label>          <input name="creditCard" id="creditCard"             type="text" class="required credit-card" />       </div>       <div class="input-frame">          <label for="password">Password:</label>          <input name="password" id="password"             type="password" class="required" />       </div>       <div class="input-frame">          <label for="confirmPassword">Confirm             Password:</label>             <input name="confirmPassword"                id="confirmPassword" type="password"                class="required" />       </div>       <div class="actions">          <button class="submit-btn">Submit</button>       </div>    </form> </body> </html>

  2. Create a CSS file named styles.css in the same directory and add the following CSS code to add style to our HTML page and form:

    @import url(http: //fonts.googleapis.com/css?family=Ubuntu); body {    background-color: #FFF;    font-family: 'Ubuntu', sans-serif; } form {    width: 500px;    padding: 20px;    background-color: #333;    border-radius: 5px;    margin: 10px auto auto auto;    color: #747474;    border: solid 2px #000; } form label {    font-size: 14px;    line-height: 30px;    width: 27%;    display: inline-block;    text-align: right; } .input-frame {    clear: both;    margin-bottom: 25px;    position: relative; } form input {    height: 30px;    width: 330px;    margin-left: 10px;    background-color: #191919;    border: solid 1px #404040;    padding-left: 10px;    color: #DB7400; } form input:hover {    background-color: #262626; } form input:focus {    border-color: #DB7400; } form .header {    margin: -20px -20px 25px -20px;    padding: 10px 10px 10px 20px;    position: relative;    background-color: #DB7400;    border-top-left-radius: 4px;    border-top-right-radius: 4px; } form .header h1 {    line-height: 50px;    margin: 0px;    padding: 0px;    color: #FFF;    font-weight: normal; } .actions {    text-align: right; } .submit-btn {    background-color: #DB7400;    border: solid 1px #000;    border-radius: 5px;    color: #FFF;    padding: 10px 20px 10px 20px;    text-decoration: none;    cursor: pointer; } .error input {    border-color: red; } .error-data {    color: red;    font-size: 11px;    position: absolute;    bottom: -15px;    left: 30%; }

  3. In addition to the jQuery library, the previous HTML page also uses another JavaScript file. Create a blank JavaScript file in the directory where the index.html file is saved. Save this file as validation.js and add the following JavaScript code:

    $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       //Remove old errors       $('.input-frame').removeClass('error');       $('.error-data').remove();       for (var i = 0; i < inputs.length; i++) {          var input = inputs[i];          if ($(input).hasClass('required') &&             !validateRequired($(input).val())) {             addErrorData($(input), "This is a required             field");             isError = true;          }         }       if (isError === false) {          //No errors, submit the form          $('#webForm').submit();       }    }); });   function validateRequired(value) {    if (value == "") return false;    return true; }   function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); }

  4. Open index.html in a web browser and you should see a form similar to the following screenshot:

  5. If you click on the Submit button to submit an empty form, you will be presented with error messages under the required fields.

How it works…

Now, let us understand the steps performed previously in detail.

HTML

The HTML creates a web form with various fields that will take a range of data inputs, including text, date of birth, and credit card number. This page forms the basis for most of this article. Each of the input elements has been given different classes depending on what type of validation they require. For this recipe, our JavaScript will only look at the required class, which indicates a required field and therefore cannot be blank. Other classes have been added to the input fields, such as date and number, which will be used in the later recipes in this article.

CSS

Basic CSS has been added to create an attractive web form. The CSS code styles the input fields so they blend in with the form itself and adds a hover effect. The Google Web Font Ubuntu has also been used to improve the look of the form.

jQuery

The first part of the jQuery code is wrapped within $(function(){});, which will ensure the code is executed on page load. Inside this wrapper, we attach a click event handler to the form submit button, shown as follows:

$(function(){     $('.submit-btn').click(function(event){         //Prevent form submission         event.preventDefault();             }); });

As we want to handle the form submission based on whether valid data has been provided, we use event.preventDefault(); to initially stop the form from submitting, allowing us to perform the validation first, shown as follows:

var inputs = $('input'); var isError = false;

After the preventDefault code, an inputs variable is declared to hold all the input elements within the page, using $('input') to select them. Additionally, we create an isError variable, setting it to false. This will be a flag to determine if our validation code has discovered an error within the form. These variable declarations are shown previously. Using the length of the inputs variable, we are able to loop through all of the inputs on the page. We create an input variable for each input that is iterated over, which can be used to perform actions on the current input element using jQuery. This is done with the following code:

for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; }

After the input variable has been declared and assigned the current input, any previous error classes or data is removed from the element using the following code:

$(input).parent().removeClass('error'); $(input).next('.error-data').remove();

The first line removes the error class from the input's parent (.input-frame), which adds the red border to the input element. The second line removes the error information that is displayed under the input if the validation check has determined that this input has invalid data.

Next, jQuery's hasClass() function is used to determine if the current input element has the required class. If the current element does have this class, we need to perform the required validation to make sure this field contains data. We call the validateRequired() function within the if statement and pass through the value of the current input, shown as follows:

if ($(input).hasClass('required') && !validateRequired($(input).val())) { addErrorData($(input), "This is a required field");    isError = true; }

We call the validateRequired() function prepended with an exclamation mark to check to determine if this function's results are equal to false; therefore, if the current input has the required class and validateRequired() returns false, the value of the current input is invalid. If this is the case, we call the addErrorData() function inside the if statement with the current input and the error message, which will be displayed under the input. We also set the isError variable to true, so that later on in the code, we will know a validation error occurred.

The JavaScript's for loop will repeat these steps for each of the selected input elements on the page. After the for loop has completed, we check if the isError flag is still set to false. If so, we use jQuery to manually submit the form, shown as follows:

if (isError === false) {    //No errors, submit the form    $('#webForm').submit(); }

Note that the operator === is used to compare the variable type of isError (that is, Boolean) as well as its value. At the bottom of the JavaScript file, we declare our two functions that have been called earlier in the script. The first function, validateRequired(), simply takes the input value and checks to see if it is blank or not. If the value is blank, the function returns false, meaning validation failed; otherwise, the function returns true. This can be coded as follows:

function validateRequired(value) {     if (value == "") return false;     return true; }

The second function used is the addErrorData() function, which takes the current input and an error message. It uses jQuery's addClass() function to add the error class to the input's parent, which will display the red border on the input element using CSS. It then uses jQuery's after() function to insert a division element into the DOM, which will display the specified error message under the current input field, shown as follows:

function validateRequired(value) {    if (value == "") return false;    return true; } function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); }

There's more...

This structure allows us to easily add additional validation to our web form. Because the JavaScript is iterating over all of the input fields in the form, we can easily check for additional classes, such as date, number, and credit-card, and call extra functions to provide the alternative validation. The other recipes in this article will look in detail at the additional validation types and add these functions to the current validation.js file.

See also

  • Implementing input character restrictions

Adding number validation

When collecting data from a user, there are many situations when you will want to only allow numbers in a form field. Examples of this could be telephone numbers, PIN codes, or ZIP codes, to name a few. This recipe will show you how to validate the telephone number field within the form we created in the previous recipe.

Getting ready

Ensure that you have completed the previous recipe and have the same files available. Open validation.js in your text editor or IDE of choice.

How to do it…

Add number validation to the form you created in the previous recipe by performing the following steps:

  1. Update validation.js to be as follows, adding the valdiateNumber() function with an additional hasClass('number') check inside the for loop:

    $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       //Remove old errors       $('.input-frame').removeClass('error');       $('.error-data').remove();       for (var i = 0; i < inputs.length; i++) {          var input = inputs[i];            if ($(input).hasClass('required') &&             !validateRequired($(input).val())) {                addErrorData($(input), "This is a required                   field");                isError = true;             } /* Code for this recipe */          if ($(input).hasClass('number') &&             !validateNumber($(input).val())) {                addErrorData($(input), "This field can only                   contain numbers");                isError = true;             } /* --- */         }       if (isError === false) {          //No errors, submit the form          $('#webForm').submit();       }    }); });   function validateRequired(value) {    if (value == "") return false;    return true; }   /* Code for this recipe */ function validateNumber(value) {    if (value != "") {       return !isNaN(parseInt(value, 10)) && isFinite(value);       //isFinite, in case letter is on the end    }    return true; } /* --- */ function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); }

  2. Open index.html in a web browser, input something other than a valid integer into the telephone number field, and click on the Submit button. You will be presented with a form similar to the following screenshot:

How it works…

First, we add an additional if statement to the main for loop of validation.js to check to see if the current input field has the class number, as follows:

if ($(input).hasClass('number') &&    !validateNumber($(input).val())) {    addErrorData($(input), "This field can only contain numbers");    isError = true; }

If it does, this input value needs to be validated for a number. To do this, we call the validateNumber function inline within the if statement:

function validateNumber(value) {    if (value != "") {       return !isNaN(parseInt(value, 10)) && isFinite(value);       //isFinite, in case letter is on the end    }    return true; }

This function takes the value of the current input field as an argument. It first checks to see if the value is blank. If it is, we do not need to perform any validation here because this is handled by the validateRequired() function from the first recipe of this article.

If there is a value to validate, a range of actions are performed on the return statement. First, the value is parsed as an integer and passed to the isNaN() function. The JavaScript isNaN() function simply checks to see if the provided value is NaN (Not a Number). In JavaScript, if you try to parse a value as an integer and that value is not actually an integer, you will get the NaN value. The first part of the return statement is to ensure that the provided value is a valid integer. However, this does not prevent the user from inputting invalid characters. If the user was to input 12345ABCD, the parseInt function would ignore ABCD and just parse 12345, and therefore the validation would pass. To prevent this situation, we also use the isFinite function, which returns false if provided with 12345ABCD.

Adding credit card number validation

Number validation could be enough validation for a credit card number; however, using regular expressions, it is possible to check for number combinations to match credit card numbers from Visa, MasterCard, American Express, and more.

Getting ready

Make sure that you have validation.js from the previous two recipes in this article open and ready for modification.

How to do it…

Use jQuery to provide form input validation for credit card numbers by performing the following step-by-step instructions:

  1. Update validation.js to add the credit card validation function and the additional class check on the input fields:

    $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       for (var i = 0; i < inputs.length; i++) {   // -- JavaScript from previous two recipes hidden                       if ($(input).hasClass('credit-card') &&             !validateCreditCard($(input).val())) {             addErrorData($(input), "Invalid credit card                number");             isError = true;          }         } // -- JavaScript from previous two recipes hidden    }); });   // -- JavaScript from previous two recipes hidden   function validateCreditCard(value) {    if (value != "") {       return /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9]) [0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}| (?:2131|1800|35\d{3})\d{11})$/.test(value);    }    return true; } // -- JavaScript from previous two recipes hidden }

  2. Open index.html and input an invalid credit card number. You will be presented with the following error information in the form:

How it works…

To add credit card validation, as with the previous two recipes, we added an additional check in the main for loop to look for the credit-card class on the input elements, as follows:

if ($(input).hasClass('credit-card') &&
   !validateCreditCard($(input).val())) {    addErrorData($(input), "Invalid credit card number");    isError = true; }

The validateCreditCard function is also added, which uses a regular expression to validate the input value, as follows:

function validateCreditCard(value) {    if (value != "") {       return /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-          9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-          9]{13}|3(?:0[0-5]|[68][0-9])[0-          9]{11}|(?:2131|1800|35\d{3})\d{11})$/.test(value);    }    return true; }

The first part of this function determines if the provided value is blank. If it isn't, the function will perform further validation; otherwise, it will return true. Most credit card numbers start with a prefix, which allows us to add additional validation to the inputted value on top of numeric validation. The regular expression used in this function will allow for Visa, MasterCard, American Express, Diners Club, Discover, and JCB cards.

See also

  • Adding number validation
jQuery 2.0 Development Cookbook Over 90 recipes providing modern solutions to web development problems with real-world examples with this book and ebook
Published: February 2014
eBook Price: £16.99
Book Price: £27.99
See more
Select your format and quantity:

Adding date validation

Dates are common items of data, and it is important that the user be able to easily input a date into your web form. Typically, you would use a date picker that has date validation included to provide an easy input method. This recipe shows you how to manually validate a date in the UK format (that is, DD/MM/YYYY).

Getting ready

Continuing the trend of the previous recipes of this article, ensure that you have validation.js open and ready for modification and that you have completed the previous three recipes.

How to do it…

Add date validation to your web form by performing the following simple steps:

  1. Update validation.js to add the additional date validation function and class check within the main for loop, shown as follows:

    $(function(){    $('.submit-btn').click(function(event){       // -- JavaScript from previous three recipes hidden         for (var i = 0; i < inputs.length; i++) {          // -- JavaScript from previous three recipes hidden            if ($(input).hasClass('date') &&             !validateDate($(input).val())) {             addErrorData($(input), "Invalid date             provided");             isError = true;          }            // -- JavaScript from previous three recipes hidden         }       // -- JavaScript from previous three recipes hidden     }); });   // -- JavaScript from previous three recipes hidden   function validateDate(value) {    if (value != "") {       if (/^\d{2}([.\/-])\d{2}\1\d{4}$/.test(value)) {          // Remove leading zeros          value = value.replace(/0*(\d*)/gi,"$1");          var dateValues = value.split(/[\.|\/|-]/);          // Correct the month value as month index starts             at 0 now 1 (e.g. 0 = Jan, 1 = Feb)          dateValues[1]--;          var date = new Date(dateValues[2], dateValues[1],             dateValues[0]);          if (             date.getDate() == dateValues[0] &&                date.getMonth() == dateValues[1] &&             date.getFullYear() == dateValues[2]             ) {             return true;          }       }       return false;    } else {       return true;    } } // -- JavaScript from previous three recipes hidden

  2. Open index.html in a web browser, input an invalid date, and click on Submit to generate the invalid date error, shown in the following screenshot:

How it works…

Once again, we add an additional class check to the main for loop to see if the current input needs to have date validation applied. If it does, the validateDate() function is called.

Just like the other validation functions, we first check to see if the value is blank. If it is not blank, the value can be validated. A regular expression is used to determine if the string value provided is of a valid date format, as follows:

if (/^\d{2}([.\/-])\d{2}\1\d{4}$/.test(value)) {

This test will pass if the provided value is separated with a slash, a hyphen, or a full stop and where the first two parts consist of two numbers and the last part consists of four numbers. This will ensure the provided value is DD/MM/YYYY, as required.

If this test passes, the next step is to remove all of the leading zeros so that the provided date string can be converted into a date object with JavaScript (for example, 08-08-1989 will become 8-8-1989). The code for the same is as follows:

value = value.replace(/0*(\d*)/gi,"$1");

After this, an array is created as follows, splitting the date string on either -, /, or:

var dateValues = value.split(/[\.|\/|-]/);

Now, it is possible to use these date values to create a JavaScript date object and test its validity. Before this can happen, we must convert the month value. JavaScript months start from 0, whereas our user will have started from 1. For example, the user will use 1 for January, 2 for February, and so on, whereas JavaScript uses 0 for January, 1 for February, and so on. To account for this, we simply subtract 1 from the provided date value, shown as follows:

dateValues[1]--;

With this done, it is possible to create the JavaScript date object and check that the outcome matches the input date, proving its validity:

var date = new Date(dateValues[2], dateValues[1], dateValues[0]); if (    date.getDate() == dateValues[0] &&    date.getMonth() == dateValues[1] &&    date.getFullYear() == dateValues[2] ) {    return true; }

Adding e-mail address validation

E-mail address validation is one of the most common types of validation on the Web. Most people would believe that a valid e-mail address only contains alphanumeric characters with the exception of the @ symbol and a full stop. While most e-mail addresses are typically of this format, a valid e-mail address can actually contain a variety of other characters. This recipe will show you how to add e-mail validation to the web form we have been using in the last four recipes.

How to do it…

Create e-mail validation that can be reused again and again by performing the following instructions:

  1. Add the additional hasClass check and if statement to the main for loop in validation.js as follows:

    if ($(input).hasClass('email') &&    !validateEmail($($(input)).val())) {    addErrorData($(input), "Invalid email address    provided");    isError = true; }

  2. Add the following validateEmail() function to the end of validation.js:

    function validateEmail(value) {    if (value != "") {       return /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%& '*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+ [a-z0-9](?:[a-z0-9-]*[a-z0-9])?/i.test(value);    }    return true; }

  3. Open index.html in a web browser, input an invalid e-mail address, and submit the form. You will be presented with an appropriate error in the same fashion as the other types of validation errors.

How it works…

The e-mail validation function, however simple, contains a complex regular expression to validate an e-mail address to a practical version of RFC 5322 standards, which was provided by http://www.regular-expressions.info/email.html.

The first part of the validateEmail() function checks to see if there is a value to validate. If so, it uses the complex regular expression to test the string values' validity, returning true or false accordingly.

Finally, as with the other validation functions, there is the class check inside the main for loop, which determines which inputs need to be validated for e-mail addresses. If these input fields fail validation, it will provide the appropriate error output on screen.

There's more…

It is important to understand that this method of e-mail validation only validates the syntax to cut down on the amount of rubbish data provided by users. To truly validate an e-mail address, you would have to actually send an e-mail to verify that it exists and is ready to receive e-mail.

Implementing live form validation

It can be very useful for the user to get real-time feedback regarding validation errors as they type in your web form. If you are performing client-side validation with JavaScript as well as server-side validation, this can be achieved easily as you do not need to send a request to the server every time the user types in an input—you can do it all within the client. Once again, it is very important that the same data undergoes additional validation on the server side. The server-side validation can then be fed back to the web form after the user has submitted the form.

Getting ready

This recipe will adapt the client-side validation that has been created as part of the last five recipes. Ensure that you have completed these recipes beforehand.

How to do it…

Provide real-time validation to users by performing the following steps:

  1. First, we need to move all of the class checks from the for loop into their own function so that they can be reused. Move all of the if statements, which perform the hasClass checks for required, email, number, date, and credit-card, into a function called doValidation(), shown as follows:

    // --- Hidden JavaScript from previous recipes   function doValidation(input) {    //Remove old errors    $(input).parent().removeClass('error');    $(input).next('.error-data').remove();    if ($(input).hasClass('required') &&       !validateRequired($(input).val())) {       addErrorData($(input), "This is a required field");    }    if ($(input).hasClass('email') &&       !validateEmail($($(input)).val())) {       addErrorData($(input), "Invalid email address          provided");    }    if ($(input).hasClass('number') &&       !validateNumber($(input).val())) {       addErrorData($(input), "This field can only contain          numbers");    }    if ($(input).hasClass('date') &&       !validateDate($(input).val())) {       addErrorData($(input), "Invalid date provided");    }    if ($(input).hasClass('credit-card') &&       !validateCreditCard($(input).val())) {       addErrorData($(input), "Invalid credit card number");    } }   // --- Hidden JavaScript

  2. Now, we need to update the main for loop to use this function so that the form validation is still performed when the user clicks on the submit button, as follows:

    for (var i = 0; i < inputs.length; i++) {    var input = inputs[i];    doValidation(input); }

  3. Update the isError check after the for loop to use an alternative method to determine if there were errors so that the form can still be submitted, as follows:

    if ($('.error-data').length == 0) {    //No errors, submit the form    $('#webForm').submit(); }

  4. To perform validation on the field that the user is typing into, we need to call the doValidation() function on the keyup event. Add the following code inside the $(function(){}); block to attach a keyup event handler to each of the form inputs:

    $('input').on("keyup", function(){    doValidation($(this)); });

  5. Open index.html in a web browser, start typing inside the e-mail field, and you will be provided with the appropriate error message as you type until you have entered a valid e-mail address.

How it works…

It is easy to adapt the previous validation code to provide real-time validation for the user. Moving the main validation triggers to another function means that the code can be reused without the need for duplication. The function that holds these triggers takes one argument, which is the input it needs to perform the validation checks on. The for loop is still used to provide this input, shown as follows:

for (var i = 0; i < inputs.length; i++) {    var input = inputs[i];    doValidation(input); }

Instead of relying on the doValidation function to return an isError value, we look to the DOM directly to see if there are any errors being displayed on screen by looking for any elements with the error-data class, as follows:

if ($('.error-data').length == 0) {    //No errors, submit the form    $('#webForm').submit(); }

If there are no errors, the form is submitted manually as before.

To provide real-time validation, a keyup event handler is attached to each of the form inputs using the following jQuery code:

$('input').on("keyup", function(){    doValidation($(this)); });

The callback function for the on() method will be executed every time the user presses and releases a key inside one of the input fields. It is then possible to use $(this), which refers to the input that triggered the event, thereby providing the doValidation() function with the input object it requires to perform the validation checks.

jQuery 2.0 Development Cookbook Over 90 recipes providing modern solutions to web development problems with real-world examples with this book and ebook
Published: February 2014
eBook Price: £16.99
Book Price: £27.99
See more
Select your format and quantity:

Adding a password strength indicator

Users like to create a really simple password that is easy to remember, such as cat, john, or even password. However, most people, especially web developers, know that these types of passwords are too insecure and are incredibly easy to decrypt from an encrypted database using techniques such as a dictionary attack, for example. Password strength indicators are useful to nudge the user in the right direction of using more complex passwords.

Getting ready

To be able to validate password strength, we need to create some rules that our code will use. There are no hard-and-fast rules regarding this, but plenty of information can be found online about what types of passwords are best. We will give the password a score out of five, one point for each of the following rules:

  • It is greater than six characters in length
  • It is greater than eight characters
  • It has both upper and lowercase characters
  • It has at least one number
  • It has one of the following symbols: @, $,!, &, and ^

This recipe will add password strength indicator to the web form that we have been creating over the last six recipes. Ensure that you have the code from these recipes available before you begin this recipe.

How to do it…

Create an effective password strength indicator for web forms by performing each of the following steps:

  1. Update index.html, adding some additional classes to the password form elements and also some additional HTML, which will create the password strength indicator, as follows:

    // --- ADDITIONAL HTML HIDDEN <div class="input-frame"> <label for="password">Password:</label> <input name="password" id="password" type="password" class="required password" /> <div class="password-strength">    <div class="inner"></div>    <div class="text"></div> </div> </div> <div class="input-frame"> <label for="confirmPassword">Confirm Password:</label> <input name="confirmPassword" id="confirmPassword" type="password" class="confirm-password" /> </div> // --- ADDITIONAL HTML HIDDEN

  2. Add the following styles to the end of styles.css to position the strength indicator under the password field. These styles will also allow the strength indicator to act as a load bar showing the percentage of password strength.

    .password-strength {    position: absolute;    width: 150px;    height: 20px;    left: 69%;    top: 35px;    line-height: 20px;    border: solid 1px #191919; } .password-strength .inner {    position: absolute;    left: 0;    top: 0; } .password-strength .text {    font-size: 11px;    color: #FFF;    text-align: center;    position: relative;    z-index: 10; }

  3. Add the validatePasswords() function to the end of validation.js, which will be used to ensure both passwords are entered and that they match, as follows:

    // --- HIDDEN JAVASCRIPT function validatePasswords(value) {    var password = $('.password').val();    if (value == "") {       return "Both passwords are required";    } else if (value != password) {       return "Passwords do not match";    }    return true; }

  4. Add the following code to the end of the doValidation() function to run the validatePasswords() function on the confirm-password input:

    function doValidation(input) { // --- HIDDEN JAVASCRIPT if ($(input).hasClass('confirm-password')) {    var result = validatePasswords($(input).val());       if (result != true) {          addErrorData($(input), result);       }    } }

  5. Add the following keyup event handler inside the $(function(){}); block in validation.js to score the password strength when the user types in the first password field:

    $('.password').on("keyup", function(){    var score = 0;    var password = $('.password');    var passwordAgain = $('.confirm-password');    //Remove any old errors for the password fields    password.parent().removeClass('error');    password.next('.error-data').remove();    passwordAgain.parent().removeClass('error');    passwordAgain.next('.error-data').remove();    //Password is greater than 6 characters    if (password.val().length > 6) {       score++;    }    //Password is greater than 8 characters    if (password.val().length > 8) {       score++;    }    //Password has both uppercase and lowercase characters    if (/(?=.*[A-Z])(?=.*[a-z])/.test(password.val())) {       score++;    }    //Password has at least one number    if (/(?=.*[0-9])/.test(password.val())) {       score++;    }    //Password has at least one symbol (@$!&^) character    if (/@|\$|\!|&|\^/.test(password.val())) {       score++;    }    var fill = (100 - ((score * 2) * 10));    var percent = (100 - fill);    var level,    colour;    switch (score) {    case 0:    case 1:    level = "Weak";    colour = "green";    break;    case 2:    case 3:    level = "Medium";    colour = "orange";    break;    case 4:    level = "Strong";    colour = "red";    break;    case 5:    level = "Excellent";    colour = "purple";    break;    }    $('.password-strength .inner').css('right', fill +       "%").css('background-color', colour);    $('.password-strength .text').html(level + " (" + percent +       "%)");    });

  6. Open index.html in a web browser and you will see an additional black box under the first password field. Start typing in a password and this field will provide information on the password strength as you type. This is illustrated in the following screenshot:

How it works…

The HTML for the indicator itself has an inner element and a text element. The text element is used by jQuery to display the password strength and percentage based on the calculated score of the inputted password. The inner element is used to form the colored bar. Based on the calculated score, jQuery is used to change the inner element's color and positioning, creating the load bar impression, which can be seen in the previous screenshot.

The CSS used needs little explanation since it provides basic styles and positioning. The inner element has an absolute position so that it can fill the password-strength element at different percentages. The text division has its z-index parameter set to ensure that the text will always display above the inner element.

The validatePasswords function, which was created as part of this recipe, simply adds basic password validation to our application. It checks to ensure that the confirm-password field has been filled and that the value matches the first password field. An additional check is added to the doValdiation function to ensure this validation gets applied along with the other validation methods created in earlier recipes.

To update the password strength indicator as the user types within the password field, the same method is used as that used in the Implementing live form validation recipe, which is to use the keyup event. An event handler is attached to the password field using the jQuery on() function, shown as follows:

$('.password').on("keyup", function(){ });

The code to calculate the score and update the password-strength HTML element is then placed within the callback function to this event handler. The first part of this code is to remove any current errors displayed for the password fields.

After this, there are a series of if statements which validate the password against the rules that were defined at the beginning of this recipe. The first basic validation is the password length, shown as follows:

//Password is greater than 6 characters if (password.val().length > 6) {    score++; } //Password is greater than 8 characters if (password.val().length > 8) {    score++; }

The score variable is incremented by 1 using score++ every time a validation condition is met.

The more complex rules use regular expressions to determine whether the password value meets the requirements for the additional score points, shown as follows:

//Password has both uppercase and lowercase characters if (/(?=.*[A-Z])(?=.*[a-z])/.test(password.val())) {    score++; } //Password has at least one number if (/(?=.*[0-9])/.test(password.val())) {    score++; } //Password has at least one symbol (@$!&^) character if (/@|\$|\!|&|\^/.test(password.val())) {    score++; }

After all five rules have been considered, the final score is used to calculate the fill value. The fill value is the percentage of the inner element that needs to be filled from the right-hand side of the strength indicator. This allows us to create the load bar effect. In addition to the fill value, a normal percentage is calculated to be displayed along with the strength level text as follows:

var fill = (100 - ((score * 2) * 10)); var percent = (100 - fill);

After this, the score value is used once more to determine the background color of the inner element and the strength level text as follows:

var level, colour; switch (score) { case 0: case 1:    level = "Weak";    colour = "green"; break; case 2: case 3:    level = "Medium";    colour = "orange";    break; case 4:    level = "Strong";    colour = "red"; break; case 5:    level = "Excellent";    colour = "purple"; break; }

Finally, using the jQuery password-strength, the HTML code is updated with the acquired information to display the results to the user, as follows:

$('.password-strength .inner').css('right', fill +    "%").css
('background-color', colour); $('.password-strength .text').html(level + " (" + percent + "%)");

There's more…

This code should be easily adaptable so that you can add your own rules regarding password strength. There are many discussions and resources online to point you to what a strong password should look like.

See also

  • Implementing live form validation

Adding anti-spam measures

Most web developers will know that if you have a contact form or any kind of web form publically available on your website, there will be web bot submissions and a lot of spam. Most web bots will be thwarted by the JavaScript-only web form we have been creating over the last seven recipes, but with browser automation and web bots becoming ever cleverer, it is still important to add anti-spam measures to your web forms.

Getting ready

Ensure that you have completed the last seven recipes and have the code readily available. Remember that if you would just like to use the code without fully understanding how it works, skip to the end of this article, to the How it works... section, to grab it all.

How to do it…

Add simple anti-spam measures to your web form by performing each of the following steps:

  1. Update index.html to have an additional form input under the input labeled Confirm Password as follows:

    <!-- HIDDEN HTML CODE --> <div class="input-frame">    <label>Confirm Password:</label>    <input type="password" class="confirm-password" /> </div> <div class="input-frame">    <label>Enter the number <span class="anti-spam-       number"></span>:</label>    <input type="text" class="required anti-spam-input" /> </div> <!-- HIDDEN HTML CODE -->

  2. Using JavaScript, generate a random number between 1 and 100 at the top of validation.js using the following code:

    var spamNumber = Math.floor(Math.random() * (100 - 1 + 1))    + 1; $(function(){ // --- HIDDEN JAVASCRIPT CODE

  3. At the very end of the $(function(){}); jQuery block, add the following code to update the HTML anti-spam-number span element with the random number:

    // --- HIDDEN JAVASCRIPT CODE $('.anti-spam-number').html(spamNumber); });

  4. Add the following additional validation check to the end of the doValidation() function:

    if ($(input).hasClass('anti-spam-input') &&
       !validateAntiSpam($(input).val())) {    addErrorData($(input), "Incorrect Anti-Spam answer"); }

  5. Finally, at the end of validation.js, add the validateAntiSpam() function, which is called by the previous code:

    // --- HIDDEN JAVASCRIPT CODE function validateAntiSpam(value) {    if (value != "") {       if (parseInt(value)!= spamNumber) return false;    }    return true; }

  6. Open index.html in a web browser and you will see the additional anti-spam form input field. Every time you refresh the page, it will ask you to input a different number.

How it works…

By declaring the spamNumber global variable outside any function, it is available for use by the whole JavaScript file. A new number between 1 and 100 is generated on every page load so that a web bot cannot store the answer and submit the form. Within the HTML code, there is a span element with the class anti-spam-number, which is updated with a random number on page load using the following code:

$('.anti-spam-number').html(spamNumber);

This will ensure the user is being told to input the correct number. We created an additional validation function named validateAntiSpam and called it from the doValidation() function for all inputs that have the anti-spam-input class. This will then validate the user-entered number with the globally available spamNumber variable, shown as follows:

function validateAntiSpam(value) {    if (value != "") {       if (parseInt(value)!= spamNumber) return false;    }    return true; }

Note that the input is parsed as an integer to ensure a number-on-number comparison. If the values do not match, this function will return false so that the doValidation() function can create the appropriate error message on-screen for the user.

There's more…

This type of client-side spam validation cannot be completely relied upon. It is effective towards general web bots that are not directly targeting your website. If someone wants to write a bot script specific to your site, bypassing this JavaScript would not be a difficult process. If you think this is possible, more extreme server-side spam prevention must be used.

There are many effective spam-prevention methods available for free on the Internet. The most popular are CAPTCHAs. One of the most popular CAPTCHAs is available for free by Google at http://www.google.com/recaptcha.

See also

  • Adding a password strength indicator

Implementing input character restrictions

Until now, all of the recipes in this article have concentrated on input validation and providing appropriate feedback to the user. There are situations where it is better to simply prevent the user from inputting invalid characters in the first place. This method would not typically be used, because it can be confusing for some users; for example, if they are not being told why they cannot input %. A situation where this would work is a login form. If you know your registration system does not allow % in the username, you know that the user would be inputting % by mistake, and therefore preventing the input is acceptable. This recipe provides a method to prevent users from inputting non-alphanumeric characters into an input field.

Getting ready

This recipe does not use any code from the last eight recipes; however, there are similarities in the CSS code. To complete this recipe, you are going to need three files. Create recipe-9.html, recipe-9.js, and recipe-9.css in the same directory as you have stored the latest version of jQuery.

How to do it…

Use jQuery to prevent users from inputting invalid articles into text inputs by performing the following steps:

  1. Add the following HTML code to recipe-9.html. This creates a basic login form and includes the two other files along with the jQuery library:

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/html"> <head>    <title>Chapter 5 :: Recipe 7</title>    <link type="text/css" media="screen" rel="stylesheet" href="recipe-9.css" />    <script src = "jquery.min.js"></script>    <script src = "recipe-9.js"></script> </head> <body> <form id="webForm" method="POST">    <div class="header">       <h1>Register</h1>    </div>    <div class="input-frame">       <label for="username">Username:</label>       <input name="username" id="username" type="text" class="username" />    </div>    <div class="input-frame">       <label for="password">Password:</label>       <input name="password" id="password" type="text" class="required" />    </div>    <div class="actions">       <button class="submit-btn">Submit</button>    </div> </form> </body> </html>

  2. Add the following CSS code to recipe-9.css, which adds style to the login form:

    @import url(http: //fonts.googleapis.com/css?family=Ubuntu); body {    background-color: #FFF;    font-family: 'Ubuntu', sans-serif; } form {    width: 500px;    margin: 10px auto auto auto;    padding: 20px;    background-color: #333;    border-radius: 5px;    color: #747474;    border: solid 2px #000; } form label {    font-size: 14px;    line-height: 30px;    padding-bottom: 8px;    width: 140px;    display: inline-block;    text-align: right; } .input-frame {    clear: both;    margin-bottom: 25px;    position: relative; } form input {    height: 30px;    width: 330px;    margin-left: 10px;    background-color: #191919;    border: solid 1px #404040;    padding-left: 10px;    color: #DB7400; } form input:hover {    background-color: #262626; } form input:focus {    border-color: #DB7400; } form .header {    margin: -20px -20px 25px -20px;    padding: 10px 10px 10px 20px;    position: relative;    background-color: #DB7400;    border-top-left-radius: 4px;    border-top-right-radius: 4px; } form .header h1 {    line-height: 50px;    margin: 0;    padding: 0;    color: #FFF;    font-weight: normal; } .actions {    text-align: right; } .submit-btn {    background-color: #DB7400;    border: solid 1px #000;    border-radius: 5px;    color: #FFF;    padding: 10px 20px 10px 20px;    text-decoration: none;    cursor: pointer; }

  3. Add the following JavaScript code to recipe-9.js in order to watch for user input on the username field and ensure non-alphanumeric characters are not inputted:

    $(function(){     $('.username').on("keypress", function(event){         //Get key press character code         var key = String.fromCharCode(event.which);         if (/[^a-zA-Z\d\s:]/.test(key)) {             event.preventDefault();             return false;         }     }); });

  4. Open recipe-9.html in a web browser and attempt to input a non-alphanumeric character (for example, $) inside the username field. You will see it will not be placed inside the field.

How it works…

A key press event handler is attached to the username field on page load. The callback function for this event handler has a single argument, which is the event object. This event object provides access to the key code of the key that the user is pressing. When the username field has focus and the user presses a key, the callback function is executed.

First, String.fromCharCode(event.which); is used to get the string value of the pressed key; for example, D, H, and 4. A regular expression is then used to determine whether or not this character is alphanumeric. If not, the character is prevented from being inputted into the form field using the following code:

if (/[^a-zA-Z\d\s:]/.test(key)) {    event.preventDefault();    return false; }

There's more…

Ensure that the event used in this recipe is the keypress event. If an alternative event is used, such as keydown, you may not achieve the desired result. If the keydown event is used, when the user presses Shift + 4 to input a $ symbol, the keydown event will provide its event handler as just 4, and not $, therefore passing validation.

Summary

In this article, we learned how to use jQuery to build robust client-side validation and an intuitive user experience for web forms.

Resources for Article:


Further resources on this subject:


About the Author :


Leon Revill

Leon Revill  has over five years' commercial web development experience with PHP5 and MySQL technologies on large and small projects. His development skillset extends over many JavaScript technologies, such as jQuery, AngularJS, and NodeJS. Being an all-round tech enthusiast, some of Leon's spare time is spent working on personal projects to allow him get to grips with new technologies quickly. Leon runs a web development blog ( http://www.revillweb.com/), where he shares his knowledge in the form of articles and tutorials.

Books From Packt


jQuery UI 1.10: The User Interface Library for jQuery
jQuery UI 1.10: The User Interface Library for jQuery

jQuery Game Development Essentials
jQuery Game Development Essentials

Instant jQuery Boilerplate for Plugins
Instant jQuery Boilerplate for Plugins

jQuery Hotshot
jQuery Hotshot

Learning jQuery : Better Interaction Design and Web Development with Simple JavaScript Techniques
Learning jQuery : Better Interaction Design and Web Development with Simple JavaScript Techniques

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

jQuery for Designers: Beginner’s Guide
jQuery for Designers: Beginner’s Guide

jQuery 2.0 Animation Techniques: Beginner's Guide
jQuery 2.0 Animation Techniques: Beginner's Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software