Getting Valid Input - Client-Side Programming with JavaScript - HTML5 and CSS3 All-in-One For Dummies (2014)

HTML5 and CSS3 All-in-One For Dummies (2014)

Book IV Client-Side Programming with JavaScript

Chapter 5 Getting Valid Input

In This Chapter

arrow Extracting data from drop-down lists

arrow Working with multiple-selection lists

arrow Getting data from check boxes and radio groups

arrow Validating input with regular expressions

arrow Using character, boundary, and repetition operators

arrow Using pattern memory

Getting input from the user is always nice, but sometimes users make mistakes. Whenever you can, you want to make the user's job easier and prevent certain kinds of mistakes.

Fortunately, you can take advantage of several tools designed exactly for that purpose. In this chapter, you discover two main strategies for improving user input: specialized input elements and pattern-matching. Together, these tools can help ensure that the data the user enters is useful and valid.

Getting Input from a Drop-Down List

The most obvious way to ensure that the user enters something valid is to supply him with valid choices. The drop-down list is an obvious and easy way to do this, as you can see from Figure 5-1.

The list-box approach has a lot of advantages over text field input:

· The user can input with the mouse, which is faster and easier than typing.

· You shouldn't have any spelling errors because the user didn't type the response.

· The user knows all the answers available because they're listed.

· You can be sure the user gives you a valid answer because you supplied the possible responses.

· User responses can be mapped to more complex values — for example, you can show the user Red and have the list box return the hex value #FF0000.

If you want to know how to build a list box with the HTML select object, refer to Book I, Chapter 7.

9781118289389-fg2201.tif

Figure 5-1: The user selects from a predefined list of valid choices.

Building the form

When you're creating a predefined list of choices, create the HTML form first because it defines all the elements you'll need for the function. The code is a standard form:

<body>
<form action = "">
<h1>Please select a color</h1>
<fieldset>
<select id = "selColor">
<option value = "#FFFFFF">White</option>
<option value = "#FF0000">Red</option>
<option value = "#FFCC00">Orange</option>
<option value = "#FFFF00">Yellow</option>
<option value = "#00FF00">Green</option>
<option value = "#0000FF">Blue</option>
<option value = "#663366">Indigo</option>
<option value = "#FF00FF">Violet</option>
</select>

<input type = "button"
value = "change color"
onclick = "changeColor()" />
</fieldset>
</form>

</body>
</html>

The select object's default behavior is to provide a drop-down list. The first element on the list is displayed, but when the user clicks the list, the other options appear.

A select object that the code refers to should have an id field.

tip.eps In this and most examples in this chapter, I add CSS styling to clean up each form. Be sure to look over the styles if you want to see how I did it. Note also that I'm only showing the HTML right now. The entire code listing also includes JavaScript code, which I describe in the next section.

The other element in the form is a button. When the user clicks the button, the changeColor() function is triggered.

technicalstuff.eps Because the only element in this form is the select object, you may want to change the background color immediately without requiring a button click. You can do so by adding an event handler directly onto the select object:

<select id = "selColor"
onchange = "changeColor()">

The event handler causes the changeColor() function to be triggered as soon as the user changes the select object's value. Typically, you'll forego the user clicking a button only when the select is the only element in the form. If the form includes several elements, processing doesn't usually happen until the user signals she's ready by clicking a button.

Reading the list box

Fortunately, standard drop-down lists are quite easy to read. Here's the JavaScript code:

<script type = "text/javascript">
// from dropdownList.html

function changeColor(){
var selColor = document.getElementById("selColor");
var color = selColor.value;
document.body.style.backgroundColor = color;
} // end function
</script>

As you can see, the process for reading the select object is much like working with a text-style field:

· Create a variable to represent the select object. The document.getElementById() trick works here just like it does for text fields.

· Extract the value property of the select object. The value property of the select object reflects the value of the currently selected option. So, if the user has chosen Yellow, the value of selColor is “#FFFF00”.

· Set the document's background color. Use the DOM mechanism to set the body's background color to the chosen value.

Managing Multiple Selections

You can use the select object in a more powerful way than the method I describe in the preceding section. Figure 5-2 shows a page with a multiple-selection list box.

9781118289389-fg2202.tif

Figure 5-2: You can pick multiple choices from this list.

To make multiple selection work, you have to make a few changes to both the HTML and the JavaScript code.

Coding a multiple selection select object

You modify the select code in two ways to make multiple selections:

· Indicate multiple selections are allowed. By default, select boxes have only one value. You'll need to set a switch to tell the browser to allow more than one item to be selected.

· Make the mode a multiline select. The standard drop-down behavior doesn't make sense when you want multiple selections because the user needs to see all the options at once. Most browsers automatically switch into a multiline mode, but you should control the process directly.

The HTML code for multiSelect.html is similar to the dropdownList page, described in the preceding section, but note a couple of changes.

<body>
<h1>Multiple Selections</h1>
<form action = "">
<fieldset>
<label>
Select the language(s) you know.
(ctrl-click to select multiple lines)
</label>
<select id = "selLanguage"
multiple = "multiple"
size = "10">
<option value = "HTML">HTML</option>
<option value = "CSS">CSS</option>
<option value = "JavaScript">JavaScript</option>
<option value = "PHP">PHP</option>
<option value = "MySQL">MySQL</option>
<option value = "Java">Java</option>
<option value = "VB.NET">VB.NET</option>
<option value = "Python">Python</option>
<option value = "Flash">Flash</option>
<option value = "Perl">perl</option>
</select>
<button type = "button"
onclick = "showChoices()">
Submit
</button>
</fieldset>
</form>

<div id = "output">

</div>
</body>
</html>

The code isn't shocking, but it does have some important features:

· Call the select object selLanguage. As usual, the form elements need an id attribute so that you can read it in the JavaScript.

· Add the multiple attribute to your select object. This attribute tells the browser to accept multiple inputs using Shift+click (for contiguous selections) or Ctrl+click (for more precise selection).

· Set the size to 10. The size indicates the number of lines to be displayed. I set the size to 10 because my list has ten options.

· Make a button. With multiple selection, you probably won't want to trigger the action until the user has finished making selections. A separate button is the easiest way to make sure the code is triggered when you want it to happen.

· Create an output div. This code holds the response.

Writing the JavaScript code

The JavaScript code for reading a multiple-selection list box is a bit different than the standard selection code described in the section “Reading the list box” earlier in this chapter. The value property usually returns one value, but a multiple-selection list box often returns more than one result.

tip.eps The key is to recognize that a list of option objects inside a select object is really a kind of array, not just one value. You can look more closely at the list of objects to see which ones are selected, which is essentially what the showChoices() function does:

<script type = "text/javascript">
//from multi-select.html
function showChoices(){
//retrieve data
var selLanguage = document.getElementById("selLanguage");

//set up output string
var result = "<h2>Your Languages<\/h2>";
result += "<ul> \n";

//step through options
for (i = 0; i < selLanguage.length; i++){
//examine current option
currentOption = selLanguage[i];

//print it if it has been selected
if (currentOption.selected == true){
result += " <li>" + currentOption.value + "<\/li> \n";
} // end if
} // end for loop

//finish off the list and print it out
result += "<\/ul> \n";

output = document.getElementById("output");
output.innerHTML = result;
} // end showChoices
</script>

At first, the code seems intimidating, but if you break it down, it's not too tricky.

1. Create a variable to represent the entire select object.

The standard document.getElementById() technique works fine.

var selLanguage = document.getElementById("selLanguage");

2. Create a string variable to hold the output.

When you're building complex HTML output, working with a string variable is much easier than directly writing code to the element.

var result = "<h2>Your Languages<\/h2>";

3. Build an unordered list to display the results.

An unordered list is a good way to spit out the results, so I create one in my result variable.

result += "<ul> \n";

4. Step through selLanguage as if it were an array.

Use a for loop to examine the list box line by line. Note that selLanguage has a length property like an array.

for (i = 0; i < selLanguage.length; i++){

5. Assign the current element to a temporary variable.

The currentOption variable holds a reference to each option element in the original select object as the loop progresses.

currentOption = selLanguage[i];

6. Check to see whether the current element has been selected.

The object currentOption has a selected property that tells you whether the object has been highlighted by the user. selected is a Boolean property, so it's either true or false.

if (currentOption.selected == true){

7. If the element has been selected, add an entry to the output list.

If the user has highlighted this object, create an entry in the unordered list housed in the result variable.

result += " <li>" + currentOption.value + "<\/li> \n";

8. Close up the list.

After the loop has finished cycling through all the objects, you can close up the unordered list you've been building.

result += "<\/ul> \n";

9. Print results to the output div.

The output div's innerHTML property is a perfect place to print the unordered list.

output = document.getElementById("output");
output.innerHTML = result;

technicalstuff.eps Something strange is going on here. The options of a select box act like an array. An unordered list is a lot like an array. Bingo! They are arrays, just in different forms. You can think of any listed data as an array. Sometimes you organize the data like a list (for display), sometimes like an array (for storage in memory), and sometimes it's a select group (for user input). Now you're starting to think like a programmer!

Check, Please: Reading Check Boxes

Check boxes fulfill another useful data input function. They're useful any time you have Boolean data. If some value can be true or false, a check box is a good tool. Figure 5-3 illustrates a page that responds to check boxes.

remember.eps Check boxes are independent of each other. Although they're often found in groups, any check box can be checked or unchecked regardless of the status of its neighbors.

9781118289389-fg2203.tif

Figure 5-3: You can pick your toppings here. Choose as many as you like.

Building the check box page

To build the check box page shown in Figure 5-3, start by looking at the HTML:

<body>
<h1>What do you want on your pizza?</h1>
<form action = "">
<fieldset>
<input type = "checkbox"
id = "chkPepperoni"
value = "pepperoni" />
<label for = "chkPepperoni">Pepperoni</label>
<input type = "checkbox"
id = "chkMushroom"
value = "mushrooms" />
<label for = "chkMushroom">Mushrooms</label>
<input type = "checkbox"
id = "chkSausage"
value = "sausage" />
<label for = "chkSausage">Sausage</label>
<button type = "button"
onclick = "order()">
Order Pizza
</button>
</fieldset>
</form>
<h2>Your order:</h2>
<div id = "output">
</div>
</body>

Each check box is an individual input element. Note that check box values aren't displayed. Instead, a label (or similar text) is usually placed after the check box. A button calls an order() function.

tip.eps Note the labels have a for attribute which connects each label to the corresponding check box. When you connect a label to a check box in this way, the user can activate the check box by clicking on the box or the label. This provides a larger target for the user, making their life easier. Happy users make fewer mistakes, which makes your life easier.

Responding to the check boxes

Check boxes don't require a lot of care and feeding. After you extract it, the check box has two critical properties:

· You can use the value property to store a value associated with the check box (just like you do with text fields in Chapter 2 of this minibook).

· The checked property is a Boolean value, indicating whether the check box is checked or not.

The code for the order() function shows how it's done:

//from checkBoxes.html
function order(){
//get variables
var chkPepperoni = document.getElementById("chkPepperoni");
var chkMushroom = document.getElementById("chkMushroom");
var chkSausage = document.getElementById("chkSausage");
var output = document.getElementById("output");
var result = "<ul> \n"
if (chkPepperoni.checked){
result += "<li>" + chkPepperoni.value + "</li> \n";
} // end if
if (chkMushroom.checked){
result += "<li>" + chkMushroom.value + "</li> \n";
} // end if
if (chkSausage.checked){
result += "<li>" + chkSausage.value + "</li> \n";
} // end if
result += "</ul> \n"
output.innerHTML = result;
} // end function

For each check box,

1. Determine whether the check box is checked.

Use the checked property as a condition.

2. If so, return the value property associated with the check box.

tip.eps Often, in practice, the value property is left out. The important thing is whether the check box is checked. If chkMushroom is checked, the user obviously wants mushrooms, so you may not need to explicitly store that data in the check box itself.

Working with Radio Buttons

Radio button groups appear pretty simple, but they're more complex than they seem. Figure 5-4 shows a page using radio button selection.

9781118289389-fg2204.tif

Figure 5-4: One and only one member of a radio group can be selected at one time.

The most important thing to remember about radio buttons is that, like wildebeests and power-walkers, they must be in groups. Each group of radio buttons has only one button active. The group should be set up so that one button is always active.

You specify the radio button group in the HTML code. Each element of the group can still have a unique id (which comes in handy for associating with a label). Look over the code, and you'll notice something interesting. All the radio buttons have the same name!

<body>
<h1>With what weapon will you fight the dragon?</h1>
<form action = "">
<fieldset>
<input type = "radio"
name = "weapon"
id = "radSpoon"
value = "spoon"
checked = "checked" />
<label for = "radSpoon">Spoon</label>
<input type = "radio"
name = "weapon"
id = "radFlower"
value = "flower" />
<label for = "radFlower">Flower</label>
<input type = "radio"
name = "weapon"
id = "radNoodle"
value = "wet noodle" />
<label for = "radNoodle">Wet Noodle</label>
<button type = "button"
onclick = "fight()">
fight the dragon
</button>
</fieldset>
</form>
<div id = "output">
</div>
</body>

Using a name attribute when everything else has an id seems a little odd, but you do it for a good reason. The name attribute is used to indicate the group of radio buttons. Because all the buttons in this group have the same name, they're related, and only one of them will be selected. Each button can still have a unique ID (and in fact it does). The ID is still useful for associating a label with the button. Once again, this provides a larger click target so the user can click on either the button or the label associated with that button.

The browser recognizes this behavior and automatically unselects the other buttons in the group whenever one is selected.

I added a label to describe what each radio button means.

tip.eps You need to preset one of the radio buttons to true with the checked = “checked” attribute. If you fail to do so, you have to add code to account for the possibility that there is no answer at all.

Interpreting Radio Buttons

Getting information from a group of radio buttons requires a slightly different technique than most of the form elements. Unlike the select object, there is no container object that can return a simple value. You also can't just go through every radio button on the page because you may have more than one group. (Imagine a page with a multiple-choice test.)

This issue is where the name attribute comes in. Although ids must be unique, multiple elements on a page can have the same name. If they do, you can treat these elements as an array.

Look over the code to see how it works:

// from radioGroup.html
function fight(){
var weapon = document.getElementsByName("weapon");
for (i = 0; i < weapon.length; i++){
currentWeapon = weapon[i];
if (currentWeapon.checked){
var selectedWeapon = currentWeapon.value;
} // end if
} // end for
var output = document.getElementById("output");
var response = "<h2>You defeated the dragon with a ";
response += selectedWeapon + "</h2> \n";
output.innerHTML = response;
} // end function

This code looks much like all the other code in this chapter, but it has a sneaky difference:

· It uses getElementsByName to retrieve an array of elements with this name. Now that you're comfortable with getElementById, I throw a monkey wrench in the works. Note that it's plural — getElementsByName — because this tool is used to extract an array of elements. It returns an array of elements. (In this case, all the radio buttons in the weapon group.)

· It treats the result as an array. The resulting variable (weapon in this example) is an array. As usual, the most common thing to do with arrays is process them with loops. Use a for loop to step through each element in the array.

· Assign each element of the array to currentWeapon. This variable holds a reference to the current radio button.

· Check to see whether the current weapon is checked. The checked property indicates whether any radio button is checked.

· If so, retain the value of the radio button. If a radio button is checked, its value is the current value of the group, so store it in a variable for later use.

· Output the results. You can now process the results as you would with data from any other resource.

Working with Regular Expressions

Having the right kinds of form elements can be helpful, but things can still go wrong. Sometimes, you have to let the user type things, and that information must be in a particular format. As an example, take a look at Figure 5-5.

A mechanism that checks whether input from a form is in the correct format would be great. This program implements such a feature, checking whether there is content in every field and ensuring the e-mail address and phone number are formatted correctly. You can create this kind of testing feature with string functions, but it can be really messy. Imagine how many if statements and string methods it would take to enforce the following rules on this page:

9781118289389-fg2205.tif

Figure 5-5: This page is a mess. No username, plus an invalid e-mail and phone number.

· An entry must appear in each field. This one is reasonably easy — just check for non-null values.

· The e-mail must be in a valid format. That is, it must consist of a few characters, an “at” sign (@), a few more characters, a period, and a domain name of two to four characters. That format would be a real pain to check for.

· The phone number must also be in a valid format. Phone numbers can appear in multiple formats, but assume that you require an area code in parentheses, followed by an optional space, followed by three digits, a dash, and four digits. All digits must be numeric.

Although you can enforce these rules, it would be extremely difficult to do so using ordinary string manipulation tools.

JavaScript strings have a match method, which helps find a substring inside a larger string. This tool is good, but we're not simply looking for specific text, but patterns of text. For example, we want to know whether something's an e-mail address (text, an @, more text, a period, and two to four more characters).

Imagine how difficult that code would be to write, and then take a look at the code for the validate.html page:

<script type = "text/javascript">
function validate(){
// get inputs
name = document.getElementById("txtName").value;
email = document.getElementById("txtEmail").value;
phone = document.getElementById("txtPhone").value;

//create an empty error message
errors = "";

//check name - It simply needs to exist
if (name == ""){
errors += "please supply a name \n";
} // end if

//check email
emailRE = /^.+@.+\..{2,4}$/;
if (email.match(emailRE)){
//console.log("email match");
//do nothing.
} else {
//console.log("email not a match");
errors += "please check email address \n";
} // end if

//check phone number
phoneRE = /^\(\d{3}\) *\d{3}-\d{4}$/;
if (phone.match(phoneRE)){
//console.log("phone matches");
//do nothing
} else {
//console.log("phone problem");
errors += "please check phone #\n";
} // end phone if

//check for errors
if (errors == ""){
alert ("now processing data");
//process the form
} else {
alert(errors);
} // end if

} // end function

tip.eps I only show the JavaScript code here to save space. Look on the website to see how the HTML and CSS are written.

The code isn't really all that difficult!

· It extracts data from the form. It does so in the usual way.

· The validation is a series of nested if statements. Look at the overall structure. The if statements go three layers deep.

· The name check is very simple. The only way it can go wrong is to have no name.

· Don't check anything else if the name is wrong. If the name isn't right, you don't need to check the other things.

· Build a regular expression. This verification seems pretty simple until you look at the line that contains the emailRE = /^.+@.+\..{2,4}$/; business. That line looks like a cursing cartoonist. The weird-looking text is a regular expression and the key to this program. For now, just accept it as a magic incantation. I explain it in a moment, but focus on the big picture here.

· Match the regular expression against the e-mail address. The next line checks to see whether the e-mail address is a match to the regular expression. The result is true if the expression matches an e-mail address or null if it doesn't.

· Check the phone number. Once again, the phone number check is simple except the match business, which is just as mysterious: /^\(\d{3}\) *\d{3}-\d{4}$/ (seriously, who makes this stuff up?). That's another regular expression.

· If everything worked, process the form. Usually, at this point, you call some sort of function to finish handling the form processing.

technicalstuff.eps Frequently, you do validation in JavaScript before you pass information to a program on the server. This way, your server program already knows the data is valid by the time it gets there. Look ahead to AJAX in Book VII, Chapter 1 to see how this is done.

Introducing regular expressions

Of course, the secret of this program is to decode the mystical expressions used in the match statements. They aren't really strings at all, but very powerful text-manipulation techniques called regular expression parsing. Regular expressions have migrated from the Unix world into many programming languages, including JavaScript.

A regular expression is a powerful mini-language for searching and replacing text patterns. Essentially, what it does is allow you to search for complex patterns and expressions. It's a weird-looking language, but it has a certain charm once you know how to read the arcane-looking expressions.

tip.eps Regular expressions are normally used with the string match() method in JavaScript, but you can also use them with the replace() method and a few other places.

Table 5-1 summarizes the main operators in JavaScript regular expressions.

2201
2201

Don't memorize this table! I explain in the rest of this chapter exactly how regular expressions work. Keep Table 5-1 handy as a reference.

To see how regular expressions work, take a look at regex.html in Figure 5-6.

9781118289389-fg2206.tif

Figure 5-6: This tool allows you to test regular expressions.

The top textbox accepts a regular expression, and the second text field contains text to examine. You can practice the examples in the following sections to see how regular expressions work. They're really quite useful after you get the hang of them. While you walk through the examples, try them out in this tester. (I include it on the website for you, but I don't reproduce the code here. Of course you're always welcome to view the source code.)

Using characters in regular expressions

The main thing you do with a regular expression is search for text. Say that you work for the bigCorp company, and you ask for employee e-mail addresses. You can make a form that accepts only e-mail addresses with the term bigCorp in them by using the following code:

if (email.match(/bigCorp/)){
alert("match");
} else {
alert("no match");
} // end if

The text in the match() method is enclosed in slashes (/) rather than quote symbols because the expression isn't technically a string; it's a regular expression. The slashes help the interpreter realize this special kind of text requires additional processing.

tip.eps If you forget and enclose a regular expression inside quotes, it will still work most of the time. JavaScript tries to convert string values into regular expressions when it needs to. However, if you've ever watched a science fiction movie, you know it's generally not best to trust computers. Use the slash characters to explicitly coerce the text into regular expression format. I'm not saying your computer will take over the world if you don't, but you never can tell. . . .

This match is the simplest type. I'm simply looking for the existence of the needle (bigCorp) in a haystack (the e-mail address stored in email). If bigCorp is found anywhere in the text, the match is true, and I can do what I want (usually process the form on the server). More often, you want to trap for an error and remind the user what needs to be fixed.

Marking the beginning and end of the line

You may want to improve the search because what you really want are addresses that end with bigCorp.com. You can put a special character inside the match string to indicate where the end of the line should be:

if (email.match(/bigCorp.com$/)){
alert("match");
} else {
alert("no match");
} // end if

The dollar sign at the end of the match string indicates that this part of the text should occur at the end of the search string, so andy@bigCorp.com is a match, but not bigCorp.com announces a new Website.

technicalstuff.eps If you're an ace with regular expressions, you know this example has a minor problem, but it's pretty picky. I explain it in the upcoming “Working with special characters” section. For now, just appreciate that you can include the end of the string as a search parameter.

Likewise, you can use the caret character (^) to indicate the beginning of a string.

If you want to ensure that a text field contains only the phrase oogie boogie (and why wouldn't you?), you can tack on the beginning and ending markers. The code /^oogie boogie$/ is a true match only if nothing else appears in the phrase.

Working with special characters

In addition to ordinary text, you can use a bunch of special character symbols for more flexible matching:

· Matching a character with the period: The most powerful character is the period (.), which represents a single character. Any single character except the newline (\n) matches against the period. A character that matches any character may seem silly, but it's actually quite powerful. The expression /b.g/ matches big, bag, and bug. In fact, it matches any phrase that contains b followed by any single character and then g, so bxg, b g, and b9g are also matches.

· Using a character class: You can specify a list of characters in square braces, and JavaScript matches if any one of those characters matches. This list of characters is sometimes called a character class. For example, /b[aeiou]g/ matches on bag, beg, big, bog, or bug. This method is a really quick way to check a lot of potential matches.

You can also specify a character class with a range. [a-zA-Z] checks all the letters.

· Specifying digits: One of the most common tricks is to look for numbers. The special character \d represents a number (0-9). You can check for a U.S. phone number (without the area code — yet) using a pattern that looks for three digits, a dash, and four digits: /\d\d\d-\d\d\d\d/.

· Marking punctuation characters: You can tell that regular expressions use a lot of funky characters, such as periods and braces. What if you're searching for one of these characters? Just use a backslash to indicate that you're looking for the actual character and not using it as a modifier. For example, the e-mail address would be better searched with bigCorp\.com because it specifies there must be a period. If you don't use the backslash, the regular expression tool interprets the period as “any character” and allows something like bigCorpucom. Use the backslash trick for most punctuation, such as parentheses, braces, periods, and slashes.

If you want to include an area code with parentheses, just use backslashes to indicate the parentheses: /\(\d\d\d\) \d\d\d-\d\d\d\d/. And if you want to ensure the only thing in the sample is the phone number, just add the boundary characters: /^\(\d\d\d\) \d\d\d \d\d\d\d$/.

· Finding word boundaries: Sometimes you want to know whether something is a word. Say that you're searching for the, but you don't want a false positive on breathe or theater. The \b character means “the edge of a word,” so /\bthe\b/ matches the but not words containing “the” inside them.

Conducting repetition operations

All the character modifiers refer to one particular character at a time, but sometimes you want to deal with several characters at once. Several operators can help you with this process.

· Finding one or more elements: The plus sign (+) indicates “one or more” of the preceding character, so the pattern /ab+c/ matches on abc, abbbbbbc, or abbbbbbbc, but not on ac (there must be at least one b) or on afc (it's gotta be b).

· Matching zero or more elements: The asterisk means “zero or more” of the preceding character. So /I'm .* happy/ matches on I'm happy (zero occurrences of any character between I'm and happy). It also matches on I'm not happy (because characters appear in between).

The .* combination is especially useful, because you can use it to improve matches like e-mail addresses: /^.*@bigCorp\.com$/ does a pretty good job of matching e-mail addresses in a fictional company.

· Specifying the number of matches: You can use braces ({}) to indicate the specific number of times the preceding character should be repeated. For example, you can rewrite a phone number pattern as /\(\d{3}\) *\d{3}-\d{4}/. This structure means “three digits in parentheses, followed by any number of spaces (zero or more), and then three digits, a dash, and four digits. Using this pattern, you can tell whether the user has entered the phone number in a valid format.

You can also specify a minimum and maximum number of matches, so /[aeiou]{1, 3}/ means “at least one and no more than three vowels.”

Now you can improve the e-mail pattern so that it includes any number of characters, an @ sign, and ends with a period and two to four letters: /^.+@.+\..{2,4}$/.

remember.eps A regular expression can check to see if an e-mail address matches the right pattern, but it can't tell if it's a valid address that really exists on the Internet. You actually have to try to send an e-mail to see if it's valid, which is beyond the scope of JavaScript. (I show how to send e-mails through PHP in Book V.)

Working with pattern memory

Sometimes you want to remember a piece of your pattern and reuse it. You can use parentheses to group a chunk of the pattern and remember it. For example, /(foo){2}/ doesn't match on foo, but it does on foofoo. It's the entire segment that's repeated twice.

You can also refer to a stored pattern later in the expression. The pattern /^(.).*\1$/ matches any word or phrase that begins and ends with the same character. The \1 symbol represents the first pattern in the string; \2 represents the second, and so on.

After you've finished a pattern match, the remembered patterns are still available in special variables. The variable $1 is the first pattern stored; $2 is the second, and so on. You can use this trick to look for HTML tags and report what tag was found: Match ^<(.*)>.*<\/\1>$ and then print $1 to see what the tag was.

There's much more to discover about regular expressions, but this basic overview should give you enough to write some powerful and useful patterns.

New HTML5/CSS3 Tricks for Validation

HTML5 and CSS3 add a few more tricks to simplify validation, and they are absolutely wonderful.

While you can always use JavaScript and regular expressions to validate your pages (as described in this chapter), HTML5 promises a much easier solution. When you use the special-purpose input elements (described in Book I, Chapter 7), the browser will automatically check the form field to ensure it is in a proper format. If the entry is not valid, the form will (generally) not submit, and the special :invalid CSS pseudo-class will be associated with the invalid field. Simply supply CSS to your page handling the :invalid state:

:invalid {
background-color: red;
}

When this CSS state is active, any invalid fields will have the :invalid styling. For example, if you have an email field defined and the content of that field is not a valid e-mail address, the invalid style will be applied. As soon as the address is in the right format, the invalidstyle will be removed.

The developer doesn't need to add any other code to the form. Simply add CSS to display invalid entries, and the browser will do the rest. You don't even need to specify the regular expression for e-mail addresses or any other specialty input fields — the appropriate regular expression for each field type is already built in.

Note that if a field is required (with the required attribute), it will be considered invalid until it contains some value.

It is possible that the browser will refuse to process a form until all fields are validated, but this behavior does not yet seem to be universal among HTML5-compliant browsers.

If you wish, you can turn off the validation for any field by adding the novalidate attribute to that element.

Figure 5-7 shows the newElements.html page from Book I, Chapter 7 modified with a nice style sheet and the validation modifiers in place. Note that the name field is required and the e-mail address is invalid, so these fields show the red background I specified for invalid fields.

9781118289389-fg2207.tif

Figure 5-7: The new HTML5 form elements have automatic validation.

Please look over the code for html5validation.html on the website — the code hasn't changed substantially from Book I, Chapter 7. The CSS code is new, so I reproduce that here:

<style type = "text/css">
fieldset {
width: 600px;
background-color: #EEEEEE;
margin-left: auto;
margin-right: auto;
box-shadow: 5px 5px 5px gray;
}
label {
float: left;
clear: left;
width: 250px;
text-align: right;
padding-right: 1em;
}

input {
float: left;
}

:required {
border: 1px solid red;
}

:invalid {
color: white;
background-color: red;
}

button {
display: block;
margin-left: auto;
margin-right: auto;
clear: both;
}
</style>

Adding a pattern

The pattern attribute allows you to specify a regular expression used to validate the form. If the content matches the regular expression, the field will be considered valid. (See the “Working with Regular Expressions” section of this chapter for more details.) The pattern attribute should be used only when the standard validation techniques are not sufficient (that is, you're using an ordinary input element that doesn't have an automatic pattern) because it can be difficult to debug regular expressions.

<input type = "text"
id = "txtPhone"
pattern = "\(\d{3}\) +\d{3}-\d{4}"
title = "(ddd) ddd-dddd" />

When you specify a pattern, you should also include a title attribute. The title should indicate what the pattern is. The browser can use this as a tip for the user. It may also be useful to add pattern information as placeholder text. (See the placeholder attribute later.)

Marking a field as required

The required attribute allows you to specify a particular field as required. Supporting browsers will mark all required fields (perhaps by highlighting them in red) if they are not filled in. Some browsers will also send a warning if the user tries to submit a form with empty required fields.

<input type = "text"
required />

The special :required pseudo-class allows you to apply a CSS style to all required elements in your form (giving them a border or background-color, for example). Here's an example of a CSS style for marking required elements with a red border:

:required {
border: 1px solid red;
}

If you have a required field and it has no content, that field will trigger the invalid style.

Adding placeholder text

The placeholder attribute allows you to add a special placeholder value in your text fields. This placeholder acts as a temporary label showing the purpose of the field without requiring a label tag. As soon as the user activates the field, the placeholder text disappears.

<input type = "text"
placeholder = "Name" />

Not all browsers support placeholder text. Other browsers will simply ignore the placeholder attribute. Likewise, if the field is already filled in, the placeholder will not be visible. For these reasons, it is still preferred to add a label so users know what to type in each text area. Placeholder text is especially helpful when it is used to indicate how the input should be formatted (especially if this will be enforced by validation or a pattern).