十
DOM
1.节点层次
//每个节点都拥有各自的特点,数据和方法
节点也与其他节点存在关系,节点间的关系构成了层次,
所有的页面标记则表现为一个特定节点为根节点的树形结构
例
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World</p>
</body>
</html>
//在此里中,文档节点只有一个子节点,即<html>元素
我们称之为文档元素。
Node类型
DOM1级定义一个Node接口,js中的所有节点类型都继承自Node
类型,因此所有的节点类型都共享着相同的基本属性和方法。
每个节点都有一个nodeType属性,属于表明节点的类型
节点类型由在Node类型中定义的12个数值常量来表示。
Node.ELEMENT_NODE(1);
Node.ATTRIBUTE_NODE(2);
Node.TEXT_NODE(3);
Node.CDATA_SECTION_NODE(4);
通过比较上面这些常量,可以很容易的确定节点的类型
例
if(someNode.,nodeType==Node.ELEMENT_NODE){//在IE中无效
alert("Node is an element");
}
//若二者相等,则意味着someNode确实是一个元素
if(someNode.nodeType==1){//适用于所有的浏览器
alert("Node is an element");
}
1.nodeName和nodeValue属性
了解节点的具体信息可用,其值完全取决于节点的类型
//检验节点类型
if(someNode.nodeType==1){//适用与所有的浏览器
value=someNode.nodeName;//nodeName的值是元素的标签名
}
//对于元素节点,nodeName中保存的始终都是元素的标签名,而nodeValue的值则始终为Null.
2.节点关系
每个节点都有一个childNodes属性,其中保存这一个NodeList对象,
NodeList是一种类数组对象,用来保存一组有序的节点。
NodeList对象也有length属性,但他不是Array的实例。
//访问保存在NodeList中的节点——可以通过方括号,也可以使用item[]方法。
var firstChild=someNode.childNodes[0];
var secondChild=someNode.childNodes.item[1];
var count=someNode.childNode.length;
//对arguments对象使用Array.prototype.slice[]方法可以将其转换为数组。
//将NodeList对象转换为数组
var arrayOfNodes=Array.prototype.slice.call(someNode.childNodes,0);
在IE8及更早版本中,要想在IE中将NodeList转换为数组,必须手动枚举所有的成员
function convertToArray(nodes){
var array=null;
try{
array=Array.prototype.slice.call(node,0);//针对非IE浏览器
}catch(ex){
array=new Array();
for(var i=0,len=nodes.length;i<len; i++){
array.push(node[i]);
}
}
return array;
}//这也是另一种检测怪癖的形式。
包含在childNodes列表中的所有节点都具有相同的父节点,故其parentNode属性都指向同一节点
使用previousSibling和nextSibling属性,可以访问同一列表中的其他节点。
第一个节点的previousSibling属性值为null,而列表中最后的一个节点的nextSibling属性值也为null
例
if(someNode.nextSibling===null){
alert("Last node in the parent's childNodes list");
}else if(someNode.previousSibling===null){
alert("First node in the parenthildNodes list");
}
父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点
someNode.firstChild的值始终等于someNode.childNodes[0],
someNode.lastChild的值始终等于someNode.childNodes[someNode.childNodes.length-1].
若没有子节点,那么firstChild和lastChild的值均为null。
操作节点
appendChild()方法,用于向childNodes列表的末尾添加一个节点。
添加节点后,childNodes的新增节点,父节点及以前的最后一个节点的关系指针都会得到相应的更新。
例
var returnedNode=someNode.appendChild(newNode);
alert(returnedNode==newNode);//true;
alert(someNode.lastChild==newNode);//true;
//任何DOM节点也不 能同时出现在文档中的多个位置上
故调用appendChild()时传入了父节点的第一个子节点,
则该节点就会成为父节点的最后一个子节点
例
var returnedNode=someNode.appendChild(someNode.firstChild);
alert(returnedNode==someNode.firstChild);//false
alert(returnedNode==someNode.lastChilld);//true;
把节点放在childNodesl列表中某个特定的位置上,而不是放在末尾,那么可以使用
insertBefore()方法,
这个方法接受两个参数:要插入参数的节点和作为参照的节点
插入节点后,被插入的节点会变成参照节点的前一个同胞节点返回。
若参照节点是null,则insertBefore()与appendChild()执行相同的操作。
//插入后成为最后一个子节点
returnedNode=someNode.insertBefore(newNode,null);
alert(newNode==someNode.lastChild);//true
//插入后成为第一个子节点
var returneNode=someNode.insertBefore(newNode,someNode.firstChild);
alert(returnedNode==newNode);//true
alert(newNode==someNode.firstChild);//true
//插入到最后一个子节点前面
returnedNode=someNode.insertBefore(newNode,someNode.lastChild);
alert(newNode==someNode.childNodes(someNode.childNodes.length-2));//true
replaceChild()方法参数是:要插入的节点和要替换的节点
例
//替换第一个子节点
var returnedNode=someNode.replaceChild(newNode,someNode.firstChild);
//替换最后一个节点
returnedNode=someNode.replaceChild(newNode,lastChild);
//通过removeChild()移除的节点仍然为文档所有,只不过在文档中已没有了自己的位置。
4.其他方法
cloneNode(),用于创建调用这个方法的节点的一个完全相同的副本。
cloneNode()方法接受一个布尔值参数,表示是否执行深复制。
在参数为true的情况下,执行深复制。
在参数为false的情况下,执行浅复制。
例如
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
var deepList=myList.cloneNode(true);
alert(deepList.childNode(true));//3(IE<9)的浏览器
var shallowList=myList.cloneNode(false);
alert(shallowList.childNodes.length);//0,浅复制,不包含子节点
Document类型
在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面。
而且,document对象是window对象的一个属性,故可以将其作为全局对象来访问。
文档的子节点
documentElement属性,该属性始终指向HTML页面中的<html>元素。
例
<html>
<body>
</body>
</html>
在这个页面经浏览器解析后,其文档中只包含一个子节点。即<html>元素。可以
通过documentElement属性则能快捷,更直接的访问该元素。
var html=document.documentElement;//取得对<html>的引用
alert([html]===document.childNode[0]);//true;
alert([html]===document.firstChild);//true
document对象还有一个body属性,直接指向<body>元素
用法如下
var body=document.body;//取得对<body>的引用
所有的浏览器都支持document.documentElement和document.body属性。
另一个子节点就是documentType.
//取得对<!DOCTYPE>的引用
var doctype=document.doctype;
文档信息
document对象还有一些属性
1.title包含着<title>元素中的文本
//修改title属性的值不会改变<title>元素
例
//取得文档标题
var originalTitle=document.title;
//设置文档标题
document.title="New page title";
URL属性中包含完整的URL(即地址栏中显示的URL)
domain属性中只包含页面的域名
referrer属性则会保存着链接到当前页面的URL.
例
//取得完整的URL
var url=document.URL;
//取得域名
var domain=document.domain;
//取得来源页面的URL
var referrer=document.referrer;
URL与domain属性是关联的
例如
document.URL等于http://www.wrox.com/WileyCDA/.
document.domain等于www.wrox.com。
如果域名一开始是松散的,那么他就不能在被设置为紧绷的
例
//假设页面来自A2A.wrox.com域
document.domain="wrox.com"//松散的成功
document。domain="A2A.wrox.com"//紧绷的出错
3.查找元素
取得元素的操作
getElementById()和getElementsByTagName().
getElementById()接受一个参数:要取得元素的ID,
若找到相应的元素则返回该元素,否则返回null。
注:ID需与页面中元素的id特性严格匹配,包括大小写
例
<div id="myDiv">Some text</div>
可以使用下面的代码取得这个元素:
var div=document.getElementById("myDiv");//取得<div>元素的引用
getElementByTagName()方法返回一个参数,即要取得元素的标签名
而返回的是包含零或多个元素的NodeList.
例,下面代码会取得页面中的<img>元素,并返回一个HTMLCollection.
var images=document.getElementsByTagName("img");
alert(images.length);//输出图像的数量
alert(images[0].src);//输出第一个图元素的src
alert(images.item(0).src);//输出第一个图元素的src
nameItem()方法,此方法可以通过元素的name特性
取得集合中的项。
例
<img src="myimage.gif" name="myImage">
//通过此方法从images变量中取得这个<img>元素
var myImage=images.namedItem("myImage");
//取得文档中的所有元素
var allElements=document.getElementByTagName("*");
getElementsByName()方法
返回带有给定name特性的所有元素。
例
<fieldset>
<legend>Which color do you prefer?</legend>
<ul>
<li><input type="radio" value="red" name="color"id="colorRed">
<label for="colorRed">Red</label></li>
<li><input type="radio" value="blue" name="color" id="colorGreen">
<label for="colorGreen">Green</label></li>
</ul>
</fiedset>
//所有的name 的特性值都是“color”,但他们的ID可以不同
ID的作用在于将<lable>元素应用到每个单选按钮,而name特性则用于确保三个值中只有一个被发送
给浏览器
var radios=document.getElementsByName("color");//取得所有的单选按钮
4.特殊集合
document.anchors,包含文档中所用带name特性的<a>元素
document.applets,包含文档中所有的<applet>元素,(不建议使用)
document.forms包含文档中所有的<form>元素;
document.images包含文档中所有的<img>元素;
document.links包含文档中所有带href特性的<a>元素;
DOM一致性检测
document.implementation属性为检测浏览器实现了DOM的那些部分提供相应信息和功能的对象
hasFeature()方法
接受两个参数,1要检测的DOM功能的名称 2.版本号
例
var hasXmlDom=document.implemention.hasFeature("XML","1.0");
文档写入
write()和witeIn()方法都接受一个字符串参数,即要写入到输入流的文本
write()会原样写入,而writeln()则会在字符串的末尾添加一个换行符(\n)。
例
<html>
<head>
<title>document.write()Example</title>
</head>
<body>
<p>The current data and time is;
<script type="text/javascript">
document.write("<strong>"+(new Date()).toString()+"</strong>");
</script>
</p>
</body>
</html>
open()方法和close()风别用于打开和关闭网页的输出流。
Element类型
Element类型用于表现XML或HTML元素
提供了对元素签名,子节点,及特性的访问。
要访问元素的标签名,可以使用nodeName属性,也可以使用tagName属性
例
<div id="myDiv"></div>
var div=document.getElementById("myDiv");
alert(div.tagName);//"DIV"
alert(div.tagName==div.nadeName);//true
HTML元素
所有的HTML元素都由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示。
HTMLElement类型直接继承自Element并添加了一些属性
例
<div id="myDiv" class=“bd”title="Body text"lang="en" dir="Itr"></div>
元素中指定的所有信息,都可以通过下列JS代码取得
var div=document.getElementById("myDiv");
alert(div.id);//"myDiv"
alert(div.className);//"bd";
alert(div.title);//"Body text"
alert(div.lang);//"en";
alert(div.dir);//"Itr";
//修改对应的每个特性
div.id="someOtherId";
div.className="ft";
div.title="some other text";
div.lang="fr";
div.dir="rtl";
//对dir的修改会在属性被重写的那一刻,立即应用新的样式
2.取得特性
操作特性的DOM方法主要有三个
getAttribute()、setAttribute()和removeAttribute()
例
var div=document.getElementById("myDiv");
alert(div.getAttribute("id"));//"myDiv"
alert(div.getAttribute("class"));//"bd"
alert(div.getAttribute("title"));//"Body text"
alert(div.getAttribute("lang"));//"en"
alert(div.getAttribute("dir"));//"Itr"
//注,传递给getAttributes()的特性名与实际的特性名相同。故要想得到class特性值
应该传入“class”而不是“className”
getAttribute()方法取得自定义特性
例
<div id="myDiv" my_special_attribute="hello!"></div>
//取得一个名为 my_special_attribute的自定义特性,值是"hello!"
var value=div.getAttribute("my_special_attribute");
只有公认的(非自定义的)特性才会以属性的形式添加到DOM对象中
例
<div id="myDiv" align="left"my_special_attribute="hello!"></div>
id 和align在HTML中是<div>的公认特性,因此该元素的DOM对象中也将存在
对应的属性
设置特性
setAttribute()方法可以接受两个参数
要设置的特性名和值,如果特性已经存在,setAttribute()会以
指定的值替换现有的值,如果特性不存在,setAttribute()则创建
该属性并设置相应的值。
例
div.setAttribute("id","someOtherId");
div.setAttribute("class","ft");
div.setAttribute("title","Some other text");
div.setAttribute("lang","fr");
//注。通过此方法设置的特性名会被统一转换为小写形式
直接给属性赋值可以设置特性的值
div.id="someOtherId";
div.align="left";
//为DOM元素添加一个自定义的属性,该属性不会自动成为元素的特性
div.mycolor="red";
alert(div.getAttribute("mycolor"));//null(IE除外)
attributes属性
每个节点的nodeName就是特性的名称
节点的nodeValue就是特性的值。
var id=element.attributes.getNamedItem("id").nodeValue;
//取得元素的id特性
var
创建元素
使用document.createElement()方法可以创建新元素,此方法只接受一个参数,即创建元素的标签名
var div=document.createElement("div");
为新元素设置了ownerDocument属性,操作元素的特性,为他添加更多的子节点
div.id="myNewDiv";
div.className="box";
//把新创建的元素添加到文档的<body>中
document.body.appendChild(div);
注,一旦将元素添加到文档树中,浏览器就会立即呈现该元素。
为这个方法传入完整的元素标签,也可以包含属性
例
var div=document.createElement("<div id=\"myNewDiv\"class=\"box\"></div>);
元素的子节点
在执行某项操作之前,通常先检查一下nodeType属性
例
for(var i=0,len=element.childNode.length;i<len;i++){
if(element.childNodes[i].nodeType==1){//只在子节点等于一,即是元素节点情况,才会执行
//执行操作
}
}
Text类型
Text节点具有以下特征
nodeType的值为3;
nodeName的值为“#text”;
nodeValue的值为节点所包含的文本
parentNode是一个Element;
不支持(没有)子节点
appendData(text);将text添加到节点的末尾
deleteData(offset,count);从offset指定的位置开始删除count个字符
insertData(offset,text);从offset指定的位置插入text.
replaceData(offset,count,text);用text替换从offset指定的位置开始到offset+count为止处的文本
suplitText(offset);从offset指定的位置将当前文本节点分成两个文本节点。
例
<!--没有内容,也就没有文本节点-->
<div></div>
<!--有空格,因而有一个文本节点-->
<div> </div>//文本节点的nodeValue值是一个空格
<!--有内容,因而有一个文本节点-->
<div>Hello World!</div>//文本节点的nodeValue值是Hello World!
//开始与结束标签之间只要存在内容,就会创建一个文本节点,
可以使用一下节点访问文本子节点
var textNode=div.firstChild;//或者div.childNodes[0]
取得引用后,可以像下面这样修改它
div.firstChild.nodeValue="some other message";
创建文本节点
使用document.createTextNode()创建新文本节点,此方法接受一个参数
例
var textNode=document.createTextNode("<strong>Hello</strong>world!");
创建一个<div>元素并向其中添加一条信息
var element=document.createElement("<div>");
element.className="message";
var textNode=document.createTextNode("Hello World!");
element.appendChild(textNode);
document.body.appendChild(element);
规范化文本节点
normalize()方法:将相邻文本节点合并的方法
(此方法由Node类型定义的,故在所有节点类型中都存在)
若在一个包含两个或多个文本节点的父元素上调用normalize()方法,
则会将所有的文本节点合并成一个节点。
结果节点的nodeValue等于合并前每个文本节点的nodeValue值拼接起来的值。
例
var element=document.createElement("div");
element.className="message";
var textNode=document.createTextNode("Hello World!");
element.appendChild(textNode);
var antherTextNode=document.createTextNode("Yippee!");
element.appendChild(antherTextNode);
document.body.appendChild(element);
alert(element.childNodes.length);//2
element.normalize();
alert(element.childNodes.length);//1
alert(element.firstChild.nodeValue);//"Hello World!Yippee"
分割文本节点
splitText()方法
将一个文本节点分成两个文本节点,即按照指定的位置分隔nodeValue值
这个方法会返回一个新的文本节点,该节点与原节点的parentNode相同
例
var element=document.createElement("div");
element.className="message";
var textNode=document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);
var newNode=element.firstChild.splitText(5);
alert(element.firstChild.nodeValue);//"Hello"
alert(newNode.nodeValue);//"world!"
alert(element.childNodes.length);//2