<!--#include virtual="../s5/commontop.html" -->
<title>Lecture 11: Client-Side Form Validation — INFO 343 Autumn 2011</title>
</head>
<body>
<div class="layout">
<div id="controls"><!-- DO NOT EDIT --></div>
<div id="currentSlide"><!-- DO NOT EDIT --></div>
<div id="header"></div>
<div id="footer">
<h1>INFO 343 Lecture 11</h1>
<h2>Client-Side Form Validation</h2>
</div>
</div>
<div class="presentation">
<div class="slide">
<h1>Client-Side Form Validation</h1>
<h3>Lecture 11</h3>
<h4>Reading: 9.2.3–9.2.4</h4>
<p class="license">
Except where otherwise noted, the contents of this presentation are Copyright 2010 Marty Stepp, Jessica Miller, and/or Morgan Doocy.
</p>
<div class="w3c">
<a href="http://validator.w3.org/check/referer"><img src="../s5/images/w3c-xhtml11.png" alt="Valid XHTML 1.1" /></a>
<a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../s5/images/w3c-css.png" alt="Valid CSS!" /></a>
</div>
</div>
<div class="slide">
<h1>
Form events
<span class="readingsection">(9.1.6, 9.2.4)</span>
</h1>
<table class="standard">
<tr>
<th>
event name
</th>
<th>
description
</th>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/jsref/jsref_onsubmit.asp">submit</a></code>
</td>
<td>
form is being submitted
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/jsref/jsref_onreset.asp">reset</a></code>
</td>
<td>
form is being reset
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/jsref/jsref_onchange.asp">change</a></code>
</td>
<td>
the text or state of a form control has changed
</td>
</tr>
<!--
<li><code><a href="http://www.w3schools.com/jsref/jsref_onabort.asp">onabort</a></code> : the loading of an image is aborted</li>
-->
</table>
<ul>
<li>
Prototype adds the following methods to form controls' DOM objects:
</li>
</ul>
<table class="standard">
<tr>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/activate"><code>activate</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/clear"><code>clear</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/disable"><code>disable</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/enable"><code>enable</code></a></td>
</tr>
<tr>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/focus"><code>focus</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/getValue"><code>getValue</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/present"><code>present</code></a></td>
<td><a class="popup" href="http://www.prototypejs.org/api/form/element/select"><code>select</code></a></td>
</tr>
</table>
</div>
<div class="slide">
<h1>
Prototype form shortcuts
<span class="readingsection">(9.1.6)</span>
</h1>
<pre class="syntaxtemplate js">
$F("<var>formID</var>")["<var>name</var>"]
</pre>
<ul style="margin-bottom: 1em">
<li>
gets parameter with given <strong>name</strong> from form with given <strong>id</strong>
</li>
</ul>
<pre class="syntaxtemplate js">
<em>$F</em>("<var>controlID</var>")
</pre>
<ul>
<li>
<a class="popup" href="http://www.prototypejs.org/api/utility/dollar-f"><code>$F</code> function</a> returns the <strong>value</strong> of a form control with the given <strong>id</strong>
<pre class="examplecode js">
if (<em>$F("username")</em>.length < 4) {
$("username").<em>clear</em>();
$("login").<em>disable</em>();
}
</pre>
</li>
</ul>
</div>
<div class="slide">
<h1>Stopping an event</h1>
<pre class="examplecode html">
<form <em>id="exampleform"</em> action="http://foo.com/foo.php">...</form>
</pre>
<pre class="examplecode js">
document.observe('dom:loaded', function() {
$("exampleform").observe(<em>"submit"</em>, checkData);
});
function checkData(<em>event</em>) {
if ($F("city") == "" || $F("state").length != 2) {
alert("Error, invalid city/state."); <span class="comment">// show error message</span>
<em>event.stop();</em>
<em>return false;</em>
}
}
</pre>
<ul>
<li>to abort a form submit or other event, call Prototype's <a href="http://www.prototypejs.org/api/event/stop"><code>stop</code></a> method on the event</li>
</ul>
</div>
<!--
<div class="slide">
<h1>Benefits of DOM over <code>innerHTML</code></h1>
<pre class="examplecode js">
function slideClick() {
var p = document.createElement("p");
<em>p.className = "special";
p.onclick = myOnClick;</em>
p.innerHTML = "A paragraph!";
$("thisslide").appendChild(p);
}
</pre>
<pre class="examplecode css">
.special {
color: red;
margin-left: 50px;
}
</pre>
<ul>
<li>cleaner to attach event handlers to DOM object</li>
<li>cleaner to set styles by attaching classes to DOM objects</li>
</ul>
</div>
-->
<div class="slide">
<h1>What is form validation?</h1>
<ul>
<li><span class="term">validation</span>: ensuring that form's values are correct</li>
<li>some types of validation:
<ul>
<li>preventing blank values (email address)</li>
<li>ensuring the type of values
<ul>
<li>integer, real number, currency, phone number, Social Security number, postal address, email address, date, credit card number, ...</li>
</ul>
</li>
<li>ensuring the format and range of values (ZIP code must be a 5-digit integer)</li>
<li>ensuring that values fit together (user types email twice, and the two must match)</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>A real form that uses validation</h1>
<div style="text-align: center">
<a href="https://online.wamu.com/IdentityManagement/SignUp.aspx"><img src="images/wamu.png" alt="wamu" style="border: 0" /></a>
</div>
</div>
<div class="slide">
<h1>Client vs. server-side validation</h1>
<p>
Validation can be performed:
</p>
<ul>
<li><span class="term">client-side</span> (before the form is submitted)
<ul>
<li>can lead to a better user experience, but not secure (why not?)</li>
</ul>
</li>
<li><span class="term">server-side</span> (in PHP code, after the form is submitted)
<ul>
<li>needed for truly secure validation, but slower</li>
</ul>
</li>
<li>both
<ul>
<li>best mix of convenience and security, but requires most effort to program</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>An example form to be validated</h1>
<div class="example">
<pre class="examplecode html">
<form action="http://foo.com/foo.php" method="get">
<div>
City: <input <em>name="city"</em> /> <br />
State: <input <em>name="state"</em> size="2" maxlength="2" /> <br />
ZIP: <input <em>name="zip"</em> size="5" maxlength="5" /> <br />
<input type="submit" />
</div>
</form>
</pre>
<div class="exampleoutput insertoutput"></div>
</div>
<ul>
<li>Let's validate this form's data before we send it...</li>
</ul>
</div>
<div class="slide">
<h1>Basic client-side validation</h1>
<pre class="examplecode php">
var city = $("city").value;
var state = $("state").value;
var zip = $("zip").value;
<em>if (!city || state.length != 2 || zip.length != 5) {
alert("Error, invalid city/state/zip submitted.");
}</em>
</pre>
<ul>
<li><em>basic idea:</em> examine field values, and if they are bad, show an error message and halt submission. But:
<ul>
<li>How do you test for integers vs. real numbers vs. strings?</li>
<li>How do you test for a valid credit card number?</li>
<li>How do you test that a person's name has a middle initial?</li>
<li class="incremental">(How do you test whether a given string matches a particular complex format?)</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Regular expressions</h1>
<pre class="examplecode">
/^[a-zA-Z_\-]+@(([a-zA-Z_\-])+\.)+[a-zA-Z]{2,4}$/
</pre>
<ul>
<li><span class="term">regular expression</span> ("regex"): a description of a pattern of text
<ul>
<li>can test whether a string matches the expression's pattern</li>
<li>can use a regex to search/replace characters in a string</li>
</ul>
</li>
<li>regular expressions are extremely powerful but tough to read<br />
(the above regular expression matches email addresses)</li>
<li>regular expressions occur in many places:
<ul>
<li>Java: <code>Scanner</code>, <code>String</code>'s <code>split</code> method (CSE 143 sentence generator)</li>
<li>supported by PHP, JavaScript, and other languages</li>
<li>many text editors (TextPad) allow regexes in search/replace</li>
</ul>
</li>
</ul>
</div>
<!-- <div class="slide">
<h1><a href="http://www.php.net/pcre">Regular expressions</a> in PHP (<a href="http://www.phpguru.org/downloads/PCRE%20Cheat%20Sheet/PHP%20PCRE%20Cheat%20Sheet.pdf">PDF</a>)</h1>
<ul>
<li><a href="http://www.php.net/manual/en/reference.pcre.pattern.syntax.php">regex syntax</a>: strings that begin and end with <code>/</code>, such as <code>"/[AEIOU]+/"</code></li>
</ul>
<table class="standard">
<tr>
<th>function</th>
<th>description</th>
</tr>
<tr>
<td>
<code><a href="http://www.php.net/preg-match">preg_match</a>(<var>regex</var>, <var>string</var>)</code>
</td>
<td>
returns <code>TRUE</code> if <var>string</var> matches <var>regex</var>
</td>
</tr>
<tr>
<td>
<code><a href="http://www.php.net/preg-replace">preg_replace</a>(<var>regex</var>, <var>replacement</var>, <var>string</var>)</code>
</td>
<td>
returns a new string with all substrings that match <var>regex</var> replaced by <var>replacement</var>
</td>
</tr>
<tr>
<td>
<code><a href="http://www.php.net/preg-split">preg_split</a>(<var>regex</var>, <var>string</var>)</code>
</td>
<td>
returns an array of strings from given <var>string</var> broken apart using given <var>regex</var> as delimiter (like <code>explode</code> but more powerful)
</td>
</tr>
</table>
</div> -->
<!-- <div class="slide">
<h1>JavaScript form validation w/ regexes</h1>
<pre class="examplecode php">
var state = $("state");
if (!<em>state.match(/^[A-Z]{2}$/)</em>) {
alert("Error, invalid state entered.");
}
</pre>
<ul>
<li><code>preg_match</code> and regexes help you to validate parameters</li>
<li>sites often <em>don't</em> want to give a descriptive error message here (why?)</li>
</ul>
</div> -->
<div class="slide">
<h1>Basic regular expressions</h1>
<pre class="examplecode">
/abc/
</pre>
<ul>
<li>in JavaScript, regexes begin and end with <code>/</code></li>
<li>the simplest regexes simply match a particular substring</li>
<li>the above regular expression matches any string containing <code>"abc"</code>:
<ul>
<li>
YES:
<code>"abc"</code>,
<code>"abcdef"</code>,
<code>"defabc"</code>,
<code>".=.abc.=."</code>,
...
</li>
<li>
NO:
<code>"fedcba"</code>,
<code>"ab c"</code>,
<code>"PHP"</code>,
...
</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Wildcards: <code>.</code></h1>
<ul>
<li>A dot <code>.</code> matches any character except a <code>\n</code> line break
<ul>
<li><code>/.oo.y/</code> matches
<code>"Doocy"</code>,
<code>"goofy"</code>,
<code>"LooNy"</code>,
...
</li>
</ul>
</li>
<li>A trailing <code>i</code> at the end of a regex (after the closing <code>/</code>) signifies a case-insensitive match
<ul>
<li>
<code>/mart/i</code> matches
<code>"Marty Stepp"</code>,
<code>"smart fellow"</code>,
<code>"WALMART"</code>,
...
</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Special characters: <code>|</code>, <code>()</code>, <code>\</code></h1>
<ul>
<li><code>|</code> means <em>OR</em>
<ul>
<li><code>/abc|def|g/</code> matches <code>"abc"</code>, <code>"def"</code>, or <code>"g"</code></li>
<li>There's no <em>AND</em> symbol. Why not?</li>
</ul>
</li>
<li><code>()</code> are for grouping
<ul>
<li><code>/(Homer|Marge) Simpson/</code> matches <code>"Homer Simpson"</code>
or <code>"Marge Simpson"</code></li>
<!--
<li>What does <code>/Homer|Marge|Bart|Lisa|Maggie S/</code> match?</li>
-->
</ul>
</li>
<li><code>\</code> starts an <span class="term">escape sequence</span>
<ul>
<li>many characters must be escaped to match them literally: <code>/ \ $ . [ ] ( ) ^ * + ?</code></li>
<li><code>/<br \/>/</code> matches lines containing <code><br /></code> tags</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Quantifiers: <code>*</code>, <code>+</code>, <code>?</code></h1>
<ul>
<li><code>*</code> means 0 or more occurrences
<ul>
<li><code>/abc*/</code> matches <code>"ab"</code>, <code>"abc"</code>, <code>"abcc"</code>, <code>"abccc"</code>, ...</li>
<li><code>/a(bc)*/</code> matches <code>"a"</code>, <code>"abc"</code>, <code>"abcbc"</code>, <code>"abcbcbc"</code>, ...</li>
<li><code>/a.*a/</code> matches <code>"aa"</code>, <code>"aba"</code>, <code>"a8qa"</code>, <code>"a!?xyz__9a"</code>, ...</li>
</ul>
</li>
<li><code>+</code> means 1 or more occurrences
<ul>
<li><code>/a(bc)+/</code> matches <code>"abc"</code>, <code>"abcbc"</code>, <code>"abcbcbc"</code>, ...</li>
<li><code>/Goo+gle/</code> matches <code>"Google"</code>, <code>"Gooogle"</code>, <code>"Goooogle"</code>, ...</li>
</ul>
</li>
<li><code>?</code> means 0 or 1 occurrences
<ul>
<li><code>/a(bc)?/</code> matches <code>"a"</code> or <code>"abc"</code></li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>More quantifiers: <code>{min,max}</code></h1>
<ul>
<li><code>{<var>min</var>,<var>max</var>}</code> means between <var>min</var> and <var>max</var> occurrences (inclusive)
<ul>
<li><code>/a(bc){2,4}/</code> matches <code>"abcbc"</code>, <code>"abcbcbc"</code>, or <code>"abcbcbcbc"</code></li>
</ul>
</li>
<li><var>min</var> or <var>max</var> may be omitted to specify any number
<ul>
<li><code>{2,}</code> means 2 or more</li>
<li><code>{,6}</code> means up to 6</li>
<li><code>{3}</code> means exactly 3</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Anchors: <code>^</code> and <code>$</code></h1>
<ul>
<li><code>^</code> represents the beginning of the string or line; <br />
<code>$</code> represents the end
<ul>
<li>
<code>/Jess/</code> matches all strings that contain <code>Jess</code>; <br />
<code>/^Jess/</code> matches all strings that <em>start with</em> <code>Jess</code>; <br />
<code>/Jess$/</code> matches all strings that <em>end with</em> <code>Jess</code>; <br />
<code>/^Jess$/</code> matches the exact string <code>"Jess"</code> only
</li>
<li>
<code>/^Mart.*Stepp$/</code> matches <code>"MartStepp"</code>, <code>"Marty Stepp"</code>, <code>"Martin D Stepp"</code>, ... <br />
but NOT <code>"Marty Stepp stinks"</code> or <code>"I H8 Martin Stepp"</code>
</li>
</ul>
</li>
<li>
(on the other slides, when we say, <code>/PATTERN/</code> matches <code>"text"</code>, we really mean that it matches any string that contains that text)
</li>
</ul>
</div>
<div class="slide">
<h1>Character sets: <code>[]</code></h1>
<ul>
<li>
<code>[]</code> group characters into a <span class="term">character set</span>; will match any single character from the set
<ul>
<li><code>/[bcd]art/</code> matches strings containing <code>"bart"</code>, <code>"cart"</code>, and <code>"dart"</code></li>
<li>equivalent to <code>/(b|c|d)art/</code> but shorter</li>
</ul>
</li>
<li>inside <code>[]</code>, many of the modifier keys act as normal characters
<ul>
<li><code>/what[!*?]*/</code> matches <code>"what"</code>, <code>"what!"</code>, <code>"what?**!"</code>, <code>"what??!"</code>, ...</li>
</ul>
</li>
<li>What regular expression matches DNA (strings of A, C, G, or T)?
<ul>
<li class="incremental"><code>/[ACGT]+/</code></li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Character ranges: <code>[<var>start</var>-<var>end</var>]</code></h1>
<ul>
<li>inside a character set, specify a range of characters with <code>-</code>
<ul>
<li><code>/[a-z]/</code> matches any lowercase letter</li>
<li><code>/[a-zA-Z0-9]/</code> matches any lower- or uppercase letter or digit</li>
</ul>
</li>
<li>an initial <code>^</code> inside a character set negates it
<ul>
<li><code>/[^abcd]/</code> matches any character other than a, b, c, or d</li>
</ul>
</li>
<li>inside a character set, <code>-</code> must be escaped to be matched
<ul>
<li><code>/[+\-]?[0-9]+/</code> matches an optional <code>+</code> or <code>-</code>, followed by at least one digit</li>
</ul>
</li>
<li>What regular expression matches letter grades such as A, B+, or D- ?
<ul>
<li class="incremental"><code>/[ABCDF][+\-]?/</code></li>
</ul>
</li>
<!--
<li class="incremental">What regular expression would match UW Student IDs?</li>
<li class="incremental">What regular expression would match consonants, assuming that the string consists only of lowercase letters?</li>
-->
</ul>
</div>
<div class="slide">
<h1>Escape sequences</h1>
<ul>
<li>special escape sequence character sets:
<ul>
<li>
<code>\d</code> matches any digit (same as <code>[0-9]</code>);
<code>\D</code> any non-digit (<code>[^0-9]</code>)
</li>
<li>
<code>\w</code> matches any <q>word character</q> (same as <code>[a-zA-Z_0-9]</code>);
<code>\W</code> any non-word char
</li>
<li>
<code>\s</code> matches any whitespace character ( , <code>\t</code>, <code>\n</code>, etc.);
<code>\S</code> any non-whitespace
</li>
<!--
<li><code>\b</code> matches a word boundary (0 chars wide)</li>
<li><code>\B</code> matches a non-word boundary</li>
-->
</ul>
</li>
<li>What regular expression matches dollar amounts of at least $100.00 ?
<ul>
<li class="incremental"><code>/\$\d{3,}\.\d{2}/</code></li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Regular expressions in JavaScript</h1>
<ul>
<li><code><var>string</var>.match(<var>regex</var>)</code>
<ul>
<li>if string fits the pattern, returns the matching text; else returns <code>null</code></li>
<li>can be used as a Boolean truthy/falsey test:<br />
<code>var name = $("name").value;<br />if (name.match(<em>/[a-z]+/</em>)) { ... }</code></li>
</ul>
</li>
<li>an <code>i</code> can be placed after the regex for a case-insensitive match
<ul>
<li><code>name.match(/Marty/i)</code> will match <code>"marty"</code>, <code>"MaRtY"</code>, ...</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Replacing text with regular expressions</h1>
<ul>
<li><code><var>string</var>.replace(<var>regex</var>, "<var>text</var>")</code>
<ul>
<li>replaces the <strong>first</strong> occurrence of given pattern with the given text
<code>var str = "Marty Stepp";</code><br />
<code>str.replace(/[aeiou]/, "*")</code> returns <code>"M<em>*</em>rty St<em>e</em>pp"</code>
</li>
</ul>
</li>
<li>a <code>g</code> can be placed after the regex for a global match (replace <strong>all</strong> occurrences)
<ul>
<li><code>str.replace(/[aeiou]/<em>g</em>, "*")</code> returns <code>"M<em>*</em>rty St<em>*</em>pp"</code></li>
</ul>
</li>
<li>does not modify the string itself; returns the modified string as its result<br />
<pre><code>str.replace(/[aeiou]/g, "*"); <span class="comment">// str still "Marty Stepp" !</span>
<em>str = </em>str.replace(/[aeiou]/g, "*"); <span class="comment">// str now "M*rty St*pp"</span></code></pre>
</li>
<li>remove disallowed characters ("filter") by replacing with empty string
<ul>
<li><code>str = str.replace(/[^A-Z]+/<em>g</em>, <em>""</em>)</code> turns <code>str</code> into <code>"MS"</code></li>
</ul>
</li>
</ul>
</div>
<!-- <div class="slide">
<h1>Regular expression PHP example</h1>
<pre class="examplecode php">
<span class="comment"># replace vowels with stars</span>
$str = "the quick brown fox";
$str = <em>preg_replace</em>("/[aeiou]/", "*", $str);
<span class="comment"># "th* q**ck br*wn f*x"</span>
<span class="comment"># break apart into words</span>
$words = <em>preg_split</em>("/[ ]+/", $str);
<span class="comment"># ("th*", "q**ck", "br*wn", "f*x")</span>
<span class="comment"># capitalize words that had 2+ consecutive vowels</span>
for ($i = 0; $i < count($words); $i++) {
if (<em>preg_match</em>("/\\*{2,}/", $words[$i])) {
$words[$i] = strtoupper($words[$i]);
}
} <span class="comment"># ("th*", "Q**CK", "br*wn", "f*x")</span>
</pre>
<ul>
<li>notice how <code>\</code> must be escaped to <code>\\</code></li>
</ul>
</div> -->
<!--#include virtual="../s5/commonbottom.html" -->