## 表單
Web表單是開發人員與用戶交互的重要控件。
**1、form**
**1.1 form獨有的屬性和方法**
在HTML中,表單是由`<form>`來表示的,而在JavaScript中,表單對應的是HTMLFormElement類型。HTMLFormElement繼承了HTMLElement,因此它跟其他HTML元素具有相同的默認屬性。
`<form>`也有自己獨有的屬性和方法:
```
acceptCharset:服務器能夠處理的字符集
action:接收請求的URL
elements:表單中所有控件的集合(HTMLCollection)
enctype:請求的編碼類型
length:表單中控件的數量
method:要發送的HTTP請求類型,通常是“get”或“post”
name:表單的名稱
reset():將所有表單域重置為默認值
submit():提交表單
target:用于發送請求和接收響應的窗口名稱
```
**1.2 獲取表單元素**
獲取表單元素一般有兩種方式:
- 通過id來獲取,比如獲取一個id名為form1的表單元素:
```
document.getElementById('form1');
```
-通過docuemnt.forms獲取name名為form1的表單元素:
```
document.forms['form1]
```
`document.forms`可以獲取到當前頁面中所有的表單元素,我們又可以通過方括號表示法獲取某個屬性,傳入數值索引或`name`值。
**1.3 提交表單**
提交表單也有兩種方式:
- 通過`<input>`或`<button>`提交:
```
<input type="submit" />
<button type="submit"></button>
<input type="image" src="example.png" />
```
只要`<form>`內有上面這三種按鈕,點擊的時候就會提交表單,而且,當相應表單控件擁有焦點時,按回車鍵也會提交表單(焦點在textarea里例外,回車鍵是換行)。
- 通過JavaScript觸發submit()提交:
```
var form1 = document.getElementById('form1');
form1.submit();
```
在請求發送給服務器之前,瀏覽器會觸發submit事件,我們可以主動監聽它:
```
var form1 = document.getElementById('form1');
form1.onsubmit = function(){
}
```
注意:在調用submit()方法提交表單時,不會觸發submit事件。
**1.4 重置表單**
重置表單也有兩種方式:
- 重置按鈕
```
<input type="reset" />
<button type="reset"></button>
```
當點擊重置按鈕時,會觸發reset事件:
```
form1.onreset = function(){
}
```
- 通過reset()方法
```
form1.reset();
```
與調用submit()不同,調用reset()方法時也會觸發reset事件。
**1.5 表單字段**
除了使用原生DOM方法訪問表單元素外,每一個表單都有elements屬性,該屬性是表單中所有元素的集合(比如`<input>、<textarea>、<button>、<fieldset>`),elements是一個有序列表,包含著表單中的所有字段。
```
<form id="form1">
<input type="text" name="yourname" />
<textarea name="intro"></textarea>
</form>
form1.elements[0] // 取得表單中的第一個字段
form1.elements['yourname']; // 取得name名為“yourname”的字段
```
如果表單內有多個同名(name)表單控件,那么用name取時,就會返回一個NodeList集合。
```
<form id="form1">
<input type="radio" name="color" /> red
<input type="radio" name="color" /> green
</form>
var colors = form1.elements['color']
```
colors是一個NodeList集合,包含了上面兩個radio。
**1.5.1 表單字段的共有屬性**
除了`<fieldset>`元素,所有表單字段都擁有一些相同的屬性。
共有的屬性和方法:
```
disabled:布爾值,表單當前字段是否被禁用
form:指向當前字段所屬表單的指針,只讀
name:當前字段的名稱
readonly:布爾值,表示當前字段是否只讀
tabIndex:表單當前字段的切換(tab)序號
type:當前字段的類型
value:當前字段將被提交給服務器的值。
```
`<input>`和`<button>`元素的type屬性是可以修改,但`<select>`元素則是只讀的。
**1.5.2 表單字段的共有方法**
每個表單字段都有兩個方法:focus()和blur()。
- focus()方法用于讓表單字段獲取到焦點
- blur()方法用于讓表單字段失去焦點
HTML5新增了一個autofocus屬性,作用相當于focus(),只要設置了此屬性,表單字段就會自動獲取焦點。
**1.5.3 表單字段的共有事件**
所有表單都支持下列三個事件:
- blur:當前字段失去焦點時觸發
- change:對于`<input>、<textarea>`元素,在它們失去焦點且value值改變時觸發,對于`<select>`元素,在選項改變時觸發
- focus:當前字段獲得焦點時觸發
如果你要實時的監聽表單字段的值是否變化,可使用如下代碼:
```
if('oninput' in docuemnt){
input.addEventListener('input',function(){});
}else{
input.onpropertychange = function(){};
}
```
當支持input事件時,就使用input,否則使用onpropertychange(IE特有)
**onchange、oninput和onpropertychange三個事件的區別**:
`onchange`事件在內容改變(兩次內容有可能還是相等的)且失去焦點時觸發;
`oninput`事件是IE之外的大多數瀏覽器支持的事件,在value改變時觸發,實時的,即每增加或刪除一個字符就會觸發,然而通過js改變value時,卻不會觸發;
`onpropertychange`事件是任何屬性改變都會觸發的,而oninput卻只在value改變時觸發,oninput要通過addEventListener()來注冊。
**失效情況**:
- oninput事件: 當腳本中改變value時,不會觸發;從瀏覽器的自動下拉提示中選取時,不會觸發。
- onpropertychange事件:當input設置為disabled=true后,onpropertychange不會觸發。
**2、文本框**
文本框有兩種:`<input>`和`<textarea>`。
```
<input type="text" />
<textarea cols ="10" rows ="5"></textarea>
```
**2.1 文本框獨有的屬性**
`<input>`的獨有屬性:
```
size:指定文本框能夠顯示的字符數
maxlength:指定文本框可以接受的最大字符數
```
對于`<textarea>`,它還有一些獨有屬性:
```
rows:指定的文本框的字符行數
cols:指定的文本框的字符列數
```
注意:`<textarea>`的初始值是放在`<textarea>`和`</textarea>`之間的。
**2.2 選擇文本**
文本框都支持select()方法,用于選擇文本框中的所有文本。當調用select()方法時,大多數瀏覽器都會將焦點設置到文本框中。
當用戶選擇了文本框中的文本時,會觸發select事件。
```
input.addEventListener('select',function(){});
```
**2.2.1 取得選擇的文本**
在支持HTML5的瀏覽器中,我們可以獲取到用戶選擇了什么文本,通過兩個屬性:selectionStart和selectionEnd,這兩個屬性保存的是基于0的數值,表示所選擇文本的范圍。
取得用戶選擇的文本:
```
function getSelectedText(textbox){
if(typeof textbox.selectionStart == 'number'){
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}else if(document.selection){
return document.selection.createRange().text;
}
}
```
IE8之前不支持selectionStart。
**2.2.2 選擇部分文本**
所有文本框都有一個`setSelectionRange()`方法(支持HTML5的瀏覽器中),它接受兩個參數:要選擇的第一個字符的索引和要選擇的最后一個字符的索引。
不過在IE8及之前的版本并不支持這個方法。當然,也有替代的方法。
在IE上,我們使用`createTextRange()`創建一個范圍,然后使用`moveStart()`和`moveEnd()`方法將這個范圍移動到需要獲取文本的位置上。不過,在使用這兩個方法之前,還必須使用`collpase()`將范圍折疊刀文本框的開始文章,此時,`moveStart()`將范圍的起點和終點都移動到了相同的位置,只要再給`moveEnd()`傳入要選擇的字符總數即可。最后一步,就是使用范圍的`select()`方法選擇文本。
```
function selectText(textbox, startIndex, stopIndex){
if(textbox.setSelectionRange){
textbox.setSelectionRange(startIndex, stopIndex);
}else if(textbox.createTextRange()){
var range = document.createTextRange();
range.collapse(true);
range.moveStart('character', startIndex);
range.moveEnd('character', stopIndex - startIndex);
range.select();
}
textbox.focus();
}
```
`moveStart()`和`moveEnd()`兩個方法其實可用看做是`setSelectionRange()`的兩個分解方法,獲取開始點和獲取結束點。
**2.2.3 過濾輸入**
對于很多文本框來說,都不會任由用戶輸入文本,或多或少都會有所限制,這個時候,我們就需要監聽`keypress`鍵盤事件,通過`event`事件對象中的字符編碼`keyCode`來判斷輸入字符是否該被屏蔽
```
textbox.addEventListener('keypress', function(event){
var keycode = event.keyCode;
});
```
**2.2.4 操作剪貼板**
剪切板事件:
- `beforecopy`:在發生復制操作前觸發
- `copy`:在發生復制操作時觸發
- `beforecut`:在發生剪切操作前觸發
- `cut`:在發生剪切操作時觸發
- `beforepaste`:在發生黏貼操作前觸發
- `paste`:在發生黏貼操作時觸發
要訪問剪切板中的數據,可以使用`clipboardData`對象,在IE下,這個對象是`window`屬性,在其他瀏覽器,這個對象是相應`event`對象的屬性。
注意:在IE中,可以隨時訪問`clipboardData`對象;在其他瀏覽器中,只有在處理剪貼板事件期間`clipboardData`對象才有效。
`clipboardData`對象有三個方法:
- getData():用于從剪切板中取得數據,它接受一個參數,即要取得的數據的格式。在IE中,有兩種數據格式:“text”和“URL”;在其他瀏覽器中,這個參數是一種MIME類型,比如“text/plain”,不過可以使用“text”代替“text/plain”
- setData():用于放置剪切板中的文本,它接受兩個參數,第一個參數是數據格式(和getData()中的數據格式一樣,IE支持“text”和“URL”,其他瀏覽器只支持MIME類型),第二個參數是要放在剪切板中的文本。成功的將文本放到剪切板后,都會返回true。
clearData():用于刪除剪切板中指定格式的數據,它接受一個參數,即要刪除數據的格式。
```
function getClipboardText(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData('text');
}
function setClipboardText(event, value){
if(event.clipboardData){
return event.clipboardData.setData('text/plain', value);
}else if(window.clipboardData){
return window.clipboardData.setData('text', value);
}
}
```
**2.2.5 HTML5 約束驗證 API**
HTML5位表單字段提供了自動驗證的功能,當然,要使用這些功能,開發者必須指定一些約束。
**(1)必填字段**
可以使用`required`屬性來將字段定位必填字段:
```
<input type="text" required />
```
只要設置了`required`屬性,這個表單字段就不能為空。
當然,我們也可以使用JavaScript來獲取或設置字段是否必填:
```
document.forms[0].elements['name'].required
```
由于是HTML5中定義的,我們有時需要檢測瀏覽器是否支持:
```
if( 'required' in document.createElement('input') ){
}
```
**(2)輸入模式**
HTML5位文本字段新增了`pattern`屬性,這個屬性的值是一個正則表達式,用于匹配文本框中的值
```
<input type="text" pattern="\d+" />
```
**(3)檢測有效性**
使用`checkValidity()`方法可以檢測表單中的某個字段是否有效。所有表單字段都有這個方法,如果字段的值有效,則返回true,否則返回false。
```
if( document.forms[0].elements[0].checkValidity() ){}
```
當然,如果要檢測整個表單是否有效,可以在表單自身調用這個方法,當所有表單字段有效,才返回true,只要有一個字段無效,則返回false。
```
if( document.forms[0].checkValidity() ){}
```
每個表單字段還有一個更有效的的屬性:validity,它包含了一系列屬性,每個屬性會返回一個布爾值
```
customError:如果設置了setCustomValidity(),則為true,否則為false。
patternMismatch:如果值與指定的pattern屬性不匹配,返回true
rangeOverflow:如果值比max值大,返回true
rangeUnderflow:如果值比min值小,返回true
stepMisMatch:如果min和max之間的步長值不合理,返回true
tooLong:如果值的長度超過了maxlength屬性指定的長度,返回true
typeMismatch:如果值不是“mail”或“url”要求的格式,返回true
valid:如果這里的其他屬性都是false,返回true
valueMissing:如果標注為required的字段中沒有值,返回true
```
例子:
```
if( input.validity && !input.validity.valid){
}
```
**(4)禁用驗證**
通過設置`novalidate`屬性,可以告訴表單不進行驗證。
```
<form novalidate></form>
```
當然,也可以通過JavaScript設置:
```
document.forms[0].noValidate = true; // 禁用驗證
```
我們也可以通過給提交按鈕添加`formnovalidate`屬性來禁用驗證
```
<form>
<input type="submit" formnovalidate />
</form>
```
**3、選擇框**
HTML中的選擇框通過`<select>`和`<option>`元素創建。
`<select>`屬于HTMLSelectElement類型,有下列的獨有屬性和方法:
- add(newOption, relOption):向控件中插入新的`<option>`元素,其位置在相關項(relOption)之前。
- multiple:布爾值,表示是否允許多項選擇
- options:控件中所有`<option>`元素的HTMLCollection。
- remove(index):移除給定位置的選項
- selectedIndex:基于0的選中項的索引,如果沒有選中項,則值為-1;對于多選項來說,只保存選中項中第一項的索引
- size:選擇框中可見的行數
選擇框的type屬性不是“select-one”,就是“select-multiple”。
選擇框的value屬性由當前選中項決定,相應規則如下:
- 如果沒有選中的項,則選擇框的value屬性保存空字符串
- 如果有一個選中項,而且該項的value屬性已經制定,則選擇框的value等于選中項的value屬性的值
- 如果有一個選中項,但該項的value屬性沒有指定,則選擇框的value等于該項的文本
- 如果有多個選中項,則選擇框的value將依據前兩條規則取得第一個選中項的值。
在DOM中,每個`<option>`元素都有一個HTMLOptionElement對象,其有下列屬性:
- index:當前選項在options集合中的索引
- label:當前選項的標簽
- selected:布爾值,表示當前選項是否被選中。將其設置為true可以選中該項
- text:選項的文本
- value:選項的值
- 前言
- JavaScript簡介
- 基本概念
- 語法
- 數據類型
- 運算符
- 表達式
- 語句
- 對象
- 數組
- 函數
- 引用類型(對象)
- Object對象
- Array對象
- Date對象
- RegExp對象
- 基本包裝類型(Boolean、Number、String)
- 單體內置對象(Global、Math)
- console對象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應用
- 客戶端存儲(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測設備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向對象的程序設計
- 概述
- this關鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯誤處理機制
- JavaScript開發技巧合集
- 編程風格
- 垃圾回收機制