JavaScript高级程序设计读书笔记14

第14章 表单脚本

表单的基础知识

  • 在HTML中,表单是由<form>表示的,在JS中,表单对应的是HTMLFormElemnt类型
  • 取得form表单元素的方法:1.添加id属性 2.通过数值索引 3.通过name值取得
  • 表单的id和name属性,它们的值不一定相同

提交表单

  • 提交表单的方式:
  • 通用提交按钮 <input type="submit" value="Submit Form">
  • 自定义提交按钮<button type="submit">Submit Form</button>
  • 图像按钮<input type="image" src="graphic.gif">
  • 以编程方式提交表单form.submit()
  • 提交表单最大的问题是重复提交表单,解决方法:1.第一次提交表单后就禁用提交按钮2.利用onsubmit事件处理程序取消后续的表单提交操作

重置表单

  • 重置表单的方式:
  • 通用提交按钮 <input type="reset" value="Reset Form">
  • 自定义提交按钮<button type="reset">Reset Form</button>

表单字段

  • 每个表单都有elements属性,该属性是表单中所有表单元素的集合
  • 解决重复提交表单问题,在第一次单击后就禁用提交按钮

    1
    2
    3
    4
    5
    6
    7
    8
    EventUtil.addHandler(form,"submit",function(event){
    event=EventUtil.getEvent(event);
    var target=EventUtil.getTarget(event);
    //取得提交按钮
    var btn=target.elements["submit-btn"];
    //禁用它
    btn.disabled=true;
    });
  • focus和blur事件以某种方式改变用户界面,要么是向用户给出视觉提示,要么是向界面中添加额外的功能。change事件经常用于验证用户在字段中的输入数据。

文本框脚本

  • 在HTML中,有两种方式来表现文本框:1.使用<input>元素的单行文本框 2.使用<textarea>的多行文本框。
  • 这两种文本框都会将用户输入的内容保存在value属性中。可以通过这个属性读取和设置文本框的值。

选择文本

  • select():上述两种文本框都支持,用于选择文本框中的所有文本。
  • 在文本框获得焦点时选择其所有文本,特别是在文本框包含默认值的时候。这样做可以让用户不必一个一个地删除文本。
    1
    2
    3
    4
    5
    EventUtil.addHandler(textbox,"focus",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    target.select();
    });

选择事件

  • 在选择了文本框中的文本时,就会触发select事件。
  • 在调用select()方法时也会触发select事件。

取得选择的文本

  • 通过select事件我们可以知道用户什么时候选择了文本,但是不知道用户选择了什么文本。HTML5 通过一些扩展方案解决了这个问题,以便更顺利的取得选择的文本。
  • 该规范采取的办法:添加两个属性,selectionStart和selectionEnd。这两个属性中保存的是基于0的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function getSelectedText(textbox){
    //IE9+、Firefox、Safari、Chrome和Opera
    if(typeof textbox.selectionStart == "number"){
    return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
    //IE8 及更早版本
    } else if (document.selection){
    return document.selection.createRange().text;
    }
    }

选择部分文本

  • setSelectionRange()方法,参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引
  • IE8 及更早的版本支持使用范围选择部分文本。

    1.首先使用createTextRange()方法创建一个范围,并将其放在恰当的位置上。

    1. 使用collapse()将范围折叠到文本框的开始位置。
      3.再使用moveStart()和moveEnd()这两个范围方法将范围移动到位。此时,moveStart()将范围的起点和终点移动到了相同的位置,只要给moveEnd()传入要选择的字符总数即可。
      4.最后,使用范围的select()方法选择文本。
  • 跨浏览器实现选择部分文本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function selectText(textbox, startIndex, stopIndex) {
    if (textbox.setSelectionRange) {
    textbox.setSelectionRange(startIndex, stopIndex);
    } else if (textbox.createTextRange) {
    var range = textbox.createTextRange();
    range.collapse(true);
    range.moveStart("character", startIndex);
    range.moveEnd("character", stopIndex - startIndex);
    range.select();
    }
    textbox.focus();
    }

过滤输入

屏蔽字符

1
2
3
4
5
6
7
8
9
10
EventUtil.addHandler(textbox, "keypress", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
//屏蔽非数值字符,不屏蔽也会触发keypress事件的基本按键,确保用户没有按下ctrl键
if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 &&
!event.ctrlKey) {
EventUtil.preventDefault(event);
}
});

操作剪贴板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);
}
}
};
var textbox = document.forms[0].elements["textbox1"]
EventUtil.addHandler(textbox, "paste", function (event) {
event = EventUtil.getEvent(event);
var text = EventUtil.getClipboardText(event);

if (!/^\d*$/.test(text)) {
EventUtil.preventDefault(event);
}
});

自动切换焦点

1
2
3
<input type="text" name="tel1" id="txtTel1" size="3" maxlength="3" />
<input type="text" name="tel2" id="txtTel2" size="3" maxlength="3" />
<input type="text" name="tel3" id="txtTel3" size="4" maxlength="4" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(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) {
form.elements[i + 1].focus(); //将焦点切换到下一个文本框
return;
}
}
}
}

var textbox1 = document.getElementById("txtTel1");
var textbox2 = document.getElementById("txtTel2");
var textbox3 = document.getElementById("txtTel3");
//这个函数指定为每个文本框的onkeyup事件处理程序
EventUtil.addHandler(textbox1, "keyup", tabForward);
EventUtil.addHandler(textbox2, "keyup", tabForward);
EventUtil.addHandler(textbox3, "keyup", tabForward);
})();

HTML5约束验证API

  • 必填字段:required
  • 其他输入类型:email、url
  • 数值范围:number、range、datetime、datetime-local、date、month、week、time、stepUp()方法、stepDown()方法
  • 输入模式:pattern
  • 检测有效性:checkValidity()、validity
  • 禁用验证:novalidate、formnovalidate

选择框脚本

  • 在DOM中,每个<option>元素都有一个HTMLOptionElement对象表示。

选择选项

  • 对于只能选择一项的选项,访问选中项的方式是使用选择框的selectedIndex属性。对于多选项,selectedIndex只返回第一项的索引值。
  • 多选的情况下可以设置多个选项的selected属性为true
  • 以下适用于单选和多选选择框
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function getSelectedOptions(selectbox) {
    var result = new Array();
    var option = null;
    for (var i = 0,len=selectbox.options.length; i <len; i++) {
    option =selectbox.options[i];
    if (option.selected) {
    result.push(option);
    }
    }
    return result;
    }

添加项

  • 有三种方法:第一种方法DOM方法(appendChild方法),第二种方法Option构造函数(接收两个参数:text,value),第三种方法使用add函数(接收两个参数:新选项,位于新选项最后的选项;如果要插入成为最后的选项,第二个参数应该设置为undefined)

移除选项

  • 第一种方法DOM方法(利用removeChild方法),第二种方法用选择框的remove方法,第三种为设置null。

移动和重排选项

  • 如果为appendChild()方法传入一个文档中已有的元素,那么久从该元素的父节点中移除它,再把它添加到指定的位置,移动选项会充值每一个选项的index属性
  • 重排选项次序最好的方法是DOM:insertBefore()

表单序列化

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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-multiple":

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["value"].specified ? option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue));
}
}
}
break;

case undefined:
//字段集
case "file":
//文件输入
case "submit":
//提交按钮
case "reset":
//重置按钮
case "button":
//自定义按钮
break;

case "radio":
//单选按钮
case "checkbox":
//复选框
if (!field.checked) {
break;
}

default:
//不包含没有名字的表单字段
if (field.name.length) {
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}

富文本编辑

  • 有两种编辑富文本的方式,一种是使用iframe元素,另一种是使用contenteditable属性

    1.在页面中嵌入一个包含空HTML页面的iframe。通过设置designMode属性位“on”,这个空白的HTML页面可以被编辑,
    2.把contenteditable属性应用给页面中的任何元素,然后用户立即就可以编辑该元素

  • document.execCommand():可以对文档执行预定义的命令

  • queryCommandEnabled():查询浏览器中指定的编辑指令是否可用
  • queryCommandState():确定是否已将指令命令应用到了选择的文本
  • queryCommandValue():取得执行命令时传入的值
  • 使用框架(iframe)的getSelection()方法可以确定实际选择的文本,返回一个Selection对象
  • 富文本编辑器中的HTML不会被自动提交给服务器,而需要手工提取并提交HTML。在提交表单之前,从iframe中提取出HTML,并将其插入到隐藏的字段中。