Simple Form Validation

G

greg.scharlemann

I've been playing with this form validation method for a while and have
tried an array of things but haven't had any luck with a couple items.

1. The validateForm() function doesn't detect when the Min price is
greater than the maximum price.
2. The validateForm() function doesn't call isNumber() on the minBaths,
maxBaths, minBeds, or maxBeds.
3. Despite errors in input and the validateForm() function returning
false, the form is still submitted.

These are probably obvious fixes...I'm just not seeing them. thanks for
any help.

Here's the code:
<html>
<head>
<title></title>
<link rel="stylesheet" href="css/main.css">
<script language="JavaScript">
<!--
function validateForm(thisForm){
alert("validateForm() called");
//alert("'" + thisForm.minBaths.value + "'");
//alert(isNumber(thisForm.minBaths.value));
if (thisForm.minPrice.value == "") {
alert("You must enter a starting price.");
thisForm.minPrice.focus();
return false;
} else if(!isNumber(thisForm.minPrice.value)) {
alert("Please enter a number for the starting price.");
thisForm.minPrice.focus();
return false;
} else if (thisForm.maxPrice.value == "") {
alert("You must enter a maximum price.");
thisForm.maxPrice.focus();
return false;
} else if(!isNumber(thisForm.maxPrice.value)) {
alert("Please enter a number for the maximum price.");
thisFormForm.maxPrice.focus();
return false;
} else if(thisForm.minPrice.valueOf() >
thisForm.maxPrice.valueOf()) {
alert("The starting value is greater than the maximum price.");
thisForm.minPrice.focus();
return false;
} else if(!isNumber(thisForm.minBaths.value)) {
alert("Please enter a number for the minimum bathrooms.");
thisForm.minBaths.focus();
return false;
} else if(!isNumber(thisForm.maxBaths.value)) {
alert("Please enter a number of the maximum bathrooms.");
thisForm.maxBaths.focus();
} else if(!isNumber(thisForm.minBeds.value)) {
alert("Please enter a number for the minimum bedrooms.");
thisForm.minBeds.focus();
return false;
} else if(!isNumber(thisForm.maxBeds.value)) {
alert("Please enter a number for the maximum bedrooms.");
thisForm.maxBeds.focus();
return false;
} else {
return false;
}
}

function isNumber(entry) {
//alert("isNumber() Called");
validChar='0123456789'; // characters allowed
strlen=entry.length; // how long is test string
if (strlen < 1) {return false;} // no check!
// Now scan string for illegal characters
for (i=0; i < strlen; i++ ) {
if (validChar.indexOf(entry.charAt(i)) < 0) {
return false;
}
}
//alert("returning true");
return true;
}

//-->
</script>
</head>
<body>
<!-- HEADER START -->
<table border="0" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="bottomborder" colspan="3">
<div align="right" style="font-size:12px;">| <a
href="/">Home</a> |
<a href="/about.php">About</a> |
<a href="/contact.php">Contact</a> |&nbsp;</div>
</td>
</tr>
<!-- HEADER END -->
<tr>
<td valign="top" width="550">
<form name="searchForm" onSubmit="return validateForm(this)"
method="post">
<input type="hidden" name="advanced" value="true" />
<input type="hidden" name="valid" value="true" />
<table width="600" cellspacing="1" cellpadding="1" border="0"
class="padLeft">
<tr>
<td nowrap align="right">Street:</td>
<td colspan="7" nowrap>&nbsp;&nbsp;&nbsp;<input
type="text" name="StreetName" size="30" value=""/></td>
</tr>
<tr>
<td nowrap align="right">City:</td>
<td nowrap colspan="4">&nbsp;&nbsp;&nbsp;<input
type="text" name="City" size="20"
value=""/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;State:
&nbsp;&nbsp;&nbsp;
<select name="State">
<option value="NC">NC</option>
<option value="SC">SC</option>
</select>
<span
style="padding-left:6px;padding-right:6px;font-size:12px;font-weight:bold;color:$999";>-OR-</span>
Zip Code:&nbsp;&nbsp;&nbsp;<input type="text" name="ZipCode" size="6"
maxlength="5" value=""/></td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<td colspan="5" style="padding-left:10px">
<table border="0" cellpadding="1" cellspacing="1">
<tr>
<td nowrap align="right">Min Price:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minPrice" size="4" value="120000"/></td>
<td nowrap align="right">Max Price:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxPrice" size="4" value="125000"/></td>
</tr>
<tr>
<td nowrap align="right">Min Beds:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minBeds" size="4" maxlength="2" /></td>
<td nowrap align="right">Max Beds:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxBeds" size="4" maxlength="2" /></td>
</tr>
<tr>
<td nowrap align="right">Min Baths:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minBaths" size="4" maxlength="2" value="ax" /></td>
<td nowrap width="75" align="right">Max Baths:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxBaths" size="4" maxlength="2" /></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="3"><input type="submit" value="Submit"
name="submit" /></td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>
 
M

Michael Winter

On 15/10/2005 21:28, (e-mail address removed) wrote:

[snip]
<script language="JavaScript">

The language attribute has long been deprecated in favour of the
required type attribute:


Don't use SGML comment delimiters in SCRIPT elements.

[snip]
if (thisForm.minPrice.value == "") {

Form controls shouldn't be thought of as properties of the FORM object.
FORM objects have a property, elements, that contain the controls as a
collection.

A simpler test for an empty string is to convert it to a boolean. Empty
strings type-convert to boolean false:

var controls = thisForm.elements;

if(!controls.minPrice.value) {

[snip]
} else if(thisForm.minPrice.valueOf() >
thisForm.maxPrice.valueOf()) {

Depending which browser you run this in, it either won't do what you
want (compare the user input values as numbers), or it will error out.

IE does the latter, and this is most likely why the form submission
isn't stopped.

[snip]
} else {
return false;
}

The else clause should return true. Was this just for testing purposes?


function validateForm(form) {
var controls = form.elements,
minPrice = controls.minPrice,
maxPrice = controls.maxPrice,
minBaths = controls.minBaths,
maxBaths = controls.maxBaths,
minBeds = controls.minBeds,
maxBeds = controls.maxBeds;

/* The isNumber function used here should be the second one
* proposed below. That regular expression ensures that at
* least one character is present, and that it's a number.
*/
if(!isNumber(minPrice.value)) {
alert('Please enter a number for the minimum price.');
minPrice.focus();
return false;
}
if(!isNumber(maxPrice.value)) {
alert('Please enter a number for the maximum price.');
maxPrice.focus();
return false;
}
/* Notice below that the string values are type-converted
* to numbers before the comparison is made.
* We already know that the string represents a number.
*/
if(+minPrice.value > +maxPrice.value) {
/* String literal wrapped for posting, only. */
alert('The starting value must not be '
+ 'greater than the maximum price.');
minPrice.focus();
return false;
}
if(!isNumber(minBaths.value)) {
alert('Please enter a number for the '
+ 'minimum number of bathrooms.');
minBaths.focus();
return false;
}
if(!isNumber(maxBaths.value)) {
alert('Please enter a number for the '
+ 'maximum number of bathrooms.');
maxBaths.focus();
return false;
}
if(!isNumber(minBeds.value)) {
alert('Please enter a number for the '
+ 'minimum number of bedrooms.');
minBeds.focus();
return false;
}
if(!isNumber(maxBeds.value)) {
alert('Please enter a number for the '
+ 'maximum number of bedrooms.');
maxBeds.focus();
return false;
}
return true;
}
function isNumber(entry) {
//alert("isNumber() Called");
validChar='0123456789'; // characters allowed
strlen=entry.length; // how long is test string
if (strlen < 1) {return false;} // no check!
// Now scan string for illegal characters
for (i=0; i < strlen; i++ ) {
if (validChar.indexOf(entry.charAt(i)) < 0) {
return false;
}
}
//alert("returning true");
return true;
}

A simpler, quicker test for numbers is to use regular expressions.

function isNumber(string) {
return !/\D/.test(string);
}

This simply ensures that the string doesn't contain non-digit
characters, which is fine in most simple cases where only integers are
permitted as input. Something a little more complex would be:

function isNumber(string) {
return /^(0|[1-9]\d*)(\.\d+)?$/.test(string);
}

which allows for decimal values, too.

[snip]
<div align="right" style="font-size:12px;">| <a
href="/">Home</a> |
<a href="/about.php">About</a> |
<a href="/contact.php">Contact</a> |&nbsp;</div>

That should be marked-up as a list (UL) of links.

[snip]
<form name="searchForm" onSubmit="return validateForm(this)"
method="post">

I assume you omitted the action attribute just for this example?
<input type="hidden" name="advanced" value="true" />

You seem to be confused about whether you're writing HTML or XHTML. Just
use the former.

[snip]
<span style="padding-left:6px;padding-right:6px;font-size:12px;

Don't specify font sizes using pixels as this prevents IE from resizing
the text. Use percentages, instead (preferably no lower than 85% of
default).
font-weight: bold;color:$999";>-OR-</span>

Was the dollar symbol ($) intentional, or a typo for a hash (#)?

[snip]

Mike
 
N

Nag

1. The validateForm() function doesn't detect when the Min price is
greater than the maximum price.
You should use 'value' method insted of valueOf().
2. The validateForm() function doesn't call isNumber() on the minBaths,

maxBaths, minBeds, or maxBeds.
There is some problem in your logic. Please find my changed logic
below. Also, you can make use of built in javascript function for
checking number or not by isNaN()
3. Despite errors in input and the validateForm() function returning
false, the form is still submitted.
Check the changed form below.

Pls test this form, let me know if you have any problem.

Thanks,
Nag.

---------------------------
Starts here
---------------------------

<html>
<head>
<title></title>
<link rel="stylesheet" href="css/main.css">
<script language="JavaScript">
<!--
function validateForm(thisForm){
var okay = true;
alert("validateForm() called");
alert("Value of minprice" + thisForm.minPrice.value);
if (thisForm.minPrice.value == "") {
alert("You must enter a starting price.");
thisForm.minPrice.focus();
okay = false;
} else if(isNaN(thisForm.minPrice.value)) {
alert("Please enter a number for the starting price.");
thisForm.minPrice.focus();
okay = false;
}

if(okay)
{
alert("Inside maxPrice block:");
if (thisForm.maxPrice.value == "") {
alert("You must enter a maximum price.");
thisForm.maxPrice.focus();
okay = false;
} else if(isNaN(thisForm.maxPrice.value)) {
alert("Please enter a number for the maximum price.");
thisFormForm.maxPrice.focus();
okay = false;
}
}



if(okay)
{
alert("in comparision block");
if(thisForm.minPrice.value > thisForm.maxPrice.value) {
alert("The starting value is greater than the maximum price.");
thisForm.minPrice.focus();
okay = false;
}
else
okay = true;
}

if(okay)
{
if(isNaN(thisForm.minBaths.value)) {
alert("Please enter a number for the minimum bathrooms.");
thisForm.minBaths.focus();
okay = false;
} else if(isNaN(thisForm.maxBaths.value)) {
alert("Please enter a number of the maximum bathrooms.");
okay = false;
} else if(isNaN(thisForm.minBeds.value)) {
alert("Please enter a number for the minimum bedrooms.");
thisForm.minBeds.focus();
okay = false;
} else if(isNaN(thisForm.maxBeds.value)) {
alert("Please enter a number for the maximum bedrooms.");
thisForm.maxBeds.focus();
okay = false;
} else {
okay = true;
}
}

if(okay)
return true;
else
return false;
}
//-->
</script>
</head>
<body>
<!-- HEADER START -->
<table border="0" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="bottomborder" colspan="3">
<div align="right" style="font-size:12px;">| <a
href="/">Home</a> |
<a href="/about.php">About</a> |
<a href="/contact.php">Contact</a> |&nbsp;</div>
</td>
</tr>
<!-- HEADER END -->
<tr>
<td valign="top" width="550">
<form name="searchForm" onSubmit="return validateForm(this)"
method="post">
<input type="hidden" name="advanced" value="true" />
<input type="hidden" name="valid" value="true" />
<table width="600" cellspacing="1" cellpadding="1" border="0"

class="padLeft">
<tr>
<td nowrap align="right">Street:</td>
<td colspan="7" nowrap>&nbsp;&nbsp;&nbsp;<input
type="text" name="StreetName" size="30" value=""/></td>
</tr>
<tr>
<td nowrap align="right">City:</td>
<td nowrap colspan="4">&nbsp;&nbsp;&nbsp;<input
type="text" name="City" size="20"
value=""/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;State:
&nbsp;&nbsp;&nbsp;
<select name="State">
<option value="NC">NC</option>
<option value="SC">SC</option>
</select>
<span
style="padding-left:6px;padding-right:6px;font-size:12px;font-weight:bold;c­olor:$999";>-OR-</span>

Zip Code:&nbsp;&nbsp;&nbsp;<input type="text" name="ZipCode" size="6"
maxlength="5" value=""/></td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<td colspan="5" style="padding-left:10px">
<table border="0" cellpadding="1" cellspacing="1">
<tr>
<td nowrap align="right">Min Price:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minPrice" size="4" value="120000"/></td>
<td nowrap align="right">Max Price:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxPrice" size="4" value="125000"/></td>
</tr>
<tr>
<td nowrap align="right">Min Beds:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minBeds" size="4" maxlength="2" /></td>
<td nowrap align="right">Max Beds:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxBeds" size="4" maxlength="2" /></td>
</tr>
<tr>
<td nowrap align="right">Min Baths:</td>
<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="minBaths" size="4" maxlength="2" value="ax" /></td>
<td nowrap width="75" align="right">Max Baths:</td>

<td nowrap>&nbsp;&nbsp;&nbsp;<input type="text"
name="maxBaths" size="4" maxlength="2" /></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="3"><input type="submit" value="Submit"
name="submit" /></td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>
 
R

RobG

Michael Winter wrote:
[...]
/* Notice below that the string values are type-converted
* to numbers before the comparison is made.
* We already know that the string represents a number.
*/
if(+minPrice.value > +maxPrice.value) {

A question Mike:

You are using the unary '+' to convert the strings to numbers, but when
strings are used in a numeric comparison they are converted to numbers
automatically. Therefore the use of '+' seems to be redundant.

Is there some other reason for it?

[...]
 
R

Richard Cornford

RobG said:
Michael Winter wrote:
[...]
/* Notice below that the string values are type-converted
* to numbers before the comparison is made.
* We already know that the string represents a number.
*/
if(+minPrice.value > +maxPrice.value) {

A question Mike:

You are using the unary '+' to convert the strings to numbers,
but when strings are used in a numeric comparison they are
converted to numbers automatically.
<snip>

Not true. The Abstract Relational Comparison Algorithm (ECMA 262 3rd
edition; section 11.8.5) has a strong preference for doing its
comparisons with numeric value but set 3 tests to see if both operands
are strings and if they are it jumps to step 16, where the strings are
subject to comparison as a sequence of characters.

As form the control's - value - properties are of string type, comparing
two of them will require the explicit type-conversion if numeric
comparison is required, (Though it would only be strictly necessary to
explicitly type-convert one of the operands to avoid step 3 jumping to
step 16.)

Richard.
 
R

RobG

Richard said:
RobG said:
Michael Winter wrote:
[...]
/* Notice below that the string values are type-converted
* to numbers before the comparison is made.
* We already know that the string represents a number.
*/
if(+minPrice.value > +maxPrice.value) {

A question Mike:

You are using the unary '+' to convert the strings to numbers,
but when strings are used in a numeric comparison they are
converted to numbers automatically.

<snip>

Not true. The Abstract Relational Comparison Algorithm (ECMA 262 3rd
edition; section 11.8.5) has a strong preference for doing its
comparisons with numeric value but set 3 tests to see if both operands
are strings and if they are it jumps to step 16, where the strings are
subject to comparison as a sequence of characters.

As form the control's - value - properties are of string type, comparing
two of them will require the explicit type-conversion if numeric
comparison is required, (Though it would only be strictly necessary to
explicitly type-convert one of the operands to avoid step 3 jumping to
step 16.)

Thanks Richard, it was clearly a misunderstanding on my part.

I realise now that it came from comparing values to numbers
(e.g. minPrice.value > 0) where the 'jump to step 16' is prevented.
 
D

Dr John Stockton

JRS: In article <[email protected]>,
dated Sat, 15 Oct 2005 13:28:18, seen in (e-mail address removed) posted :
I've been playing with this form validation method for a while and have
tried an array of things but haven't had any luck with a couple items.

Don't rely on luck. If something does not work, isolate it as a minimal
test case, reducing it until you understand. Also, read the newsgroup
FAQ.

You've used .value in some places and .valueOf() in others.
Strings are compared as strings, and can be converted to numbers with
unary +.
You don't need else after if () { ... return } .


Repetitive code should be replaced with function calls.
Untested Example :

function Empty(Item, Name) {
var Bad = Item.value > ""
if (Bad) { alert("You must enter a " + Name) ; Item.focus() }
return Bad

....

if (Empty(thisForm.minPrice, "starting price.")) return false
if (Empty(thisForm.maxPrice, "maximum price.")) return false


function isNumber(entry) { return /^\d+$/.test(entry) }
if (strlen < 1) {return false;} // no check! // no need.

<div align="right" style="font-size:12px;">| <a

Specifying absolute sizes is in breach of disabled access legislation
principles in civilised countries. Likewise absolute widths.

<form name="searchForm" onSubmit="return validateForm(this)"
method="post">

Don't let your posting agent wrap lines, whether HTML or script. The
experts prefer not to waste time with unnecessary errors.

Read the newsgroup FAQ again. And read <URL:http://www.merlyn.demon.co.
uk/js-valid.htm>.
 
G

Greg Scharlemann

Mike

Thanks for such a thorough response. I've updated my validateForm()
method and it works great. one question I had on your comments however
is related to the links:
That should be marked-up as a list (UL) of links.

Can you give me an example of what you mean with the <ul> tag and the
links ?

Thanks, Greg
 
R

RobG

Greg said:
Mike

Thanks for such a thorough response. I've updated my validateForm()
method and it works great. one question I had on your comments however
is related to the links:




Can you give me an example of what you mean with the <ul> tag and the
links ?

Search for "css horizontal list", below is an example but for a fairly
thorough treatment:

<URL:http://www.alistapart.com/articles/taminglists/>



<head>
<style type="text/css">
#navLinks li {
display: inline;
list-style-type: none;
padding: 0 5px 0 0;
}
</style>


<body>
<ul id="navLinks">
<li><a href="/about.php">About</a></li>
<li><a href="/contact.php">Contact</a></li>
</ul>
 
T

Thomas 'PointedEars' Lahn

Michael said:
Don't use SGML comment delimiters in SCRIPT elements.

That would still allow for "<!" and ">" :)

Better to say not to use SGML CDO (Comment Declaration Open[1]) and
CDC (Comment Declaration Close[2]) delimiters in `script' elements.


SCNR

PointedEars
___________
[1] Informal abbreviation to be found in W3C WG's docs for "SGML
Declaration Open delimiter followed by SGML Comment Open delimiter"
[2] Informal abbreviation to be found in W3C WG's docs for "SGML
Comment Close delimiter followed by SGML Declaration Close delimiter"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top