[TOC]
# 表單的基礎知識
在 HTML 中,表單是由`<form>`元素來表示的,而在 JavaScript 中,表單對應的則是 HTMLFormElement 類型。HTMLFormElement 繼承了 HTMLElement,因而與其他 HTML 元素具有相同的默認屬性。不過,HTMLFormElement 也有它自己下列獨有的屬性和方法。
- acceptCharset:服務器能夠處理的字符集;等價于 HTML 中的 accept-charset 特性。
- action:接受請求的 URL;等價于 HTML 中的 action 特性。
- elements:表單中所有控件的集合(HTMLCollection)。
- enctype:請求的編碼類型;等價于 HTML 中的 enctype 特性。
- length:表單中控件的數量。
- method:要發送的 HTTP 請求類型,通常是"get"或"post";等價于 HTML 的 method 特性。
- name:表單的名稱;等價于 HTML 的 name 特性。
- reset():將所有表單域重置為默認值。
- submit():提交表單。
- target:用于發送請求和接收響應的窗口名稱;等價于 HTML 的 target 特性。
獲取`<form>`元素:可以通過為其添加 id 值然后使用 getElementById()來獲取;也可以通過 document.forms 取得頁面中所有的表單的集合,然后通過數值索引或 name 值來取得特定的表單,如下:
```
var firstForm = document.forms[0]
var myForm = document.forms['form2']
```
另外,可以同時為表單指定 id 和 name,它們的值不一定相同。
## 提交表單
1.通過表單中的提交按鈕提交
只要<span style="color: red">表單中存在</span>下面列出的任何一種按鈕,那么在相應表單控件擁有焦點的情況下,按回車鍵就可以提交該表單。(textarea 是一個例外,在文本區中回車會換行。)如果表單里沒有提交按鈕,按回車鍵不會提交表單。
```html
<!-- 通用提交按鈕 -->
<input type="submit" value="Submit Form">
<!-- 自定義提交按鈕 -->
<button type="submit">Submit Form</button>
<!-- 圖像按鈕 -->
<input type="image" src="graphic.gif">
```
以這種方式提交表單時,瀏覽器會在將<span style="color: red">請求發送給服務器之前</span>觸發 submit 事件。這樣,我們就有機會驗證表單數據,并據以決定是否允許表單提交。阻止這個事件的默認行為就可以取消表單提交。例如,下列代碼會阻止表單提交
```
var form = document.getElementById('myForm')
form.addEventListener('submit', function (event) {
event = event ? event : window.event
event.preventDefault()
})
```
2.顯式調用 submit() 方法:
```
var form = document.getElementById('myForm')
form.submit() // 提交表單
```
在以調用 submit() 方法的形式提交表單時,不會觸發 submit 事件,因此要記得在調用此方法之前先驗證表單數據
> 提交表單時可能出現的最大問題,就是重復提交表單。在第一次提交表單后,如果長時間沒有反應,用戶可能會變得不耐煩。這時候,他們也許會反復單擊提交按鈕。結果往往很麻煩(因為服務器要處理重復的請求),或者會造成錯誤(如果用戶是下訂單,那么可能會多訂好幾份)。解決這一問題的辦法有兩個:在第一次提交表單后就禁用提交按鈕,或者利用 onsubmit 事件處理程序取消后續的表單提交操作。
## 重置表單
使用 type 特性值為"reset"的`<input>`或`<button>`都可以創建重置按鈕,如下面的例子所示:
```html
<!-- 通用重置按鈕 -->
<input type="reset" value="Reset Form">
<!-- 自定義重置按鈕 -->
<button type="reset">Reset Form</button>
```
這兩個按鈕都可以用來重置表單。在重置表單時,所有表單字段都會恢復到頁面剛加載完畢時的初始值。如果某個字段的初始值為空,就會恢復為空;<span style="color: red">而帶有默認值的字段,也會恢復為默認值。</span>用戶單擊重置按鈕重置表單時,會觸發 reset 事件。
與 submit 一樣,也可以通過 JavaScript 來重置表單 :`form.reset()`,其不同之處在于,調用 reset() 方法也會像單擊重置按鈕一樣觸發 reset 事件。
## 表單字段
每個表單都有 elements 屬性,該屬性是表單中所有表單元素(字段)的集合。這個 elements 集合是一個有序列表,其中包含著表單中的所有字段,例如`<input>`、`<textarea>`、`<button>`和`<fieldset>`。每個表單字段在 elements 集合中的順序,與它們出現在標記中的順序相同,可以按照位置和 name 特性來訪問它們。下面來看一個例子:
```
var form = document.getElementById("form1")
// 取得表單中的第一個字段
var field1 = form.elements[0]
// 取得名為"textbox1"的字段
var field2 = form.elements["textbox1"]
// 取得表單中包含的字段的數量
var fieldCount = form.elements.length
```
如果有多個表單控件都在使用一個 name(如單選按鈕),那么就會返回以該 name 命名的一個 NodeList
### 表單字段共有的屬性、方法、事件
*****
**表單字段共有的屬性如下:**
- disabled:布爾值,表示當前字段是否被禁用。
- form:指向當前字段所屬表單的指針;只讀。
- name:當前字段的名稱。
- readOnly:布爾值,表示當前字段是否只讀。
- tabIndex:表示當前字段的切換(tab)序號。
- type:當前字段的類型,如"checkbox"、"radio",等等。
- value:當前字段將被提交給服務器的值。對<u>文件字段</u>來說,這個屬性是只讀的,包含著文件在計算機中的路徑。
**表單字段共有的方法:**
每個表單字段都有兩個方法:focus() 和 blur()。其中,focus() 方法用于將瀏覽器的焦點設置到表單字段,即激活表單字段,使其可以響應鍵盤事件。接收到焦點的文本框會顯示插入符號, 隨時可以接收輸入。例如:偵聽頁面的 load 事件,并在該事件發生時在表單的第一個字段上調用 focus() 方法
```
window.addEventListener('load', function (event) {
document.forms[0].elements[0].focus()
})
```
HTML5 為表單字段新增了一個 autofocus 屬性。在支持這個屬性的瀏覽器中,只要設置這個屬性, 不用 JavaScript 就能自動把焦點移動到相應字段。例如:
```html
<input type="text" autofocus>
```
> 在默認情況下,只有表單字段可以獲得焦點。對于其他元素而言,如果先將其 tabIndex 屬性設置為 -1,然后再調用 focus()方法,也可以讓這些元素獲得焦點。
**表單字段共有的事件:**
除了支持鼠標、鍵盤、更改和 HTML 事件之外,所有表單字段都支持下列 3 個事件:
- blur:當前字段失去焦點時觸發。
- change:對于`<input>`和`<textarea>`元素,在它們失去焦點且 value 值改變時觸發;對于`<select>`元素,在其選項改變時觸發。
- focus:當前字段獲得焦點時觸發。
需要區別的是,對于`<input>`元素,其 change 事件在失去焦點時才觸發,而 input 事件在元素值發生改變時觸發(如 Vue 的 v-model 指定綁定的就是 input 事件)
# 文本框腳本
在 HTML 中,有兩種方式來表現文本框:一種是使用`<input>`元素的單行文本框,另一種是使用`<textarea>`的多行文本框。這兩個控件非常相似,而且多數時候的行為也差不多。不過,它們之間仍然存在一些重要的區別。
要表現文本框,必須將`<input>`元素的 type 特性設置為"text"。而通過設置 size 特性,可以指定文本框中能夠顯示的字符數。通過 value 特性,可以設置文本框的初始值,而 maxlength 特性則用于指定文本框可以接受的最大字符數。如果要創建一個文本框,讓它能夠顯示 25 個字符,但輸入不能超過 50 個字符,可以使用以下代碼:
```html
<input type="text" size="25" maxlength="50" value="initial value">
```
相對而言,`<textarea>`元素則始終會呈現為一個多行文本框。要指定文本框的大小,可以使用 rows 和 cols 特性。其中,rows 特性指定的是文本框的字符行數,而 cols 特性指定的是文本框的字符列數(類似于`<input>`元素的 size 特性)。與`<input>`元素不同,`<textarea>`的初始值必須要放在`<textarea>`和`</textarea>`之間,如下面的例子所示:
```html
<textarea rows="25" cols="5">initial value</textarea>
```
不能在 HTML 中指定 textarea 的最大字符數。
## 屏蔽特定字符
如果想屏蔽特定的字符,需要檢測 keypress 事件對應的字符編碼,然后再決定如何響應。例如,下列代碼只允許用戶輸入數值:
```
textbox.addEventListener('keypress', function (event) {
event = event || window.event
var target = event.target
var charCode = event.charCode
// 另外還要確保用戶沒有按下 Ctrl 鍵
if (!/\d/.test(String.fromCharCode(charCode)) && event.ctrlKey) {
event.preventDefault() // 屏蔽按鍵事件
}
})
```
## 操作剪貼板
下列就是 6 個剪貼板事件:
- beforecopy:在發生復制操作前觸發。
- copy:在發生復制操作時觸發。
- beforecut:在發生剪切操作前觸發。
- cut:在發生剪切操作時觸發。
- beforepaste:在發生粘貼操作前觸發。
- paste:在發生粘貼操作時觸發。
可以使用 clipboardData 對象訪問剪貼板中的數據,clipboardData 對象有三個方法:getData()、setData() 和 clearData()
>[warning] 操作剪貼板的不同瀏覽器的實現方式不同,暫不深入
## 自動切換焦點
所謂自動切換焦點即用戶填寫完當前字段自動將焦點切換到下一個字段,通常需要借助 maxlength 屬性來確定用戶是否輸入了既定長度的字數
```html
<form>
<input type="text" name="tel1" id="txtTel1" maxlength="3">
<input type="text" name="tel2" id="txtTel2" maxlength="3">
<input type="text" name="tel3" id="txtTel3" maxlength="4">
</form>
```
```js
(function () {
function tabForward(event) {
event = event || window.event
let target = event.target // 觸發事件的元素
if (target.value.length === target.maxLength) {
let form = target.form // 可以獲取包裹這個表單字段的 form 元素
for (let i = 0, len = form.elements.length; i < len; i++) { // 通過 form 的 elements 屬性獲取表單字段
if (form.elements[i] === target) {
if (form.elements[i + 1]) {
form.elements[i + 1].focus()
}
return
}
}
}
}
let textbox1 = document.getElementById('txtTel1')
let textbox2 = document.getElementById('txtTel2')
let textbox3 = document.getElementById('txtTel3')
textbox1.addEventListener('keyup', tabForward) // 松開鍵盤后觸發
textbox2.addEventListener('keyup', tabForward)
textbox3.addEventListener('keyup', tabForward)
})()
```
# HTML5 約束驗證 API
1、必填字段:`required`屬性,任何標注有 required 屬性的字段,在提交表單時都不能空著。
```html
<input type="text" name="username" required>
```
在 JavaScript 中,通過對應的 required 屬性,可以檢查某個表單字段是否為必填字段。
```js
var isUsernameRequired = document.forms[0].elements["username"].required
```
另外,使用下面這行代碼可以測試瀏覽器是否支持 required 屬性。
```js
var isRequiredSupported = "required" in document.createElement("input") // 通過特性檢測來確定新創建的元素中是否存在 required 屬性
```
> 對于空著的必填字段,不同瀏覽器有不同的處理方式。Firefox 4 和 Opera 11 會阻止表單提交并在相 應字段下方彈出幫助框,而 Safari(5 之前)和 Chrome(9 之前)則什么也不做,而且也不阻止表單提交

2、其他輸入類型:HTML5 為 `<input>` 的 type 屬性增加了新的幾個值,這些新的類型不僅能反應數據類型的信息,還能提供一些默認的驗證功能,其中 "email" 和 "url" 是得到支持最多的類型,各瀏覽器也都為其增加了定制的驗證機制。
3、數值范圍:"number"、"range"、"datetime"、"datetime-local"、"date"、"month"、"week"、"time" 這些屬性要求填寫某種基于數字的值
例如,想讓用戶只能輸入 0 到 100 的值,而且這個值必須是 5 的倍數,可以這樣寫代碼:
```html
<input type="number" min="0" max="100" step="5" name="count">
```
4、輸入模式:HTML5 為文本字段新增了 pattern 屬性。這個屬性的值是一個正則表達式,用于匹配文本框中的值。例如,如果只想允許在文本字段中輸入數值,可以像下面的代碼一樣應用約束:
```html
<input type="text" pattern="\d+" name="count">
```
注意,模式的開頭和末尾不用加`^`和`$`符號(假定已經有了)。這兩個符號表示輸入的值必須從頭到尾都與模式匹配。
5、檢測有效性:使用 `checkValidity()`方法可以檢測表單中的某個字段是否有效。所有表單字段都有這個方法,如果字段的值有效,這個方法返回 true,否則返回 false。字段的值是否有效的判斷依據是本節前面介紹過的那些約束。換句話說,必填字段中如果沒有值就是無效的,而字段中的值與 pattern 屬性不匹配也是無效的。例如:
```js
if (document.forms[0].elements[0].checkValidity()){
// 字段有效,繼續
} else {
// 字段無效
}
```
要檢測整個表單是否有效,可以在表單自身調用`checkValidity()`方法。如果所有表單字段都有效,這個方法返回 true;即使有一個字段無效,這個方法也會返回 false。
```js
if(document.forms[0].checkValidity()){
// 表單有效,繼續
} else {
// 表單無效
}
```
# 富文本編輯
推薦閱讀:[利用 javaScript 實現副本文編輯器 | 百度EUX](http://eux.baidu.com/blog/fe/%E5%88%A9%E7%94%A8-javascript-%E5%AE%9E%E7%8E%B0%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8)
## 使用 contenteditable 屬性
可以把 contenteditable 屬性應用給頁面中的任何元素,然后用戶立即就可以編輯該元素
```html
<div class="editable" id="richedit" contenteditable></div>
```
這樣,元素中包含的任何文本內容就都可以編輯了,就好像這個元素變成了`<textarea>`元素一樣。通過在這個元素上設置 contenteditable 屬性,也能打開或關閉編輯模式
```js
var div = document.getElementById("richedit")
div.contentEditable = "true";
```
## 操作富文本
與富文本編輯器交互的主要方式,就是使用 document.execCommand()。這個方法可以對文檔執行預定義的命令,而且可以應用大多數格式。可以為 document.execCommand()方法傳遞 3 個參數:
- 要執行的命令名稱
- 表示瀏覽器是否應該為當前命令提供用戶界面的一個布爾值
- 執行命令必須的一個值(如果不需要值,則傳遞 null)。
為了確保跨瀏覽器的兼容性,第二個參數應該始終設置為 false,因為 Firefox 會在該參數為 true 時拋出錯誤。不同瀏覽器支持的預定義命令也不一樣。下表列出了那些被支持最多的命令。
|命 令 |值(第三個參數)| 說 明|
| --- | --- | --- |
|backcolor |顏色字符串 |設置文檔的背景顏色|
|bold |null |將選擇的文本轉換為粗體|
|copy| null| 將選擇的文本復制到剪貼板|
|createlink |URL字符串| 將選擇的文本轉換成一個鏈接,指向指定的URL|
|cut |null| 將選擇的文本剪切到剪貼板|
|delete |null |刪除選擇的文本|
|fontname| 字體名稱| 將選擇的文本修改為指定字體|
|fontsize| 1~7 |將選擇的文本修改為指定字體大小|
|forecolor| 顏色字符串| 將選擇的文本修改為指定的顏色|
|formatblock| 要包圍當前文本塊的HTML標簽;如`<h1>`|使用指定的HTML標簽來格式化選擇的文本塊
|indent| null |縮進文本|
|inserthorizontalrule |null |在插入字符處插入一個`<hr>`元素|
|insertimage| 圖像的URL |在插入字符處插入一個圖像|
|insertorderedlist |null |在插入字符處插入一個`<ol>`元素|
|insertunorderedlist |null| 在插入字符處插入一個`<ul>`元素|
|insertparagraph| null |在插入字符處插入一個`<p>`元素|
|italic |null |將選擇的文本轉換成斜體|
|justifycenter| null |將插入光標所在文本塊居中對齊|
|justifyleft| null| 將插入光標所在文本塊左對齊|
|outdent| null |凸排文本(減少縮進)|
|paste| null| 將剪貼板中的文本粘貼到選擇的文本|
|removeformat| null |移除插入光標所在文本塊的塊級格式。這是撤銷formatblock命令的操作|
|selectall |null| 選擇文檔中的所有文本|
|underline |null |為選擇的文本添加下劃線|
|unlink |null |移除文本的鏈接。這是撤銷createlink命令的操作|
其中,與剪貼板有關的命令在不同瀏覽器中的差異極大。Opera 根本沒有實現任何剪貼板命令,而Firefox 在默認情況下會禁用它們(必須修改用戶的首選項來啟用它們)。Safari 和 Chrome 實現了 cut 和 copy,但沒有實現 paste。不過,即使不能通過 document.execCommand()來執行這些命令,但卻可以通過相應的快捷鍵來實現同樣的操作。可以在任何時候使用這些命令來修改富文本區域的外觀,如下面的例子所示。
```js
// 轉換粗體文本
document.execCommand("bold", false, null)
// 轉換斜體文本
document.execCommand("italic", false, null)
// 創建指向 www.wrox.com 的鏈接
document.execCommand("createlink", false,"http://www.wrox.com")
// 格式化為 1 級標題
document.execCommand("formatblock", false, "<h1>")
```
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直線、矩形、多邊形
- Part2-曲線圖形
- Part3-線條操作
- Part4-文本操作
- Part5-圖像操作
- Part6-變形操作
- Part7-像素操作
- Part8-漸變與陰影
- Part9-路徑與狀態
- Part10-物理動畫
- Part11-邊界檢測
- Part12-碰撞檢測
- Part13-用戶交互
- Part14-高級動畫
- CSS
- SCSS
- codePen
- 速查表
- 面試題
- 《CSS Secrets》
- SVG
- 移動端適配
- 濾鏡(filter)的使用
- JS
- 基礎概念
- 作用域、作用域鏈、閉包
- this
- 原型與繼承
- 數組、字符串、Map、Set方法整理
- 垃圾回收機制
- DOM
- BOM
- 事件循環
- 嚴格模式
- 正則表達式
- ES6部分
- 設計模式
- AJAX
- 模塊化
- 讀冴羽博客筆記
- 第一部分總結-深入JS系列
- 第二部分總結-專題系列
- 第三部分總結-ES6系列
- 網絡請求中的數據類型
- 事件
- 表單
- 函數式編程
- Tips
- JS-Coding
- Framework
- Vue
- 書寫規范
- 基礎
- vue-router & vuex
- 深入淺出 Vue
- 響應式原理及其他
- new Vue 發生了什么
- 組件化
- 編譯流程
- Vue Router
- Vuex
- 前端路由的簡單實現
- React
- 基礎
- 書寫規范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 與 Hook
- 《深入淺出React和Redux》筆記
- 前半部分
- 后半部分
- react-transition-group
- Vue 與 React 的對比
- 工程化與架構
- Hybird
- React Native
- 新手上路
- 內置組件
- 常用插件
- 問題記錄
- Echarts
- 基礎
- Electron
- 序言
- 配置 Electron 開發環境 & 基礎概念
- React + TypeScript 仿 Antd
- TypeScript 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs