Warning:
This wiki has been archived and is now read-only.

HTML5/association-of-controls-and-forms

From HTML5 Chinese Interest Group Wiki
Jump to: navigation, search

控制項與表單的連結

一個表單連結元素可以與一個 form 元素有連結,為它的主表單。若一個表單連結元素並沒有一個相連的 form 元素,則稱其主表單為空值。

一個表單連結元素預設為與最近的祖先 form 元素(下面描述),但是 form 屬性可以覆蓋這個設定。

注:由於瀏覽器不支援巢狀 form 元素,這個功能提供了一個繞道方法。

若網頁作者在一個表單連結元素上指定一個 form 屬性的值,則該值必須為該元素主 Document 裡的一個 form 元素的 ID

注:儘管符合規範的文件絕不會有巢狀 form 元素 ,生成這種文件(比如說使用操作 DOM 的腳本)卻是可能的,這讓本小節的規則變得複雜。由於歷史因素,HTML 解析器會產生與不是其祖先的 form 元素相連的表單連結元素,更增加複雜度。

當一個表單連結元素誕生時,使用者代理必須將其主表單初始化為空值(沒有主表單)。

當一個表單連結元素與一個表單相連時,使用者代理必須將其主表單設為該表單。

當一個表單連結元素的祖先鏈變動(比如說使用者將它或是它的祖先進入到該 Document 或是從該 Document 離去)時,使用者代理必須重設該元素的主表單
注:HTML 解析器在插入表單控制項的時候無視這項規則

當一個表單連結元素form 屬性被設置、變更、移去時,使用者代理必須重設該元素的主表單

當一個表單連結元素form 屬性且該 Document 的任一個元素的 ID 更動時,使用者代理必須重設該表單連結元素的主表單

當一個表單連結元素form 屬性且一個有 ID 的元素進入到該 Document 或是從該 Document 離去時,使用者代理必須重設該表單連結元素的主表單

當使用者代理要重設一個表單連結元素的主表單時,它必須執行下列步驟:

  1. 若該元素的主表單不為空值,且該元素沒有 form 內容屬性,且祖先鏈變動後該元素的主表單是最近的祖先 form 元素,則不做任何事並退出這些步驟。
  2. 設該元素的主表單為空值。
  3. 若該元素有內容屬性 form ,執行以下步驟:
    1. 若第一個「滿足Document且其 ID區分大小寫下等同於表單連結元素的內容屬性 form 的值」的元素是一個 form 元素,則將該表單連結元素form 元素相連
    2. 退出「重設一個表單連結元素的主表單」的步驟。
  4. 否則,若該表單連結元素有一個祖先 form 元素,則將該表單連結元素與最近的祖先 form 相連
  5. 否則,該元素沒有相連表單。
在下面的不合法片段裡:
...
 <form id="a">
  <div id="b"></div>
 </form>
 <script>
  document.getElementById('b').innerHTML =
     '<table><tr><td><form id="c"><input id="d"></table>' +
     '<input id="e">';
 </script>
...

"d" 的主表單是巢狀表單內測的 "c",但 "e" 的主表單是外側的 "a"。

事情發生順序如下:首先,"e" 節點在 HTML 解析器內與 "c" 相連。後來,innerHTML 演算法將這些節點從暫時文件移到 "b" 元素上。在這個時候,這些節點看到祖先鏈的變動,也因此解析器的「魔法」相連被重設成一般的祖先相連。

此範例為為不合法的文件,因為它違背了內容模型不允許巢狀 form 元素的規定。
此区块中不是标准描述,实现要求在下面给出。

元素 . form

回傳元素的主表單

若沒有則回傳空值。

表單連結元素 有 IDL 屬性 form。該屬性在獲取時必須回傳元素的主表單,或是在沒有主表單時回傳空值。

表單控制項的共通屬性

為表單控制項命名

內容屬性 name 可以用來命名表單控制項,表單的命名直接影響表單提交的過程與 form 元素的 elements 物件。若網頁作者欲設定此屬性,則它的取值必不可為空字串。

本規範允許任何非空的 name 值,但是 "_charset_" 與 "isindex" 這兩個值有特殊作用:

isindex

若一個用 application/x-www-form-urlencoded 作為提交機制的表單的第一個控制項為文字控制項且其名字為這個值,則表單僅提交這個控制項取值,不送出名字。

_charset_

若沒有 value 屬性的隱藏控制項的名字為這個值,則表單提交時的控制項取值自動變成提交的編碼。

IDL 屬性 name 必須反映內容屬性 name

啟用和停用控制項

內容屬性 disabled 是一個布林屬性

若一個表單控制項設有 disabled 屬性,或者它是一個設有 disabled 屬性的 fieldset 元素的子嗣但「不是」該 fieldset 元素的第一個 legend 子元素(若存在)的子嗣,則這個表單控制項處於停用狀態

處於停用狀態的表單控制項必須防止任何使用者互動任務源隊列click 事件被分發到元素上。

約束驗證:若一個元素處於停用狀態,則不進行這個元素的約束驗證

IDL 屬性 disabled 必須反映內容屬性 disabled

控制項的取值

每個表單控制項都具有取值確認標記。(僅有 input 元素有後者)。這些是描述使用者與控制項互動狀態的變數。

為了定義有 multiple 屬性的 input 元素的約束驗證行為,input 元素也可能會有另外的取值組變數。

控制項的自動聚焦

內容屬性 autofocus 讓網頁作者可以選定頁面讀取完成同時該獲得焦距的控制項,這讓使用者可以立即輸入內容而不需要手動給主要控制項焦距。

autofocus 屬性是一個布林屬性

網頁作者必不可指定 autofocus 屬性在超過一個文件裡的元素上。

當設置了 autofocus 屬性的元素進入到文件裡時,使用者代理應該執行下列步驟:

  1. 目標為元素的 Document
  2. 目標沒有瀏覽上下文,退出這些步驟。
  3. 目標瀏覽上下文沒有頂級瀏覽上下文(例如,目標是沒有父瀏覽上下文嵌套的瀏覽上下文),退出這些步驟。
  4. 目標瀏覽上下文在創建的時候不設有沙盒中的自動機能瀏覽上下文標記,退出這些步驟。
  5. 目標來源目標父瀏覽上下文中此時有焦距的元素的 Document來源相同,退出這些步驟。
  6. 目標來源目標頂級瀏覽上下文現行文件來源相同,退出這些步驟。
  7. 若使用者代理曾經為了回應一個頂級瀏覽上下文現行文件目標頂級瀏覽上下文現行文件相同的元素進入一個 Document 的事件,退出這些步驟。
  8. 若可以由使用者的行為(例如開始在表單控制項輸入內容)推論使用者不希望聚焦改變,可以退出這些步驟。
  9. 將以下任務排入隊列:確認該元素可得到焦距,若可,執行該元素的聚焦步驟。使用者代理也可以改變文件的捲軸位置,或是用其他方法讓使用者注意到該元素。此任務的任務源DOM 操作任務源
注:給控制項焦距不代表使用者代理必須給予已失焦的瀏覽器視窗焦距。

IDL 屬性 autofocus 必須反映同樣名稱的內容屬性。

在下面的片段裡,當文件讀取完成的時文字控制項會得到焦距:
<input maxlength="256" name="q" value="" autofocus>
<input type="submit" value="Search">
限制使用者的輸入長度

髒值標記控制的表單控制項 maxlength 屬性可以用來宣告使用者能輸入的字符數限制。

若網頁作者欲指定一個元素的表單控制項 maxlength 屬性,該屬性值必須是合法非負整數。若使用者指定此屬性且使用者代理對這個值使用非負整數解析規則進行解析可以得到一個數字,則該數字是此元素的最大容許取值長度 。若使用者未指定此屬性或解析屬性值發生錯誤,則沒有最大容許取值長度

約束驗證:若一個元素具有最大容許取值長度髒值標記為真,取值最後一次的更改是透過使用者(而不是腳本造成的改變),且元素取值代碼點長度大於元素的最大容許取值長度,則該元素苦於過長

使用者代理可以阻止使用者進行讓元素的取值代碼點長度大於元素的最大容許取值長度的行為。

表單提交

網頁作者可以在 form 元素或是提交按鈕(提交表單按鈕的代表原素,例如 type 屬性處於提交按鈕狀態的 input 元素)上指定表單提交用屬性

網頁作者可以指定在 form 元素上的表單提交用屬性actionenctypemethodnovalidatetarget

網頁作者可以指定在提交按鈕上的表單提交用屬性有相對的 formactionformenctypeformmethodformnovalidateformtarget。若未指定,這些屬性的預設值是 form 元素上對應屬性的值。

若網頁作者指定內容屬性 actionformaction,則取值必須是可能有兩邊空白的合法非空網址

若一個元素為提交按鈕且它具有 formaction 屬性,則它的行動是該屬性的值,否則此元素的行動是其主表單 action 屬性(若有)的值,否則此元素的行動是空字串。

內容屬性 methodformmethod 是有以下關鍵字與狀態的列舉屬性

  • 對應到 GET 狀態的關鍵字 get,表示 HTTP GET 方法。
  • 對應到 POST 狀態的關鍵字 post,表示 HTTP POST 方法。

這兩個屬性的失蹤預設值GET 狀態。

一個元素的方法是這兩個狀態其一。若此元素為提交按鈕且它具有 formmethod 屬性,則此元素的方法是該屬性的狀態,否則此元素的方法是其主表單 method 屬性的狀態。

內容屬性 enctypeenctype 是有以下關鍵字與狀態的列舉屬性

  • 關鍵字 "application/x-www-form-urlencoded" 與對應的狀態。
  • 關鍵字 "multipart/ford-data" 與對應的狀態。
  • 關鍵字 "text/plain" 與對應的狀態。

這兩個屬性的失蹤預設值application/x-www-form-urlencoded 狀態。

一個元素的編碼型別是這兩個狀態其一。若此元素為提交按鈕且它具有 formenctype 屬性,則此元素的編碼型別是該屬性的狀態,否則此元素的編碼型別是其主表單 enctype 屬性的狀態。

若網頁作者指定內容屬性 targetformtarget,則取值必須是合法瀏覽上下文名稱或關鍵字

如果一个元素是一个提交按钮,且该元素拥有formtarget属性,则该元素的目标为该属性值;或者,如果该元素的所属表单拥有target属性,则为该属性的值;或者,如果Document包含一个拥有target属性的base元素,则为第一个这样的base元素的target属性的值;或者,如果没有这样的元素,则为空字符串。

內容屬性 novalidateformnovalidate布林屬性。若存在,代表提交時不驗證該表單。

若一個元素為提交按鈕且它具有 formnovalidate 屬性,或此元素的主表單具有 novalidate 屬性,則此元素的不驗證狀態為真,否則為假。

在表單具有驗證約束的時候,這個屬性可以用來做「儲存」按鈕,讓使用者儲存書寫到一半的表單資料。下面的例子是個簡單的表單,有兩個必填欄位與三個按鈕:一個用來提交表單,但是非填完不能提交,一個用來儲存表單,讓使用者可以繼續未完的作業,一個用來清空表單。
<form action="editor.cgi" method="post">
 <p><label>姓名:<input required name=fn></label></p>
 <p><label>短文:<textarea required name=essay></textarea></label></p>
 <p><input type=submit name=submit value="提交短文"></p>
 <p><input type=submit formnovalidate name=save value="儲存短文"></p>
 <p><input type=submit formnovalidate name=cancel value="取消"></p>
</form>

IDL 屬性 action 必須反映同樣名稱的內容屬性,除非在獲取的時候內容屬性不存在或是屬性的取值為空字串,在這種情形下必須回傳文件的位置。IDL 屬性 target 必須反映同樣名稱的內容屬性。IDL 屬性 methodenctype 必須反映同樣名稱的內容屬性,受限於已知取值。IDL 屬性 encoding 必須反映內容屬性 enctype限制於已知取值。IDL 屬性 noValidate 必須反映內容屬性 novalidate。IDL 屬性 formAction 必須反映內容屬性 formaction,除非在獲取的時候內容屬性不存在或是屬性的取值為空字串,在這種情形下必須回傳文件的位置。IDL 屬性 formEnctype 必須反映內容屬性 formenctype限制於已知取值。IDL 屬性 formMethod 必須反映內容屬性 formmethod限制於已知取值。IDL 屬性 formNoValidate 必須反映內容屬性 formnovalidate。IDL 屬性 formTarget 必須反映內容屬性 formtarget

提交元素方向性

表單控制項元素上的表單控制項 dirname 屬性可以用來提交此元素的方向性,並可以用來命名表單提交時含有這個值的欄位。若網頁作者欲設定此屬性,值必不可為空字串。

文本字段选择API

inputtextarea元素在其DOM接口中定义了下列成员,用来对它们的选择进行操作:

void select();
         attribute unsigned long selectionStart;
         attribute unsigned long selectionEnd;
         attribute DOMString selectionDirection;
void setSelectionRange(in unsigned long start, in unsigned long end, in optional DOMString direction);

这些方法和属性暴露和控制了inputtextarea文本字段中的选择。

此区块中不是标准描述,实现要求在下面给出。

selection . select()

选择文本字段中的所有内容。

selection . selectionStart [ = value ]

返回选择部分起始位置的偏移量。

可以被设置,用来修改选择部分的起始位置。

selection . selectionEnd [ = value ]

返回选择部分结束位置的偏移量。

可以被设置,用来修改选择部分的结束位置。

selection . selectionDirection [ = value ]

返回选择部分的当前方向。

可以被设置,用来修改选择部分的方向。

可能的值包括“forward”、“backward”和“none”。

selection . setSelectionRange(start, end [, direction] )

在给出的方向下,用给出的子字符串修改选择部分。如果忽略了方向,则被重置为平台的默认值(none或forward)。

如果这些方法和属性被用于不适用的input元素,则必须抛出一个INVALID_STATE_ERR异常。否则,必须按需下面的描述执行。

对于input元素,这些方法和属性必须操作该元素的。对于textarea元素,这些方法和属性必须操作该元素的原始值

在可能的情况下,用户界面中修改inputtextarea元素的文本选中部分的功能必须在本节所描述的DOM API下实现,以便可以全部触发相同的事件等。

inputtextarea元素的选中部分拥有一个方向,其值为forwardbackwardnone。这个方向将在用户对选择部分进行操作时设置。选择部分方向的精确意义有平台决定。

注:在Windows下,方向指定了符号相对于选择部分的位置:一个向前的选择,其符号在选择部分之后;一个向后的选择,其符号在选择部分之前。Windows没有none方向。在Mac下,方向指定了在用户在Shift模式下使用方向键调整选择部分的大小时将影响选中部分的那一端:向前的选择将修改选中部分的结尾;向后的选择将修改选择部分的开头。none方向是Mac的默认方向,它表示没有特点的方向尚未选定。用户在第一次调整选择部分时指定隐式方向,这取决于使用了哪个方向键。

select()方法必须全选文本字段的内容,如果平台支持none方向,则其方向为none,否则方向为forward。用户代理必须以用户交互任务源作为任务源排入一个任务以在该元素上冒泡地触发一个简单事件,其名称为select。

对于selectionStart属性,在获取时,必须返回紧接在选择部分起始位置之后的字符的偏移量(按照逻辑上的顺序)。如果没有选择部分,则必须返回紧接在文本输入光标之后的字符的偏移量(按照逻辑上的顺序)。

在设置时,必须如同调用了setSelectionRange()方法,其中,使用新值作为第一个参数;如果selectionEnd属性的值不小于新值,则使用selectionEnd属性的值作为第二个参数,否则必须使用新值作为第二个参数;使用selectionDirection属性的当前值作为第三个参数。

对于selectionEnd属性,在获取时,必须返回紧接在选择部分结束位置之后的字符的偏移量(按照逻辑上的顺序)。如果没有选择部分,则必须返回紧接在文本输入光标之后的字符的偏移量(按照逻辑上的顺序)。

在设置时,必须如同调用了setSelectionRange()方法,其中,使用selectionStart属性的当前值作为第一个参数;使用新值作为第二个参数;使用selectionDirection属性的当前值作为第三个参数。

对于selectionDirection属性,在获取时,必须返回与当前选择部分方向对应的字符串:如果方向为向前则“forward”;如果方向为向后则“backward”;否则“none”。

在设置时,必须如同调用了setSelectionRange()方法,其中,使用selectionStart属性的当前值作为第一个参数;使用selectionEnd属性的当前值作为第二个参数;使用新值作为第三个参数。

setSelectionRange(start, end, direction)方法必须将文本字段的选择部分设为以第start个位置(按照逻辑上的顺序)的字符为开始、以第(end-1)个位置(按照逻辑上的顺序)的字符为结束的字符串序列。大于文本字段值的长度的参数必须被视为指向文本字段的结尾。如果end小于等于start,则选中部分的开始和结束必须都被指向紧靠偏移量为end的字符之前。对于没有空选择概念的用户代理,必须将光标定位于紧靠偏移量为end的字符之前。如果direction区分大小写地匹配字符串“backward”,则选择部分的方向为向后;如果direction区分大小写地匹配字符串“forward”或平台不支持方向为none,则选择部分的方向为向前;否则选择部分的方向为none(包括参数被忽略)。用户代理必须以用户交互任务源为任务源排入一个任务以在该元素上冒泡地触发一个简单事件,该事件名为select。

对于所有适用这些API的元素,在所有任何时候都拥有一个选择部分或一个文本输入光标(即使元素尚未被渲染)。用户代理应该按照平台的约定确定其初始状态。

在渲染时不可见的字符——例如U+200D零宽度联合字符——仍然算作字符。因此,选择部分可以只包含这些不可见字符,文本输入光标也可以放在这些字符的两侧。

为了获得当前选择的文字,必须执行下列JavaScript代码:

var selectionText = control.value.substring(control.selectionStart, control.selectionEnd);

……其中control为一个inputtextarea元素。

为了向一个文本控件的开始位置插入一些文本,并保持文本选择部分,则必须保持三个属性:

var oldStart = control.selectionStart;
var oldEnd = control.selectionEnd;
var oldDirection = control.selectionDirection;
var prefix = "http://";
control.value = prefix + control.value;
control.setSelectionRange(oldStart + prefix.length, oldEnd + prefix.length, oldDirection);

……其中control为一个inputtextarea元素。

约束

定义

对于可列的表单相关元素,除非该元素禁止约束验证,都将作为约束验证的候选。(举例说明,如果一个元素是outputfieldset元素,则该元素禁止约束验证。)

一个元素可以定义一个自定义有效性验证错误信息。初始化时,元素必须将其自定义有效性验证错误信息设为空字符串。当其值不是空字符串时,则表示该元素出现自定义错误。这可以通过setCustomValidity()方法设置。用户代理应该在向同于提示控件的问题时使用该自定义有效性验证错误信息

一个元素可以通过多种途径进行验证。下列列出了表单控件可以处于的有效性状态的列表,这些状态基于约束验证的原因使控件无效。(下面的定义是不规范的;本规范的其他部分精确的定义了何时应该应用这些状态。)

注:即使元素被禁用,其仍然可以出现这些状态;因此这些状态仍然会被表现在DOM中,即使表单验证发生在表单提交时用户无法看到这些状态。

如果一个元素没有出现上述有效性状态,则该元素满足其约束条件

约束验证

如果用户代理被要求静态验证form元素表单的约束,则必须执行下列步骤。这些步骤返回一个肯定结果(表单中的全部控件均有效)或一个否定结果(存在无效的控件),以及一个(可能为空的)无效元素的列表。这些步骤不适用脚本程序。

  1. 控件集合为所有所属表单表单可提交元素的列表,保持树形结构顺序
  2. 无效控件集合为一个元素列表,该列表初始化为空。
  3. 按照树形结构顺序遍历控件集合的每一个字段,执行下列子步骤:
    1. 如果字段不是一个约束验证的候选,则进入下一个元素。
    2. 否则,如果字段满足其约束条件,则进入下一个元素。
    3. 否则,将字段插入到无效控件集合中。
  4. 如果无效控件集合为空,则返回肯定的结果并跳过这些步骤。
  5. 按照树形结构顺序遍历无效控件集合的每一个字段,执行下列子步骤
    1. 字段触发一个简单事件,该事件名为invalid,且可撤销。
    2. 如果事件没有被撤销,则将字段插入到未处理无效控件集合中。
  6. 返回否定结果以及在未处理无效控件集合中的元素的列表。

如果用户代理被要求交互式地验证form元素表单的约束,则用户代理必须执行下列步骤:

  1. 静态验证表单的约束,并且,如果返回否定结果,则设未处理无效控件集合为返回的元素列表。
  2. 如果返回的结果是肯定的,则返回该结果并跳过这些步骤。
  3. 向用户报告未处理无效控件集合中给出的至少一个元素约束所出现的问题。用户代理可能会在处理过程中通过对这些元素中的一个执行聚焦步骤使该元素获得焦点,还可能会通过改变滚动条位置或其他行为使该元素进入用户视野。用户代理可能会报告超过一个约束冲突。如果恰当,用户代理可能会合并相关的约束冲突报告(例如,如果在一个中的多个单选按钮被标为必填项,则只需要报告一个错误)。如果一个空间没有被渲染(例如,其设置了hidden属性)则用户代理可能会报告一个脚本错误。
  4. 返回否定结果。
约束验证API

此区块中不是标准描述,实现要求在下面给出。

element . willValidate

如果该元素在表达提交时将要进行验证,则返回真;否则返回假。

element . setCustomValidity(message)

设置一个自定义错误,使该元素不能通过验证。给出的信息是向用户报告问题时将要展示的消息。

如果攒书为空字符串,则清除自定义错误。

element . validity . valueMissing

如果该元素没有值但是一个必填字段,则返回真;否则返回假。

element . validity . typeMismatch

如果该元素的值的语法不正确,则返回真;否则返回假。

element . validity . patternMismatch

如果该元素的值不匹配指定的格式,则返回真;否则返回假。

element . validity . tooLong

如果该元素的值超过指定的最大长度,则返回真;否则返回假。

element . validity . rangeUnderflow

如果该元素的值低于指定的最小值,则返回真;否则返回假。

element . validity . rangeOverflow

如果该元素的值高于指定的最大值,则返回真;否则返回假。

element . validity . stepMismatch

如果该元素的值不适合由step属性给出的规则,则返回真;否则返回假。

element . validity . customError

如果该元素拥有一个自定义错误,则返回真;否则返回假。

element . validity . valid

如果该元素的值通过验证,则返回真;否则返回假。

valid = element . checkValidity()

如果该元素的值通过验证,则返回真;否则返回假并在该元素上触发一个invalid事件。

element . validationMessage

如果该元素检查过有效性,则返回将会向用户展示的错误信息。

如果一个元素约束验证的候选,则willValidate属性必须返回真,否则必须返回假(例如,如果任意条件禁止表单验证,则返回假)。

当调用setCustomValidity(message)时,必须将自定义有效性验证错误信息message参数给出的值。

在下面的例子中,脚本程序在一个表单控件每次被编辑时检查其值,一旦其不是一个有效的值,则使用setCustomValidity()方法设置一个恰当的消息。

<label>感觉:<input name=f type="text" oninput="check(this)"></label>
<script>
 function check(input) {
   if (input.value == "开心" ||
       input.value == "不错" ||
       input.value == "疲劳") {
     input.setCustomValidity('"' + input.value + '"不是一个感觉。');
   } else {
     // 输入正确,重置错误信息。
     input.setCustomValidity('');
   }
 }
</script>

validity属性必须返回一个ValidityState对象,该对象表示该元素的有效性状态。该对象是活动的,且每次调用该元素的validity属性时必须返回同一个对象。

interface ValidityState {
  readonly attribute boolean valueMissing;
  readonly attribute boolean typeMismatch;
  readonly attribute boolean patternMismatch;
  readonly attribute boolean tooLong;
  readonly attribute boolean rangeUnderflow;
  readonly attribute boolean rangeOverflow;
  readonly attribute boolean stepMismatch;
  readonly attribute boolean customError;
  readonly attribute boolean valid;
};

ValidityState对象拥有下列属性。在获取这些属性时,如果在下面的列表中给出的对应的条件为真,则它们必须返回真,否则必须返回假。

在调用checkValidity()方法时,如果当前元素是一个约束验证的候选且不满足其约束条件,则用户代理必须在该元素上触发一个简单事件并返回假,该事件名为invalid,且可以被撤销。否则,必须不进行其他操作并返回真。

如果当前元素不是一个约束验证的候选或如果是但其满足其约束条件,则validationMessage属性必须返回空字符串;否则,如果唯一的存在有效性约束问题的表单控件,其必须返回一个用户代理将要将其展示给用户的适当的本地化消息。如果用户代理不会在这种情况下显示一个文本消息(例如,它会显示一个图形化的提示),则该属性必须返回一个恰当的本地化消息,其表示(一个过多个)使该控件不安全的有效性约束。如果当前元素是一个约束验证的候选出现自定义错误,则返回值应该包括自定义有效性错误消息

安全性

服务器不应依赖客户端验证。客户端验证可以被恶意用户故意绕开,还可以被使用没有实现这些特性的旧用户代理或自动化工具的用户无意地忽略。约束验证功能只用于改进用户体验,不提供任何形式的安全机制。

表單提交

介绍

此章節不具有規範性

當使用者提交表單時,使用者代理會根據編碼型別將表單的資料專換成相應的結構,並使用給定的方法將該結構送至行動指定的目的地。

拿以下的表單來當例子:

<form action="/find.cgi" method=get>
 <input type=text name=t>
 <input type=search name=q>
 <input type=submit>
</form>

若使用者在第一個欄位輸入 "cats",在第二個輸入 "fur",並按下提交按鈕,則使用者代理會載入 /find.cgi?t=cats&q=fur

另一外面,若以下表單:

<form action="/find.cgi" method=post enctype="multipart/form-data">
 <input type=text name=t>
 <input type=search name=q>
 <input type=submit>
</form>

有了同樣的使用者輸入,提交的結果不太一樣:使用者代理會對給定的網址 HTTP POST 以下的實體內容:

 ------kYFrd4jNJEgCervE
 Content-Disposition: form-data; name="t"

 cats
 ------kYFrd4jNJEgCervE
 Content-Disposition: form-data; name="q"
 
 fur
 ------kYFrd4jNJEgCervE--
隱式提交

用户代理可为每个表單建立一個按鈕作为表單的預設按鈕預設按鈕應該是以樹排序算的第一個所属表單是該form元素的提交按鈕,不過使用者代理可選另一個適合特定平台的按鈕。若平台支援使用者啟動隱式表單提交(舉例來說,在一些平台上,在一個文字欄位有焦距的時候按「輸入鍵」會啟動隱式表單提交),則隱式提交必須觸發預設按鈕啟動行為

注:因此,若預設按鈕處於停用狀態,則當使用者使用隱式提交機制時,使用者代理不會提交表單。(處於停用狀態的按鈕沒有啟動行為。)

若表單沒有提交按鈕,則使用者代理必須在隱式提交發生時由 form 元素提交 form 元素自己。

表单提交算法

当一个form元素表单通过某元素提交器(通常是一个按钮)进行提交时,可选的设置一个通过脚本提交标记,用户代理必须执行下列步骤:

  1. 表单所属文档表单所在的Document
  2. 如果表单所属文档没有与其关联的浏览器上下文或其浏览器上下文在该Document创建时设置了沙箱中的表单浏览器上下文标记,则不进行任何操作并跳过这些步骤。
  3. 表单浏览器上下文表单所属文档浏览器上下文
  4. 如果表单已经被提交(例如,在处理下两步中触发的事件时表单被再次提交,这可能是由于脚本程序重复的在表单上调用了submit()方法),则跳过这些步骤。这不影响本算法早先的实例。
  5. 如果没有设置通过脚本提交标记,且提交器元素的未验证状态为假,则交互式验证表单的约束并检查其结果:如果返回否定结果(约束验证的结论是该字段无效,并且可能会通知用户)则跳过这些步骤。
  6. 如果没有设置通过脚本提交标记,则需要在表单触发一个简单事件,该事件名为submit,且可以被撤销。如果该事件的默认行为被阻止(例如,如果该事件被撤销)则跳过这些步骤。否则,继续(有效的默认行为是执行提交)。
  7. 行为提交器元素的行为
  8. 如果行为是空字符串,则设行为表单所属文档文档的地址
    注:这步故意违反RFC 3986,这需要基于URL处理。这种违反行为是为了与旧版相兼容。[RFC3986]
  9. 相对于提交器元素解释URL行为。如果失败,则跳过这些步骤。否则,设行为是返回的绝对URL
  10. scheme是返回的绝对URL<scheme>
  11. enctype提交器元素的enctype
  12. method提交器元素的method
  13. target提交器元素的target
  14. 如果在提交表单时,用户指定了一个特点的浏览器上下文,则设目标浏览器上下文为该浏览器上下文。否则,使用目标为名称、表单浏览器上下文为上下文应用通过给出的浏览器上下文名称选择浏览器上下文的规则,并将目标浏览器上下文设为返回的浏览器上下文
  15. 如果目标浏览器上下文在上一步被创建,或者如果表单文档尚未被完全加载,则设替换为真,否则设为假。
  16. 基于每行的第一个单元格中给出的scheme的值在下表中选择一个适当的行。之后,基于每列的第一个单元格中给出的method的值在该行内选择一个适当的单元格。之后,跳转至该表格下面定义的与单元格中的内容同名的步骤。
GET POST
http 改变行为URL 提交实体主体
https 改变行为URL 提交实体主体
ftp 获得行为URL 获得行为URL
javascript 获得行为URL 获得行为URL
data 获得行为URL 发送数据
mailto 邮寄报头 邮寄主体

如果scheme没有在表格中列出,则其行为没有被本规范定义。在其他规范的定义了该scheme的情况下,用户代理应该按照其类似于本规范中相似的scheme的方式执行。

行为如下:

  • 改变行为URL
    1. query为通过application/x-www-form-urlencoded编码算法表单数据集进行编码,并解释为一个US-ASCII字符串。
    2. 目标为一个新的URL,其等于行为,但其<query>组件被替换为query(如果恰当,加入一个U+003F问号字符(?))。
    3. 目标浏览器上下文导航目标。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。
  • 提交实体主体
    1. 实体主体为通过恰当的表单编码算法表单数据集进行编码的结果。
    2. MIME类型有下列确定:
    3. 如果enctypeapplication/x-www-form-urlencoded
      • MIME类型为“application/x-www-form-urlencoded”。
    4. 如果enctypemultipart/form-data
    5. 如果enctypetext/plain
      • MIME类型为“text/plain”。
    6. 否则,将目标浏览器上下文导航目标,其中以实体主体作为实体主体使用method给出的HTTP方法,其类型为MIME类型。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。
  • 获得行为URL
    1. 目标浏览器上下文导航行为。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。
  • 发送数据
    1. 数据为通过恰当的表单编码算法表单数据集进行编码的结果。
    2. 如果行为包含字符串“%%%%”(四个U+0025百分号字符),则如果按照US-ASCII进行解释,则%转义数据中不匹配URI通用语法产生的unreserved的所有字节,之后按照US-ASCII字符串处理返回的结果,进一步的%转义所有U+0025百分号字符并用返回的双重转义的字符串替换行为中的第一个“%%%%”。RFC3986
    3. 否则,如果行为包含字符串“%%”(一行中的两个U+0025百分号字符,并非四个),则如果按照US-ASCII进行解释,则%转义数据中不匹配URI通用语法产生的unreserved的所有字符,之后按照US-ASCII字符串处理返回的结果,用返回的转义字符串替换行为中的第一个“%%”。RFC3986
    4. 目标浏览器上下文导航至经过隐式修改的行为(可能为一个data: URL)。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。
  • 邮寄报头
    1. 头部为通过application/a-www-form-urlencoded编码算法表单数据集进行编码,并解释为一个US-ASCII字符串。
    2. 头部中出的的U+002B加号字符(+)替换为字符串“%20”。
    3. 目标行为中从第一个字符到紧靠第一个U+003F分号字符(?)之前的字符(如果存在)或者字符串结尾的所有字符。
    4. 目标追加一个单独的U+003F问号字符(?)。
    5. 目标追加头部
    6. 否则,将目标浏览器上下文导航目标。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。
  • 邮寄主体
    1. 主体为通过恰当的表单编码算法表单数据集进行编码的结果并且如果按照US-ASCII进行解释,则%转义返回值中不匹配URI通用语法产生的unreserved的所有字节。
    2. 目标为与行为相同的值。
    3. 如果目标不包含U+003F问号字符(?),则追加一个单独的U+003F问号字符(?)。否则,追加一个单独的U+0026与字符(&)。
    4. 目标追加一个字符串“body=”。
    5. 目标追加按照US-ASCII解释的主体
    6. 目标浏览器上下文导航目标。如果替换为真,则目标浏览器上下文必须以启用替换方式进行导航。

恰当的表单编码算法由下列条件确定:

构建表单数据集

为表单表单构建表单数据集的算法如下:

  1. 控件集合为一个所属表单表单的所有可提交元素的列表,保持树形结构顺序
  2. 表单数据集为一个“名称-值-类型”元组的列表,初始化为空。
  3. LOOP:按照树形结构顺序遍历控件集合中的每一个字段,执行下列子步骤:
    1. 如果满足下列任意条件,则该元素跳过这些子步骤:
    2. 类型字段type IDL属性的值。
    3. 如果'字段元素是一个type属性处于图片按钮状态的input元素,则进一步嵌套运行下列子步骤:
      1. 如果字段标记了一个name属性且其值不是空字符串,则设名称为该值并紧跟一个单独的U+002E句号字符(.)。否则,设名称为空字符串。
      2. 名称x为将名称和一个单独的U+0078拉丁小写字母X字符(x)串联而组成的字符串。
      3. 名称y为将名称和一个单独的U+0079拉丁小写字母Y字符(y)串联而组成的字符串。
      4. 字段元素是提交器,且在调用当前算法之前用户指定了一个坐标。设x为用户所选择的坐标的X坐标,设y为用户所选择的坐标的y坐标。
      5. 表单数据集追加一个实体,其名称为名称x、值为x、类型为类型
      6. 表单数据集追加一个实体,其名称为名称y、值为y、类型为类型
      7. 跳过本元素的其余子步骤:如果控件集合中村中其他元素,则返回上方标有LOOP的步骤,否则跳转至下方标有END的步骤。
    4. 名称字段元素的name属性的值。
    5. 如果字段元素是一个select元素,则对于该select元素中的每一个选择状态为真的HTML5/the-button-element#the-option-element#option元素,向表单数据集中追加一个实体,其名称为名称、值为HTML5/the-button-element#the-option-element#option元素的、类型为类型
    6. 否则,如果字段元素是一个type属性处于复选框状态或单选按钮状态的input元素,则进一步嵌套运行下列子步骤:
      1. 如果字段元素标记了value属性,则设为该属性的值;否则,设为字符串“on”。
      2. 表单数据集中追加一个实体,其名称为名称、值为、类型为类型
    7. 否则,如果字段元素是一个type属性处于文件上传状态的input元素,则对于该input元素中选择的每一个文件,向表单数据集中追加一个实体,其名称为名称、值为该文件(包含名称、类型和主体)、类型为类型。如果没有选择文件,则向表单数据集中追加一个实体,其名称为名称、值为空字符串、类型为“application/octet-stream”。
    8. 否则,如果字段元素是一个object元素:尝试从plugin中获得表单提交值,如果成功,则像表单数据集中追加一个实体,其名称为名称、值为返回的提交值、类型为字符串“object”。
    9. 否则,向表单数据集中追加一个实体,其名称为名称、值为字段元素的、类型为类型
    10. 如果该元素拥有一个表单控件dirname属性,且该属性的值不是一个空字符,则执行下列子步骤:
      1. dirname为该元素dirname属性的值。
      2. 如果该元素的书写方向为‘ltr’,则设dir为字符串“ltr”,否则设为字符串“rtl”(例如当该元素的书写方向为‘rtl’)。
      3. 表单数据集追加一个实体,其名称为dirname、值为dir、类型为字符串“direction”。
        注:如果一个元素是一个textarea元素或一个type属性处于文本状态或搜索状态的input元素,则该元素可以仅拥有一个表单控件dirname属性
  4. END:返回表单数据集
URL编码表单数据

application/x-www-form-urlencoded编码算法如下:

  1. 结果为空字符串。
  2. 如果form元素拥有一个accept-charset属性,则综合考虑从表单数据集的名称和值中找到的字符和用户代理所支持的字符编码,在formaccept-charset属性所给出的列表中选择一个兼容ASCII的字符编码。如果没有支持的编码或列表中没有编码,则设选中的字符编码为UTF-8。
    否则,如果文档的字符编码是一个兼容ASCII的字符编码,则其为选中的字符编码。
    否则,设选中的字符编码为UTF-8。
  3. 字符集为选中的字符编码的首选MIME名称
  4. 对于表单数据集中的每个实体,执行下列子步骤:
    1. 如果实体的名称为“_charset_”且其类型为“hidden”,将其值替换为字符集
    2. 如果实体的类型为“file”,将其值替换为文件的文件名。
    3. 对于实体的名称和值中的每个不能用选中的字符编码表示的字符,将该字符替换为一个由一个U+0026与字符(&)、一个U+0023井号字符(#)、一或多个U+0030数字零(0)到U+0039数字九(9)范围内的表示十进制的Unicode码位的字符和一个U+003B分号字符(;)组成的字符串。
    4. 对于实体的名称和值中的每个字符,应用下列相应的子子步骤:
      • 该字符是一个U+0020空格字符
        • 将该字符替换为一个单独的U+002B加号字符(+)。
      • 如果该字符不属于U+0020、U+002A、U+002D、U+002E、U+0030至U+0039、U+0041至U+005A、U+005F、U+0061至U+007A
        • 将该字符替换为下列格式的字符串:
          1. s为一个空字符串。
          2. 对于该字符按选中的字符编码表示的每个字节b,依次执行下列恰当的子子子步骤:
            • 如果该字节属于0x20、0x2A、0x2D、0x2E、0x30至0x39、0x41至0x5A、0x5F、0x61至0x7A
              • s追加码位等于该字节的Unicode字符。
            • 否则
              • s追加一个U+0025百分号字符(%)紧跟两个在U+0030数字零(0)至U+0039数字九(9)和U+0041罗马大写字符A至U+0046罗马大写字符F范围内的表示该字节的十六进制值(如果必要使用零进行填充)。
      • 否则
        • 保留该字符
    5. 如果实体的名称为“isindex”,其类型为“text”,且其为表单数据集的第一个实体,则将其值追加至结果中,并跳过本实体的其余子步骤,移至下一个实体(如果存在),或整个算法中的下一步。
    6. 如果不是第一个实体,向结果中追加一个单独的U+0026与字符(&)。
    7. 结果中追加实体的名称。
    8. 结果中追加一个单独的U+003D等于号字符(=)。
    9. 结果中追加实体的值。
  5. 结果按照US-ASCII编码并返回编码后的字节流。
多部分表单数据

multipart/form-data编码算法如下:

  1. 结果为空字符串。
  2. 如果调用该算法时明确了字符编码,则将选中的字符编码设为该编码。(该算法用于其他提供了明确的字符编码的规范,避免像下一段中所描述的依赖form元素。)
    否则,如果form元素拥有一个accept-charset属性,则综合考虑从表单数据集的名称和值中找到的字符和用户代理所支持的字符编码,在formaccept-charset属性所给出的列表中选择一个兼容ASCII的字符编码。如果没有支持的编码或列表中没有编码,则设选中的字符编码为UTF-8。
    否则,如果文档的字符编码是一个兼容ASCII的字符编码,则其为选中的字符编码。
    否则,设选中的字符编码为UTF-8。
  3. 字符集为选中的字符编码的首选MIME名称
  4. 对于表单数据集中的每个实体,执行下列子步骤:
    1. 如果实体的名称为“_charset_”且其类型为“hidden”,将其值替换为字符集
    2. 对于实体的名称和值中的每个不能用选中的字符编码表示的字符,将该字符替换为一个由一个U+0026与字符(&)、一个U+0023井号字符(#)、一或多个U+0030数字零(0)到U+0039数字九(9)范围内的表示十进制的Unicode码位的字符和一个U+003B分号字符(;)组成的字符串。
  5. 使用RFC 2388中描述的规则对(现在已经改变的)表单数据集进行编码,从表单返回值:multipart/form-data,并返回编码后的字节流。[RFC2388]

表单数据集中的每个实体是一个字段,实体的名称是字段名、实体的值是字段值

各部分之间的顺序必须和表单数据集中个字段的顺序相同。拥有相同名称的多个实体必须作为不同的字段进行处理。

注:特别的,这意味着,对于作为一个单独的<input type=file multiple>元素的一部分提交的多个文件,将造成每个文件拥有其各自的字段;不适用RFC 2388的“文件集”功能(“multipart/mixed”)。

对于与非文件字段相对应的multipart/form-data资源产生的部分,禁止其标记一个Content-Type头。它们的名称和值必须使用上面选择的字符编码进行编码(特别的,字段名字没有按照RFC 2388中所建议的转换为一个7位安全编码)。

用于用户代理产生该算法的返回值的边界是multipart/form-data边界字符串。(该值是用于产生由该算法产生的表单提交酬载的MIME类型的。)

纯文本表单数据

text/plain编码算法如下:

  1. 结果为空字符串。
  2. 如果form元素拥有一个accept-charset属性,则综合考虑从表单数据集的名称和值中找到的字符和用户代理所支持的字符编码,在formaccept-charset属性所给出的列表中选择一个字符编码。如果没有支持的编码或列表中没有编码,则设选中的字符编码为UTF-8。
    否则,设选中的字符编码为文档的字符编码
  3. 字符集为选中的字符编码的首选MIME名称
  4. 如果实体的名称为“_charset_”且其类型为“hidden”,将其值替换为字符集
  5. 如果实体的类型为“file”,将其值替换为文件的文件名。
  6. 对于表单数据集中的每个实体,执行下列子步骤:
    1. 结果中追加实体的名称。
    2. 结果中追加一个单独的U+003D等于号字符(=)。
    3. 结果中追加实体的值。
    4. 结果中追加一个U+000D回车(CR)U+000A换行(LF)字符对。
  7. 使用选择的字符编码对结果进行编码并返回编码返回的字节流。

表單重置

若一个form元素表单重置,用户代理必须在表单激活一个简单事件,该事件名为reset,且该事件可取消。之后,如果事件没有被取消,必须调用对每一个所属表单表单可重设元素调用重置算法

每种可重设元素定义了它们的重置算法。这些算法的一部分中对表单控件的修改不计入用户引发的修改(因此,例如,不会触发input事件)。