在服务端模型中,具有输入数据的表单会被立刻提交给web服务器。它的重点在于处理整批输入的数据,然后动态地生成一个新网页。而js程序设计模型的重点在于事件处理。一个表单及其所有输入元素都具有事件句柄,js可以使用这些处理程序响应用户与表单的交互。
//页面加载完成时,调用init();
if(window.addEventListener) window.addEventListener('load',init,false);
else if (window.attachEvent) window.attachEvent('onload',init);
//为任何需要的表单和表单元素定义事件句柄
function init(){
for(var i=0;i<document.forms.length;i++)
var f = document.forms[i];
var needsValidation = false;
//现在遍历表单中的元素
for(j=0;j<f.elements.length;j++){
var e = f.elements[j];
if (e.type != 'text') continue;
var pattern = e.getAttribute('pattern');
var required = e.getAttribute('required') != null;
//required代表一个简单的pattern
if (required && !pattern)
{
pattern = '\\S';
e.setAttribute('pattern',pattern);
}
//若这个元素需要校验
if(pattern){
//每次改变时校验该元素
e.onchange = validateOnChange;
//记得添加onsubmit句柄到这个表单
needsValidation = true;
}
}
//若至少有一个表单元素需要校验,也需要为这个表单添加onsubmit事件句柄
if (needsValidation) f.onsubmit = validateOnSubmit;
}
}
//这个函数是需要校验的文本框的onchange句柄,我们已经将required属性转换为pattern属性了
function validateOnChange(){
var textfield = this; //文本框
var pattern = textfield.getAttribute('pattern'); //pattern
var value = this.value; //用户的输入
//若value不匹配pattern,将class属性设置为invalid
if(value.search(pattern) == -1) textfield.className = "invalid";
else textfield.className = 'valid';
}
//这是任何需校验的表单的onsubmit句柄
function validateOnSubmit(){
//表单提交时,重新校验表单中的所有域,然后检查类名看它们是否无效.若其中任何一个无效,则alert并阻止表单提交
var invalid = false;
for(var i = 0; i < this.elements.length; i++){
var e = this.elements[i];
if ( e.type = 'text' && e.onchange == validateOnChange){
e.onchange(); //调用句柄重新校验
if ( e.className == 'invalid' ) invalid = true;
}
}
//若表单无效,alert并阻止提交
if( invalid ) {
alert('The form is incompletely or incorrectly filled out.\n'+'please correct the hightlighted fields and try again.');
return false;
}
}
1 Form对象
document.forms中引用的表单对象按照它们在文档中出现的顺序存放,Form对象的elements[]数组属性包含表示各种表单输入元素的js对象,这个数组中的元素也是按照它们在文档中出现的顺序存放的。Form对象的action,encoding,method和target属性直接对应于标记<form>的同名属性,因为它们只有在表单真正提交的时候才会有用,所以并不太重要。
js中的Form对象支持的两种方法:
submit():提交表单
reset():重置表单元素
2 定义表单元素
表1
对象 type属性 事件
Checkbox checkbox onclick
Hidden hidden ----
Option ---- Select中一项目
Password password onchange
Radio radio onclick
Reset reset onclick
Select select-one onchange
Select select-multiple onchange
Submit submit onclick
Text text onchange
Textarea textarea onchange
3 脚本化表单元素
为表单和表彰元素命名name属性可以极大地增加引用它们的方便性,为了使HTML表单中的一组Radio元素表现出'单选钮'互斥行为,它们必须具有相同的name属性
大部分表单元素都共有的属性有:
type: 一个只读字符串,标识表单元素的类型
form:对包含该元素的Form对象的只读引用
name:由HTML的name属性指定的只读字符串
value:一个可读可写的字符串,指定表单元素包含或表示的‘值’。在提交表单时,将把这个字符串,发送到web服务器,js程序只是偶尔对它有兴趣。对于Text元素和Textarea元素,value存放用户输入的文本;对于Button元素,value指定按钮上显示的文本。对于Radio元素和Checkbox元素,无论如何都不能编辑value属性或将它显示给用户。它只是HTML的value属性设置的字符串,在提交表单时要传递给web服务器。
表单元素的事件句柄:
onclick:在元素上点击鼠标时触发,对于Button元素和与之相关的表单元素格外有用
onchange:用户改变元素值时触发,该事件句柄不是用户每次在文本框中敲击一个键都会触发,它只在用户改变一个元素的值,并把输入焦点移到其他表单元素时才会触发,也就是说,这个事件句柄的调用说明发生了完整的变化。
onfocus:表单元素收到输入焦点时触发
onblue:表单元素失去输入焦点时触发
按钮:
Button对象没有自己的默认行为,除非它具有onclick事件句柄,否则它在表单中没有用处。
可以用<button>标记代替传统的<input>标记创建包括Submit和Reset在内的按钮。它不显示由value属性指定的纯文本,而显示出现在<button>和</button>之间的HTML内容。并且button标记可以出现在HTML文档中的任何地方,且不需要放置在<form>标记内。
切换按钮:
Checkbox元素和Radio元素都是切换按钮,它们有两种不同的视觉状态,即可以被选中或取消。Radio元素总被组合在相关元素的组中,这些元素具有相同的HTML name属性值。用这种方法创建的Radio元素是互斥的,在选中一个元素后,前面被选中的元素就会被取消。Checkbox也常用于共享name属性的组中,在使用名字引用这些元素时,必须记住用名字引用的对象是与元素同名的数组。
Radio元素和Checkbox元素都定义了checked属性。这个可读可写的布尔值指定元素当前是否被选中。属性defaultChecked是一个布尔值,它具有HTML的checked属性值,声明第一次装载页面时该元素是否被选中。
Select元素和Option元素:
Select元素表示用户可以选择的选项集合,如果<select>标记有multiple属性,就允许用户进行多项选择,否则为单选。多选有点类似Checkbox,单选有点类似Radio,但Select元素不同于切换按钮元素,因为一个Select元素表示所有选项的集合。这些选项由HTML标记<option>设置,在js中它们由Option对象表示,这些对象存储在Select元素的options[]数组中。Select元素没有value属性,但每个Option对象都定义了value属性
当用户选中或取消一个选项时,Select元素将触发它的onchange事件句柄。对于“单选”型的Select元素,可读可写的属性selectedIndex用数字指定了当前被选中的选项。对于“多选”型的Select元素,一个selectedIndex属性不够,要确定选中了哪些选项,必须遍历options[]数组的所有元素,检查每个Option对象的selected属性的值。
除selected属性外,Option元素还有text属性,用于指定Select元素显示那个选项使用的纯文本串。设置这一属性可以改变显示给用户的文本。value也是可读写的字符串,指定了提交表单时要发送给web服务器的文本。
除了设置Option对象的text属性外,可通过把options.length设置为某数来截取Option元素的数组,设为0可删除所有Option对象。
可以把options[]数组的某个元素设置为null,从而在Select元素中删除一个Option对象。删除一个Option对象后,options[]数组中的位于这个Option对象后的元素会被自动前移,以填充空位。2级DOM中可使用Select.add()添加新选项;Option元素定义了构造函数Option()动态创建新的Option元素,把它们附加在options[]数组尾部可以给Select元素增加新选项。
eg.
var zaire = new Option("Zaire","zaire",false,false);//参数分别为text,value,defaultSelected,selected属性
var countries = document.address.country;
countries.options[countries.options.length] = zaire;
可以用<optgroup>标记对Select元素中的相关选项分组。<optgroup>标记具有label属性,它指定显示在Select元素中的文本。<optgroup>标记可见,但用户不可选择它,对应<optgroup>标记的对象不会出现在options[]数组中。
Hidden元素:
在表单中不可见。它的作用是在提交表单时把任意文本发送给服务器。服务器端程序用它来保存表单提交时返回给它们的状态信息。由于Hidden元素没有可视化的外观,所以它不能生成事件,没有事件句柄。value属性允许读写与Hidden元素相关的文本,但客户端js程序通常不用Hidden元素。
Fieldset元素:
<fieldset>和<label>标记不能以有趣的方式脚本化。需要知道<fieldset>标记仅仅是因为将它放在一个表单中,从而使得相应的对象能够添加到表单的elements[]数组中。和elements[]数组中所有其他对象不同,表示<fieldset>标记的对象并没有一个type属性。
4 表单验证示例
无干扰的客户端js执行表单验证的模块,要使用它,只需在HTML页面中包含该模块,定义一个CSS样式来显示验证失效的表单字段,然后为表单字段添加额外的属性。要让一个字段必需,只要添加一个required属性。要确保用户输入和一个正则表达式匹配,只需把pattern属性设置为所要的正则表达式。
HTML:
<script src="Validate.js"></script>
<style>
//Validate.js要求我们为无效类定义样式,以为无效域显示一个用户可辩认的可视化界面。当然,我们也可以选择性地为有效域定义样式
input.invalid{background:#faa;}
input.valid{background:#afa;}
</style>
<form>
Name:<input type="text" name="name" required><br>
email:<input type="text" name="email" pattern="^\s*\w+@\w+\.\w+\s*$"><br>
zipcode:<input type="text" name="zip" pattern="^\s*\d{5}\s*$"><br>
unvalidated:<input type="text"><br>
<input type="submit">
</form>
这个模块会自动注册一个onload事件句柄,这个事件句柄遍历文档中的所有表单,查找required和pattern属性并且在需要的时候添加onchange和onsubmit句柄。这些事件句柄设置它们验证为“有效”或“无效”的每个表单字段的className属性,并且,应该使用CSS至少为“无效”类提供一个区分的可视化表现。
(function(){
})();
</form>