第12章 DOM2和DOM3
DOM变化
- 可以通过下列代码来确定浏览器是否支持这些DOM模块
1
2
3
4
5var supportsDOM2Core = document.implementation.hasFeature("Core", "2.0");
var supportsDOM3Core = document.implementation.hasFeature("Core", "3.0");
var supportsDom2HTML = document.implementation.hasFeature("HTML", "2.0");
var supportsDOM2Views = document.implementation.hasFeature("Views", "2.0");
var supportsDOM2XML = document.implementation.hasFeature("XML", "2.0");
针对XML命名空间的变化
- HTML不支持XML命名空间,单XHTML支持XML命名空间。
其他方面的变化
DocumentType类型的变化
- DocumentType类型新增了3个属性:publicId、systemId和internalSubset.
- publicId、systemId表示文档类型声明中的两个信息段,在DOM1中无法访问。
Document类型的变化
- Document类型的变化中唯一与命名空间无关的方法是importNode()。
- 用途:从文档中取得一个节点,然后将其导入另一个文档,使其成为文档结构的一部分。
- 注意:每个节点都有一个ownerDocument属性,表示所属文档,如果调动appendChild()是传入的节点属于不同的文档
Node类型的变化
- Node类型中唯一与命名空间无关的变化,为添加了isSupported()方法。与DOM1级document.implementation引入的hasFeature()方法类似。
- isSupported()方法用于确定当前节点具有什么能力,接受两个参数:特性名和特性版本号。
框架的变化
- 框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示,在DOM2中新增contentDocument(包含一个指针,指向表示框架内容的文档对象)
样式
访问元素的样式
- 任何支持style特性的HTML元素在JavaScript中都有一个对应的style属性,这个style对象是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。
- 支持style特性的HTML元素在JavaScript中都有一个对应的style属性。对于使用短划线的css属性,必须将其转换成驼峰大小写形式。
- 多数情况下,都可以通过简单地转化属性名的格式来实现转换。其中一个不能直接转换的CSS属性就是float。
- 由于float是JavaScript中的保留字,因此不能用作属性名。
操作样式表
- insertRule():创建规则。参数:规则文本和表示在哪里插入规则的索引。
- deletRule():删除规则。参数:要删除的规则位置。
元素大小
偏移量:元素在屏幕上占用的所有可见的空间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while(current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actuaLeft;
}
function getElementTop(element){
var actualTop += current.offsetTop;
var current = current.offsetParent;
while (current != null){
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
}客户区大小(client dimension),指的是元素内容及其内边距所占的空间大小。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function getViewport(){
// 检查document.compatMode属性,以确定浏览器是否运行在混杂模式
if (document.compatMode == "BackCompat"){
return(
width: document.body.clientWidth,
height: document.body.clientHeight
);
}else{
return{
//documentElement 属性可返回文档的根节点
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
};
}
}滚动大小: 包含滚动内容的元素的大小。
- scrollHeight 在没有滚动条的情况下,元素内容的高度
- scrollWidth 在没有滚动条的情况下,元素内容的总宽度
- scrollLeft 隐藏在内容区域左侧的像素数
- scrollTop 隐藏在内容区域上方的像素数
在确定文档的总高度时(包括基于视口的最小高度),必须取得scrollWidth/clientWidth和scrollHeight/clientHeight中的最大值,才能保证在跨浏览器的环境下得到精确的结果:
1
2
3
4//对于运行在混杂模式下的IE,则需要用document.body代替document.documentElement
var docHeight = Math.max(document.documentElement.scrollHeight, documentElement.clientHeight);
var docWidth = Math.max(document.documentElement.scrollWidth, documentElement.clientWidth);确定元素大小,在IE8及以前认为文档左上角坐标是(2,2),其他浏览器包括IE9则将传统的(0,0)作为起点坐标。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36function getBoundingClientRect(element){
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
if(element.getBoundingClientRect(element)){
var temp = document.createElement("div");
temp.style.cssText = "position:absolute; left:0; top:0;";
document.body.appendChild("temp");
arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;
document.body.removeChild(temp);
temp = null;
}
var rect = element.getBoundingClientRect();
var offset = arguments.callee.offset;
return(
left: rect.left + offset,
right: rect.right + offset,
top: rect.top + offset,
bottom: rect.bottom + offset,
);
}else{
var actualLeft = getElementLeft(element);
var actualTop = getElementTop(element);
return{
left: aotualLeft - scrollLeft,
right: actualLeft + element.offsetWidth - scrollLeft,
top: actualTop - scrollTop,
bottom: actualTop + element.offsetHeight - scrollTop
}
}
遍历
- NodeIterator(迭代节点)和TreeWalker;这两个类型能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作。
NodeIterator
- 可以使用document.createNodeIterator()方法创建新的实例,接收4个参数。
- root:想要作为搜索起点的树中的节点
- whatToShow:表示要访问哪些节点的数字代码
- filter:是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数
- entityRefrenceExpansion:布尔值,表示是否要扩展实体引用。在HTML页面中没用,因为其中的实体引用不能扩展。
- 如何创建一个只显示p元素的节点迭代器
1
2
3
4
5
6
7
8var filter = {acceptNode: function(){
return node.tageName.toLowerCase() == "p"?
NodeFilter.FILTER_ACCEPT:
NodeFilter.FILTER_SKIP;
}
};
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);
TreeWalker
- 比NodeIterator更高级的版本。除了nextNode()和previousNode()在内的相同功能之外还提供其他方法。
- parentNode():遍历到当前节点的父节点;
- firstChild():遍历当前节点的第一个子节点;
- lastChild():遍历当前节点的最后一个子节点;
- nextSibling():遍历当前节点的下一个同辈节点;
- previousSibling():遍历当前节点的上一个同辈节点;
- TreeWalker真正强大的地方在于能够在DOM结构中沿任何方向移动,即使不使用过滤器也可以得到想要的元素.
范围
DOM中的范围
- createRange()方法创建范围。
var range = document.createRange();
简单选择
- selectNode() 选择整个节点
- selectNodeContents() 选择节点的子节点
复杂选择
- setStart()和setEnd()方法:接受两个参数,一个是参照节点,一个是偏移量
操作DOM范围中的内容
- deleteContents(),删除范围中的内容。调用方式:range.deleteContents();
- extractContents(),从文档区域移除范围的内容,返回范围内容的文档片段,可以对文档片段进行进一步操作,调用方式:
var fragment=range.extractContents();
- cloneContents(),创建一个文档片段,保存范围的副本,可以对文档片段进行进一步操作,调用方式:
var fragment=range.cloneContents();
插入DOM范围中的内容
- 除了向范围内部插入内容之外,还可以环绕范围插入内容,此时要使用surroundContents()方法。这个方法接收一个参数,即环绕范围内容的节点。
折叠DOM范围
- 范围折叠就是指范围中未选择文档的任何部分。通俗的描述就是当你选择范围内的文本,点击左键的时候,光标会落在范围的开始或者范围的结束。
- 使用collapse()进行折叠,接收一个参数,一个布尔值,表示要折叠到范围的那一端,true表示范围的起点,false表示范围的终点。要确定范围已经折叠外币,可以用collapsed属性检查。
比较DOM的范围
- 在有多个范围的情况下,可以使用compareBoundaryPoints()方法来确定这些范围是否有公共边界。
- 这个方法接收两个参数:比较方式的常量值和要比较的范围。
复制DOM的范围
- 可以使用cloneRange()方法复制范围,返回范围的一个副本
var newRange=range.cloneRange();
清理DOM范围
- 在使用完范围之后,最好调用detach()方法,清理范围,回收内存.
range.detach();// 从文档中分离
range=null;// 解除引用