客户端javascript
1.浏览器中的Javascript
1.1 BOM
window对象是整个BOM的核心
1.1.1 window对象
window对象代表整个浏览器窗口。如果使用框架集合,每个框架(帧)都由它自己的window对象表示,存放在frames集合中。可以用window.frames[0]或window.frames[“topFrame”]引用框架(帧).
top对象始终指向的都是最顶层的(最外层的)框架,即浏览器窗口自身。如果页面上没有框架那么top与window和self是等价的。而window和self始终是等价的。
每个窗口还含有一个parent属性,它引用包含这个窗口的父Window对象,这样,窗口中的第一个框架(帧)就可以引用它的兄弟框架(帧)(即窗口的第二个帧),如:parent.frames[1];
由于window是整个BOM的中心,所以在使用函数,对象或集合时,可以直接使用这些,而不必指定window对象,如,window.framees[0],可以写成frames[0].。如果一个窗口是一个顶级窗口,而不是帧,那么parent属性引用的就是这个窗口本身。如:parent==self.
框架(帧)之间的引用关系,参考JS权威指南P295.
1.窗口操作
moveBy(dx,dy)(相对当前位置移动浏览器窗口的距离,水平dx,垂直dy)
moveTo(x,y)(绝对移动浏览器窗口位置,使它的左上角位于(x,y)处。
resizeBy(dw,dh)(相对于浏览器窗口的当前大小,调用它的宽度和高度,dw,dh
resizeTo(w,h) (绝对调整浏览器窗口大小,宽度为w,高度为h.)
IE中用window.screenLeft和window。screenTop来判断窗口的位置,用document.body.offsetWidth和document.body.offsetHeight属性可以获取视口的大小(显示HTML的区域)
Mozilla用window.screenX和window.screenY判断窗口的位置。用window.innerWidth和window.innerHeight属性来判断视口的大小,用window.outerWidth和window.outerHeight属性判断浏览器窗口自身的大小。
2.导航和打开新窗口
window.open()方法打开新窗口,它接受四个参数,即要载入的新URL、新窗口的名字、特性字符串和说明是否有新载入的页面替换当前载入的页面的Boolean值.
特性字符串:
left 新建窗口的左坐标,不能为负数
top 新建窗口的上坐标,不能为负数
height 新建窗口的高度,不能小于100
width 新建窗口的宽度,不能小于100
resizable 判断新建窗口是否能改变大小,默认值为no
scrollable 判断新建窗口是否允许滚动,默认为值no
toolbar 判断窗口是否显示工具栏,默认值为no
status 判断窗口是否显示状态栏,默认值为no
location 判断窗口是否显示WEB地址样,默认为no
特性字符串用逗号分隔,且在逗号或等号前后不能有空格。
test=window.open(“http://www.wrox.com/”,”wroxwindow”,”height=150,width=300”);
window.open方法返回新打开窗口的window对象。
关闭新打开的窗口,test.close();
新窗口有对打开它的窗口的引用,存放在opener属性中,只在新窗口中的最顶层window对象才有opener属性,。
3.系统对话框
prompt和confirm、alert对话框。
confirm此对话框返回一个布尔值。根据点击对话框上的ok或cancel来返回不同的布尔值 。
prompt这是一个在对话框中输入某些信息,点击ok这个对话框会把输入的文本值作为函数值返回;点击cancel会返回一个null.。
4.状态栏(一般不对此操作)
5.时间间隔和暂停
window对象的setTimeout()方法设置暂停,它有两个参数,第一个是要执行的代码和第二个是在执行它之前要等待的毫秒数。第一个参数可以是字符串或函数指针。
setTimeout(“alert(‘bb’)”,1000);
或
function hello() { alert(“ok”);}
setTimeout(hello,1000);
调用setTimeout时,它创建一个暂停ID,与操作系统中的进程ID相似,暂停ID本质上是要延迟的进程的ID。要取消还未执行的暂停,可调用clearTimeout方法,并将暂停ID传递给它。
var id=setTimeout(“alert(‘ok’)”,1000);
clearTimeout(id);
setInterval方法使用与setTimeout方法相似。只是它无限次的每隔一段时间重复执行指定的代码。
var id=setInterval(“alert(‘ok’)”,1000);//它也有时间间隔ID
clearInterval(id);//用时间间隔ID消除
6.历史
go()方法有一个参数指定前进后退的页数。
后退一页用下面的代码:
history.go(-1);或history.back();
前进一页
history.go(1);或history.forward();
1.1.2document对象
此对象是window的一个属性,它是唯一个既于BOM又属性DOM的对象。
它的属性:
title(可读写) <title>标签中显示的文本
referer(只读) 浏览器中后退一个位置的URL
Url(只读) 当前URL
集合:
anchors[] 所有锚的集合
applets[]
embeds[]
forms[] 所有表单集合
images[] 所有图像集合
links[] 所有超链接集合
使用:
document.links[0]或document.links[“linMy”]
还有write和writeln方法。
1.1.3location对象
此对象表示载入窗口的URL,它是window和document对象的属性。这可以解析URL
location.href属性和document.URL属性相似也是可读写的。
location.href=”www.wrox.com”;//改变属性的值导航到新页面
location.assign()方法实现的相同的操作。
使用这种方式导航,新地址会加到浏览器的历史栈中。
location.replace()这个方法也是导航的方法,不过它会把浏览器历史中删除包含脚本的页面,这样就不能通过浏览器的Back和Forward的按钮访问它了。
reload()方法重载当前页面。此方法有一个布尔参数,如果为true,则从服务器端载入,若为false则从缓存中载入。
1.1.4navigator对象
这个对象包含大量web浏览器的信息。
1.1.5screen对象
这个对象表示客户的屏幕信息。
availHeight 窗口可以使用的屏幕高度,排除像工具栏的空间
availWidth 同上,只是宽度
widht 整个屏幕宽度
height 整个屏幕高度
2.DOM基础
2.1什么是DOM
2.1.1节点的层次(核心DOM)
DOM是针对XML的基于树的API,也即DOM和具体语言(JAVA和JS和C#等)是无关的API。DOM定义了Node接口以及许多种节点类型来表示XML节点的多个方面:
Document―最顶层的节点,所有其它节点都是附属于它的。
DocumentType―DTD对象表现形式<!DOCTYPE 。。。。>不包含节点
DocumentFragment―像Document一样保存其它节点
Element―表示起始标签和结束标签之间的内容。它是唯一同时包含属性和子节点的节点类型。
Attr―代表一对属性名和属性值。此节点不包含子节点
Text―代表XML文档中的在起始标签和结束标签之间,或者CdataSection内包含的普通文本。不能包含子节点。
CdataSection--<![CDATA[]]>的对象表现形式。此节点仅能包含文本节点Text为子节点。
Entity―表示在DTD中的一个实体定义。如<!ENTITY foo “foo”>,不包含子节点。
EntityReference―代表一个实体引用,如".不包含子节点。
ProcessingInstruction―代表一个PI。不包含子节点
Comment―代表XML注释。不包含子节点。
Notation―代表在DTD中定义的记号。用得少。
Node接口定义了对应不同节点类型的12个常量。
Node.ELEMENT_NODE 值 1以下相同
Node.ATTRIBUTE_NODE 2
Node.TEXT_NODE 3
Node.CDATA_SECTION_NODE 4
Node.ENTITY_REFERENCE_NODE 5
Node.ENTITY_NODE 6
Node.PROCESSING_INSTRUCTION 7
Node.COMMENT_NODE 8
Node.DOCUMENT_NODE 9
Node.DOCUMENT_TYPE_NODE 10
Node.DOCUMENT_FRAGMENT_NODE 11
Node.NOTATION_NODE 12
Node接口定义了一些所有类型节点包含的特性和方法。如下:
特性/方法 类型/返回类型 说明(一看就明)
nodeName string
nodeValue string
nodeType Number
ownerDocument Document
firstChild node
lastChild node
childNodes NodeList
previousSibling node
nextSibling node
parentNode Node
hasChildNodes() Boolean
attributes NamedNodeMap
appendChild(node) Node
removeChild(node) Node
replaceChild(newnode,oldnode) Node
insertBefore(newnode,refnode) Node
NodeList―节点数组,按照数值进行索引。
NameNodeMap―同时用数值和名字进行索引的节点表。
2.1.2特定语言的DOM
还针对XHTML和HTML的DOM。这个DOM为HTMLDocument和HTMLElement。每个HTML元素通过它的HTMLElement类型来表示。如HTMLDIVElement代表了<div>,但有少数元素除外,它们只包含HTMLElement提供的属性和方法。
上面就是一个接口继承图,每个接口对应一种节点类型。
Node是根接口,那12种类型都有相应的接口,也即每个节点对象实现了一种子接口。这些接口的属性和方法是继承的,因此使用子接口对象时可以使用父接口的所有属性和方法,这里主要是针对Element,HTMLElement及其标记接口。
2.1.3遗留DOM的元素访问
命名Document对象
<form name=”f1”></form>
访问方式
document.forms[0],document.forms[“f1”],document.forms.f1;
实际上,设置一个<form>,<img>等的name属性也使得相应的form,image对象可以作为文档对象自身的一个有名字的属性被访问。可以这样使用
document.f1
也可以给一个表单中的元素给定名字。
如:
<form name=”shipping”>
<input name=”zipcode” type=”text”>
</form>
可以这样访问input元素:
document.shipping.zipcode
2.2对DOM的支持
IE对level 1实现不完全。
2.3使用DOM
2.3.1访问相关节点
要访问html元素,用document的documentElement属性。
访问body元素用document.body属性
2.3.3处理特性
只有Element节点才有属性,此节点attributes属性其实是NamedNodeMap.它有如下方法:
getNamedItem(name)―nodeName属性等于name的节点
removeNamedItem(name)--
setNamedItem(node)―
item(pos)--
这些方法都是返回一个Attr节点,而非特性值。
如:
<p style=”color:red” id=”p1”>Hello Word</p>
var sId=oP.attributes.getNamedItem(“id”).nodeValue;
var sId=oP.attributes.item(1).nodeValue;
或
oP.attributes.item(1).nodeValue=”newId”;
Element接口定义了几个更简洁的方法来访问属性:
getAttribute(name)―
setAttribute(name,newvalue)―
removeAttribute(name)―
2.3.4访问指定节点
1.getElementByTagName()此方法返回一个NodeList数组
2.getElementByName()此方法返回一个NodeList数组
3.getElementById()返回一个Node节点
2.3.5创建和操作节点
1.创建新节点
document对象常用方法createDocumentFragment(),createElement()和createTextNode()。
2.4HTML DOM特性功能
2.4.1让特性像属性一样
在HTML DOM中,可以使用元素的特性作为节点的属性来使用:
oImg.src;
oImg.border=”1”等
唯一特性名和发展名不一样的是class特性,它在JS代码中用className作为属性名。oDiv.className.
2.4.2HTML命名规则
首先HTML是不区分大小写的,但是JS区分。HTML专有的接口的属性应该以小写字母开头。如果属性名由多个单词构成,第二个单词以及接下来的每个单词的首字母都要大写。
当html属性名和JS关键字发生冲突时,就在属性前加前缀”html”来避免。如<label>标记的属性for将被转换成HTMLLabelElement属性的htmlFor。
2.4.3innerHTML属性
它是HTMLElement接口的属性,相应的属性outerHTML,innerText,outerText
2.5IE 4 DOM中的特有属性
2.5.1搜索文档元素
document对象和所有文档元素都有属性all[]。这个数组表示文档中的所有元素或元素中包含的所有元素。注意,all[]不只表示文档或元素的子节点,它表示所有子孙,无论它们嵌套得多深。
all[]数组有几种使用方法,用整数n做下标,下标以0开始;还可以用名称字符串用做下标。用名称字符串时,IE4将返回id属性或name属性具有指定值的元素,如果这样的一个元素不止一个,结果就是这些元素的数组。
var specialPara=document.all[“special”];
JS还允许把数组下标表示为属性名:
var specialPara=document.all.special;
var buttons=document.all.shippingMethod;
以这种方式使用all[]数组可以提供与getElementById()和getElementByName()一样的功能。主要差别all[]数组将这两种方法的功能合并起来,如果无意中使不相关的id属性和name属性使用了相同的值,就会引发问题。
3.事件
3.1事件流
3.1.1冒泡型事件
IE中使用冒泡事件,某个事件是从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。换句话说当你在页面的某个元素上触了某个事件后,那么其父乃至祖宗都会响应这个事件。例如:
<body onclick="handleClick();">
inner3
<div onclick="handleClick();">
inner2
<div onclick="handleClick();">inner1</div>
</div>
</body>
当点击inner1这个块元素后,其上的所有onclick事件都会响应。
IE6.0中向上冒泡会上升到html元素。
而在Mozilla中事件到上升到window对象。
3.1.2捕获型事件
Netscape Naviagator用的捕获型事件。
3.1.3DOM事件流
DOM同时支持两种事件流。但是捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在doucument对象结束(大部分兼容标准的浏览器会继续将事件的捕获/冒泡延续至window对象)。
DOM事件模型最独特的性质是,文本节点也触发事件(IE中不会)。
3.2事件处理函数/监听函数(一回事)
在JS代码中分配事件处理函数如下:
var oDiv=document.getElementById(“div1”);
oDiv. alert(“I was clicks”);}
用这个分配方法,事件处理函数名称必须小写,才能正确响应事件。
在HTML中分配事件处理函数时,记住特性值中的代码(双引号之间的)是被包装在匿名函数中的,所以HTML代码实际上是执行了JS代码。例:
<div was clicked’)”></div>类似下面代码
oDiv. alert(“I was clicked”);}
3.2.1IE
IE中,每个元素和window对象都有两个方法:attachEvent()和detachEvent()。这两个方法来附加事件处理函数和解除事件处理函数。
var oDiv=document.getElementById(“div”);
oDiv.attachEvnet(“onclick”,fnclick);//第一个参数是事件类型,第二个是事件处理函数
这样可以为一个元素添加多个事件处理函数,事件处理函数总是按照添加的顺序进行调用。
3.2.2DOM
DOM方法用addEventListener()和removerEventListerner()方法来分配和和解除事件处理函数。每个对象和window对象中也有这两方法。
这两个方法多个一个参数是用来判断是用在什么阶段,如果事件处理函数是用于捕获阶段,第三个参数为true;如果事件处理函数用在冒泡阶段,则为false。
例:
oDiv. addEventListener (“click”,fnclick,false)//注意这里事件处理句柄没有加on前缀
如果使用addEventListener()将事件处理函数加入到捕获阶段,则必须在removerEventListerner()中指明是捕获阶段。否则和解除不会成功。
如果使用传统方法直接给JS事件属性赋值,事件处理函数被添加到事件的冒泡阶段。
一个元素添加多个事件处理函数,DOM标准不确定调用一个对象的事件处理函数的顺序,所以不应该认为它们以注册的顺序调用。如果在同一个元素上多次注册了同个处理函数,那么第一次注册后的所有注册都将被忽略。
IE中的attachEvent()和detachEvent()与addEventListener()和removeEventListener()方法和区别:
1.只是由于IE事件模型不支持事件捕捉,IE中的分配函数少一个参数
2.传递给IE方法的事件句柄应该包括一个”on”前缀。而DOM方法没有”on”前缀。
3.用attachEvent()注册的函数将被作为全局函数调用,而不是作为发生事件的文档元素的方法。也就是说,在attachEvent()注册的事件句柄执行时,关键字this引用的是Window对象,而不是事件的目标元素。
4.attachEvent()允许同一个事件处理函数注册多次。当指定类型的一个事件发生的时候,注册函数被调用的次数和它被注册的次数一样多。而DOM却不行,重复注册的会被忽略掉。
3.3事件对象
事件对象只在发生事件时才被创建,且只有事件处理函数才能访问,所有事件处理函数执行完毕后,事件对象就被销毁。
3.3.1定位
IE中,事件对象是window对象的一个属性event,也即在处理函数中必须这样访问对象:
oDiv. var oEvent=window.event;}
DOM标准,event对象必须作为唯一的参数传递给事件处理函数。例:
oDiv. var oEvent=arguments[0];}
或
oDiv. ……..}//有唯一的参数
还可以在HTML事件处理函数中把event这个对象作为函数参数。这在任何浏览器中都是可行的,因为一旦发生事件,就会创建event对象,且这时是一个全局对象。
<input type=”button” onclick=”handleClick(event)”/>
3.3.2属性/方法
IE和DOM中的事件对象(event)的属性和方法。这去参考资料。
3.4事件的类型
click,dbclick,mousedown,mouseup,mouseover,mousemove,mouseout
3.4.1鼠标事件
可以在HTML事件处理函数中直接使用this关键字,如:
<img src=”image1.gif” onmouseover=”"http://blog.51cto.com/viewpic.php?refimg=" + this.src=’image2.gif’”/>
原因:事件处理函数会被认为是分配给对象的方法,于是,可以用this来访问事件对象。
1.事件的属性
每个鼠标事件都会给以下event对象的属性填入值
坐标属性(clientX,clientY等);
type
target或srcElement
shiftKey,ctrlKey,altKey和metaKey属性
button属性
2.顺序
发生dbclick
mousedown
mouseup
click
mousedown
mouseup
click
dbclick
3.4.2键盘事件
keydown―只要按下就发生
keyup―只要放开就发生
keypress―产生字符才发生
1.事件的属性
keyCode属性
charCode属性
target或srcElement属性
shiftKey,ctrlKey,altKey和metaKey属性
3.5HTML事件
load,unload,abort,error,select,change,submit,reset,resize,scroll,focus,blur事件。
像load等事件最好分配给window对象。因为它本身有onload,onblur,onunload,onerror,onresize,onscroll事件。
3.6事件句柄作用域
在把一个HTML属性的值设置为JS代码串,以便定义事件够本时,隐式地下定义了一个函数。在这种方式定义的事件处理处理函数的作用域和用常规方法定义的全局JS的函数不同。
常规全局函数的作用域链,链头为调用对象,接着是全局对象。而HTML属性定义的事件句柄的事件处理函数它的链头也是调用对象,但是接下来的对象不是全局对象,而是触发事件句柄的对象。例:假定使用<input>标记在HMTL表单中定义了一个Button对象,然后用了onclick属性定义了一个事件句柄。如果该事件句柄的代码使用了一个form的变量,那么该变量就会被解析为Button对象的form属性。代码如下:
<form>
<input id=”b1” type=”button” value=”buton1”
onclick=”alert(this.form.b2.value);”>
<input id=”b2” type=”button” value=”buton2”
onclick=”alert(form.b1.value);”>
<input id=”b3” type=”button” value=”buton3”
onclick=”alert(b4.value);”>
<input id=”b4” type=”button” value=”buton4”
onclick=”alert(getElementById(‘b3’).value);”>
</form>
上面的后面两个例子有点复杂,不用深入理解。一般来说,在HTML属性的事件句柄只调用别的地方的全局函数。
记住:关于事件句柄作用域的完整讨论只适用于定义为HTML属性的事件句柄。如果把一个函数赋予适当的JS属性来设置事件句柄,那么根本不会有特殊的作用域链。