## 表单
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开发技巧合集
- 编程风格
- 垃圾回收机制