Appearance
表单的基础知识
本节目标:理解“表单的基础知识”的核心思路,并能把它用于实际开发或面试表达。
说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 在HTML中,表单是由<form>元素来表示的,而在JavaScript中,表单对应的则是HTMLFormElement类型,它继承了HTMLElement。
**HTMLFormElement****特有****的属性和方法****:**acceptCharset:服务器能够处理的字符集;等价于HTML中的accept-charsetaction:接受请求的URL;等价于HTML中的action特性。elements:表单中所有控件的集合(HTMLCollection )。enctype:请求的编码类型;等价于HTML中的enctype特性。length:表单中控件的数最。method:要发送的HTTP请求类型,通常是get或post;等价于HTML的method特性。name:表单的名称;等价于HTML的name特性。reset():将所有表单域重置为默认值。submit():提交表单。target:用于发送请求和接收响应的窗口名称;等价于HTML的target特性。**引用表单元素**为其添加id特性,然后再像下面这样使用getElementById()方法找到它。var form = document.getElementById("form1");通过document.forms可以取得页面中所有的表单。然后通过数值索引或name值来取得特定的表单。
var firstForm = document.forms[0]; // 取得页面中的第一个表单
var myForm = document.forms["form2"]; // 取得页面中名称为form2的表单提交表单 一般通过按钮的点击事件来提交表单,按钮主要有三种类型:
使用<input>类型提交按钮使用<button>类型提交按钮使用图像按钮,通过将<input>的type特性值设置为image来定义的如果表单里没有提交按钮,按回车键不会提交表单具体如下: <!-- 通用提交按钮 --> <input type="submit" value="Submit Form"> <!-- 自定义提交按钮 --> <button type="submit">Submit Form</button> <!-- 图像按钮 --> <input type="image" src="graphic.gif"></input> 点击或在相应表单控件拥有焦点的情况下按回车键就可以提交该表单。(textarea是一个例外,在文本区中回车会换行)
提交事件 提交表单时,浏览器会在将请求发送给服务器之前触发submit事件。
**表单验证**
在submit事件发生后,我们就有机会验证表单数据,并决定是否允许表单提交。
阻止这个事件的默认行为就可以取消表单提交。如:
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function (event) {
// 取得事件对象
event = EventUtil.getEvent(event);
// 阻止默认事件
EventUtil.preventDefault(event);
});**JavaScript****提交表单**
在JavaScript中,以编程方式调用submit()方法也可以提交表单。而且,这种方式无需表单包含提交按钮,任何时候都可以正常提交表单。如:
var form = document.getElementById("myForm");
// 提交表单
form.submit();
在以调用submit()方法的形式提交表单时,不会触发submit事件,因此记得在调用此方法之
前先验证表单数据。表单提交的问题 可能出现的最大问题就是重复提交表单。 在第一次提交表单后,如果长时间没有反应,用户可能会变得不耐烦。这时候,他们也许会反复单击提交按钮。
解决这一问题的办法有两个:在第一次提交表单后就禁用提交按钮利用onsubmit事件处理程序取消后续的表单提交操作重置表单 使用type特性值为reset的<input>或<button>都可以创建重置按钮,如: <input type="reset" value="Reset Form"> <button type="reset">Reset Form</button> 如果某个字段的初始值为空,就会恢复为空;而带有默认值的字段,也会恢复为默认值。
**重置事件**
用户单击重置按钮重置表单时,会触发reset事件。利用这个机会,我们可以在必要时取消重置操作,如:
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "reset", function (event) {
// 取得事件对象
event = EventUtil.getEvent(event);
// 阻止表单重置
EventUtil.preventDefault(event);
});**使用js重置表单**
var form = document.getElementById("myForm");
// 重置表单
form.reset();
与调用submit方法不同,调用reset()方法会像单击重置按钮一样触发reset事件。事实上,重置表单的需求是很少见的。重置筛选条件表单倒是比较常见。
**表单字段**
可以使用原生DOM方法访问表单元素。此外,每个表单都有elements属性,该属性是表单中所有表单元素(字段)的集合。这个elements集合是一个有序列,其中包含着表单中的所有字段,例如<input>、<textarea>、<button>和<fieldset>。每个表单字段在 elements集合中的顺序,与它们出现在标记中的顺序相同,可以按照位置和name特性来访问它们。如:
var form = document.getElementById("form1");
// 取得表单中的第一个字段
var field1 = form.elements[0];
// 取得name为textbox1的字段
var field2 = form.elements["textbox1"];
// 取得表单中包含的字段的数量
var fieldCount = form.elements.length;如果有多个表单控件都在使用一个name (如单选按钮),那么就会返回以该name命名的一个NodeList。例如:
<form method="post" 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>
在这个HTML表单中,有3个单选按钮,它们的name都是color,意味着这3个字段是一起的。在访问elements['color']时,就会返回一个NodeList,其中包含这3个元素;不过,如果访问elements [0],则只会返回第一个元素。如:
var form = document.getElementById("myForm");
var colorFields = form.elements["color"];
alert(colorFields.length); //3
var firstColorField = colorFields[0];
var firstFormField = form.elements[0];
alert(firstColorField === firstFormField); //true
也可以通过访问表单的属性来访问元素,例如form[0]可以取得第一个表单字段,而form['color']则可以取得第一个命名字段。这些属性与通过elements集合访问到的元素是相同的。但是,我们应该尽可能使用elements,通过表单属性访问元素只是为了与旧浏览器向后兼容而保留的一种过渡方式。共有的表单字段属性 除了fieldset元素之外,所有表单字段都拥有相同的一组属性。由于input类型可以表示多 种表单字段,因此有些属性只适用于某些字段,但还有一些属性是所有字段所共有的。表单字段共有的属性如下:
disabled:布尔值,表示当前字段是否被禁用。form:指向当前字段所属表单的指针;name:当前字段的名称。readonly:布尔值,表示当前字段是否只读。tabindex.表示当前字段的切换(tab)序号。type:当前字段类型,如checkbox, radio等等。value:当前字段将被提交给服务器的值。对文件字段来说,这个属性是只读的,包含着文件在计算机中的路径。
除了form闻性之外,可以通过JavaScript动态修改其他任何属性。来看下面的例子:
var form = document.getElementById("myForm");
var field = form.elements[0];
// 修改value属性
field.value = "Another value";
// 检查form属性的值
alert(field.form === form); //true
// 把焦点设置到当前字段
field.focus();
// 禁用当前字段
field.disabled = true;
// 修改type属性,不推荐,但对input来说是可行的
field.type = "checkbox";
能够动态修改表单字段属性,意味着我们可以在任何时候,以任何方式来动态操作表单。例如, 很多用户可能会重复单击表单的提交按钮。只要侦听submit事件,并在该事件发生时禁用提交按钮即可。如:
EventUtil.addHandler(form, "submit", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
// 取得提交按钮
var btn = target.elements["submit-btn"];
// 禁用它
btn.disabled = true;
});
注意:不能通过onclick事件处理程序来实现这个功能,因为有的浏览器会在触发表单的submit事件之前触发click事件,而有的浏览器则相反。对于先触发click事件的浏览器,意味着会在提交发生之前禁用按钮,结果永远都不会提交表单。因此,最好是通过submit事件来禁用提交按钮。不过,只有在包含提交按钮的情况下,才有可能触发表单的submit事件,通过js直接提交的情况下,不适用这种方式。除了fieldset之外,所有表单字段都有type属性。对于input元素,这个值等于HTML特 性type的值。对于其他元素,这个type属性的值如下表所列:
此外,<input>和<button>元素的type属性是可以动态修改的,而select元素的type属性则是只读的。
**共有的表单字段方法**
每个表单字段都有两个方法:focus()和blur(),其中,focus()方法用于将浏览器的焦点设置到表单字段,即激活表单字段,使其可以响应键盘事件。例如,接收到焦点的文本框会显示插入符号,随时可以接收输入。使用focus()方法,可以将用户的注意力吸引到页面中的某个部位,例如,在页面加载完毕后,将焦点转移到表单中的第一个字段。为此,可以侦听页面的load事件,并在该事件发生时在表单的第一个字段上调用focus()方法,如下面的例子所示。
EventUtil.addHandler(window, "load", function (event) {
document.forms[0].elements[0].focus();
});
要注意的是,如果第一个表单字段是一个input元素,且其type特性的值为hidden,那么以上代码会导致错误。另外,如果使用CSS的display和visibility属性隐藏了该字段,同样也会
导致错误。HTML5为表单字段新增了一个autofocus属性。在支持这个属性的浏览器中,只要设置这个原性,不用JavaScript就能自动把焦点移动到相应字段。例如:
<input type="text" autofocus>
为了保证前面的代码在设置autofocus的浏览器中正常运行,必须先检测是否设置了该属性,如果设置了,就不用再调用focus()了。
EventUtil.addHandler(window, "load", function (event) {
var element = document.forms[0].elements[0];
if (element.autofocus !== true) {
element.focus(); console.log("JS focus");
}
});因为autofocus是一个布尔值属性,所以在支持的浏览器中它的值应该是true。(在不支持的浏览器中,它的值将是空字符串。为此,上面的代码只有在autofocus不等于true的情况下才会调用focus(),从而保证向前兼容a支持autofocus属性的浏览器有Firefox4+、Safari 5+、Chrome和Opera9.6。
在默认情况下,只有表单字段可以获得焦点。对于其他元素而言,如果tabindex属性设置为-1,然后再调用focus ()方法,也可以让这些元素获得焦点。只有Opera不支持这种技术。
与focus()方法相对的是blur()方法,它的作用是从元素中移走焦点。在调用blur()方法时,并不会把焦点转移到某个特定的元素上;仅仅是将焦点从调用这个方法的元素上面移走而已。 在早期Web开发中,那时候的表单字段还没有readonly特性,因此就可以使用blur ()方法来创建只读字段。现在,虽然需要使用blur()的场合不多了,但必要时还可以使用的。用法如下: document.forms[0].elements[0].blur();
共有的表单字段事件 除了支持鼠标、键盘、更改和HTML事件之外,所有表单字段都支持下列3个事件。
blur:当前字段失去焦点时触发。change:对于<input>和<textare>元素,在它们失去焦点且value值改变时触发;对于select元素,在其选项改变时触发。
focus:当前字段获得焦点时触发。当用户改变了当前字段的焦点,或者我们调用了blur()或focus()方法时,都可以触发发blur和focus事件。这两个事件在所有表单字段中都是相同的。
但是,change事件在不同表单控件中触发的次数会有所不同。对于input和textarea元素,当它们从获得焦点到失去焦点且value值改变时,才会触发change事件。对于select元素,只要用户选择了不同的选项,就会触发change事件;换句话说,不失去焦点也会触发change事件。通常,可以使用focus和blur事件来以某种方式改变用户界面,要么是向用户给出视觉提示,要么是向界面中添加额外的功能(例如,为文本框显示一个下拉选项菜单E而change事件则经常用于验证用户在字段中输入的数据。例如,假设有一个文本框,我们只允许用户输入数值。此时,可以利用focus事件修改文本框的背景顏色,以便更清楚地表明这个字段获得了焦点。可以利用blur事件恢复文本框的背景颜色,利用change事件在用户输入了非数值字符时再次修改背景顏色。下面就给出了实现上述功能的代码。
var textbox = document.forms[0].elements[0];
EventUtil.addHandler(textbox, "focus", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.style.backgroundColor != "red") {
target.style.backgroundColor = "yellow";
}
});
EventUtil.addHandler(textbox, "blur", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (/[^\d]/.test(target.value)) {
target.style.backgroundColor = "red";
} else {
target.style.backgroundColor = "";
}
});
EventUtil.addHandler(textbox, "change", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (/[^\d]/.test(target.value)) {
target.style.backgroundColor = "red";
} else {
target.style.backgroundColor = "";
}
});为了测试用户输入的是不是非数值,这里针对文本框的value属性性使用了简单的正则表达式。而且,为确保无论文本框的值如何变化,验证规则始终如一,onblur和onchanqe事件处程序中使用了相同的正则表达式。 注意:关于blur和change事件的关系,并没有严格的规定。在某些浏器5中,blur事件会先于change事件发生;而在其他浏览器中,则恰好相反。为此,不能假定这两个事件总会以某君顺序依次触发,这一点要特别注意。
