《Javascript 高级程序设计(第三版)》笔记0x15 DOM2和DOM3:遍历、范围

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/funkstill/article/details/85034990

目录

遍历

    NodeIterator

     TreeWalker

范围

    DOM中的范围

        用 DOM 范围实现简单选择

        用 DOM 范围实现复杂选择

        操作 DOM 范围中的内容

         插入 DOM 范围中的内容

        折叠 DOM 范围

扫描二维码关注公众号,回复: 4547845 查看本文章

        比较 DOM 范围

         复制 DOM 范围

        清理 DOM 范围


遍历

        “DOM2 级遍历和范围”模块定义了两个用于辅助完成顺序遍历 DOM 结构的类型: NodeIterator和 TreeWalker。这两个类型能够基于给定的起点对 DOM 结构执行深度优先(depth-first)的遍历操作。在与 DOM 兼容的浏览器中(Firefox 1 及更高版本、 Safari 1.3 及更高版本、 Opera 7.6 及更高版本、 Chrome0.2 及更高版本),都可以访问到这些类型的对象。 IE 不支持 DOM 遍历。

var supportsTraversals = document.implementation.hasFeature("Traversal", "2.0");
var supportsNodeIterator = (typeof document.createNodeIterator == "function");
var supportsTreeWalker = (typeof document.createTreeWalker == "function");

<!DOCTYPE html>
<html>
	<head>
		<title>Example</title>
	</head>
	<body>
		<p><b>Hello</b> world!</p>
	</body>
</html>
以 document 为根节点的 DOM 树进行深度优先遍历的先后顺序

    NodeIterator

    NodeIterator 类型是两者中比较简单的一个,可以使用 document.createNodeIterator()方法创建它的新实例。这个方法接受下列 4 个参数。
    root:想要作为搜索起点的树中的节点。
    whatToShow:表示要访问哪些节点的数字代码。whatToShow 参数是一个位掩码,通过应用一或多个过滤器(filter)来确定要访问哪些节点。
    filter:是一个 NodeFilter 对象,或者一个表示应该接受还是拒绝某种特定节点的函数。
    entityReferenceExpansion:布尔值,表示是否要扩展实体引用。这个参数在 HTML 页面中没有用,因为其中的实体引用不能扩展。

//创建一个只显示<p>元素的节点迭代器
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);

//第三个参数也可以是一个与 acceptNode()方法类似的函数
var filter = function(node){
	return node.tagName.toLowerCase() == "p" ?
	NodeFilter.FILTER_ACCEPT :
	NodeFilter.FILTER_SKIP;
};
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,filter, false);

//创建一个能够访问所有类型节点的简单的 NodeIterator
var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL,null, false);

        NodeIterator 类型的两个主要方法是 nextNode()和 previousNode()。顾名思义,在深度优先的 DOM 子树遍历中, nextNode()方法用于向前前进一步,而 previousNode()用于向后后退一步。

<div id="div1">
	<p><b>Hello</b> world!</p>
	<ul>
		<li>List item 1</li>
		<li>List item 2</li>
		<li>List item 3</li>
	</ul>
</div>
//遍历<div>元素中的所有元素
var div = document.getElementById("div1");
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT,null, false);
var node = iterator.nextNode();
while (node !== null) {
	alert(node.tagName); //输出标签名
	node = iterator.nextNode();
}

//只返回遍历中遇到的<li>元素
var div = document.getElementById("div1");
var filter = function(node){
	return node.tagName.toLowerCase() == "li" ?
	NodeFilter.FILTER_ACCEPT :
	NodeFilter.FILTER_SKIP;
};
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT,filter, false);
var node = iterator.nextNode();
while (node !== null) {
	alert(node.tagName); //输出标签名
	node = iterator.nextNode();
}

     TreeWalker

    TreeWalker 是 NodeIterator 的一个更高级的版本。除了包括 nextNode()和 previousNode()在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历 DOM 结构的方法。
    parentNode():遍历到当前节点的父节点;
    firstChild():遍历到当前节点的第一个子节点;
    lastChild():遍历到当前节点的最后一个子节点;
    nextSibling():遍历到当前节点的下一个同辈节点;
    previousSibling():遍历到当前节点的上一个同辈节点

var div = document.getElementById("div1");
var filter = function(node){
	return node.tagName.toLowerCase() == "li"?
		NodeFilter.FILTER_ACCEPT :
		NodeFilter.FILTER_SKIP;
};
var walker= document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT,filter, false);
var node = iterator.nextNode();
while (node !== null) {
	alert(node.tagName); //输出标签名
	node = iterator.nextNode();
}

//使用 TreeWalker遍历 DOM 树,即使不定义过滤器,也可以取得所有<li>元素
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
walker.firstChild(); //转到<p>
walker.nextSibling(); //转到<ul>
var node = walker.firstChild(); //转到第一个<li>
while (node !== null) {
	alert(node.tagName);
	node = walker.nextSibling();
}

范围

    DOM中的范围

        用 DOM 范围实现简单选择

<!DOCTYPE html>
<html>
	<body>
		<p id="p1"><b>Hello</b> world!</p>
	</body>
</html>
var range1 = document.createRange();
	range2 = document.createRange();
	p1 = document.getElementById("p1");
range1.selectNode(p1);//选择整个节点,包括其子节点
range2.selectNodeContents(p1);//只选择节点的子节点

        用 DOM 范围实现复杂选择

var range1 = document.createRange();
	range2 = document.createRange();
	p1 = document.getElementById("p1");
	p1Index = -1;
	i, len;
for (i=0, len=p1.parentNode.childNodes.length; i < len; i++) {
	if (p1.parentNode.childNodes[i] == p1) {
		p1Index = i;
		break;
	}
}
range1.setStart(p1.parentNode, p1Index);
range1.setEnd(p1.parentNode, p1Index + 1);
range2.setStart(p1, 0);
range2.setEnd(p1, p1.childNodes.length);

        操作 DOM 范围中的内容

var p1 = document.getElementById("p1");
	helloNode = p1.firstChild.firstChild;
	worldNode = p1.lastChild;
	range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
range.deleteContents();

var p1 = document.getElementById("p1");
	helloNode = p1.firstChild.firstChild;
	worldNode = p1.lastChild;
	range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
var fragment = range.extractContents();
p1.parentNode.appendChild(fragment);

//使用 cloneContents()创建范围对象的一个副本,然后在文档的其他地方插入该副本。
var p1 = document.getElementById("p1"),
	helloNode = p1.firstChild.firstChild,
	worldNode = p1.lastChild,
	range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
var fragment = range.cloneContents();
p1.parentNode.appendChild(fragment);

         插入 DOM 范围中的内容

<span style="color: red">Inserted text</span>
var p1 = document.getElementById("p1");
	helloNode = p1.firstChild.firstChild;
	worldNode = p1.lastChild;
	range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
var span = document.createElement("span");
span.style.color = "red";
span.appendChild(document.createTextNode("Inserted text"));
range.insertNode(span);
<p id="p1"><b>He<span style="color: red">Inserted text</span>llo</b> world</p>

        折叠 DOM 范围

        指范围中未选择文档的任何部分。可以用文本框来描述折叠范围的过程。假设文本框中有一行文本,你用鼠标选择了其中一个完整的单词。然后,你单击鼠标左键,选区消失,而光标则落在了其中两个字母之间。同样,在折叠范围时,其位置会落在文档中的两个部分之间,可能是范围选区的开始位置,也可能是结束位置。

        比较 DOM 范围

        在有多个范围的情况下,可以使用 compareBoundaryPoints()方法来确定这些范围是否有公共的边界(起点或终点)。这个方法接受两个参数:表示比较方式的常量值和要比较的范围。表示比较方式的常量值如下所示。
    Range.START_TO_START(0):比较第一个范围和第二个范围的起点;
    Range.START_TO_END(1):比较第一个范围的起点和第二个范围的终点;
    Range.END_TO_END(2):比较第一个范围和第二个范围的终点;
    Range.END_TO_START(3):比较第一个范围的终点和第一个范围的起点。 

var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById("p1");
range1.selectNodeContents(p1);
range2.selectNodeContents(p1);
range2.setEndBefore(p1.lastChild);
alert(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //0
alert(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //1

         复制 DOM 范围

var newRange = range.cloneRange();

        清理 DOM 范围

range.detach(); //从文档中分离
range = null; //解除引用

猜你喜欢

转载自blog.csdn.net/funkstill/article/details/85034990