《JavaScript高级程序设计》第14、17、20章
第十四章 表单脚本
1、表单的基础知识
1)HTMLFormElement类型的属性和方法
acceptCharset:服务器能够处理的字符集
action:接收请求的URL,等价于HTML中的action特性;
elements:表单中所有控件的集合;
encype:请求的编码类型,等价于HTML中的enctype特性;
length:表单中控件的数量;
method:要发送的HTTP请求类型,通常是“get”或“post”,等价于HTML中的method特性;
name:表单的名称,等价于HTML中的name特性;
reset():将所有表单域重置为默认值;
submit():提交表单;
target:用于发送请求接收响应的窗口名称,等价于HTML中的target特性;
2)提交表单
<!-- 通用提交按钮 -->
<input type=”submit” value=”Submit Form”>
<!-- 自定义提交按钮 -->
<bottom type=”submit” >Submit Form</bottom>
<!-- 图像按钮 -->
<input type=”submit” src=”submit-form.gif”>
3)重置表单
<!-- 通用重置按钮 -->
<input type=”reset” value=”Reset Form”>
<!-- 自定义重置按钮 -->
<bottom type=”reset” >Reset Form</bottom>
4)表单字段
取得表单字段
var form=document.getElementById(“form1”);
//取得表单中的第一个字段
var field1=form.elements[0];
//取得名为“textbox1”的字段
var field2=form.elements[“textbox1”];
//取得表单中包含的字段的数量
var fieldCount=form.elements.length;
共有的表单字段属性(<fieldset>除外)
disable:布尔值,表示当前字段是否被禁用;
form:表示当前字段所属表单的指针,只读;
name:当前字段的名称;
readOnly:布尔值,表示当前字段是否只读;
tabIndex:表示当前字段的切换(tab)序号;
type:当前字段的类型;
value:当前字段将被提交给服务器的值;
共有的表单字段方法(<fieldset>除外)
focus():用于将浏览器的焦点设置到表单字段,使其可以响应键盘事件;
blur():用于从元素中移走焦点;
共有的表单字段事件
blur事件:当前字段失去焦点时触发;
change事件:对于<input>和<textarea>元素,在它们失去焦点且value值改变时触发,对于<select>元素,在其选项改变时触发;
focus事件:当前字段获得焦点时触发;
2、文本框脚本
1)<input>元素的单行文本框:<input type=”text” size=”25” maxlength=”50” value=”initial value”>
2)<inputarea>元素的多行文本框:<textarea rows=”25” cols=”5”>initial value</textarea>
3)选择文本:
select()方法
select事件
取得选择的文本:属性selectionStart和selectionEnd,值为基于0的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)
Function getSelectedText(textbox){
return textbox.value.subString(textbox.selectionStart,textbox.selectionEnd);
}
选择部分文本:setSelectionRange()方法,接收两个参数——要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引
4)过滤输入
屏蔽字符
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);
}
});
操作剪切板
beforecopy事件:在发生复制操作前触发;
copy事件:在发生复制操作时触发;
beforecut事件:在发生剪切操作前触发;
cut事件:在发生剪切操作时触发;
beforepaste事件:在发生粘贴操作前触发;
paste事件:在发生粘贴操作时触发;
clipboardData对象:用于访问剪切板的数据,getData()、setData()和clearData()方法<TextboxClipboardExample01.htm>
var EventUtil = {
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
setClipboardText: function(event, value){
if (event.clipboardData){
event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData){
window.clipboardData.setData("text", value);
}
}
};
5)自动切换焦点:<TextboxTabForwardExample01.htm>
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;
}
}
}
}
6)HTML5约束验证API
必填字段:required属性
其他输入类型:type=”email”、type=”url”
数值范围:可以指定min属性(最小的可能值)、max属性(最大的可能性)和step属性(从min到max的两个刻度间的差值)
输入模式:pattern属性,值为正则表达式,用于匹配文本框中的值
检测有效性:checkValidity()方法可以检测表单中的某个字段是否有效
禁用验证:novalidate属性
3、选择框脚本
1)HTMLSelectElement类型的属性和方法
add(newOption,relOption):向控件中插入新<option>元素,其位置在相关项relOption之前;
multiple:布尔值,表示是否允许多项选择,等价于HTML中的multiple特性;
options:控件中所有<option>元素的HTMLCollection;
remove(index):移除给定位置的选项;
selectedIndex:基于0的选中项的索引,如果没有选中项,则为-1;
size:选择框中可见的行数,等价于HTML中的size特性;
2)HTMLOptionElement对象的属性
index:当前选项在options集合中的索引;
label:当前选项的标签,等价于HTML中的label特性;
selected:布尔值,表示当前选项是否被选中;
text:选项的文本;
value:选项的值,等价于HTML中的value特性;
3)选择选项:第一种方法使用选择框的selectedIndex属性,不过只允许选择一项;第二种方法是将要取得的那一项的selected属性设置为true,而且允许动态选择任意多项;
4)添加选项:
第一种方法是使用DOM方法<SelectboxExample04.htm>
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode(textTextbox.value));
newOption.setAttribute("value", valueTextbox.value); selectbox.appendChild(newOption);
第二种方法是使用Option构造函数来创建新选项,接收两个参数——文本和值(可选)
var newOption = new Option(“Option text”,”Option value”);
selectbox.appendChild(newOption);
第三种方法是使用选择框的add()方法,接收两个参数——要添加的新选项和将位于新选项之后的选项(可选)
var newOption = new Option(“Option text”,”Option value”);
selectbox.add(newOption,undefined);
5)移除选项
第一种方法是使用DOM方法:selectbox.removeChild(selectbox.options[0]);
第二种方法是使用remove()方法,接收一个参数——要移除选项的索引:selectbox.remove(0);
第三种方法是将相应选项设置为null:selectbox.option[0]=null;
6)移动和重排选项
将第一个选择框中的第一个选项移动到第二个选择框中
var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);
在选择框中向前移动一个选项的位置
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);
4、表单序列化<FormSerializationExample01.htm>
function serialize(form){
var parts = [],
field = null,
i,
en,
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: //fieldset
case "file": //file input
case "submit": //submit button
case "reset": //reset button
case "button": //custom button
break;
case "radio": //radio button
case "checkbox": //checkbox
if (!field.checked){
break;
}
/* falls through */
default:
//don't include form fields without names
if (field.name.length){
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}
5、富文本编辑
1)使用designMode属性:首先在页面中嵌入一个包含空HTML页面的iframe,其次设置designMode属性(默认值为off)为on时,整个文档就会变得可以编辑;
2)使用contenteditable属性:通过将contenteditable属性应用给页面中的任何元素,该元素就可以立即被编辑;通过设置contenteditate属性打开或关闭编辑模式,值为true(打开)、false(关闭)和inherit(从父元素那里继承)
3)操作富文本:document.execCommand()用于对文档执行预定义的命令,接收三个参数——要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值(始终为false)和执行命令必须一个值(如果不需要值,则传递null)
4)富文本选区:使用ifram的getSelection()方法,返回一个表示当前选择文本的Selection对象
5)表单与富文本<RichTextEditingExample01.htm>
EventUtil.addHandler(form, "submit", function(){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event); target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
});
第十七章 错误处理与检测
1、浏览器报告的错误
1)IE:IE 是唯一一个在浏览器的界面窗体(chrome)中显示 JavaScript 错误信息的浏览器。在发生 JavaScript错误时,浏览器左下角会出现一个黄色的图标,图标旁边则显示着 "Error on page" (页面中有错误)。打开“Tools”(工具)菜单中的“Internet Options”(Internet 选项)对话框,切换到“Advanced”(高级)选项卡,选中“Display a notification about every script error”(显示每个脚本错误的通知)复选框。单击“OK”(确定)按钮保存设置。
2)Firefox:默认情况下,Firefox 在 JavaScript 发生错误时不会通过浏览器界面给出提示。但它会在后台将错误记录到错误控制台中。单击“Tools”(工具)菜单中的“Error Console”(错误控制台)可以显示错误控制台。
3)Safari:Windows 和 Mac OS 平台的 Safari 在默认情况下都会隐藏全部 JavaScript 错误。为了访问到这些信息,必须启用“Develop”(开发)菜单。为此,需要单击“Edit”(编辑)菜单中的“Preferences”(偏好设置),然后在“Advanced”(高级)选项卡中,选中“Show develop menu in menubar”(在菜单栏中显示“开发”菜单)。启用此项设置之后,就会在 Safari 的菜单栏中看到一个“Develop”菜单。
4)Opera:Opera 在默认情况下也会隐藏 JavaScript 错误,所有错误都会被记录到错误控制台中。要打开错误控制台,需要单击“Tools”(工具)菜单,在“Advanced”(高级)子菜单项下面再单击“Error Console”(错误控制台)。
5)Chrome:与 Safari 和 Opera 一样,Chrome 在默认情况下也会隐藏 JavaScript 错误。所有错误都将被记录到Web Inspector 控制台中。要查看错误消息,必须打开 Web Inspector。为此,要单击位于地址栏右侧的“Control this page”(控制当前页)按钮,选择“Developer”(开发人员)、“JavaScript console”(JavaScript控制台)。
2、错误处理
1)try-catch语句
try{
// 可能会导致错误的代码
} catch(error){
// 在错误发生时怎么处理
}
finally语句:虽然在 try-catch 语句中是可选的,但是finally 子句一经使用,其代码无论如何都会执行。只要代码中包含 finally 子句,则无论 try 或 catch 语句块中包含什么代码——甚至 return 语句,都不会阻止 finally 子句的执行。
function testFinally(){
try {
return 2;
} catch (error){
return 1;
} finally {
return 0;
}
}
2)抛出错误:throw操作符,用于随时抛出自定义操作符。抛出错误时,必须要给 throw 操作符指定一个值。
3)error(错误)事件:在任何 Web 浏览器中, onerror 事件处理程序都不会创建 event 对象,但它可以接收三个参数:错误消息、错误所在的 URL 和行号。
4)常见的错误类型
类型转化错误:类型转换错误发生在使用某个操作符,或者使用其他可能会自动转换值的数据类型的语言结构时,在使用相等(==)和不相等(!=)操作符,或者在 if 、 for 及 while 等流控制语句中使用非布尔值时。
数据类型错误:在将预料之外的值传递给函数的情况下,最容易发生数据类型错误。
通信错误:第一种通信错误与格式不正确的 URL 或发送的数据有关。最常见的问题是在将数据发送给服务器之前,没有使用 encodeURIComponent() 对数据进行编码;另外,在服务器响应的数据不正确时,也会发生通信错误。
5)区分致命错误和非致命错误:对于非致命错误,可以根据下列一或多个条件来确定:不影响用户的主要任务;只影响页面的一部分;可以恢复;重复相同操作可以消除错误。对于致命错误,可以根据下列一或多个条件来确定:应用程序根本无法继续运行;错误明显影响到了用户的主要操作;会导致其他连带错误。
6)把错误记录到服务器:要建立这样一种 JavaScript 错误记录系统,首先需要在服务器上创建一个页面(或者一个服务器入口点),用于处理错误数据。这个页面的作用无非就是从查询字符串中取得数据,然后再将数据写入错误日志中。
3、调试技术
1)将消息记录到控制台
2)将消息记录到当前页面
3)抛出错误
4、常见的IE错误
1)操作中止:在修改尚未加载完成的页面时,就会发生操作终止错误。发生错误时,会出现一个模态对话框,告诉你“操作终止。”单击确定(OK)按钮,则卸载整个页面,继而显示一张空白屏幕。要避免这个问题,可以等到目标元素加载完毕后再对它进行操作,或者使用其他操作方法。
2)无效字符:所谓无效字符,就是 JavaScript 语法中未定义的字符。在 JavaScript 文件中存在无效字符时,IE 会抛出无效字符(invalid character)错误。
3)未找到成员错误:IE 中的所有 DOM 对象都是以 COM 对象,而非原生 JavaScript 对象的形式实现的。IE 中的未找到成员(Member not found)错误,就是由于垃圾收集例程配合错误所直接导致的。
4)未知运行时错误:当使用 innerHTML 或 outerHTML 以下列方式指定 HTML 时,就会发生未知运行时错误(Unknown runtime error):一是把块元素插入到行内元素时,二是访问表格任意部分( <table> 、 <tbody> 等)的任意属性时。
5)语法错误:只要 IE 一报告发生了语法错误(syntax error),原因可能是代码中少了一个分号,或者花括号前后不对应。如果引用了外部的 JavaScript 文件,而该文件最终并没有返回 JavaScript 代码,IE 也会抛出语法错误。
6)系统无法找到指定资源:在使用 JavaScript请求某个资源 URL,而该 URL的长度超过了 IE对 URL最长不能超过 2083 个字符的限制时,就会发生这个错误。IE 不仅限制JavaScript 中使用的 URL 的长度,而且也限制用户在浏览器自身中使用的 URL 长度。IE 对 URL路径还有一个不能超过 2048 个字符的限制。
第二十章 JSON
1、语法
1)简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null。但 JSON 不支持 JavaScript 中的特殊值 undefined。JavaScript 字符串与 JSON 字符串的最大区别在于,JSON 字符串必须使用双引号(单引号会导致语法错误)。
2)对象:与 JavaScript 的对象字面量相比,JSON 对象有三个地方不一样。首先,没有声明变量(JSON 中没有变量的概念)。其次,没有末尾的分号(因为这不是 JavaScript 语句,所以不需要分号)。最后,对象的属性必须加双引号,属性的值可以是简单值也可以是复杂类型值。
3)数组:JSON 数组也没有变量和分号。把数组和对象结合起来,可以构成更复杂的数据集合。
2、解析与序列化
1)JSON对象:JSON 对象有两个方法: stringify() 和 parse() 。在最简单的情况下,这两个方法分别用于把JavaScript 对象序列化为 JSON 字符串和把 JSON 字符串解析为原生 JavaScript 值。在序列化 JavaScript 对象时,所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为undefined 的任何属性也都会被跳过。结果中最终都是值为有效 JSON 数据类型的实例属性。
2)序列化选项:
JSON.stringify() 还可以接收另外两个参数,这两个参数用于指定以不同的方式序列化 JavaScript 对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数;第二个参数是一个选项,表示是否在 JSON 字符串中保留缩进。如果过滤器参数是数组,那么 JSON.stringify() 的结果中将只包含数组中列出的属性;如果过滤器参数是函数,传入的函数接收两个参数,属性(键)名和属性值。如果函数返回了undefined ,那么相应的属性会被忽略。JSON.stringify() 方法的第三个参数用于控制结果中的缩进和空白符。如果这个参数是一个数值,那它表示的是每个级别缩进的空格数。
toJSON() 方法用于返回其自身的 JSON 数据格式。假设把一个对象传入 JSON.stringify() ,序列化该对象的顺序如下:
(1) 如果存在 toJSON() 方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
(2) 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
(3) 对第(2)步返回的每个值进行相应的序列化。
(4) 如果提供了第三个参数,执行相应的格式化。
3)解析选项:JSON.parse() 方法也可以接收另一个参数,该参数是一个函数,将在每个键值对儿上调用。如果还原函数返回 undefined ,则表示要从结果中删除相应的键;如果返回其他值,则将该值插入到结果中。