1.文档信息
作为HTML Document的一个实例,document对象还有一些标准的Document对象所没有的属性。
URL属性中包含页面完整的URL(即地址栏中显示的URL),domain属性中只包含页面的域名,而referrer属性中则保存着链接到当前页面的URL。
URL与domain属性时相互关联的。例如,如果document.URL等于http://www.wrox.com/WileyCDA/,那么document.domain就等于www.wrox.com。
在这三个属性中,只有domain是可以设置的。但由于安全方面的限制,也并非可以给domain设置任何值。如果URL中只包含一个子域名,例如p2p.wrox.com,那么就只能将domain设置为“wrox.com”,不能将这个属性设置为URL中不包含的域。
浏览器对domain属性还有一个限制,即如果域名一开始是“松散的”(loose),那么不能将它再设置为“紧绷的”(tight)。即,在将document.domain设置为“wrox.com”之后,就不能再将其设置回“p2p.wrox.com”,否则将会导致错误。
2.特殊集合
除了属性和方法,document对象还有一些特殊的集合。这些集合都是HTML Collection对象,为访问文档常用的部分提供了快捷方式。
document.anchors,包含文档中所有带有name特性的```<a>```元素;
document.links,包含文档中所有带有href特性的```<a>```元素
3.Element类型
<div id="myDiv"></div>
可以像下面这样获取这个元素及其标签名:
var div=document.getElementById("myDiv");
alert(div.tagName);//"DIV"
alert(div.tagName==div.nodeName);//true
这里的元素标签名是div,它拥有一个值为"myDiv"的ID,可是div.tagName实际上输出的是“DIV”而非“div”。在HTML中,标签名始终都以全部大写表示;而在XML(有时候也包括XHTML)中,标签名则始终会与源代码中的保存一致。最好是在比较之前将标签名转换为相同的大小写形式,如下面的例子所示:
if(element.tagName=="div"){
// 不能这样比较,很容易出错!
// 在此执行某些操作
}
if(element.tagName.toLowerCase()=="div"){
// 这样最好(适用于任何文档)
// 在此执行某些操作
}
4.HTML元素
所有HTML元素都由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型表示。HTMLElement类型直接继承自Element并添加了一些属性。添加的这些属性分别对应于每个HTML元素中都存在的下列标准特性。
id,元素在文档中的唯一标识符
title,有关元素的附加说明信息,一般通过工具提示条显示出来
lang,元素内容的语言代码,很少使用
className,与元素的class特性对应,即为元素指定的CSS类。没有将这个属性命名为class,是因为class是ES的保留字
5.取得特性
操作特性的DOM方法主要有三个,分别是getAttribute()、setAttribute()和removeAttribute()。
var div=document.getElementById("myDiv");
alert(div.getAttribute("id"));//"myDiv"
alert(div.getAttribute("class"));//"bd"
alert(div.getAttribute("title"));//"bodeText"
alert(div.getAttribute("lang"));//"en"
alert(div.getAttribute("dir"));//"ltr"
注意,传递给getAttribute()的特性名与实际的特性名相同。因此要想得到class特性值,应该传入“class”而不是“className”,后者只有在通过对象属性访问特性时才有用。如果给定名称的特性不存在,getAttribute()返回null。
有两类特殊的特性,它们虽然有对应的属性名,但属性的值与通过getAttribute()返回的值并不相同。第一类就是style,用于通过CSS为元素指定样式。在通过getAttribute()访问时,返回的style特性值中包含的是CSS文本,而通过属性来访问它则会返回一个对象。由于style属性是用于以编程方式访问元素样式的,因此并没有直接映射到style特性。
第二类与众不同的特性是onclick这样的事件处理程序。当在元素上使用时,onclick特性中包含的是JS代码,如果通过getAttribute()访问,则会返回相应代码的字符串。而在访问onclick属性时,则会返回一个JS函数(如果未在元素中指定相应特性,则返回null)。这是因为onclick及其他事件处理程序属性本身就应该赋予函数值。
由于存在这些差别,在通过JS以编程方式操作DOM时,开发人员经常不使用getAttribute(),而是只使用对象的属性。只有在取得自定义特性值的情况下,才会使用getAttribute()方法。
6.事件流
事件流描述的是从页面接受事件的顺序。IE和Netscape开发团队提出了完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获流。
事件冒泡:
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
事件捕获:
NetScape Communicator团队提出的另一种事件流叫做事件捕获。事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于事件达到预定目标之前捕获它。
DOM事件流:
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截取事件提供了机会,然后是实际的目标接收到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。
7.事件处理程序
事件就是用户或浏览器自身执行的某种动作。诸如click、load和mouseover,都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。事件处理程序的名字以“on”开头,因此click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。为事件指定处理程序的方式有好几种。
HTML事件处理程序:
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JS代码。
<input type="button" value="Click Me" onclick="alert('Clicked')"/>
当单机这个按钮时,就会显示一个警告框。这个操作是通过指定onclick特性并将一些JS代码作为它的值来定义的。由于这个值是JS,因此不能在其中使用未经转义的HTML字符,例如和好(&)、双引号("")、小于号(<)或大于号(>)。为了避免使用HTML实体,这里使用了单引号。如果想要使用双引号,那么就要将代码改写成如下所示:
<input type="button" value="Click Me" onclick="alert("Clicked")"/>
在HTML中指定事件处理程序有两个缺点。首先,存在一个时差问题。因为用户可能在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。
另一个缺点是,**这样扩展事件处理程序的作用域链在不同浏览器会导致不同结果。**不同JS引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。
DOM0级事件处理程序:
通过JS指定事件处理程序的传统方式,就是讲一个函数赋值给一个事件处理程序属性。要使用JS指定事件处理程序,首先必须取得一个要操作的对象的引用。
在每个元素(包括window和document)都有自己的事件处理程序属性,这些属性通常全部小写,例如onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序。
var btn=document.getElementById("myBtn");
btn.onclick=function(){
alert("Clicked");
};
使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的this引用当前元素。
var btn=document.getElementById("myBtn");
btn.onclick=function(){
alert(this.id);//"myBtn"
};
实际上,可以在事件处理程序中通过this访问元素的任何属性和方法。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。
也可以删除通过DOM0级方法指定的事件处理程序,只要像下面这样将事件处理程序属性的值设置为null即可:
btn.onclick=null;//删除事件处理程序
DOM2级事件处理程序:
“DOM2级事件”定义了两个方法用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
var btn=document.getElementById("myBtn");
btn.addEvebtListener("click",function(){
alert(this.id);
},false);
与DOM0级方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。
var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert(this.id);
},false);
btn.addEventListener("click",function(){
alert("Hello world!");
},false);
这里为按钮添加了两个事件处理程序,这两个事件处理程序会按照添加它们的顺序触发,因此首先会显示元素的ID,其次会显示“Hello world!”消息。
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除是传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除。
var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert(this.id);
},false);
// 这里省略了其他代码
btn.removeEventListener("click",function(){
// 没有用!
alert(this.id);
},false);
在这个例子中,使用addEventListener()添加了一个事件处理程序。虽然调用removeEventListener()是看似使用了相同的参数,但实际上,第二个参数与传入addEventListener()中的那一个是完全不同的函数。
var btn=document.getElementById("myBtn");
var handler=function(){
alert(this.id);
};
btn.addEventListener("click",handler,false);
// 这里省略了其他代码
btn.removeEventListener("click",handler,false);// 有效
IE事件处理程序:
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8及更早版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert("Clicked");
});
注意,attachEvent()的第一个参数是“onclick”,而非DOM的addEventListener()方法中的“click”。
在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。在DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window。
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert(this===window);//true
});
在编写跨浏览器的代码时,牢记这一区别非常重要。
与addEventListener()类似,attachEvent()方法也可以用来为一个元素添加多个事件处理程序。
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert("Clicked");
});
btn.attachEvent("onclick",function(){
alert("Hello world!");
});
这里调用了两次attachEvent(),为同一个按钮添加了两个不同的事件处理程序。不过,与DOM方法不同的是,这些事件处理程序不是以添加它们的顺序这些,而是以相反的顺序被触发。单击这个例子中的按钮,首先看到的是“Hello world!”,然后才是“Clicked”。
使用attachEvent()添加的事件可以通过detachEvent()来移除,条件是必须提供相同的参数。与DOM方法一样,这也意味着添加的匿名函数将不能被移除。
跨浏览器的事件处理程序
8.事件对象
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。
DOM中的事件对象:
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。
var btn=document.getElementById("myBtn");
btn.onclick=function(event){
alert(event.type);//"click"
};
btn.addEventListener("click",function(event){
alert(event.type);//"click"
},false);
在通过HTML特性指定事件处理程序时,变量event中保存着对象。
<input type="button" value="Click Me" onclick="alert(event.type)" />
在事件处理程序内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素,则this.currentTarget和target包含相同的值。
var btn=document.getElementById("myBtn")