以这种方式提交表单时,浏览器会在将请求发送给服务器之前触发 submit 事件。这样,我们就有机会验证表单数据,并据以决定是否允许表单提交。阻止这个事件的默认行为就可以取消表单提交。
元素之外,所有表单字段都拥有相同的一组属性。由于 类型可以表示多种表单字段,因此有些属性只适用于某些字段,但还有一些属性是所有字段所共有的。
共有属性:
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 属性(不推荐,但对 来说是可行的)
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事件。
(2)共有的表单字段方法
每个表单字段都有两个方法: focus() 和 blur() 。 focus() 方法用于将浏览器的焦点设置到表单字段,即激活表单字段,使其可以响应键盘事件。
EventUtil.addHandler(window, "load", function(event){
document.forms[0].elements[0].focus();
});
HTML5 为表单字段新增了一个 autofocus 属性。在支持这个属性的浏览器中,只要设置这个属性,不用 JavaScript 就能自动把焦点移动到相应字段。
为了保证前面的代码在设置 autofocus 的浏览器中正常运行,必须先检测是否设置了该属性:
EventUtil.addHandler(window, "load", function(event) {
var element = document.forms[0].elements[0];
if (element.autofocus !== true) {
element.focus();
console.log("JS focus");
}
});
与 focus() 方法相对的是 blur() 方法,它的作用是从元素中移走焦点。在调用 blur() 方法时,并不会把焦点转移到某个特定的元素上;仅仅是将焦点从调用这个方法的元素上面移走而已。
document.forms[0].elements[0].blur();
(3)共有的表单字段事件
除了支持鼠标、键盘、更改和 HTML 事件之外,所有表单字段都支持下列 3 个事件。
对于 和
假设有一个文本框,我们只允许用户输入数值。此时,可以利用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 = "";
}
});
二、文本框脚本
在 HTML 中,有两种方式来表现文本框:一种是使用 元素的单行文本框,另一种是使用
要表现文本框,必须将 元素的 type 特性设置为 "text" 。而通过设置 size 特性,可以指定文本框中能够显示的字符数。通过 value 特性,可以设置文本框的初始值,而 maxlength 特性则用于指定文本框可以接受的最大字符数。
能够显示 25 个字符,但输入不能超过 50 个字符的文本框。
与 元素不同,
initial value
另一个与 的区别在于,不能在 HTML 中给 指定最大字符数。
无论这两种文本框在标记中有什么区别,但它们都会将用户输入的内容保存在 value 属性中。可以通过这个属性读取和设置文本框的值:
var textbox = document.forms[0].elements["textbox1"];
alert(textbox.value);
textbox.value = "Some new value";
1、选择文本
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事件。
var textbox = document.forms[0].elements["textbox1"];
EventUtil.addHandler(textbox, "select", function(event){
var alert("Text selected" + textbox.value);
});
(2)取得选择的文本
HTML5添加了两个属性: selectionStart 和 selectionEnd 。这两个属性中保存的是基于 0 的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。
要取得用户在文本框中选择的文本:
function getSelectedText(textbox){
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}
因 为 substring() 方 法 基 于 字 符 串 的 偏 移 量 执 行 操 作 , 所 以 将 selectionStart 和selectionEnd 直接传给它就可以取得选中的文本。
(3)选择部分文本
所有文本框都有一个 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"
要看到选择的文本,必须在调用 setSelectionRange() 之前或之后立即将焦点设置到文本框。
跨浏览器解决方案:
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();
}
selectText() 函数接收三个参数:要操作的文本框、要选择文本中第一个字符的索引和要选择文本中最后一个字符之后的索引。
使用 selectText() 方法。
textbox.value = "Hello world!"
//选择所有文本
selectText(textbox, 0, textbox.value.length); //"Hello world!"
//选择前 3 个字符
selectText(textbox, 0, 3); //"Hel"
//选择第 4 到第 6 个字符
selectText(textbox, 4, 7); //"o w"
选择部分文本的技术在实现高级文本输入框时很有用,例如提供自动完成建议的文本框就可以使用这种技术。
2、过滤输入
我们经常会要求用户在文本框中输入特定的数据,或者输入特定格式的数据。
(1)屏蔽字符
有时候,我们需要用户输入的文本中包含或不包含某些字符。例如,电话号码中不能包含非数值字符。
下列代码只允许用户输入数值。
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() 屏蔽按键事件。结果,文本框就会忽略所有输入的非数值。
为了让代码更通用,只要不屏蔽那些字符编码小于 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);
}
});
还要添加一个检测条件,以确保用户没有按下 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);
}
});
3、自动切换焦点
在用户填写完当前字段时,自动将焦点切换到下一个字段。在自动切换焦点之前,必须知道用户已经输入了既定长度的数据。
4、HTML5约束验证API
只有在某些情况下表单字段才能进行自动验证。具体来说,就是要在 HTML 标记中为特定的字段指定一些约束,然后浏览器才会自动执行表单验证。
(1)必填字段
在表单字段中指定了 required 属性:
任何标注有 required 的字段,在提交表单时都不能空着。这个属性适用于 、 和 字段(Opera 11 及之前版本还不支持 的 required 属性)。
在 JavaScript 中,通过对应的 required 属性,可以检查某个表单字段是否为必填字段。
var isUsernameRequired = document.forms[0].elements["username"].required;
测试浏览器是否支持 required 属性
var isRequiredSupported = "required" in document.createElement("input");
(2)其他输入类型
"email" 和 "url" 是两个得到支持最多的类型,各浏览器也都为它们增加了定制的验证机制。
"email" 类型要求输入的文本必须符合电子邮件地址的模式, "url" 类型要求输入的文本必须符合 URL 的模式。
(3)数值范围
基于数字的值: "number" 、 "range" 、 "datetime" 、 "datetime-local" 、 "date" 、 "month" 、 "week" ,还有 "time" 。浏览器对这几个类型的支持情况并不好,因此如果真想选用的话,要特别小心。
对所有这些数值类型的输入元素,可以指定 min 属性(最小的可能值)、 max 属性(最大的可能值)和 step 属性(从 min 到 max 的两个刻度间的差值)。例如,想让用户只能输入 0 到 100的值,而且这个值必须是 5 的倍数:
(4)输入模式
HTML5 为文本字段新增了 pattern 属性。这个属性的值是一个正则表达式,用于匹配文本框中的值。例如,如果只想允许在文本字段中输入数值
在 JavaScript 中可以通过 pattern 属性访问模式。
var pattern = document.forms[0].elements["count"].pattern;
测浏览器是否支持 pattern 属性
var isPatternSupported = "pattern" in document.createElement("input");
(5)检测有效性
使用 checkValidity() 方法可以检测表单中的某个字段是否有效。所有表单字段都有个方法,如果字段的值有效,这个方法返回 true ,否则返回 false 。字段的值是否有效的判断依据是前面介绍过的那些约束。
if (document.forms[0].elements[0].checkValidity()){
//字段有效,继续
} else {
//字段无效
}
(6)禁用验证
通过设置 novalidate 属性,可以告诉表单不进行验证。
在 JavaScript 中使用 noValidate 属性可以取得或设置这个值
document.forms[0].noValidate = true; //禁用验证
三、选择框脚本
选择框是通过 和 元素创建的。为了方便与这个控件交互,除了所有表单字段共有的属性和方法外, HTMLSelectElement 类型还提供了下列属性和方法。
add(newOption, relOption) :向控件中插入新 元素,其位置在相关项( relOption )之前。
multiple :布尔值,表示是否允许多项选择;等价于 HTML 中的 multiple 特性。
options :控件中所有 元素的 HTMLCollection 。
remove(index) :移除给定位置的选项。
selectedIndex :基于 0 的选中项的索引,如果没有选中项,则值为 -1 。对于支持多选的控件,只保存选中项中第一项的索引。
size :选择框中可见的行数;等价于 HTML 中的 size 特性。
选择框的 type 属性不是 "select-one" ,就是 "select-multiple" ,这取决于 HTML 代码中有没有 multiple 特性。选择框的 value 属性由当前选中项决定,相应规则如下。
如果没有选中的项,则选择框的 value 属性保存空字符串。
如果有一个选中项,而且该项的 value 特性已经在 HTML 中指定,则选择框的 value 属性等于选中项的 value 特性。即使 value 特性的值是空字符串,也同样遵循此条规则。
如果有一个选中项,但该项的 value 特性在 HTML 中未指定,则选择框的 value 属性等于该项的文本。
如果有多个选中项,则选择框的 value 属性将依据前两条规则取得第一个选中项的值。
在 DOM 中,每个 元素都有一个 HTMLOptionElement 对象表示。 HTMLOptionElement 对象添加了下列属性:
index :当前选项在 options 集合中的索引。
label :当前选项的标签;等价于 HTML 中的 label 特性。
selected :布尔值,表示当前选项是否被选中。将这个属性设置为 true 可以选中当前选项。
text :选项的文本。
value :选项的值(等价于 HTML 中的 value 特性)。
var selectbox = document.forms[0]. elements["location"];
var text = selectbox.options[0].text; // 选项的文本
var value = selectbox.options[0].value; //选项的值
1、选择选项
对于只允许选择一项的选择框,访问选中项的最简单方式,就是使用选择框的 selectedIndex 属性
var selectedOption = selectbox.options[selectbox.selectedIndex];
对于可以选择多项的选择框, selectedfIndex 属性就好像只允许选择一项一样。设置selectedIndex 会导致取消以前的所有选项并选择指定的那一项,而读取 selectedIndex 只会返回选中项中第一项的索引值。
另一种选择选项的方式,就是取得对某一项的引用,然后将其 selected 属性设置为 true 。
selectbox.options[0].selected = true;
与 selectedIndex 不同,在允许多选的选择框中设置选项的 selected 属性,不会取消对其他选中项的选择,因而可以动态选中任意多个项。但是,如果是在单选选择框中,修改某个选项的 selected 属性则会取消对其他选项的选择。需要注意的是,将 selected 属性设置为 false 对单选选择框没有影响。
selected 属性的作用主要是确定用户选择了选择框中的哪一项。要取得所有选中的项,可以循环遍历选项集合,然后测试每个选项的 selected 属性。
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;
}
使用 getSelectedOptions() 函数取得选中项的示例
var selectbox = document.getElementById("selLocation");
var selectedOptions = getSelectedOptions(selectbox);
var message = "";
for (var i = 0, len = selectedOptions.length; i < len; i++) {
message += "Selected index: " + selectedOptions[i].index +
"\nSelected text: " + selectedOptions[i].text +
"\nSelected value: " + selectedOptions[i].value + "\n\n";
}
alert(message);
2、添加选项
可以使用 JavaScript 动态创建选项,并将它们添加到选择框中。
使用DOM方法添加选项:
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
使用 Option 构造函数来创建新选项:
var newOption = new Option("Option text", "Option value");
selectbox.appendChild(newOption); //在 IE8 及之前版本中有问题
除 IE 之外的浏览器中都可以使用。由于存在 bug,IE 在这种方式下不能正确设置新选项的文本。
使用选择框的 add() 方法:
var newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined); //最佳方案
DOM 规定这个方法接受两个参数:要添加的新选项和将位于新选项之后的选项。如果想在列表的最后添加一个选项,应该将第二个参数设置为null 。在 IE对 add() 方法的实现中,第二个参数是可选的,而且如果指定,该参数必须是新选项之后选项的索引。兼容 DOM 的浏览器要求必须指定第二个参数,因此要想编写跨浏览器的代码,就不能只传入一个参数。这时候,为第二个参数传入 undefined ,就可以在所有浏览器中都将新选项插入到列表最后了。
3、移除选项
使用 DOM 的 removeChild() 方法,为其传入要移除的选项:
selectbox.removeChild(selectbox.options[0]); //移除第一个选项
使用选择框的 remove() 方法,这个方法接受一个参数,即要移除选项的索引
selectbox.remove(0); //移除第一个选项
将相应选项设置为 null:
selectbox.options[0] = null; //移除第一个选项
要清除选择框中所有的项,需要迭代所有选项并逐个移除它们:
function clearSelectbox(selectbox) {
for (var i = 0, len = selectbox.options.length; i < len; i++) {
selectbox.remove(i);
}
}
这个函数每次只移除选择框中的第一个选项。由于移除第一个选项后,所有后续选项都会自动向上移动一个位置,因此重复移除第一个选项就可以移除所有选项了。
4、移动和重排选项
使用 DOM 的 appendChild() 方法,就可以将第一个选择框中的选项直接移动到第二个选择框中。如果为 appendChild() 方法传入一个文档中已有的元素,那么就会先从该元素的父节点中移除它,再把它添加到指定的位置。
将第一个选择框中的第一个选项移动到第二个选择框中的过程:
var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);
移动选项与移除选项有一个共同之处,即会重置每一个选项的 index 属性。
要将选择框中的某一项移动到特定位置,最合适的 DOM 方法就是 insertBefore() ; appendChild() 方法只适用于将选项添加到选择框的最后。 在选择框中向前移动一个选项的位置:
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);
将选择框中的选项向后移动一个位置:
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2]);
四、表单序列化
在 JavaScript 中,可以利用表单字段的 type 属性,连同 name 和 value 属性一起实现对表单的序列化。
在表单提交期间,浏览器是怎样将数据发送给服务器的:
在表单序列化过程中,一般不包含任何按钮字段,因为结果字符串很可能是通过其他方式提交的。除此之外的其他上述规则都应该遵循。
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("&");
}
serialize() 函数会以查询字符串的格式输出序列化之后的字符串。
五、富文本编辑
这一技术的本质,就是在页面中嵌入一个包含空 HTML 页面的 iframe 。通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,而编辑对象则是该页面
元素的 HTML 代码。 designMode 属性有两个可能的值: "off" (默认值)和 "on" 。在设置为 "on" 时,整个文档都会变得可以编辑。
1、使用contenteditable属性
另一种编辑富文本内容的方式是使用名为 contenteditable 的特殊属性,这个属性也是由 IE 最早实现的。可以把 contenteditable 属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。
这种方法之所以受到欢迎,是因为它不需要 iframe 、空白页和 JavaScript,只要为元素设置contenteditable 属性即可。
通过在这个元素上设置 contenteditable 属性,也能打开或关闭编辑模式。
var div = document.getElementById("richedit");
div.contentEditable = "true";
contenteditable 属性有三个可能的值: "true" 表示打开、 "false" 表示关闭, "inherit" 表示从父元素那里继承。
2、操作富文本
与富文本编辑器交互的主要方式,就是使用 document.execCommand() 。这个方法可以对文档执行预定义的命令,而且可以应用大多数格式。可以为 document.execCommand() 方法传递 3 个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值(如果不需要值,则传递 null )。为了确保跨浏览器的兼容性,第二个参数应该始终设置为 false ,因为 Firefox 会在该参数为 true 时抛出错误。
3、富文本选区
在富文本编辑器中,使用框架( iframe )的 getSelection() 方法,可以确定实际选择的文本。这个方法是 window 对象和 document 对象的属性,调用它会返回一个表示当前选择文本的 Selection对象。
4、表单与富文本
由于富文本编辑是使用 iframe 而非表单控件实现的,因此从技术上说,富文本编辑器并不属于表单。换句话说,富文本编辑器中的 HTML 不会被自动提交给服务器,而需要我们手工来提取并提交HTML。