Warning:
This wiki has been archived and is now read-only.
HTML5/forms
表单
介紹
本节不是标准描述
一个表单是一个拥有表单控件的Web页面中的一个组件,例如文本字段、按钮、复选框、范围控件或取色器。用户可以与这些表单进行交互并且提供将要向服务器发送来进行进一步处理(例如:返回搜索或计算的结果)的数据。在大部分情况下不需要客户端脚本,但是仍然存在一个API,使脚本可以提升用户体验或将表单用于向服务器提交数据以外的其他用途。
编写一个表单包含几个步骤,可以按任何顺序执行:编写用户界面、实现服务器端过程、使用户界面与服务器端相通。
编写用户界面
本节不是标准描述
为了进行简单介绍,我们将创建一个披萨订单的表单。
任意的表单都以一个form元素开始,在其内部放置控件。大多数控件由input元素表示,其默认提供一个一行的文本字段。为了标记一个控件,我们可以使用label元素;标记文本以及该控件本身放在label元素之内。表单中的每个部分被认为是一个段落,且通常使用p元素与其他部分分开。
<form>
<p><label>客户姓名:<input></label></p>
</form>
为了让用户选择披萨的大小,我们可以使用一组单选按钮。单选按钮同样使用input元素,这次其type属性被设为值radio。为了使单选按钮成为一个组,我们使用name属性为它们设置了一个通用名称。为了将一批控件放在一起,例如在当前情况下将单选按钮放在一起,可以使用fieldset元素。这样一组控件的标题通过作为fieldset元素第一个子元素的legend元素给出。
<form>
<p><label>客户姓名:<input></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
</form>
为了挑选披萨饼浇头,我们可以使用复选框。这将使用type属性为checkbox的input元素。
<form>
<p><label>客户姓名:<input></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox> 培根 </label></p>
<p><label> <input type=checkbox> 额外的奶酪 </label></p>
<p><label> <input type=checkbox> 洋葱 </label></p>
<p><label> <input type=checkbox> 蘑菇 </label></p>
</fieldset>
</form>
填写表单的披萨店总是犯错误,所以需要一种联系客户的方式。为此,我们可以使用表单控件,特别是电话号码(type属性被设为tel的input元素)以及E-mail地址(type属性被设为email的input元素):
<form>
<p><label>客户姓名:<input></label></p>
<p><label>电话号码:<input type=tel></label></p>
<p><label>E-mail地址:<input type=email></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox> 培根 </label></p>
<p><label> <input type=checkbox> 额外的奶酪 </label></p>
<p><label> <input type=checkbox> 洋葱 </label></p>
<p><label> <input type=checkbox> 蘑菇 </label></p>
</fieldset>
</form>
我们可以使用type属性被设为time的input元素询问用户交付时间。大部分这种控件包含以下属性,用来明确该控件能够制定哪些值;在当前情况下,特别有效地三个属性是min、max及step。它们设定了最小时间、最大时间以及允许的值之间的区间(秒数)。该披萨店只在上午十一点至下午九点之间提供配送服务,并且每次正在最少15分钟,我们可以标记如下:
<form>
<p><label>客户姓名:<input></label></p>
<p><label>电话号码:<input type=tel></label></p>
<p><label>E-mail地址:<input type=email></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox> 培根 </label></p>
<p><label> <input type=checkbox> 额外的奶酪 </label></p>
<p><label> <input type=checkbox> 洋葱 </label></p>
<p><label> <input type=checkbox> 蘑菇 </label></p>
</fieldset>
<p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900"></label></p>
</form>
textarea元素可以被用于提供一个任意格式的文本字段。在当前的情景下,我们继续使用它来提供一个允许用户给出配送要求的地方:
<form>
<p><label>客户姓名:<input></label></p>
<p><label>电话号码:<input type=tel></label></p>
<p><label>E-mail地址:<input type=email></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox> 培根 </label></p>
<p><label> <input type=checkbox> 额外的奶酪 </label></p>
<p><label> <input type=checkbox> 洋葱 </label></p>
<p><label> <input type=checkbox> 蘑菇 </label></p>
</fieldset>
<p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900"></label></p>
<p><label>派送要求:<textarea></textarea></label></p>
</form>
最后,为了使表单可以被提交,我们使用button元素:
<form>
<p><label>客户姓名:<input></label></p>
<p><label>电话号码:<input type=tel></label></p>
<p><label>E-mail地址:<input type=email></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size> 小 </label></p>
<p><label> <input type=radio name=size> 中 </label></p>
<p><label> <input type=radio name=size> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox> 培根 </label></p>
<p><label> <input type=checkbox> 额外的奶酪 </label></p>
<p><label> <input type=checkbox> 洋葱 </label></p>
<p><label> <input type=checkbox> 蘑菇 </label></p>
</fieldset>
<p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900"></label></p>
<p><label>派送要求:<textarea></textarea></label></p>
<p><button>提交订单</button></p>
</form>
实现一个表单的服务器端过程
本节不是标准描述
实现服务器端过程确切地的内容超出了本规范的范围。为了进行介绍,我们假设放置于https://pizza.example.com/order.cgi的脚本程序被配置为使用application/x-www-form-urlencoded格式接收提交的数据,预期下列参数通过HTTP POST体发送:
- custname
- 客户姓名
- custtel
- 客户电话号码
- custemail
- 客户电子邮箱地址
- size
- 披萨大小,小、中、大。
- toppings
- 披萨浇头。指定每一个选中的浇头,允许的值包括bacon、cheese、onion和mushroom。
- delivery
- 要求的配送时间
- comments
- 配送说明
配置表单使其与服务器端相通
本节不是标准描述
表单提交的内容通过不同的方式向服务器暴露,通常情况下是通过HTTP GET或POST请求发送。为了指定使用的具体方法,向form元素标记method属性。这种方法不会指定表单数据应如何编码,为了指定编码方式,你需要使用enctype属性。你还不得不使用action属性标记用于处理提交的数据的服务器的URL。
对于每个你想提交的表单控件,你不得不给出一个将要用于关联到提交的数据的名称。我们已经标记了单选按钮组的名称;相同的属性(name)依然可以标记其他提交内容的名称。单选按钮可以通过使用value属性给它们设置不同的值以便在提交的内容中区分彼此。
多个控件可以拥有相同的名称;举例说明,我们设置所有复选框拥有相同的名称,服务器通过查找提交的数据中拥有该名称的值来检查哪些复选框被选中。——与单选按钮相似,它们都需要给value属性设置不同的值。
将这些设置应用于上一节的例子中:
<form method="post" enctype="application/x-www-form-urlencoded" action="https://pizza.example.com/order.cgi"> <p><label>客户姓名:<input name="custname"></label></p> <p><label>电话号码:<input type=tel name="custtel"></label></p> <p><label>E-mail地址:<input type=email name="custemail"></label></p> <fieldset> <legend>披萨大小</legend> <p><label> <input type=radio name=size value="small"> 小 </label></p> <p><label> <input type=radio name=size value="medium"> 中 </label></p> <p><label> <input type=radio name=size value="large"> 大 </label></p> </fieldset> <fieldset> <legend> 披萨浇头 </legend> <p><label> <input type=checkbox name="topping" value="bacon"> 培根 </label></p> <p><label> <input type=checkbox name="topping" value="cheese"> 额外的奶酪 </label></p> <p><label> <input type=checkbox name="topping" value="onion"> 洋葱 </label></p> <p><label> <input type=checkbox name="topping" value="mushroom"> 蘑菇 </label></p> </fieldset> <p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p> <p><label>派生要求:<textarea name="comments"></textarea></label></p> <p><button>提交订单</button><p> </form>
举例说明,如果客户输入“Denise Lawrence”作为其姓名,“555-321-8642”作为其电话号码,没有输入电子邮箱地址,要求一个中等大小的披萨,选择额外的奶酪和蘑菇浇头,输入派送时间为晚上7点,并且留白派送要求,用户代理将向在线Web服务提交如下信息。
custname=Denise+Lawrence&custtel=555-321-8624&custemail=&size=medium&topping=cheese&topping=mushroom&delivery=19%3A00&comments=
客户端表单验证
本节不是标准描述
表单可以通过某种标记使用户代理在提交表单之前检查用户的输入。服务器依然必须验证输入的有效性(因为恶意用户可以轻松的绕过表单验证),但它允许用户避开由于只有服务器检查用户输入所造成的等待。
最简单的标记是required属性,我们可以将其标注于input元素,注明在给出一个值之前表单不能提交。通过将该属性标记于客户姓名及配送时间自动,我们允许用户代理提醒在这些字段没有填写时提交表单的用户:
<form method="post" enctype="application/x-www-form-urlencoded" action="https://pizza.example.com/order.cgi"> <p><label>客户姓名:<input name="custname" required></label></p> <p><label>电话号码:<input type=tel name="custtel"></label></p> <p><label>E-mail地址:<input type=email name="custemail"></label></p> <fieldset> <legend>披萨大小</legend> <p><label> <input type=radio name=size value="small"> 小 </label></p> <p><label> <input type=radio name=size value="medium"> 中 </label></p> <p><label> <input type=radio name=size value="large"> 大 </label></p> </fieldset> <fieldset> <legend> 披萨浇头 </legend> <p><label> <input type=checkbox name="topping" value="bacon"> 培根 </label></p> <p><label> <input type=checkbox name="topping" value="cheese"> 额外的奶酪 </label></p> <p><label> <input type=checkbox name="topping" value="onion"> 洋葱 </label></p> <p><label> <input type=checkbox name="topping" value="mushroom"> 蘑菇 </label></p> </fieldset> <p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p> <p><label>派生要求:<textarea name="comments"></textarea></label></p> <p><button>提交订单</button><p> </form>
我们还可以通过使用maxlength属性限制输入的长度。通过向textarea元素增加该属性,我们可以限制用户仅能输入1000个字符,从而防止他们输入大量文字而使送货司机不能注意重点信息。
<form method="post"
enctype="application/x-www-form-urlencoded"
action="https://pizza.example.com/order.cgi">
<p><label>客户姓名:<input name="custname" required></label></p>
<p><label>电话号码:<input type=tel name="custtel"></label></p>
<p><label>E-mail地址:<input type=email name="custemail"></label></p>
<fieldset>
<legend>披萨大小</legend>
<p><label> <input type=radio name=size value="small"> 小 </label></p>
<p><label> <input type=radio name=size value="medium"> 中 </label></p>
<p><label> <input type=radio name=size value="large"> 大 </label></p>
</fieldset>
<fieldset>
<legend> 披萨浇头 </legend>
<p><label> <input type=checkbox name="topping" value="bacon"> 培根 </label></p>
<p><label> <input type=checkbox name="topping" value="cheese"> 额外的奶酪 </label></p>
<p><label> <input type=checkbox name="topping" value="onion"> 洋葱 </label></p>
<p><label> <input type=checkbox name="topping" value="mushroom"> 蘑菇 </label></p>
</fieldset>
<p><label>希望的派送时间:<input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p>
<p><label>派生要求:<textarea name="comments" maxlength=1000></textarea></label></p>
<p><button>提交订单</button><p>
</form>
分類
本章節的各個元素在分類上除了屬於通常的流式內容、章節式內容與交互式內容以外,還屬於不同但有交集(卻有細微差異)的多個分類。
有不少元素是表單連結元素,也就是有用于存取主表單的主表單及對應 IDL 屬性 form
的 form
内容属性。
表單連結元素又分為以下幾個子分類:
被列元素
是指 form.elements
與 fieldset.elements
API 會列出的元素。
可標元素
是指可與 label
元素連結的元素。
可提交元素
是指當使用者提交 form
元素的時候,建構表單資料集用到的元素。
可重設元素
另外,可提交元素根據擁有的屬性可能是按鈕。後面說明元素是按鈕的條件。有些按鈕還是提交按鈕。
form
元素
- 分类:
- 流式内容
- 使用场景:
- 需要流式内容处
- 内容模型:
- 流式内容,但没有
form
元素的后裔。
- 允许的属性:
- 全局属性
accept-charset
action
autocomplete
enctype
method
name
novalidate
target
- DOM接口:
- [OverrideBuiltins] interface HTMLFormElement : HTMLElement { attribute DOMString acceptCharset; attribute DOMString action; attribute DOMString autocomplete; attribute DOMString enctype; attribute DOMString encoding; attribute DOMString method; attribute DOMString name; attribute boolean noValidate; attribute DOMString target; readonly attribute HTMLFormControlsCollection elements; readonly attribute long length; caller getter any (in unsigned long index); caller getter any (in DOMString name); void submit(); void reset(); boolean checkValidity(); };
form元素表示一个表单相关元素的集合,其中的一些表示可以被提及给服务器进行处理的可编辑的值。
accept-charset属性给出将被用于提交的数据的字符编码。如果指定了该属性,其值必须为一个一组有序的唯一的空格分隔的标记,其中的标记是ASCII不区分大小写形式,并且每一个标记必须是ASCII不区分大小写地匹配一个ASCII兼容字符编码的首选的MIME名称。[IANACHARSET]
name属性表示forms集合中form的名称。该值禁止为空字符串,且该值必须在其所在的forms集合中的form元素中保持唯一。
autocomplete属性是一个枚举属性。该属性有两个状态。on
关键字映射到on状态,off
关键字映射到off状态。该属性还可以被忽略。缺省默认值为on状态。默认情况下,off状态表示表单内的input元素的返回自动完成状态被设为关;默认情况下,on状态表示表单内的input元素的返回自动完成状态被设为开。
action、enctype、method、novalidate及target属性是提交表单属性。
返回表单中表单控件的一个HTMLCollection(由于历史原因,不包含图片按钮)。
form . length
返回表单中表单控件的数目(由于历史原因,不包含图片按钮)。
form[index]
form(index)
返回表单中给出的ID或name对应的表单控件(由于历史原因,不包含图片按钮)。
一旦某个元素被使用一个特别的名称引用,只要该元素仍在Document中存在,可以继续在本方法中使用该名称引用元素,即使该元素真实的ID或name发生改变。
form . submit()
提交表单。
form . reset()
重置表单。
form . checkValidity()
如果表单中的所有控件均合法,则返回真,否则返回假。autocomplete IDL属性必须反映同名的内容属性,且限制为仅支持已知的值。
name IDL属性必须反映同名的内容属性。
acceptCharset IDL属性必须反映accept-charset内容属性。
elements IDL属性必须返回一个植根于Document节点的HTMLFormControlsCollection,其过滤器匹配表单所有者为form元素的被列元素。由于历史原因,type属性为图片按钮(Image Button)状态的input元素必须被排除在这个特殊的集合之外。
length IDL属性必须返回elements集合所表示的节点的数目。
在某时刻的支持的属性索引为该时刻elements属性所返回的对象所支持的索引。
若一个form元素是一个索引属性检索中的索引,用户代理必须返回使用给出的索引作为其参数在elements集合上调用item方法所返回的值。
每一个已经有名称与其映射的form元素被称为通过名称映射。这用于留存控件的名称,即使它们已经改变名称。
支持的属性名称是elements属性返回的对象当前所支持的名称的集合,且当前通过名称映射中的名称。
若一个form元素是名称属性检索中的索引,用户代理必须执行下列步骤:
- 如果名称是elements属性返回的对象的#支持的属性名称之一,则执行下列子步骤:
- 设候选对象为在elements属性返回的对象上使用名称参数调用namedItem()方法所返回的对象。
- 如果候选对象是一个元素,则向form元素的通过名称映射中插入从名称到候选对象的映射,如果存在同名的映射,则替换之前的同名映射。
- 返回候选对象并跳过这些步骤。
- 否则,名称为form元素的通过名称映射中的某一条目的名称:返回映射中与名称关联的对象。
如果一个form元素的通过名称映射中列出的元素被从Document中移除,则该条目必须从映射中移除。
submit()方法,调用时必须从form元素本身提交form元素,并设置脚本提交标志。
reset()方法,调用时必须执行下列步骤:
如果checkValidity()方法被调用,用户代理必须对form元素进行静态约束验证,且如果约束验证返回了一个肯定的结果则返回真,如果返回了一个否定的结果则返回假。
下面的例子展示了两个搜索表单:
<form action="http://www.google.com/search" method="get"> <label>Google: <input type="search" name="q"></label> <input type="submit" value="Search..."> </form> <form action="http://www.bing.com/search" method="get"> <label>Bing: <input type="search" name="q"></label> <input type="submit" value="Search..."> </form>
fieldset
元素
- 分类:
- 流式内容
区块根
被列的表单相关元素 - 使用场景:
- 需要流式内容处
- 内容模型:
- 跟随在流式内容后的可选的
legend
元素。
- 允许的属性:
- 全局属性
disabled
form
name
- DOM接口:
- interface HTMLFieldSetElement : HTMLElement { attribute boolean disabled; readonly attribute HTMLFormElement form; attribute DOMString name; readonly attribute DOMString type; readonly attribute HTMLFormControlsCollection elements; readonly attribute boolean willValidate; readonly attribute ValidityState validity; readonly attribute DOMString validationMessage; boolean checkValidity(); void setCustomValidity(in DOMString error); };
fieldset元素表示一组可选地按一个通用名称分组的表单控件。
组的名称由fieldset元素的子元素中的第一个legend元素给出。fieldset元素的其他后裔组成小组。
如果标记了disabled属性,则fieldset元素的所有表单控件后裔,以及fieldset元素的第一个legend子元素的后裔,将被禁用。
form属性被用于明确的将fieldset元素关联到其所属表单。name属性表示元素的名称。
fieldset . type
返回字符串“fieldset”。
fieldset . elements
返回一个该元素中表单控件的HTMLFormControlsCollection。
disabled IDL属性必须反映同名的内容属性。
type IDL属性必须返回字符串“fieldset”。
elements IDL属性必须返回一个植根于fieldset元素的HTMLFormControlsCollection,其过滤器匹配被列元素。
willValidate、validity及validationMessage属性,以及chackValidity()及setCustomValidity()方法,是约束验证API的一部分。form及name IDL属性是该元素表单API的一部分。
下列片段展示了一个fieldset。其legend中有一个复选框,用于控制fieldset是否可用。fieldset的内容由两个必要的文本字段及一个可选的年/月控件组成。
<fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> 使用会员卡 </label> </legend> <p><label>姓名: <input name=clubname required></label></p> <p><label>卡号: <input name=clubnum required pattern="[-0-9]+"></label></p> <p><label>到期日: <input name=clubexp type=month></label></p> </fieldset>
你还可以嵌套使用fieldset元素。下面的例子扩展自前一个例子:
<fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> 使用会员卡 </label> </legend> <p><label>姓名: <input name=clubname required></label></p> <fieldset name="numfields"> <legend> <label> <input type=radio checked name=clubtype onchange="form.numfields.disabled = !checked"> 我的卡上有数字 </label> </legend> <p><label>卡号: <input name=clubnum required pattern="[-0-9]+"></label></p> </fieldset> <fieldset name="letfields" disabled> <legend> <label> <input type=radio name=clubtype onchange="form.letfields.disabled = !checked"> 我的卡上有字母 </label> </legend> <p><label>代码: <input name=clublet required pattern="[A-Za-z]+"></label></p> </fieldset> </fieldset>
在这个例子中,如果外面的“使用会员卡”复选框没有被选择,则外面的fieldset中的内容(包括嵌套的fieldset中的两个单选按钮)将被禁用。但是,如果复选框被选中,则单选按钮均被启用,且允许你选择启用两个内部fieldset之一。
legend
元素
- 分类:
- 无。
- 使用场景:
- 作为
fieldset
元素的第一个子元素。
- 内容模型:
- 段落式内容。
- 允许的属性:
- 全局属性
- DOM接口:
- interface HTMLLegendElement : HTMLElement { readonly attribute HTMLFormElement form; };
legend元素表示一个当前legend元素的父fieldset元素的其余内容的标题。
form IDL属性的行为由其是否在fieldset元素之中决定。如果legend拥有一个fieldset元素作为其父元素,则form IDL属性必须返回与fieldset元素的form IDL属性相同的值。否则必须返回null。
label
元素
- 分类:
- 流式内容
段落式内容
交互式内容
表单相关元素
- 使用场景:
- 需要段落式内容处
- 内容模型:
- 段落式式内容,如果其不是元素的标记控件则不包含后裔可標元素,不包含后裔
label
元素。
- 允许的属性:
- 全局属性
form
for
- DOM接口:
- interface HTMLLabelElement : HTMLElement { readonly attribute HTMLFormElement form; attribute DOMString htmlFor; readonly attribute HTMLElement control; };
label表示一个用户界面中的标题。该标题可以通过使用for属性或将表单控件仿佛label元素本身之内,将其关联到指定的表单控件(作为label元素的标记控件)。
for属性可以标记与该标题相关联的表单控件。如果标记了该属性,则属性的值必须为与该label元素在同一个Document中的一个可标表单相关元素的ID。如果标记了该属性且Document中存在一个元素,其ID等于for属性的值,且第一个这样的元素是一个可标的表单相关元素,则该元素是label元素的标记控件。
如果没有标记for属性,但该label元素拥有一个是可标的表单相关元素的后裔,则按照树形结构顺序的第一个这样的元素为该label元素的标记控件。
label元素确切的默认表示和行为(特别是其激活行为)应该与其平台的标记行为匹配。
举例说明,在点击复选框的标签来选中复选框的平台,点击下列片段中的label能够触发用户代理在input元素上执行合成点击激活步骤,就像该元素被用户触发一样:
<label><input type=checkbox name=lost> Lost</label>
在其他平台中,该行为可能仅仅聚焦到该控件,或者不做任何操作。
label . control
返回与该元素向关联的表单控件。
如果label元素存在标记控件,则control IDL属性必须返回该标记控件,否则返回null。
可标表单相关元素拥有一个与其相关联的NodeList对象,该对象表示一组label元素的列表,这些元素的标记控件为访问该属性的元素,且它们按照树形结构顺序排序。在获取可标表单相关元素的labesl IDL属性时,必须返回该NodeList对象。
form IDL属性是该元素表单API的一部分。
下列例子展示了三个包含标签的表单控件,其中的两个拥有用于展示正确格式的小字号文本。
<p><label>姓名:<input name=fn> <small>格式:姓 名</small></label></p> <p><label>年龄:<input name=age type=number min=0></label></p> <p><label>邮政编码:<input name=pc> <small>格式:AB12 3CD</small></label></p>