Adding Form Validation

Adding Form Validation

Now that we have the form looking presentable, we need to add some form validation to make sure we are getting accurate data so that we can actually start saving new tasks in the next chapter.

We will continue using jQuery from this point forward, which will give us access to some excellent validation plug-ins that will save us from having to write validation routines from the ground up. Before we get to integrating that validation plug-in, however, let’s

40 CHAPTER 2: Building a Mobile HTML Entry Form

consider how we are going to provide validation feedback in our application, as that is something we are not going to be able to just use as is.

I know it’s been mentioned before, but we need to again consider limited screen real estate. Additionally, if you have come from a desktop web application background, you will also have to come to terms with not having hover tips and associated mouseover- type functionality in your mobile web apps.

So we need an effective way of communicating validation errors that doesn’t take up excessive screen space, but provides the user enough detail to fix the problems with the data they have entered.

We will explore one option for providing that feedback by looking at an example.

Providing Feedback with Limited Screen Space

The approach we are going to take in this application is to first indicate any field that has

a problem with the data that has been provided with a visual cue that something is awry—nothing new here. While a common practice for web applications would also be to provide an overall summary of the validation errors that have been encountered for the entire form, we will not be able to incorporate this given the limited screen real- estate. As an alternative, let’s look at ways that we can leverage the power of jQuery to alter the page at runtime and display those errors when a user enters a particular field.

Given that we haven’t actually hooked up the jQuery validation plug-in yet, we’ll just use mock JavaScript to simulate some failed tests to check that our display behaves in the desired fashion.

First, let’s add some basic style information to the todolist.css file for invalid fields: input.invalid, textarea.invalid {

background: url(exclamation.png) no-repeat 2px 2px; padding-left: 22px;

#errors { margin: 8px 6px 2px 6px; padding: 6px 14px; background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0,

#cc0000), color-stop(0.7, #770022)); -webkit-border-radius: 4px; color: white; display: none;

CHAPTER 2: Building a Mobile HTML Entry Form

NOTE: I’ve included an external image resource to draw attention to the invalid field. This is definitely one way to do things, and is great for what we are doing currently. Later in the book I will discuss how you can actually embed image data directly into your stylesheets to reduce the number of HTTP requests required by your app.

Oh, and you may notice that I’ve used another gradient. It might be time to start admitting I have

a problem with gradient addiction.

With a way to see that a field is invalid, let’s implement some code to trigger the display of validation errors:

var errors = {};

function displayErrors() { // initialize variables var haveErrors = false;

// remove the invalid class for all inputs $(":input.invalid").removeClass("invalid");

// iterate through the fields specified in the errors array for (var fieldName in errors) {

haveErrors = true; $("input[name='" + fieldName + "']").addClass("invalid");

} // for

// if we have errors, then add a message to the errors div $("#errors")

.html(haveErrors ? "Errors were found." : "") .css("display", haveErrors ? "block" : "none");

} // displayErrors

$(document).ready(function() { $("#taskentry").bind("submit", function() { errors = { "task[name]": ["Task name is required"], "task[due]": ["Due date is invalid"]

displayErrors(); return false;

This code is the start of our todolist.js file, which we will build up to contain the application logic for our web app. Right now, there isn’t much to it, but by the end of Chapter 4, this will be quite a substantial amount of code. For now, the code simply binds to the submit event of the task entry form and provides the skeleton of a displayErrors function. If you click the Submit button on the web form, you should now see something similar to Figure 2–9.

42 CHAPTER 2: Building a Mobile HTML Entry Form

Figure 2–9. The Create Task form simulating an error condition Let’s move on to providing the user additional information when they focus back on a

field in the form. If you play around in the emulator or on an actual Android device, you may notice that the screen positioning of elements when the onscreen keyboard is displayed is going to make it difficult to choose a suitable location to provide the additional validation feedback. If you haven’t yet experienced this firsthand, then just take a moment to throw a few extra dummy input fields in the Create Task form and experiment with the interface.

Figure 2–10 highlights the dramatic reduction of available screen real estate when the keyboard is displayed.

CHAPTER 2: Building a Mobile HTML Entry Form

Figure 2–10. When the onscreen keyboard is displayed, the available display height is roughly halved. From my own investigations and experience, I have found that using the screen real

estate above a control is a little more reliable than below (given that scrolling is limited by the height of the current HTML document). To provide the detailed feedback, let’s add some additional JavaScript to our todolist.js file. We’ll start with adding an additional function that will be used to display any errors for a form element that is passed to it:

function displayFieldErrors(field) { var messages = errors[field.name]; if (messages && (messages.length > 0)) {

// find an existing error detail section for the field var errorDetail = $("#errordetail_" + field.id).get(0);

// if it doesn't exist, then create it if (! errorDetail) {

$(field).before("<ul class='errors-inline' id='errordetail_" + field.id +

"'></ul>"); errorDetail = $("#errordetail_" + field.id).get(0); } // if

// add the various error messages to the div for (var ii = 0; ii < messages.length; ii++) {

$(errorDetail).html('').append("<li>" + messages[ii] + "</li>"); } // for } // if } // displayFieldErrors

This code is then triggered by attaching to the focus handler of the control—the following code demonstrates how to do that when the document is loaded:

44 CHAPTER 2: Building a Mobile HTML Entry Form

$(document).ready(function() { $(":input").focus(function(evt) { displayFieldErrors(this); }).blur(function(evt) { $("#errordetail_" + this.id).remove(); }); ... });

Now we just need add an additional style definition so the inline errors are displayed differently from other ul elements:

ul.errors-inline li { border: 0px; color: red; padding: 0px;

} Once that has been implemented, errors should display above an input field when it

receives focus, as per Figure 2–11.

Figure 2–11. Detailed error messages are now displayed above an entry field when it receives focus. That’s pretty much it in terms of providing error feedback; from here all that is required is

to include the jQuery validation plug-in and let it do the hard work of validating data. Setting up the jQuery validation plug-in requires the following steps:

1. Importing the jquery.validate.js library into our HTML code

2. Adding some validation information to the class declarations of input fields that we want to validate

CHAPTER 2: Building a Mobile HTML Entry Form

3. Calling a customized version of the validate method for our form to override the default jQuery validation plug-in behavior to what we created previously

Let’s start with the tweaks to the HTML: <html>

<head> <title>Simple Mobile Web Page</title> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-

scale=1.0; user-scalable=0;" /> <link rel="stylesheet" media="screen" href="todolist.css" /> <script type="text/javascript" src="../../js/jquery-1.4.2.min.js"></script>

<script type="text/javascript" src="../../js/jquery.validate.js"></script>

<script type="text/javascript" src="../../js/prowebapps.js"></script> <script type="text/javascript" src="todolist.js"></script>

</head> <body>

<h1 class="fancy">Create Task</h1> <div id="errors"></div> <form id="taskentry"> <ul>

<li><input type="text" class="required" name="task[name]" id="taskname" placeholder="Task Name"/></li> <li>

<textarea name="task[description]" id="taskdesc" placeholder="Description"

rows="5"></textarea> </li> <li><input type="text" class="required date" name="task[due]" id="taskdue"

placeholder="Task Due" /></li> <li class="naked"><input type="submit" name="Save" /></li> </ul> </form>

</body> </html>

That takes care of steps 1 and 2; now we just need to replace the mock validation code (the jQuery bind for the submit and the associated callback) with the following code:

$("#taskentry").validate({ submitHandler: function(form) { // TO BE COMPLETED IN THE NEXT CHAPTER }, showErrors: function(errorMap, errorList) {

// initialize an empty errors map errors = {};

// iterate through the jQuery validation error map, and convert to something we can use for (var elementName in errorMap) { if (! errors[elementName]) { errors[elementName] = []; } // if

errors[elementName].push(errorMap[elementName]); } // for

// now display the errors

46 CHAPTER 2: Building a Mobile HTML Entry Form

displayErrors(); } });

Once this is done, the application should behave exactly as before, but rather than displaying our mock errors it will display error messages that have been produced from the jQuery.validate plug-in.