博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JS高程3:表单脚本

Posted on 2017-09-15 14:20  开飞机的贝塔  阅读(175)  评论(0编辑  收藏  举报

HTML和CSS对表单的操作还是比较乏力的,在表单操作中,JS势必会使用到。

  • 基础知识
  • 文本框
  • 选择框
  • 序列化
  • 富文本编辑器

基础知识

 

HTMLFormElement接口可以创建或者修改<form>对象;它继承了HTMLElement接口的方法和属性。

常见的方法和属性:

HTMLFormElement.acceptCharset

相当于HTML中的accept-charset属性,包含服务器能够接受的字符编码列表。

HTMLFormElement.action
相当于HTML中的action属性,接收请求的URL。
HTMLFormElement.elements只读
表单中所有控件的集合(HTMLFormControlsCollection)。
HTMLFormElement.enctype
相当于HTML中的enctype属性,请求编码的类型。
HTMLFormElement.length 只读
表单中控件的数量。
HTMLFormElement.method
相当于HTML中的method属性,HTTP请求的类型。
HTMLFormElement.name
相当于HTML中的name属性,表单的名称。
HTMLFormElement.target
相当于HTML中的target的属性,用于发送请求和接收响应的窗口名称。
HTMLFormElement.submit()
提交表单到服务器。
HTMLFormElement.reset()
将表单域重置为默认。

更详细的内容请访问:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLFormElement

获取<form>元素的方式有多种,其中最常见的是getElementById()方法:

var form = document.getElementById("form1");

其次,可以通过document.forms取得所有表单,然后通过数值索引或者name值来获取特定的表单:

var firstForm = document.forms[0]; //取得页面中的第一个表单
var myForm = document.forms["form2"]; //取得页面中名称为"form2"的表单

 

提交表单

 

用户点击提交按钮或者图像按钮时,就会提交表单。使用<input>或者<button>元素都可以自定义提交按钮。

元素的type属性值要设置为“submit”,图像按钮设置为“image”:

<!-- 通用提交按钮 -->
<input type="submit" value="Submit Form">
<!-- 自定义提交按钮 -->
<button type="submit">Submit Form</button>
<!-- 图像按钮 -->
<input type="image" src="graphic.gif">

在表单控件拥有焦点的情况下,按回车键就能提交表单(textarea是个例外,在文本中回车会换行)。

浏览器会在将请求发送给服务器之前触发 submit 事件。这样,我们就有
机会验证表单数据,并据以决定是否允许表单提交。阻止这个事件的默认行为就可以取消表单提交。例
如,下列代码会阻止表单提交:

var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function(event){
//取得事件对象
event = EventUtil.getEvent(event);
//阻止默认事件
EventUtil.preventDefault(event);
});

这里使用了EventUtil 对象,以便跨浏览器处理事件。调用 prevetnDefault()
方法阻止了表单提交。一般来说,在表单数据无效而不能发送给服务器时,可以使用这一技术。

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);
});
与提交表单一样,也可以通过 JavaScript 来重置表单,如下面的例子所示。
var form = document.getElementById("myForm");
//重置表单
form.reset();

与调用 submit()方法不同,调用 reset()方法会像单击重置按钮一样触发 reset 事件。

在 Web 表单设计中,重置表单通常意味着对已经填写的数据不满意。重置表单
经常会导致用户摸不着头脑,如果意外地触发了表单重置事件,那么用户甚至会很恼
火。事实上,重置表单的需求是很少见的。更常见的做法是提供一个取消按钮,让用
户能够回到前一个页面,而不是不分青红皂白地重置表单中的所有值。

 

表单字段

 

可以像访问页面中的其他元素一样,使用原生 DOM 方法访问表单元素。此外,每个表单都有 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。例如,以下面的 HTML 代码片段为例

<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.elements[0]访问到的第一个表单字段,与包含在 form.elements
["color"]中的第一个元素相同

也可以通过访问表单的属性来访问元素,例如 form[0]可以取得第一个表单字
段,而 form["color"]则可以取得第一个命名字段。这些属性与通过 elements 集
合访问到的元素是相同的。但是,我们应该尽可能使用 elements,通过表单属性访
问元素只是为了与旧浏览器向后兼容而保留的一种过渡方式。

1.共有的表单字段属性

除了<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;
});

以上代码为表单的 submit 事件添加了一个事件处理程序。事件触发后,代码取得了提交按钮
并将其 disabled 属性设置为 true。注意,不能通过 onclick 事件处理程序来实现这个功能,原
因是不同浏览器之间存在“时差”:有的浏览器会在触发表单的 submit 事件之前触发 click 事件,
而有的浏览器则相反。对于先触发 click 事件的浏览器,意味着会在提交发生之前禁用按钮,结果
永远都不会提交表单。因此,最好是通过 submit 事件来禁用提交按钮。不过,这种方式不适合表
单中不包含提交按钮的情况;如前所述,只有在包含提交按钮的情况下,才有可能触发表单的 submit
事件。

除了<fieldset>之外,所有表单字段都有 type 属性。对于<input>元素,这个值等于 HTML
type 的值。对于其他元素,这个 type 属性的值如下表所列

此外, <input><button>元素的 type 属性是可以动态修改的,而<select>元素的 type 属性
则是只读的。

2.共有的表单字段方法

每个表单字段都有两个方法: 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(),从而保证向前兼容。支持 autofocus 属性的浏览器有 Firefox 4+Safari 5+Chrome Opera
9.6

在默认情况下,只有表单字段可以获得焦点。对于其他元素而言,如果先将其
tabIndex 属性设置为1,然后再调用 focus()方法,也可以让这些元素获得焦点。
只有 Opera 不支持这种技术。

focus()方法相对的是 blur()方法,它的作用是从元素中移走焦点。在调用 blur()方法时,
并不会把焦点转移到某个特定的元素上;仅仅是将焦点从调用这个方法的元素上面移走而已。在早期
Web 开发中,那时候的表单字段还没有 readonly 特性,因此就可以使用 blur()方法来创建只读字段。
现在,虽然需要使用 blur()的场合不多了,但必要时还可以使用的。用法如下:

document.forms[0].elements[0].blur();

3.共有的表单字段事件

除了支持鼠标、键盘、更改和 HTML 事件之外,所有表单字段都支持下列 3 个事件。

 blur:当前字段失去焦点时触发。
 change:对于<input>和<textarea>元素,在它们失去焦点且 value 值改变时触发;对于
<select>元素,在其选项改变时触发。
 focus:当前字段获得焦点时触发。

通常,可以使用 focus blur 事件来以某种方式改变用户界面,要么是向用户给出视觉提示,要
么是向界面中添加额外的功能(例如,为文本框显示一个下拉选项菜单)。而 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 = "";
}
});

在此, onfocus 事件处理程序将文本框的背景颜色修改为黄色,以清楚地表明当前字段已经激活。
随后, onblur onchange 事件处理程序则会在发现非数值字符时,将文本框背景颜色修改为红色。
为了测试用户输入的是不是非数值,这里针对文本框的 value 属性使用了简单的正则表达式。而且,
为确保无论文本框的值如何变化,验证规则始终如一, onblur onchange 事件处理程序中使用了相
同的正则表达式。

关于 blur 和 change 事件的关系,并没有严格的规定。在某些浏览器中, blur
事件会先于 change 事件发生;而在其他浏览器中,则恰好相反。为此,不能假定这
两个事件总会以某种顺序依次触发,这一点要特别注意。

 

文本框

 

HTML 中,有两种方式来表现文本框:一种是使用<input>元素的单行文本框,另一种是使用
<textarea>的多行文本框。

 要表现文本框,必须将<input>元素的 type 特性设置为"text"。而通过设置 size 特性,可以指
定文本框中能够显示的字符数。通过 value 特性,可以设置文本框的初始值,而 maxlength 特性则用
于指定文本框可以接受的最大字符数。如果要创建一个文本框,让它能够显示 25 个字符,但输入不能
超过 50 个字符,可以使用以下代码:

<input type="text" size="25" maxlength="50" value="initial value">

相对而言,<textarea>元素则始终会呈现为一个多行文本框。要指定文本框的大小,可以使用 rows
cols 特性。其中, rows 特性指定的是文本框的字符行数,而 cols 特性指定的是文本框的字符列数
(类似于<inpu>元素的 size 特性)。与<input>元素不同, <textarea>的初始值必须要放在
<textarea></textarea>之间,如下面的例子所示。

<textarea rows="25" cols="5">initial value</textarea>

 另一个与<input>的区别在于,不能在 HTML 中给<textarea>指定最大字符数。
无论这两种文本框在标记中有什么区别,但它们都会将用户输入的内容保存在 value 属性中。可
以通过这个属性读取和设置文本框的值,如下面的例子所示:

var textbox = document.forms[0].elements["textbox1"];
alert(textbox.value);
textbox.value = "Some new value";

我们建议读者像上面这样使用 value 属性读取或设置文本框的值,不建议使用标准的 DOM 方法。
换句话说,不要使用 setAttribute()设置<input>元素的 value 特性,也不要去修改<textarea>
元素的第一个子节点。原因很简单:对 value 属性所作的修改,不一定会反映在 DOM 中。因此,在处
理文本框的值时,最好不要使用 DOM 方法。

 

选择文本

上述两种文本框都支持 select()方法,这个方法用于选择文本框中的所有文本。在调用 select()
方法时,大多数浏览器(Opera 除外)都会将焦点设置到文本框中。这个方法不接受参数,可以在任何
时候被调用。下面来看一个例子

var textbox = document.forms[0].elements["textbox1"];
textbox.select();

在文本框获得焦点时选择其所有文本,这是一种非常常见的做法,特别是在文本框包含默认值的时
候。因为这样做可以让用户不必一个一个地删除文本。下面展示了实现这一操作的代码

EventUtil.addHandler(textbox, "focus", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.select();
});

将上面的代码应用到文本框之后,只要文本框获得焦点,就会选择其中所有的文本。这种技术能够
较大幅度地提升表单的易用性。

1.选择事件

select()方法对应的,是一个 select 事件。在选择了文本框中的文本时,就会触发 select
事件。不过,到底什么时候触发 select 事件,还会因浏览器而异。在 IE9+OperaFirefoxChrome
Safari 中,只有用户选择了文本(而且要释放鼠标),才会触发 select 事件。而在 IE8 及更早版本中,

只要用户选择了一个字母(不必释放鼠标),就会触发 select 事件。另外,在调用 select()方法时也
会触发 select 事件。下面是一个简单的例子。

var textbox = document.forms[0].elements["textbox1"];
EventUtil.addHandler(textbox, "select", function(event){
var alert("Text selected" + textbox.value);
});

2.取得选择的文本

虽然通过 select 事件我们可以知道用户什么时候选择了文本,但仍然不知道用户选择了什么文本。
HTML5 通过一些扩展方案解决了这个问题,以便更顺利地取得选择的文本。该规范采取的办法是添加
两个属性: selectionStart selectionEnd。这两个属性中保存的是基于 0 的数值,表示所选择
文本的范围(即文本选区开头和结尾的偏移量)。因此,要取得用户在文本框中选择的文本,可以使用
如下代码

function getSelectedText(textbox){
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}

因 为 substring() 方 法 基 于 字 符 串 的 偏 移 量 执 行 操 作 , 所 以 将 selectionStart
selectionEnd 直接传给它就可以取得选中的文本。

3.选择部分文本

HTML5 也 为 选 择 文 本 框 中 的 部 分 文 本 提 供 了 解 决 方 案 , 即 最 早 由 Firefox 引 入 的
setSelectionRange()方法。现在除select()方法之外,所有文本框都有一个setSelectionRange()
方法。这个方法接收两个参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引
(类似于 substring()方法的两个参数)。来看一个例子

 

 

textbox.value = "Hello world!"
//选择所有文本
textbox.setSelectionRange(0, textbox.value.length); //"Hello world!"
//选择前 3 个字符
textbox.setSelectionRange(0, 3); //"Hel"
//选择第 4 到第 6 个字符
textbox.setSelectionRange(4, 7); //"o w"

 

 

过滤输入

如前所述,响应向文本框中插入字符操作的是 keypress 事件。因此,可以通过阻止这个事件的默
认行为来屏蔽此类字符。在极端的情况下,可以通过下列代码屏蔽所有按键操作

EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
EventUtil.preventDefault(event);
});

运行以上代码后,由于所有按键操作都将被屏蔽,结果会导致文本框变成只读的。如果只想屏蔽特
定的字符,则需要检测 keypress 事件对应的字符编码,然后再决定如何响应。例如,下列代码只允许
用户输入数值。

EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if (!/\d/.test(String.fromCharCode(charCode))){
EventUtil.preventDefault(event);
}
});

在这个例子中,我们使用 EventUtil.getCharCode()实现了跨浏览器取得字符编码。然后,使
String.fromCharCode()将字符编码转换成字符串,再使用正则表达式 /\d/ 来测试该字符串,从
而确定用户输入的是不是数值。如果测试失败,那么就使用 EventUtil.preventDefault()屏蔽按键
事件。结果,文本框就会忽略所有输入的非数值。

虽然理论上只应该在用户按下字符键时才触发 keypress 事件,但有些浏览器也会对其他键触发此
事件。 Firefox Safari3.1 版本以前)会对向上键、向下键、退格键和删除键触发 keypress 事件;
Safari 3.1 及更新版本则不会对这些键触发 keypress 事件。这意味着,仅考虑到屏蔽不是数值的字符还
不够,还要避免屏蔽这些极为常用和必要的键。所幸的是,要检测这些键并不困难。在 Firefox 中,所
有由非字符键触发的 keypress 事件对应的字符编码为 0,而在 Safari 3 以前的版本中,对应的字符编
码全部为 8。为了让代码更通用,只要不屏蔽那些字符编码小于 10 的键即可。故而,可以将上面的函数
重写成如下所示

EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9){
EventUtil.preventDefault(event);
}
});

这样,我们的事件处理程序就可以适用所有浏览器了,即可以屏蔽非数值字符,但不屏蔽那些也会
触发 keypress 事件的基本按键。
除此之外,还有一个问题需要处理:复制、粘贴及其他操作还要用到 Ctrl 键。在除 IE 之外的所有
浏览器中,前面的代码也会屏蔽 Ctrl+CCtrl+V,以及其他使用 Ctrl 的组合键。因此,最后还要添加一
个检测条件,以确保用户没有按下 Ctrl 键,如下面的例子所示

EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 &&
!event.ctrlKey){
EventUtil.preventDefault(event);
}
});

经过最后一点修改,就可以确保文本框的行为完全正常了。在这个例子的基础上加以修改和调整,
就可以将同样的技术运用于放过和屏蔽任何输入文本框的字符。

2.操作剪切板

下列就是 6 个剪贴板事件

 beforecopy:在发生复制操作前触发。
 copy:在发生复制操作时触发。
 beforecut:在发生剪切操作前触发。
 cut:在发生剪切操作时触发。
 beforepaste:在发生粘贴操作前触发。
 paste:在发生粘贴操作时触发。

要访问剪贴板中的数据,可以使用 clipboardData 对象:在 IE 中,这个对象是 window 对象的
属性;而在 Firefox 4+Safari Chrome 中,这个对象是相应 event 对象的属性。但是,在 Firefox
Safari Chorme 中,只有在处理剪贴板事件期间 clipboardData 对象才有效,这是为了防止对剪贴板
的未授权访问;在 IE 中,则可以随时访问 clipboardData 对象。为了确保跨浏览器兼容性,最好只
在发生剪贴板事件期间使用这个对象。
这个 clipboardData 对象有三个方法:getData()setData()clearData()。其中,getData()
用于从剪贴板中取得数据,它接受一个参数,即要取得的数据的格式。在 IE 中,有两种数据格式: "text"
"URL"。在 FirefoxSafari Chrome 中,这个参数是一种 MIME 类型;不过,可以用"text"代表
"text/plain"
类似地, setData()方法的第一个参数也是数据类型,第二个参数是要放在剪贴板中的文本。对于
第一个参数, IE 照样支持"text""URL",而 Safari Chrome 仍然只支持 MIME 类型。但是,与
getData()方法不同的是, Safari Chrome setData()方法不能识别"text"类型。这两个浏览器在
成功将文本放到剪贴板中后,都会返回 true;否则,返回 false。为了弥合这些差异,我们可以向
EventUtil 中再添加下列方法。

var EventUtil = {
//省略的代码
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
//省略的代码
setClipboardText: function(event, value){
if (event.clipboardData){
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData){
return window.clipboardData.setData("text", value);
}
},
//省略的代码
};

在需要确保粘贴到文本框中的文本中包含某些字符,或者符合某种格式要求时,能够访问剪贴板是非
常有用的。例如,如果一个文本框只接受数值,那么就必须检测粘贴过来的值,以确保有效。在 paste
事件中,可以确定剪贴板中的值是否有效,如果无效,就可以像下面示例中那样,取消默认的行为。

EventUtil.addHandler(textbox, "paste", function(event){
event = EventUtil.getEvent(event);
var text = EventUtil.getClipboardText(event);
if (!/^\d*$/.test(text)){
EventUtil.preventDefault(event);
}
});

 

自动切换焦点

使用 JavaScript 可以从多个方面增强表单字段的易用性。其中,最常见的一种方式就是在用户填写
完当前字段时,自动将焦点切换到下一个字段。通常,在自动切换焦点之前,必须知道用户已经输入了
既定长度的数据(例如电话号码)。例如,美国的电话号码通常会分为三部分:区号、局号和另外 4
数字。为取得完整的电话号码,很多网页中都会提供下列 3 个文本框:

<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">

为增强易用性,同时加快数据输入,可以在前一个文本框中的字符达到最大数量后,自动将焦点切
换到下一个文本框。换句话说,用户在第一个文本框中输入了 3 个数字之后,焦点就会切换到第二个文
本框,再输入 3 个数字,焦点又会切换到第三个文本框。这种“自动切换焦点”的功能,可以通过下列
代码实现:

(function(){
function tabForward(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.value.length == target.maxLength){
var form = target.form;
for (var i=0, len=form.elements.length; i < len; i++) {
if (form.elements[i] == target) {
if (form.elements[i+1]){
form.elements[i+1].focus();
}
return;
}
}
}
}
var textbox1 = document.getElementById("txtTel1");
var textbox2 = document.getElementById("txtTel2");
var textbox3 = document.getElementById("txtTel3");
EventUtil.addHandler(textbox1, "keyup", tabForward);
EventUtil.addHandler(textbox2, "keyup", tabForward);
EventUtil.addHandler(textbox3, "keyup", tabForward);
})();