ASP中JavaScript处理复杂表单的生成与验证

更新时间:2007年03月25日 00:00:00   作者:

这里所谓的复杂表单,是指表单中包含多种不同的输入类型,比如下拉列表框、单行文本、多行文本、数值等。在经常需要更换这类表单的场合,需要有一个表单的动态生成程序。本文介绍的正是这样一个系统,它以数据库保存表单定义数据,利用ASP脚本动态生成表单HTML代码以及验证表单输入的脚本。

一、定义数据库表结构

在Web上经常可以看到“每周调查”之类的表单,这就是一种需要经常更新的表单。如果有一个动态生成表单及其验证脚本的程序,可以大大减少制作这些表单的工作量。

在本文的动态表单生成与验证示例中,我们使用一个Access数据库来存储有关表单的定义信息,同时为简单计,用户在表单中输入的数据也保存到同一数据库。定义表单需要两个表:第一个表(Definitons)用于表单输入域的定义,第二个表(Lists)保存各个输入域的附加信息,比如选择列表的选择项。

表Definitons包含如下字段:

FieldName —— 赋予表单输入域的变量名字

Label —— 即文本标签,显示在输入域前面的提示性文字

Type —— 单个字符,该字符表示表单输入域的形式和输入值的类型

具体如下:

(t) 文本输入框,即。

(n) 文本输入框,但要求输入数字值。

(m) 备注型内容,用于注释或其他大量文本的输入,它是一个多行文本编辑框。

(b) 要求输入“是”或“否”。本实现中将用复选框来获取这种输入,复选框的文本标签为“是”。如果用户选中它,则返回值是“on”。

(r) 单选按钮。

(l) 下拉列表框。

Min —— 仅对数字型输入值有效,在这里给出最小值。在本例中有一个“Age”(年龄)数字型输入框,它的最小值设定为1。

Max —— 该字段的值与输入域形式有关。对于数字型输入框,它表示的是允许的最大值。例如“Age”的Max值为100。对于文本输入框,Max表示允许的最多字符个数。对于多行文本编辑框,Max表示可见区域的文本行数。

Required —— 表示是否必须输入。这种类型的值如果没有输入,则输入验证程序将报告错误。在表单中,必须输入的值以星号标记,并以脚注的形式提示用户该类值必须输入。

本文的示例表单是一个ASP程序员调查表,在Definitons表中该表单的定义主要如下:

FieldName Label Type Min Max Required

Name 姓名 文本(t) - 50 否

Age 年龄 数字(n) 1 100 否

Sex 性别 单选按钮(r) - - 是

E-mail 邮件地址 文本(t) - - 是

Language 编程语言 下拉列表框(l) - - 否

表Lists用于保存输入域定义的一些附加信息,本例有“Sex”和“Languages”两个输入值要用到它。表Lists非常简单,只包含如下三个字段:

FieldName —— 当前记录属于哪个表单输入域

Value —— 选择项的值

Label —— 用户所看到的选择项的提示文本

输入域“Sex”只能从两个值选取:“男”或“女”。“Language”列出了几种可应用于ASP环境的编程语言,包括:VBScript,JavaScript,C,Perl和“其他”。

第三个表“Records”保存用户提交的内容,它也包含三个字段,每个记录对应用户的一次提交:

Record —— 备注类型,以查询字符串形式保存的用户输入。

Created —— 用户提交该表单的日期和时间。 RemoteIP —— 表单提交者的IP地址。

在实际应用中可能要收集更多有关用户的信息,为简单计,本例只记录提交时间和用户IP地址这两个附加信息。

二、准备工作

在完成上述数据结构和表单的定义之后,接下来就可以编写脚本。脚本的任务是生成表单以及处理用户提交的表单。

无论是表单的生成还是处理,以下三个过程(任务)都是必不可少的:第一是确定验证类型,在生成表单时验证类型值通过查询字符串获得,在处理表单时从表单隐藏域读取。程序支持的表单验证方式共有以下四种类型:不进行验证,客户端JavaScript验证,服务器端ASP脚本验证,客户端和服务器端都进行验证(代号分别为0到3)。如果没有在查询字符串中指定合法的验证方式,则默认第四种验证方式。这种验证处理方式使得我们可以灵活地应用这个表单生成、处理系统,当客户端禁止使用JavaScript验证时就可以仅在服务器端执行验证过程。下面是确定验证类型的代码:

检查验证类型

以下是引用片段:

iValType = Request.QueryString("val")

If IsNumeric(iValType) = False Then iValType = 3

If iValType > 3 or iValType

第二个任务是打开数据库连接,创建两个记录集对象:RS对象,这是本程序中的主要记录集对象,用来操作Definitions表;RSList对象,主要用于从Lists表读取数据。示例程序提供两种数据库连接方法:使用ODBC DSN或不使用ODBC DSN(使用DSN时需要先创建名为Dynamic的DSN,使用DSN连接数据库的代码已经被注释掉)。

第三个任务是在生成(或处理)表单脚本的前面(和后面)输出一些静态的HTML代码,比如,以及在脚本运行结束的时候释放RS、RSList等对象占用的资源。

除了完成上述任务的代码外,示例应用中其余ASP脚本可能生成的页面有两种类型:提问表单(见上图)以及表单提交后出现的结果页面(后者同时还负责用户提交结果的记录)。要确定究竟运行哪一部分脚本,最简单的方法就是检查是否已经提交表单:如是,则处理表单;否则生成表单。

是生成表单还是处理表单?

If Len(Request.Form) = 0 Then

'生成表单

...略...

Else

'处理表单

...略...

End If

三、动态生成表单

生成表单时,程序按照Definitons表中的各个输入域定义记录,依次生成相应的表单HTML代码和JavaScript代码。HTML代码中首先要生成的是文本标签:

以下是引用片段:

sHTML = sHTML & vbTab & "" & vbCrLf & vbTab & vbTab

sHTML = sHTML & "

sHTML = sHTML & " >" & vbCrLf & vbTab & vbTab & vbTab

sHTML = sHTML & "" & RS.Fields("Label")

然后程序检查当前输入域是否必须输入。如果必须,则在标签文本之后加一个星号(表示该值必须输入),同时对于必须输入的值,还要生成相应的JavaScript代码来验证它。对于单选按钮或选择列表,需进一步检查用户确实选择了某个选项;对于所有其他输入类型,只要检查输入值不为空即可。

紧接文本标签的是表单的输入元素,这些元素的HTML代码根据Definitions表中指定的类型和属性生成。再接下来就是根据输入值要求生成执行客户端验证任务的JavaScript代码。对于本例,只有数字型的值需要进一步检查以保证用户的输入确实是数字,而且数字值在许可的最大值和最小值之间。生成上述代码之后,就可以结束一个表格行(也就是一个输入域)继续处理Definitions表的下一个记录。一旦所有的数据库记录处理完毕,下一步就可以加入“提交”按钮和“清除”按钮的HTML代码。如果换个角度来看,程序在这里的任务就是根据数据库记录生成各个输入域,每个输入域占用一个表格行,每个表格行二个单元:第一个单元用来显示文本标签,第二个单元显示输入元素本身(代码见dForm.asp)。

上述过程结束之后,表单的HTML代码和验证用JavaScript函数分别保存到了变量sHTML和sJavaScript中。在把这些内容写入页面之前,程序检查客户端是否要求执行JavaScript验证,如果不要求执行这类验证,则清除sJavaScript变量:

If iValType = 0 or iValType = 2 Then sJavaScript = ""

在输出BODY标记之后,程序输出如下JavaScript函数:

以下是引用片段:

function validate(TheForm){

//客户端表单验证

return true;

}

function CheckRadio(objRadio){

//单选按钮中是否有某个值被选中

for(var n = 0; n

if(objRadio[n].checked){

return true;

}

}

return false;

}

function CheckList(objList){

//是否已经在选择列表中选择了某个值

for(var n = 1; n

if(objList.options[n].selected){

return true;

}

}

return false;

}

//-- >

如果客户端不需要JavaScript验证,则validate函数只剩下一个“return true”语句。上面代码中的后面两个静态JavaScript函数(CheckRadio和CheckList)用于验证单选按钮和下拉列表框,当这两种输入域需要验证时validate函数将调用它们。

现在可以开始把表单写入页面:

在这里,只有当validate函数返回true时才执行表单提交操作。因此当客户端JavaScript验证功能关闭时,validate函数将自动返回true。

接下来要加入的是名为val的隐藏域。如前所述,该值指示表单的验证模式。

" >

当用户提交表单时,处理脚本将根据该值确定是否执行服务器端验证。

然后输出的是表格标记以及表格标题。标题保存在变量sTitleLabel中,该值在脚本开始执行时初始化:

以下是引用片段:

作为改进措施,可以在表Definitions、Lists和Records中增加一个字段FormID。FormID唯一标识一个表单,这样程序就可以同时地定义多个表单、保存多个表单的用户应答结果。至于上面的sTitleLabel,我们可以用另外一个表(比如Forms)来保存。

紧接着表格标记和表格标题,程序输出的是HTML表单以及“提交”、“清除”按钮的代码。在此之后,程序检查sHTML字符串中是否包含“*”,如包含的话说明表单中存在必须输入的内容,此时就输出一个脚注以说明该星号的含义。

以下是引用片段:

'是否存在必需输入的表单域,如存在,则输出表单脚注解释'*'的含义

If InStr(sHTML,"*") Then

% >

注意:有星号标记的值必需输入。

End If

% >

至此为止,表单的生成任务已经完成。

四、处理提交结果

ASP脚本剩下的任务是服务器端的表单处理,包括验证、将结果保存到数据库以及“提交成功/失败”页面的显示。在这部分表单验证代码中用到了一个字符串变量sBadForm,程序用它来保存错误信息。如果在验证过程结束时sBadForm为空,说明用户提交的表单是合法的;否则,拒绝该表单的提交并把sBadForm返回给浏览器。

不管表单采用哪种验证模式,检查HTTP_REFERER都是一种好的习惯。这种检查可以防止脚本被盗用。要检查某个POST是否来自本网站的页面或脚本,只需比较两个服务器变量即可:

以下是引用片段:

If InStr(Request.ServerVariables("HTTP_REFERER"), _

Request.ServerVariables("HTTP_HOST")) = 0 Then

sBadForm = "表单提交自不正确的位置。" & vbCrlf

End If

如果表单的隐藏域指示必须进行服务器端验证,则程序遍历表单定义数据库记录作相应的检查,其过程与表单的生成非常相似,只不过此时程序是验证表单,且把输入值非法信息加入到sBadForm中去而已。具体代码见dForm.asp。

程序最后检查sBadForm是否为空。如不为空,则拒绝表单提交并将sBadForm写入浏览器。如果sBadForm为空,则在Records表增加一个记录保存表单数据。在保存表单内容之前需要删除隐藏域val,这个隐藏域总是表单的第一个输入域:

以下是引用片段:

If Len(sBadForm) = 0 Then

RS.Open "Records", DB, 3, 2, &H0002

RS.AddNew

RS.Fields("Record") = Mid(Request.Form, InStr(Request.Form, "&") + 1)

RS.Fields("Created") = Now()

RS.Fields("RemoteIP") = Request.ServerVariables("REMOTE_ADDR")

RS.Update

Response.Write("谢谢.")

RS.Close

Else

Response.Write("表单提交失败。")

Response.Write(vbCrLf & sBadForm)

End If

End If

这就是服务器端表单处理的全部过程。根据是否存在已经提交的表单,我们可以把前面生成表单的代码和这里表单处理的代码用If语句封装,使得这两部分脚本共享部分公用代码,比如HTML文档的头、数据库对象的创建和资源释放等。

总地看来,dForm.asp只具备了动态表单生成、验证所必需的核心功能,忽略了许多细节问题的处理。比如前面已经提到的多表单问题:增加一个表管理多个表单,使得脚本具有管理、生成、处理指定表单的能力。另外一个明显的缺乏是表单定义数据的增加、删除和更新功能,以及用户提交结果数据的访问,这类功能可以在一个独立的程序中实现,而且在大多数情况下可以做成传统的应用程序(非B/S结构的应用)。最后,dForm.asp支持的输入域类型也有限,在实践中可能会有其他的表单输入要求,比如专用的e-mail地址输入框等。然而,对于那些经常要更新表单的网站来说,本文所讨论的表单动态生成、动态验证功能确实是非常有用的。

相关文章

写在前面的话:此篇还是asp相关的,相信玩ASP的都有这个感觉,当数据有5万多条时-------just like音乐网,要调用最新的10条在页面显示,糟糕的是,当n多用户打开页面访问的时候,每个用户每次都要读取数据库一次,这无疑降低了效率,很明显, 如果能把数据能保存在内存上,然后读取,无疑加快了速度.2008-04-04

防采集的原理非常简单,首先放一段动态语句,把访问者的IP加入到数据库的一个表里,然后在页面底部加入一个JS,JS直接访问动态页面,将访问者的IP加入到数据库的另外一个表里。2010-04-04

利用ASPUPLOAD,ASPJPEG实现图片上传自动生成缩略图及加上水印...2007-02-02

系统包括两个文件,其实可以合并为一个。之所以分为两个是因为部分杀毒软件会因为里边含有FSO、XMLHTTP操作而被认为是脚本木马2007-05-05

PR值查询代码制作...2006-08-08

asp做网站经常遇到日期格式处理问题,介绍一个有用的vbscript函数formatdatetime()2009-06-06

防止别人盗链的好方法推荐...2007-01-01

看到有朋友说前面一章讲得没必要,想想也确实.本来是没有打算讲这些基础的,只是行文起来没有约束,就荡开到基础知识上面了.2009-09-09

asp下返回以千分位显示数字格式化的数值...2007-08-08

asp下实现 重新排序数字数组的代码...2007-08-08

最新评论

html表单 asp验证,ASP中JavaScript处理复杂表单的生成与验证相关推荐

  1. 怎么查看oracle数据库表的主键,Oracle中查看所有的表,用户表,列名,主键,外键...

    在Oracle中查看所有的表: select * from tab/dba_tables/dba_objects/cat; 看用户建立的表 : select table_name from user_ ...

  2. django mysql 创建表_关于 django ORM 中,数据库建表方式的问题

    本人以前是做客户端的,做后端没多久. 一直有一个问题困扰我,正好现在手上有一个系统在做. 系统逻辑是写一个爬虫在网上爬取一个网站的信息, 经过加工处理后,使用 django 来展示和交互. 表结构简化 ...

  3. c ++中哈希表如何访问_C / C ++中的哈希表–完整的实现

    c ++中哈希表如何访问 A Hash Table in C/C++ (Associative array) is a data structure that maps keys to values. ...

  4. oracle表连接——处理连接过程中另外一张表没有相关数据不显示问题

    一个数据表基本上很难满足我们的查询要求,同时,将所有的数据都保存在一个表格中显然也不是一种好的数据库设计,为了避免数据的冗余,删除.更新异常,我们通常需要建立一张外键表,通过表连接,来获取我们自己想要 ...

  5. oracle不显示表和过程,oracle表连接——处理连接过程中另外一张表没有相关数据不显示问题...

    一个数据表基本上很难满足我们的查询要求,同时,将所有的数据都保存在一个表格中显然也不是一种好的数据库设计,为了避免数据的冗余,删除.更新异常,我们通常需要建立一张外键表,通过表连接,来获取我们自己想要 ...

  6. mysql delete 表关联删除数据_MYSQL中delete删除多表数据与删除关联数据

    在mysql中删除数据方法有很多种,最常用的是使用delete来删除记录,下面我来介绍delete删除单条记 录与删除多表关联数据的一些简单实例. 1.delete from t1 where 条件 ...

  7. html表单验证邮箱表达式,Javascript正则表达式实现表单验证

    今天我们通过实现用户注册页面验证来学习js当中的正则表达式的构造 1.题目:正则表达式实现用户注册页面验证 . 在各文本框中输入信息,在文本框失去焦点时,验证信息,如果输入的信息部满足要求,则提示信息 ...

  8. html2个表单,单个html angular2中的多个表单

    我有以下代码: Técnicos placeholder="Responsabilidade" required> required> placeholder=&quo ...

  9. php设置表单为整数,PHP中如何判断FROM表单提交的数字是否为整数?

    在php开发中我们经常需要用表单传递数据,如果我们传递的是整数(int),经过表单传递后,在接收页面整数的数值类型将会变成字符串(string)类型,这样我们就不能用is_int()函数来判断是否为整 ...

最新文章

  1. php 现货 结算算法,PHP算法逻辑:如何计算购买量?
  2. uniapp 页面渲染完成
  3. Js-parentNode、parentElement,childNodes、children 它们有什么区别呢?
  4. php对象json,php 把对象转化为json
  5. 家用工具套装_家居工具一:成为家居维修达人,你可能就差这个:史丹利45件套家用工具箱套装...
  6. 可穿戴在线展持续升温:聚焦产业热点 畅谈核心技术发展
  7. tcpdump启动脚本
  8. 年底清理垃圾了,整理了一整套python学习资料无偿送给大家
  9. 学习前端开发必读书籍,拥有这几本武功秘籍,让你如有神助
  10. postgres报错:FATAL: Peer authentication failed for user “zabbix“ Previous connection kept
  11. Linux字符设备驱动中container_of宏的作用
  12. 2021-06-18html基本标签学习
  13. 网络故障和网络诊断工具(5.0)
  14. 如何批量给图片加水印?
  15. 用Visio画软件(模块)功能图
  16. CentOS 系统查询开机启动项服务
  17. 一篇文章让你掌握HTML+CSS
  18. java爬移动端搜索引擎_尝试java开发搜索引擎爬虫
  19. 关于Zion真实性问题的图文分析及其他 V1.06
  20. python map函数的作用_Python map()函数介绍及用法

热门文章

  1. JavaScript脚本语言 -DOM - 事件基础与操作元素细节
  2. 换新手机后,如何将微信聊天记录迁移到新手机中?
  3. OWASP ZAP安全扫描基础流程
  4. 电脑在开机时出现了bootmenu
  5. 宁波甬江职业学校计算机实,宁波市甬江职业高级中学
  6. 如何使用latex排版并排放置两张图
  7. 将x的平方赋值给y (5分)
  8. 计算机如何将两个磁盘合在一起,Win7系统如何合并磁盘分区将两个或多个合并到一起...
  9. 云图说 | 华为云主机安全服务(新版)来啦!
  10. 知乎上的神人、大牛都有哪些?