Input validation for "unknown" field names

C

Calan

I have a server-side ASP script that dynamically creates an input form from
a database table. The table contains a field name, the table where values
are stored, type of input control, value for a label, etc.

What I need to do is create a JS validation routine that will check each
control for valid input, regardless of what the control name is. If it is a
"select", it needs to verify the index is > 1. If it is an "input", it needs
to check that it isnt't empty, etc.

Using known fields, I usually do something like this (page name is "me.asp":

***** code *****

Server-side ASP:

<%
if not isempty (Request.Form("SEND")) then
if Request("validated") = "true" then
{do something}
response.redirect "nextpage.asp"
end if
end if
%>

Document head section:

<script language="JavaScript">
function validateComplete(formObj)
{
if (emptyField(formObj.OrderNumber))
alert("Please enter the order number.");

else if (formObj.BaseModel.selectedIndex < 1)
alert("Please select a Base Model.");

else if (formObj.Length.selectedIndex < 1)
alert("Please select a length.");

else if ... etc etc

else {
formObj.validated.value="true";
return true;
}
formObj.validated.value="false";
return false;
}

function emptyField(textObj)
{
if (textObj.value.length == 0) return true;
for (var i=0; i<textObj.value.length; ++i) {
var ch = textObj.value.charAt(i);
if (ch != ' ' && ch != '\t') return false;
}
return true;
}

</script>

And then in the form definition:

<form method="POST" action="me.asp" onSubmit="return validateComplete(this)"
language="JavaScript">
...
...
</form>

***** end code *****


How could I re-write this to work for any and all input controls on the
form, when the control names are not consistent?

Something like:

for each select, make sure the index is >= 1
else show alert with control name
return false

for each input, make sure it's not empty
else show alert with control name
return false


etc etc.

Thanks in advance!

Calan

AxMaster Guitar Software
www.jcsautomation.com
www.jcsautomation.com/music.asp
Music software and web design/hosting

"Reality exists only in the minds of the extremely deranged"
 
M

Michael Winter

[snip]
<script language="JavaScript">

The language attribute is deprecated. Use the required type attribute:

<script type="text/javascript">

[snip]
<form method="POST" action="me.asp" onSubmit="return
validateComplete(this)" language="JavaScript">

FORM elements do not, and never have, had a language attribute.

[snip]
How could I re-write this to work for any and all input controls on the
form, when the control names are not consistent?

Use the obj.type attribute to determine the control type, and act
accordingly. For example,

function checkForm( form )
{
var c = form.elements, e, t;

for( var i = 0, n = c.length; i < n; ++i )
{
t = ( e = c[ i ]).type;

if(( 'select-one' == t ) && ( 0 == e.selectedIndex ))
{
// Tell user to select option
}
else if(( 'text' == t ) && ( 0 > e.value.length ))
{
// Tell user to enter text
}
// etc.
}
}

A list of the types for each form control is given with each control in
W3C's DOM HTML Specification, Netscape's JavaScript Reference (v1.3 only),
and Microsoft's DHTML Reference (watch for wrap):

DOM:
<URL:http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html.html#ID-798055546>

JS Ref:
<URL:http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/>

DHTML:
<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/objects.asp>

Hope that helps,
Mike
 
M

Michael Winter

Being a JS newbie, could you give a short blurb on what each line is
doing?
Certainly!

I'm a bit confused as to what 'select-one' and 'text' is referring to,
and what the 't = ( e = c[ i ]).type' line is doing.

That assignment can also be written

e = c[ i ];
t = e.type;

c - A reference to the collection of form controls in the form passed to
the function.
e - The current form control that's being validated.
t - The type of that form control.

The strings you mention appear in the type attribute for specific form
controls. 'text' signifies that the control is an INPUT element of type
text. 'select-one' represents a SELECT menu. There is a similar string,
'select-multiple', which is a SELECT element that specifies the multiple
attribute. As I said in my previous post, all form controls have a unique
string that allows them to be identified via the type attribute.
function checkForm( form )
{
var c = form.elements, e, t;

for( var i = 0, n = c.length; i < n; ++i )
{
t = ( e = c[ i ]).type;

Once you've established the type, you can then apply whatever validation
checks you want...

Is that any better?

Mike
 
C

Calan

Excellent Mike... one more question... (of course) :)

Can I use the value of the control's associated label in the warning message
somehow? For example, I use an ASP variable called "LabelText" (which is
part of the field definition in a database) to write a label next to the
control. Something like:

<%
blah blah
response.write "<td><span class='" & LabelClass & "'>" & LabelText &
"</span>
response.write "<" & ControlType & "name=' & ControlName & "' value='" &
CurrentValue & "'></td>"
etc etc etc
%>

I know I could probably display the control's name (e.name or something
similar?), but since these are database field equivalents, they are somewhat
archaic

Is there some way to capture the "LabelText" value and display it
client-side, so that the alert describes which control is being checked? (My
first thought is to use a hidden form control, named "Label" with
value=LabelText. But I'm not quite sure how to tie the label to each
control/ I just got home and haven't had enough beers to think clearly
yet)....

Now that I think about it as I type, there is another issue in that not all
controls are required. (There is an associated ASP variable called
"Required" for each control, which is used to change the label CSS class
from balck to red; shown as "LabelClass" in the example above). I'll need to
check for this also somehow. It just gets better and better... :)

Thanks again!

--
Calan

AxMaster Guitar Software
www.jcsautomation.com
www.jcsautomation.com/music.asp
Music software and web design/hosting

"Reality exists only in the minds of the extremely deranged"
 
C

Calan

Excellent Mike... one more question... (of course) :)

Can I use the value of the control's associated label in the warning message
somehow? For example, I use an ASP variable called "LabelText" (which is
part of the field definition in a database) to write a label next to the
control. Something like:

<%
blah blah
response.write "<td><span class='" & LabelClass & "'>" & LabelText &
"</span>
response.write "<" & ControlType & "name=' & ControlName & "' value='" &
CurrentValue & "'></td>"
etc etc etc
%>

I know I could probably display the control's name (e.name or something
similar?), but since these are database field equivalents, they are somewhat
archaic

Is there some way to capture the "LabelText" value and display it
client-side, so that the alert describes which control is being checked? (My
first thought is to use a hidden form control, named "Label" with
value=LabelText. But I'm not quite sure how to tie the label to each
control/ I just got home and haven't had enough beers to think clearly
yet)....

Now that I think about it as I type, there is another issue in that not all
controls are required. (There is an associated ASP variable called
"Required" for each control, which is used to change the label CSS class
from balck to red; shown as "LabelClass" in the example above). I'll need to
check for this also somehow. It just gets better and better... :)

Thanks again!

--
Calan

AxMaster Guitar Software
www.jcsautomation.com
www.jcsautomation.com/music.asp
Music software and web design/hosting

"Reality exists only in the minds of the extremely deranged"
 
M

Michael Winter

Can I use the value of the control's associated label in the warning
message somehow? For example, I use an ASP variable called "LabelText"
(which is part of the field definition in a database) to write a label
next to the control. Something like:

<%
blah blah
response.write "<td><span class='" & LabelClass & "'>" & LabelText &
"</span>
response.write "<" & ControlType & "name=' & ControlName & "' value='" &
CurrentValue & "'></td>"
etc etc etc
%>

I know I could probably display the control's name (e.name or something
similar?), but since these are database field equivalents, they are
somewhat archaic

Is there some way to capture the "LabelText" value and display it
client-side, so that the alert describes which control is being checked?
(My first thought is to use a hidden form control, named "Label" with
value=LabelText. But I'm not quite sure how to tie the label to each
control/ I just got home and haven't had enough beers to think clearly
yet)....

I thought you might ask about this. There are a couple of approaches. One
"abuses" the title attribute, the other takes advantage of semantic
mark-up, specifically, the LABEL element. Though the latter might be more
desirable, it requires more recent browsers to work. I'll present both and
let you use decide which one you want.

Using the title attribute.

This is really simple: concatenate obj.title into the error message. For
example (using the script from my previous post),

/* This was made a function to be consistent
throughout the rest of this post
*/
function getLabel( e )
{
return e.title;
}

if(( 'select-one' == t ) && ( 0 == e.selectedIndex ))
{
alert( "Please choose an option from the '" +
getLabel( e ) + "' menu" );
}

Base Model <select ... title="Base Model">
...
</select>


Using LABEL.

This builds nicely on to your current code generation (at least if it
follows the ASP snippet above). In fact, it would make a lot more sense if
you did use the LABEL element:

<%
response.write "<td><label for='" & ControlId & "'>" & LabelText &
"</label>"
response.write "<" & ControlType & "id='" & ControlId &
"' name='" & ControlName & "' value='" & CurrentValue & "'></td>"
%>

where ControlId could just be a nonsensical value like "id037", used
solely for the purpose of linking the label with the element[1]. You can
then style LABEL elements in general, rather than SPAN elements with a
certain class.

With this established, you can either walk the document tree, or search
through a collection of LABEL elements, to find the label text:

function getLabel( e )
{
var n = e.previousSibling;

while( n && ( 'LABEL' != n.nodeName ))
{
n = n.previousSibling;
}
if( n && n.firstChild )
{
return n.firstChild.nodeValue;
}
}

OR

function getLabel( e )
{
var c, id = e.id, l = null;

if( document.getElementsByTagName )
{
l = document.getElementsByTagName( 'label' );
}
else if( document.all && document.all.tags )
{
l = document.all.tags( 'label' );
}
if( l )
{
for( var i = 0, n = l.length; i < n; ++i )
{
c = l[ i ];
if( c.for == id )
{
if( c.firstChild )
{
return c.firstChild.nodeValue;
}
return;
}
}
}
}

if(( 'select-one' == t ) && ( 0 == e.selectedIndex ))
{
alert( "Please choose an option from the '" +
getLabel( e ) + "' menu" );
}

<label for="id13">Base Model</label>
<select id="id13" ... title="Base Model">
...
Now that I think about it as I type, there is another issue in that not
all controls are required. (There is an associated ASP variable called
"Required" for each control, which is used to change the label CSS class
from balck to red; shown as "LabelClass" in the example above). I'll
need to check for this also somehow. It just gets better and better...
:)

This is another regular consideration. You could do this by giving
required controls a "required" class name. The class attribute can contain
more than one class name by separating them with whitespace. For example,

function isRequired( e )
{
return( -1 != e.className.indexOf( 'required' ));
}

if(( 'select-one' == t ) && ( 0 == e.selectedIndex ) &&
isRequired( e ))
{
alert( "The " + getLabel( e ) + " menu is a required field." +
"\nPlease choose an option before submitting." );
}

Hope that helps,
Mike


[1] You can bind a label to an element just by including the element
within the label:

<label>A control <input type="text"></label>

However, I've read that IE doesn't support this and the link must be made
with the for and id attributes.
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top