表单脚本
JavaScript最初的一个应用,就是分担服务器处理表单的责任 ,打破处处依赖服务器的局面。由于Web表单没有为许多常见任务提供现成的解决手段,很多开发人员不仅会在验证表单 的时候使用JavaScript,而且还增强了一些标准表单控件 的默认行为。
表单的基础知识
在HTML中,表单是由<form>
元素来表示的。在JavaScript中,表单对应的是HTMLFormElement 类型。HTMLFormElement 继承自HTMLElement ,下面是HTMLFormElement 独有的属性和方法。
acceptCharset :服务器能处理的字符集;等价于HTML中的accept-charset 特性。action :接受请求的URL 。等价于action 特性。elements :表单中所有控件的集合(HTMLCollection )。enctype :请求的编码类型;等价于enctype 特性。length :表单中控件的数量(重点内容 )。method :要发送的HTTP请求类型 ,通常是get 或者post ;等价于method 特性。name :表单的名称。等价于name 特性。reset() :将所有表单域重置为默认值。submit() :提交表单。target :用于发送请求 和接收响应 的窗口名称 。等价于target 特性。 取得表单的引用除了通用的方法外,还可以通过document.forms 取得页面中所有表单。在这个集合中,我们可以通过索引 或者name特性 来取得表单。 有些较早的浏览器也会把每个设置了name 特性的表单作为属性保存在document 中,所以也可以通过document.formname
获得表单名为formname 的引用。但这种做法并不推荐。
提交表单
<input type ="submit" value ="Submit Form" >
<button type ="submit" > Submit Form</button >
<input type ="image" src ="graphic.gif" >
当表单中存在上述按钮,在表单控件拥有焦点 的情况下,按回车键 (可以认为绑定了keydown或keyup 事件)就可以提交表单(textarea 是一个例外,在文本区中回车会换行)。如果没有按钮,按回车键不会提交表单。 通过上述方式提交表单会在表单提交前到服务器之前触发submit事件。这样,我们就可以验证表单数据来决定是否取消提交表单。
var form = document.getElementById("myForm" );
form.addEventListener("submit" , function (event) {
event.preventDefault();
});
除此之外,还可以通过submit() 方法手动提交表单。这种方法无需表单包含提交按钮。缺点是不会触发submit事件 ,需要在调用这个方法之前,手动验证表单数据是否有效。
var form = document .getElementById("myForm" );
if (true ) {
form.submit();
}
提交表单的最大问题是重复提交 。在第一次提交表单后,如果长时间没有反应,用户可能会变得不耐烦。这时候,他们也许会反复单击提交按钮。在这里我们可以禁用该按钮或者通过onsubmit 事件处理程序 取消后续的表单提交操作。
重置表单
用户单击重置按钮时,表单会被重置。所谓重置,就是如果某个字段的初始值为空,就恢复为空。如果有默认值,就恢复为默认值。
<input type ="reset" value ="Reset Form" >
<button type ="reset" > Reset Form</button >
用户单击重置按钮重置表单时,会触发reset 事件 。利用这个机会,我们可以在必要时取消重置操作 。另外,通过reset() 方法也可以重置表单,与submit() 不同的是,调用这个方法会触发reset事件 (submit()不会触发submit事件):
<!DOCTYPE html>
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > Title</title >
</head >
<body >
<form id ="myForm" >
<input type ="text" value ="1" >
<input type ="text" >
<input type ="submit" value ="Submit Form" >
<button type ="submit" > Submit Form</button >
<input type ="image" src ="graphic.gif" >
<input type ="reset" value ="Reset Form" >
<button type ="reset" > Reset Form</button >
<button type ="button" onclick ="this.parentNode.reset()" > reset</button >
</form >
<script >
var form = document.getElementById("myForm" );
form.addEventListener("submit" , function (event) {
alert("submit" );
event.preventDefault();
});
form.addEventListener("reset" , function (event) {
alert("reset" );
event.preventDefault();
});
</script >
</body >
</html >
表单字段
前面提到过,取得表单引用后,我们可以通过form.elements 获得表单元素集合。这个集合包含表单中所有字段,例如<input>、<textarea>、<button>和<fieldset>
。我们可以用花括号语法获得对应的表单元素(通过索引或者name值)。特别的,如果有多个表单控件都在使用一个name(如单选按钮),那么form.elements[“ename”] 将会返回一个NodeList 。看下面的例子:
<!DOCTYPE html>
<html >
<head >
<title > Form Fields Example</title >
</head >
<body >
<form method ="post" action ="javascript:alert('Form submitted!')" id ="myForm" >
<ul >
<li > <input type ="radio" name ="color" value ="red" > Red</li >
<li > <input type ="radio" name ="color" value ="green" > Green</li >
<li > <input type ="radio" name ="color" value ="blue" > Blue</li >
</ul >
</form >
<script type ="text/javascript" >
(function () {
var form = document.getElementById("myForm" );
var colorFields = form.elements["color" ];
alert(colorFields.length);
var firstColorField = colorFields[0 ];
var firstFormField = form.elements[0 ];
alert(firstColorField === firstFormField);
alert(form.elements[1 ] === colorFields[1 ]);
})();
</script >
</body >
</html >
上面这个例子比较简单,就不解析了。另外需要注意的是:旧浏览器支持直接通过form[0] 或者form[“color”] 取得表单元素(为保证兼容现代浏览器也可以这么使用)。这种做法和通过elements属性获得表单元素是一样的。将上面的代码修改之后依然可以正常运行,但不推荐这种做法。
<script type ="text/javascript" >
(function () {
var form = document.getElementById("myForm" );
var colorFields = form["color" ];
alert(colorFields.length);
var firstColorField = colorFields[0 ];
var firstFormField = form[0 ];
alert(firstColorField === firstFormField);
alert(form[1 ] === colorFields[1 ]);
})();
</script >
共有的表单字段属性
除了<fieldset>
元素之外,所有表单字段都拥有相同的一组属性。由于<input>
类型可以表示多种表单字段 (type),因此有些属性只适用于某些字段,但还有一些属性是所有字段所共有的。表单字段共有的属性如下。
disabled :布尔值,表示当前字段是否被禁用。form :指向当前字段所属表单的指针;只读。name :当前字段的名称。readOnly :布尔值,表示当前字段是否只读。tabIndex :表示当前字段的切换(tab)序号。type :当前字段的类型,如”checkbox”、”radio”,等等。value :当前字段将被提交给服务器的值。对文件字段来说,这个属性是只读的,包含着文件在计算机中的路径。 除了form之外,其余属性都可以修改:
var form = document.getElementById("myForm" );
var field = form.elements[0 ];
field.value = "Another value" ;
alert(field.form === form);
field.focus();
field.disabled = true ;
field.type = "checkbox" ;
所以我们也可以通过disabled属性解决之前的重复提交问题:
(function () {
var form = document.forms[0 ]
//Code to prevent multiple form submissions
form.addEventListener("submit" , function(event ) {
var target = event.target
//get the submit button(name 为submit-btn)
var btn = target.elements["submit-btn" ]
//disable it
btn.disabled = true
})
}) ()
有人说上面这段代码也可以注册为submit-btn 的onclick事件处理程序 。但它的缺点有两个:
如果我用submit() 提交(当表单获得焦点时按回车,会触发提交按钮(第一个提交按钮)的onclick事件 ),自然是无法触发按钮的click 事件的(但因为submit 事件也不会触发,所以也不算是一个缺点)。 部分浏览器会先触发click事件 ,再触发submit事件 。而由于触发submit事件时,按钮已经禁用,故导致永远也无法提交表单。例如下面的代码,在IE9+和Firefox中能正常提交表单,在Chrome则不行。
<!DOCTYPE html>
<html >
<head >
<title > Form Fields Example</title >
<script type ="text/javascript" src ="EventUtil.js" > </script >
</head >
<body >
<form method ="post" action ="javascript:alert('Form submitted!')" id ="myForm" >
<ul >
<li > <input type ="radio" name ="color" value ="red" > Red</li >
<li > <input type ="radio" name ="color" value ="green" > Green</li >
<li > <input type ="radio" name ="color" value ="blue" > Blue</li >
</ul >
<input type ="submit" value ="Submit Form" name ="submit-btn" >
<button type ="button" > Whatever</button >
</form >
<script type ="text/javascript" >
(function () {
var form = document.forms[0 ];
form.elements["submit-btn" ].onclick = function () {
this .disabled = true ;
}
})();
</script >
</body >
</html >
除了<fieldset>
之外,所有表单字段都有type 属性 。对于<input>
元素,这个值等于HTML 特性type 的值。对于其他元素,见下面的例子:
<form id ="myForm" >
<select > <option > 1</option > <option > 2</option > </select >
<select multiple > <option > 1</option > <option > 2</option > </select >
<button > 自定义按钮</button >
<button type ="button" > 自定义非提交按钮</button >
<button type ="reset" > 自定义重置按钮</button >
<button type ="submit" > 自定义提交按钮</button >
</form >
<script >
var form = document.getElementById("myForm" );
for (var i=0 ,len = form.elements.length;i<len;i++) {
console.log(form.elements[i].type);
}
</script >
----------------------------
select-one
select-multiple
submit
button
reset
submit
此外,input和button元素的type是可以修改的,而select元素的type属性是只读的。
共有的表单字段方法
每个表单字段都有两个方法:focus() 和 blur() 。看看名字就知道是什么用处了。需要注意的是,调用type为hidden的input元素 的focus() 会发生错误。同样的,如果使用CSS的display和visibility 属性隐藏了该字段,也会发生错误。 HTML5 为表单字段新增了一个autofocus 属性。在支持这个属性的浏览器中,只要设置这个属性,不用JavaScript 就能自动把焦点移动到相应字段。例如<input type="text" autofocus>
与focus()方法相对的是blur() 方法,它的作用是从元素中移走焦点。在早期Web开发中,那时候的表单字段还没有readonly特性,因此就可以用blur()方法来创建只读字段(没有焦点就无法通过键盘输入 )。现在一般很少用这个方法了。
document.forms[0 ].elements[0 ].onfocus = function () {
this .blur();
}
共有的表单字段事件
除了支持鼠标、键盘、更改和HTML 事件之外,所有表单字段都支持下列3 个事件。
blur :当前字段失去焦点时触发。focus :当前字段获得焦点时触发。change :对于<input>
和<textarea>
元素,在它们失去焦点且value 值改变时触发(触发change事件和blur事件的先后顺序不同浏览器有所不同,参考:Chrome、Firefox、IE9+先change再blur );对于<select>
元素,在其选项改变时触发。 当用户改变了当前字段的焦点,或者我们调用了blur()或focus() 方法时,都可以触发blur 和focus 事件 。 通常,可以使用focus 和blur 事件来以某种方式改变用户界面,要么是向用户给出视觉提示 ,要么是向界面中添加额外的功能 (例如,为文本框显示一个下拉选项菜单)。而change 事件则经常用于验证用户在字段中输入的数据。 由于很常用,我就不举例子了。