js 的表单

JavaScript 最初的一个应用就是分担服务器处理表单的责任,打破处处依赖服务器的局限。

表单基础

HTML 中表单是由 <form> 元素来表示的。在 JavaScript 中,表单对应的则是 HTMLFormElement 类型。有下列属性和方法。

  • acceptCharset: 服务器能够处理的字符串
  • action: 接收请求的 URL
  • elements: 表单中所有控件的集合
  • enctype: 请求的编码类型
  • length: 表单中所有的控件的数量
  • method: 表单要发送的 HTTP 请求类型,通常是 “get” 或者 “post”
  • name: 表单的名称
  • reset(); 将所有的表单域重置为默认值
  • submit(); 提交表单
  • target(); 用于发送请求和接收响应的窗口名称

共有表单的字段属性

  • disabled: 布尔值,表示当前表单是否被占用。
  • form: 指向当前字段所属表单的指针;只读。
  • name: 当前字段名称。
  • readOnly: 布尔值,表示当前字段是否只读。
  • tabIndex: 表示当前字段的切换序号。
  • type: 当前字段的类型。
  • value: 当前字段将被提交给服务器的值。

共有的表单字段方法

  • focus(); 用于将浏览器的焦点设置到表单字段。
  • blur();

共有的表单事件

  • focus
  • blur
  • change:对于 <input><textaera> 元素,当它们失去焦点而且 value 值改变时该事件触发。
  • submit

阻止表单默认的同步提交的方式。

1
2
3
4
5
6
$("#form").on("submit", function(e){
e.preventDefault();
$.ajax({
// 代码段
});
});

文本框脚本

  • type: text

可以通过设置 size 的值指定文本框中能够显示的字符数,通过 value 设置文本框中的初始值,通过 maxlength 指定文本框可以接收的最大字符数。

选择文本

选择文本

  • select() 方法
1
2
var textbox = document.forms[0].elements("textbox1");
textbox.select();

在文本获得焦点时选择所有文本。

取得选择的文本

两个属性:

  • selectionStart
  • selectionEnd
1
2
3
4
5
var textbox = document.forms[0].elements("textbox1");
textbox.select();
function getSelectedText(textbox) {
return textbox.value.substring(textbox.selectionStart, selectionEnd);
}

IE9+, FireFox, Safari, Chrome, Opera 支持

选择部分文本

  • setSelectionRange() 方法
    • 两个参数:要选择的第一个字符的索引和要选择的最后一个字符的索引

IE9+, FireFox, Safari, Chrome, Opera 支持

IE8 以及之前版本:必须先使用 createTextRange(),然后调用 collapse() 将范围折叠到文本框开始位置,使用 moveStart()moveEnd

过滤输入

屏蔽字符

屏蔽字符需要结合键盘码,如果需要屏蔽特定的字符,需要检测 keypress 事件对应的字符编码,然后再做决定如何响应。

操作剪切板

剪切板事件。

  • beforecopy
  • copy
  • beforecut
  • cut
  • beforepaste
  • paste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var EventUtil = {
// 其它代码省略...
getClipboardText: function(event) {
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
setClipboardText: function(event) {
if (event.clipboardData) {
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData) {
return window.clipboardData.setData("text/plain", value);
}
}
}

自动切换焦点

常见的一种方式是用户在填写完当前字段时,自动将焦点切换到下一个字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function tabForword(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.value.length == target.maxLength) {
var form = target.form;
for (var i = 0; i < form.elements.length; i++) {
if (form.elements[i] == target) {
if (form.elements[i+1]) {
form.elements[i+1].focus();
}
return;
}
}
}
}

HTML5 约束验证 API

支持的浏览器 FireFox 4+, Safari 5+, Chrome, Opera 10+。

必填字段

  • required

检查是否支持 required 字段:

1
var isRequiredSupported = "required" in document.createElement("input");

其它输入类型

HTML5 为 type 又添加了几个类型:

  • url
  • email

数值范围

  • number
  • range
  • datetime
  • datetime-local
  • date
  • month
  • week
  • time

输入模式

HTML5 新增了 pattern 属性,值是正则表达式。

检验有效性

  • checkValidty() 方法
  • validity 对象
    • customError
    • patternMismatch
    • rangeOverflow
    • stepMisMatch
    • tooLong
    • typeMismatch
    • valid
    • valueMissing

禁用验证

  • novalidate 属性,表单不验证
  • formnovalidate 属性,某个提交按钮不验证

选择框脚本

是通过 <select><option>

  • add(newOption, relOption): 向控件中插入新的 <option> 元素,其位置在相关项之前。
  • multiple: 允许多选
  • options: 所有 <option> 的集合
  • remove(index): 移除给定位置的选项
  • selectedIndex: 基于 0 的选中项的索引
  • size: 选择框中可见行数

选择选项

  • appendChild()
  • new Option(“Option text”, “Option value”);

表单序列化

浏览器给服务器发送数据:

  • 对表单中的字段的名称和值进行 URL 编码,使用 & 分隔
  • 不发送禁用的表单字段
  • 只发送勾线的复选框和单选按钮
  • 单选选择框中的每个选中的值单独一个条目
  • 在单击提交表单的情况下,也会发送提交按钮;否则,不发送提交按钮。
  • <select> 元素的值,就是选中的 <option> 元素的 value 特性的值。如果 <option> 元素没有 value 属性,则是 <option> 元素的文本值。

表单序列化过程中,一般不包含任何按钮字段,因为结果字符串很可能是通过其他方式提交的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function serialize(form) {
var parts = [],
field = null,
i,
len,
j,
optLen,
option,
optValue;
for (i = 0, len = form.elements.length; i < len; i++) {
field = form.elements[i];
switch(field.type) {
case "select-one":
case "select-multipule":
if (field.name.length) {
for (j = 0, optLen = field.options.length; j < optLen; j++) {
option = field.options[j];
if (option.selected) {
optValue = "";
if (option.hasAttribute) {
optValue = (option.hasAttribute("value") ? option.value : option.text);
} else {
optValue = (option.attributes["values"].specified ? option.value : option.text);
}
parts.push(encodeURLComponent(field.name) + "=" + encodeURLComponent(optValue));
}
}
}
break;
case undefined:
case "file":
case "reset":
case "submit":
case "button":
break;
case "radio":
case "checkbox":
if (!field.name.length) {
break;
}
default:
if (field.name.length) {
parts.push(encodeURLComponent(field.name) + "=" + encodeURLComponent(field.value));
}
}
}
return parts.join("&");
}

富文本编辑器

1
2
3
4
5
6
<iframe src="blank.html" name="richedit" style="height: 100px; width: 100px;"></iframe>
<script>
EventUtil.addHandler(window, "load", function() {
frames["richedit"].document.designMode = "on";
});
</script>

<iframe> 指定一个简单的 HTML 页面作为其内容来源。

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<head>
<title>Blank Page for Rich Text Editing</title>
</head>
<body>
</body>
</html>

页面中就会有一个类似文本框的可编辑区字段。

使用 contenteditable 属性

为页面中的某个元素设置 contenteditable 属性,这个元素中的任何文本内容就可以编辑了。

操作富文本

与富文本交互的主要方式,使用document.execCommand(); 三个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值,第二个参数应始终设为 false。下面就是支持的命令。

  • backcolor
  • bold
  • createlink
  • cut
  • delete
  • fontname
  • forecolor
  • formatblock
  • indent
  • inserthorizontalrule
  • insertimage
  • insertorderedlist
  • insertunorderedlist
  • insertparagraph
  • italic
  • justfycenter
  • outdent
  • paste
  • removeformat
  • selectall
  • unlink

富文本选区

使用框架的 getSelection() 方法,可以确定实际选择的文本,该方法返回当前选择文本的 Selection 对象。有以下属性:

  • anchorNode: 选区起点所在起点
  • anchorOffset
  • focusNode
  • focusOffset
  • isCollapsed
  • rangeCount

方法:

  • addRange(range)
  • collapse(node, offset)
  • collapseToEnd()
  • collapseToStart()
  • containsNode(node)
  • deleteFormDocument()
  • extend(node, offset)
  • getRangeAt(index)
  • removeAllRanges()
  • selectAllChildren(node)
  • toString()

表单和富文本

富文本不会自动提交,需要手动创建表单和富文本的关系。

1
2
3
4
5
EventUtil.addHandler(form, "submit", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
});
感谢您的支持!