第5章表单当希望从访问站点的用户处收集信息时,通常需要使用表单。您很可能已经在不同的Web站点上使用多种不同类型的表单,从简单的搜索框(它允许用户输入关键字以找到所需要的内容)到复杂的表单(例如在线订购食品或预订度假的表单)。Web上的表单与需要填写的纸张表单非常类似。纸张上具有输入文本的区域、选中的方框、一些可供选择的选项等。在Web上,可以通过组合一些表单控件(例如用于输入文本的文本框、用于选中的复选框、选项框和单选按钮等)来创建表单。在本章中将介绍如何将每一种类型的控件组合到表单中。本章将介绍以下内容:使用form元素创建表单的方式可以用于建立表单的不同类型表单控件——例如文本输入框、单选按钮、选项框和提交按钮处理用户输入的数据的方式使表单具有更好的可访问性的方式结构化表单的内容的方式学习完本章之后,您将能够创建所有类型的表单,以便从站点访问者处收集信息。注意:对所收集数据的处理方式依赖于Web站点所驻留的服务器。XHTML只用于向用户提供表单;它不允许用户说明如何处理所收集的数据。为了更好地了解如何处理通过表单收集的数据,请查看关于服务器端语言(例如ASP.net、PHP或JSP)的书籍。可在Wrox.com站点列出的书籍中查看关于这些主题的书籍。5.1表单简介创建的任何表单都将位于form元素中。在起始标签form和结束标签/form之间,存在一些表单控件(文本输入框、下拉框、复选框、提交按钮等)。类似于页面的其他元素,form元素中也可以包含其他XHTML标记。用户向表单中输入数据之后,通常需要单击提交按钮(但是按钮上的实际文本可能是其他内容,例如Search、Send或Proceed——并且通常按下Enter键会具有类似于单击该按钮的相同效果)。这表明用户已经填写完表单,并且通常将表单数据发送给Web服务器。当访问者所输入的数据到达服务器之后,某个脚本或者其他程序通常会处理它们,并向访问者返回一个新Web页面。返回的页面通常响应访问者所提出的请求,或者确认访问者执行的操作。作为一个示例,您可能希望在页面中添加一个如图5-1所示的搜索表单。图5-1这个表单包含了一个文本框,用户可以在其中输入一些关键字以搜索希望找到的内容;另外包含一个提交按钮,该按钮上具有单词“Search”。当用户单击Search按钮时,信息被发送到服务器。然后服务器处理数据,并为用户生成一个新页面,该页面面告诉用户哪些页面满足搜索标准(如图5-2所示)。图5-2当用户填好一个表单后,数据以“名/值”对的形式发送给服务器,名字对应于表单控件的名称,值是用户输入的内容(如果用户可以输入一个答案)或者选择的选项值(如果表单上存在一个选项列表)。每一项都必须具有一个名称和一个值,因为如果在一个表单上有5个文本框,则需要知道哪一个数据对应哪一个文本框。然后处理应用程序才能分别处理每一个表单控件中的信息。下面是图5-1所示的简单搜索表单的代码:formaction==geth3Searchthesite/h3inputtype=textname=txtSearchItem/inputtype=submitvalue=Search//form其中form元素附带了一个称为action的属性,它的值是Web服务器中处理搜索请求的页面的URL。同时,method属性指明服务器使用哪一个HTTP方法将表单数据发送给服务器(在本章后面,您将了解到可以使用两个方法get和post)。在本章后面将介绍一些更高级的表单,但是现在首先详细地查看组成表单的元素。5.2利用form元素创建表单表单通常位于一个称为form的元素中。form元素还能包含其他标记,例如段落、题头等。但是,form元素绝对不能包含其他form元素。假设页面中的form元素相互独立(任何form元素都不包含其他form元素),则页面中可以包含任意数量的表单。例如,可以在同一个页面中包含登录表单、搜索表单、用于订阅时事通讯的表单等。如果一个页面中有多个表单,则用户一次只能向服务器发送一个表单中的数据。每一个form元素应该至少附带两个属性:actionmethodform元素也可以附带所有的通用属性、UI事件属性以及下面的属性:enctypeacceptaccept-charsetonsubmitonreset5.2.1action属性action属性表明提交表单时将如何处理数据。通常action属性的值是Web服务器中的一个页面或者一个程序,当用户单击提交按钮后,该页面或程序将接收表单中的信息。例如,如果具有一个由“用户名”和“密码”组成的登录表单,用户所输入的内容将被传递给Web服务器中以ASP.net语言编写的login.aspx页面,此时action属性将如下所示:formaction=大多数浏览器将只接受作为action属性值的以http://开头的URL。5.2.2method属性将表单数据发送给服务器的方式有两种,每一种对应于一个HTTP方法:get方法,它将数据作为URL的一部分进行发送post方法,它将数据隐藏在HTTP头中在本章的后面将详细介绍这两个方法,其中您将了解到它们的意义以及何时应当使用哪一个方法。5.2.3id属性id属性允许用户唯一标识页面中的form元素,如同可以使用该属性唯一标识页面中的任何元素一样。为每一个form元素提供一个id属性是优秀的实践,因为许多表单利用样式表和脚本,它们需要使用id属性来标识表单。注意:在第12章中将介绍,如果自动将浏览器的光标放置在表单的第一个文本框中,有时会对用户有帮助作用。为此,需要添加一个id或name属性以标识表单。在一个文档中,id属性的值应该是唯一的,它也应该遵循第1章中提到的一些其他规则。有些人以字符frm作为表单的id属性或name属性值的起始字符,然后使用该值的剩余部分描述表单所收集数据的类型,例如frmLogin或frmSearch。5.2.4name属性(逐漸淘汰)类似于在其他元素中的用法,name属性是id属性的前身。与id属性一样,name属性的值在文档中应该是唯一的。另外,该属性的值通常以字符frm作为开头,后面跟上表单的目的。5.2.5onsubmit属性您很可能遇到过这样的情况:在Web站点中填写完表单,然后单击发送表单数据的按钮(甚至在将页面发送给服务器之前就执行该操作),此时将会显示一条消息告诉您没有输入某些数据或者输入错误的数据。当这种情况发生时,您很可能是遇到了使用onsubmit属性的表单,该属性在浏览器中运行一段脚本,在表单被发送给服务器之前检查所输入数据的正确性。当用户单击提交按钮时,将会激活一个事件。这类似于浏览器举起它的手并说“嘿,我正向服务器发送这个表单的数据。”隐藏在这些事件背后的思想是,可以在将数据发送给服务器之前运行一个脚本(例如JavaScript脚本),以确保提交的数据的质量和准确性。onsubmit属性的值应该是一个脚本函数,当事件激活时将使用该函数。因此,form元素中的onsubmit属性可能类似于如下:onsubmit=validateFormDetails();在文档中必须已经定义了validateFormDetails()函数(很可能在head元素中定义它)。因此,当用户单击提交按钮时,将调用并运行这个函数。在表单数据发送给服务器之前对其进行一些检查具有如下两个关键优点:如果页面中的数据存在错误,用户不需要花费额外的时间等待页面被发送给服务器然后返回。服务器不需要处理大量的错误检查,因为已经在浏览器端执行检查。这两个优点都将节省服务器的工作,对于非常繁忙的站点来说,这一点非常重要。5.2.6onreset属性某些表单包含一个reset按钮,它能够清空表单中的所有内容,有时该按钮上显示的可能是类似于clearForm(清除表单)的文本;当按下这个按钮时,将激活onreset事件,并且运行相应的脚本。当使用onreset属性时,它的值是一个脚本(与onsubmit属性一样),当用户单击调用该脚本的按钮时执行它。注意:onreset事件和属性的使用频率远低于onsubmit。然而,如果在页面中提供一个ClearForm按钮,最好在用户计划清除表单之前执行确认操作,以防止用户无意中按下该按钮。5.2.7enctype属性如果使用HTTPpost方法向服务器发送数据,则在向服务器发送数据之前可以使用enctype属性指定浏览器编码数据的方式(以确保数据安全到达)。浏览器支持两种类型的编码方式:application/x-,这是大多数表单使用的标准方法。使用该编码方式的原因是某些字符(例如空格、加号和某些其他非字母数字字符)不能发送给Web服务器。相反,它们被用于表示它们的其他字符所替代。multipart/form-data,这种方式允许将数据以多个部分的方式发送,每个连续的部分对应于一个表单控件,发送顺序按照它们在表单中的出现顺序。每个部分可以具有一个可选的“内容-类型”头,以指明该表单控件的数据类型。如果没有使用这个属性,则浏览器将使用第一种编码方式。因此,如果表单允许用户向服务器上传文件(例如一幅图像),或者需要向服务器发送非ASCII字符,则必须使用这个属性,此时该属性被赋予第二个值:enctype=multipart/form-data“5.2.8accept-charset属性accept-charset属性的思想是,它指定一个字符编码列表(用户可以输入该列表),然后服务器可以根据该列表进行处理。但是,IE7和Firefox2浏览器不支持这个属性。该属性的值应该是以空格或者逗号隔开的字符集列表(附录E中介绍了各种字符集)。例如,下面的代码指示服务器接受UTF-8编码:accept-charset=UTF-8当前主要的浏览器允许输入任何字符集。5.2.9accept属性accept属性类似于accept-charset属性,不同之处是它采用一个以逗号隔开的内容类型(或文件类型)列表,服务器可以利用该列表处理表单。但是,IE7和Firefox2浏览器不支持这个属性。该属性的思想是用户不能上传与列表中所列举的内容类型不同的文件。下面的代码表明用户仅能上传GIF或JPEG类型的图像:accept=image/gif,image/jpg但是,当前主要的浏览器仍然允许用户上传任何类型的文件。附录H中列举了一些MIME类型。5.2.10target属性target属性通常用于a元素中,以指明新的页面将被加载到哪一个框架或者浏览器窗口中。它也操作生成新页面的表单,并且允许用户指明当提交表单时生成的页面被加载到哪一个框架或者浏览器窗口中。5.2.11空白和form元素另外需要注意的是,当浏览器遇到form元素时,它通常会在该元素周围创建一些额外的空白。这将影响您的设计,特别是希望将表单放置于较小的区域中时,例如将搜索表单放置在菜单栏中。如果利用CSS无法在目标浏览器中解决这个问题,则避免该问题的唯一方法是仔细放置form元素。为了避免创建额外的空白,可以尝试将form元素放置在文档的起始部分或者末尾附近:如果在TransitionalXHTML1.O文档中使用表进行布局,则可以将form元素放置在table元素和tr元素之间(需要清楚的是,后一种方法是一种欺骗方式,因此如果对页面进行验证,该方法可能会造成错误。但是,大多数浏览器仍将以期望的方式显示表和表单)。5.3表单控件本节将介绍一些不同类型的表单控件,可以利用它们从站点访问者处收集数据。本节主要介绍以下控件:文本输入控件按钮复选框和单选按钮