js高程读书笔记 第十二章 DOM2和DOM3

[TOC]

本章内容

  • DOM2和DOM3的变化
  • 操作样式的DOM API
  • DOM遍历与范围

DOM2 讲解核心、视图、样式、遍历和范围、DOM2级的HTML

事件在下一章

DOM3 XPath、加载与保存模块

DOM变化

以下代码确定是否支持这些DOM模块

1
2
3
4
5
var 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");

命名空间 p308

如createElementsNS(namespaceURI, tageName);

其他方面的变化

DocumentType类型变化

publicId、systemId和internalSubset

Document类型的变化

importNode()可以从文档中取得一个节点,然后将其导入到另一个文档,使其称为这个文档结构的一部分。

每个节点都有一个ownerDocument属性,表示所属的文档。

importNode()方法和Element的cloneNode()相似,接收两个参数:要复制的节点和是否复制子节点的布尔值。返回的结果是原来节点的副本。

defaultView属性保存着一个指针,指向拥有给定文档的窗口。IE和Opera有一个等价的parentWindow属性

1
var parentWindow = document.defaultView || document.parentWindow;

createDocumentType()、createDocument()

document.implementation.createHTMLDocument(“title”);

Node类型的变化

添加了isSupported()方法。

setUserData()方法。

框架的变化

可以通过contentDocument获取框架内容的文档对象。IE8之前不支持,但是有一个contentWindow属性。

1
2
var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

样式

访问元素的样式

支持style特性的HTML元素在JavaScript中都有一个对应的style属性。对于使用短划线的css属性,必须将其转换成驼峰大小写形式。

background-image就转化为style.backgroundImage

其中float是JavaScript的保留字,所以用cssFloat替代

操作样式表

元素大小

1
2
3
4
5
6
7
8
9
10
11
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;

while(current != null){
actualLeft += current.offsetLeft;
current= current.offsetParent;
}

return actuallLeft;
}

客户区大小

客户区大小指的是元素内容及其内边距所占据的空间大小clientWidth和clientHeight。

1
2
3
4
5
6
7
8
9
10
11
12
13
function getViewport(){
if(document.compatMode == "BackCompat"){
return {
width: document.body.clientWidth,
height: document.body.clientHeight
};
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
};
}
}

滚动大小

css设置overflow属性

  • scrollHeight 在没有滚动条的情况下,元素内容的高度
  • scrollWidth 在没有滚动条的情况下,元素内容的总宽度
  • scrollLeft 隐藏在内容区域左侧的像素数
  • scrollTop 隐藏在内容区域上方的像素数

在IE8及以前认为文档左上角坐标是(2,2)

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;

while (current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}

return actualLeft;
}

function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;

while (current !== null){
actualTop += current. offsetTop;
current = current.offsetParent;
}

return actualTop;
}

function getBoundingClientRect(element){

var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;

if (element.getBoundingClientRect){
if (typeof arguments.callee.offset != "number"){
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: actualLeft - scrollLeft,
right: actualLeft + element.offsetWidth - scrollLeft,
top: actualTop - scrollTop,
bottom: actualTop + element.offsetHeight - scrollTop
}
}
}

遍历

NodeIterator和TreeWalker可以对基于给定的起点对DOM结构执行深度优先的遍历操作。

NodeIterator

可以使用document.createNodeIterator()方法创建实例,接收4个参数。

  • root 起点
  • whatToShow 访问哪些节点的数字代码
  • filter NodeFilter对象
  • entityReferenceExpansion boolean值,表示是否要拓展实体引用

下列代码展示了如何创建一个只显示p元素的节点迭代器

1
2
3
4
5
6
7
8
9
var filter = {
acceptNode: function(node){
return node.tagName.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()

范围

DOM中的范围

createRange()方法创建范围。

1
var range = document.createRange();

简单选择

  • selectNode() 选择整个节点
  • selectNodeContents() 选择节点的子节点

以下面的HTML代码为例

1
2
3
4
5
6
<!DOCTYPE html>
<html>
<body>
<p id="p1"><b>Hello</b> world!</p>
</body>
</html>

1
2
3
4
5
var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById("p1");
range1.selectNode(p1);
range2.selectNodeContents(p1);

复杂选择

setStart()和setEnd()方法

1
2
3
4
5
6
<!DOCTYPE html>
<html>
<body>
<p id="p1"><b>Hello</b> world!</p>
</body>
</html>
1
2
3
4
5
6
7
var p1 = document.getElementById("p1");
helloNode = p1.firstChild.firstChild;
worldNode = p1.lastChild;

var range = document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);//空格0 w是1 o是2 l是3

就可以选择从llo到world中的o部分了

操作dom范围里的内容

deleteContents();
范围选区会在修改底层DOM时保证格式良好,执行上面这句以后,被复杂选择的html代码如下。

1
2
3
...
<p><b>He</n> rld!</p>
...

extractContents()

cloneContents()

插入内容

insertNode()可以向范围选区的开始处插入一个节点。

围绕范围插入内容:

1
2
3
4
5
6
7
8
9
10
var p1 = document.getElementById("p1");
helloNode = p1.firstChild.firstChild;
worldNode = p1.lastChild;
range = document.createRange();

range.selectNode(helloNode);

var span = document.createElement("span");
span.style.backgroundColor = "yello";
range.surroundContents(span);

折叠DOM范围

collapse(boolean), true表示折叠到范的起点,false折叠到范围的终点。

清理DOM范围

调用detac()方法,从创建范围的文档中分离出该范围。

总结

  • xml命名空间
  • document实例

DOM2样式

  • 每个元素都有style对象,用来确定和修改行内的样式
  • 计算样式 getComputedStyle()
  • IE中用currentStyle属性
  • document.stytleSheets集合访问样式表

DOM2遍历和范围

  • 遍历使用NodeIterator和TreeWalker
  • 范围是选择DOM结构中特定部分然后再执行相应操作的一种手段。