“DOM2级遍历和局限”模块定义了“局限”接口。经由过程局限能够挑选文档中的一个地区,而没必要斟酌节点的界线(挑选在背景完成,对用户是不可见的)。
DOM中的局限
DOM2级在Document范例中定义了createRange()
要领,能够用来建立DOM局限,以下所示:
var range = document.createRange();
每一个局限由一个Range范例的实例示意,这个实例有许多属性和要领:
startContainer:包含局限出发点的节点(选区中第一个节点的父节点);
startOffset:局限在startContainer中出发点的偏移量;
endContainer:包含局限尽头的节点(选区中末了一个节点的父节点);
endOffset:局限在endContainer中尽头的偏移量;
commonAncestorContainer:startContainer和endContainer合营的先人节点在文档树中位置最深的谁人;
用DOM局限完成简朴挑选
selectNode()
或selectNodeContents()
前者挑选全部节点,包含子节点;后者挑选节点的子节点。如:
<body>
<p id="p1"><b>Hello</b> world!</p>
<script>
var range1 = document.createRange(),
range2 = document.createRange(),
p1 = document.getElementById("p1");
range1.selectNode(p1);
range2.selectNodeContents(p1);
console.log(range1.startContainer); //document.body
console.log(range1.startOffset); //1 有个空格
console.log(range1.endContainer); //document.body
console.log(range1.endOffset); //2
console.log(range1.commonAncestorContainer); //document.body
console.log(range2.startContainer); //p1
console.log(range2.startOffset); //0
console.log(range2.endContainer); //p1
console.log(range2.endOffset); //2
console.log(range2.commonAncestorContainer); //p1
</script>
</body>
在挪用selectNode()时,startContainer、endContainer和commonAncestorContainer等都即是传入节点的父节点,也就是个中的document.body。而startOffset属性即是给定节点在其父节点的childNodes鸠合中的索引。endOffset即是startOffset加上1;
在挪用selectNodeContents()时,startContainer、endContainer和commonAncestorContainer即是传入的节点。而startOffset属性一直即是0.末了,endOffset即是子节点的数目(node.childNodes.length);
更邃密的挑选
为了更邃密的掌握将哪些节点包含在局限中,还能够运用以下要领:
setStartBefore(refNode):将局限的出发点设置在refNode之前;
setStartAfter(refNode):将局限的出发点设置在refNode以后;
setEndBefore(refNode):将局限的尽头设置在refNode之前;
setEndAfter(refNode):将局限的尽头设置在refNode以后;
以下html:
<p id="p1">
<b>Hello</b> world!
</p>
<div>
<p>hello</p>
</div>
js:
var range1 = document.createRange(),
range2 = document.createRange(),
p1 = document.getElementById("p1");
range1.selectNode(p1);
range1.setStartAfter(p1);
console.log(range1.startContainer); //document.body
console.log(range1.startOffset); //2 有1个空格和一个p元素
console.log(range1.endContainer); //document.body
console.log(range1.endOffset); //2 挑选了一个元素,所以是startOffset加1
console.log(range1.commonAncestorContainer); //document.body
range2.setStartAfter(p1); //结果与上面的雷同
console.log(range2.startContainer); //document.body
console.log(range2.startOffset); //2
console.log(range2.endContainer); //document.body
console.log(range2.endOffset); //2
console.log(range2.commonAncestorContainer); //document.body
用DOM局限完成越发庞杂的挑选
setStart()
和setEnd()
要领
这两个要领都吸收两个参数:一个参照节点和一个偏移量值。对前者来讲,参照节点会变成startContainer,偏移值则会变成startOffset。关于后者来讲,参照节点会变成endContainer,偏移值会变成endOffset。
html:
<p id="p1"><b>Hello</b> world!</p>
js:
var p1 = document.getElementById("p1"),
helloNode = p1.firstChild.firstChild,
worldNode = p1.lastChild;
var range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
如许就完成了对“llo wo”的挑选,但仅仅完成对该选区的挑选意义不大,主要的是对其举行操纵。
操纵DOM局限中的内容
deleteContents()
删除局限所包含的内容
如:
<p id="p1"><b>Hello</b> world!</p>
举例:
var p1 = document.getElementById("p1");
var hello = p1.firstChild.firstChild;
var world = p1.lastChild;
var range = document.createRange();
range.setStart(hello, 1);
range.setEnd(world, 2);
console.log(range.toString()); //ello w
console.log(p1.outerHTML); //<p id="p1"><b>Hello</b> world!</p>
range.deleteContents(); //删除范围内的内容
console.log(p1.outerHTML); //<p id="p1"><b>H</b>orld!</p>
又如:
<ul id="list">
<li>thi is a list No.1</li>
<li>thi is a list No.2</li>
<li>thi is a list No.3</li>
<li>thi is a list No.4</li>
<li>thi is a list No.5</li>
</ul>
举例:
var list = document.getElementById("list");
var starting = list.getElementsByTagName("li")[1];
var ending = list.getElementsByTagName("li")[3];
var range = document.createRange();
range.setStart(starting, 0);
range.setEnd(ending, 0);
console.log(range.toString());
console.log(list.outerHTML);
range.deleteContents();
console.log(list.outerHTML);
extractContents()
移除局限所包含的内容并返回文档片断
如:
<p id="p1"><b>Hello</b> world!</p>
举例:
var p1 = document.querySelector("#p1");
var helloNode = p1.firstChild.firstChild,
worldNode = p1.lastChild;
var range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
var fragment = range.extractContents();
p1.parentNode.insertBefore(fragment, p1);
又如:
<ul id="list">
<li>thi is a list No.1</li>
<li>thi is a list No.2</li>
<li>thi is a list No.3</li>
<li>thi is a list No.4</li>
<li>thi is a list No.5</li>
</ul>
举例:
var list = document.getElementById("list");
var range = document.createRange();
var starting = list.getElementsByTagName("li")[1];
var ending = list.getElementsByTagName("li")[4];
range.selectNode(list);
range.setStartBefore(starting);
range.setEndBefore(ending);
var fragment = range.extractContents();
document.body.appendChild(fragment);
console.log(document.body.innerHTML);
// <li>thi is a list No.2</li>
// <li>thi is a list No.3</li>
// <li>thi is a list No.4</li>
console.log(list.innerHTML);
// <li>thi is a list No.1</li>
// <li>thi is a list No.5</li>
cloneContents()
建立局限对象的一个副本
如:
var list = document.getElementById("list");
var range = document.createRange();
var starting = list.getElementsByTagName("li")[1];
var ending = list.getElementsByTagName("li")[4];
range.selectNode(list);
range.setStartBefore(starting);
range.setEndBefore(ending);
var fragment = range.cloneContents();
document.body.appendChild(fragment);
console.log(document.body.innerHTML);
// <li>thi is a list No.2</li>
// <li>thi is a list No.3</li>
// <li>thi is a list No.4</li>
console.log(list.innerHTML);
// <li>thi is a list No.1</li>
// <li>thi is a list No.2</li>
// <li>thi is a list No.3</li>
// <li>thi is a list No.4</li>
// <li>thi is a list No.5</li>
插进去DOM局限中的内容
insertNode()
向局限选区的最先处插进去一个节点(局限内部插进去内容)
如:
<ul id="list">
<li>thi is a list No.1</li>
<li>thi is a list No.2</li>
<li>thi is a list No.3</li>
<li>thi is a list No.4</li>
<li>thi is a list No.5</li>
</ul>
代码:
<script>
var list = document.getElementById("list");
var range = document.createRange();
var starting = list.getElementsByTagName("li")[1];
var ending = list.getElementsByTagName("li")[4];
range.selectNode(list);
range.setStartBefore(starting);
range.setEndBefore(ending);
var newLi = document.createElement("li");
newLi.appendChild(document.createTextNode("data"));
range.insertNode(newLi);
console.log(list.innerHTML);
// <li>thi is a list No.1</li>
// <li>data</li><li>thi is a list No.2</li>
// <li>thi is a list No.3</li>
// <li>thi is a list No.4</li>
// <li>thi is a list No.5</li>
</script>
又如:
<p id="p1"><b>Hello</b> world!</p>
代码:
var p = document.getElementById("p1");
var range = document.createRange();
var starting = p.firstChild.firstChild;
var ending = p.lastChild;
range.setStart(starting, 5);
range.setEnd(ending, 0);
var span = document.createElement("span");
span.appendChild(document.createTextNode(" there in this"));
range.insertNode(span);
console.log(p1.innerText); //Hello there in this world!
console.log(p1.innerHTML); //<b>Hello<span> there in this</span></b> world!
surroundContents()
向局限选区四周插进去一个节点(缭绕局限插进去内容)
一般与selectNode()
合营,由于局限必需包含全部DOM选区,不能仅仅包含选中的DOM节点。
如:
<p id="p1"><b>Hello</b> world!</p>
代码:
var p = document.getElementById("p1");
var range = document.createRange();
range.selectNode(p.firstChild);
var span = document.createElement("span");
span.style.border = "1px solid orange";
span.style.borderRadius = "3px";
range.surroundContents(span);
console.log(p1.innerHTML); //<span style="border: 1px solid orange; border-radius: 3px;"><b>Hello</b></span> world!
为了插进去span标签,局限必需包含全部DOM选区,所以引荐运用selectNode()合营。
摺叠DOM局限
collapse()
要领
摺叠就是指局限中未挑选文档的任何部份。该函数吸收一个参数,一个布尔值。true示意摺叠到局限的出发点,参数false示意摺叠到局限的尽头。要肯定局限已摺叠终了,能够搜检collapsed属性:
如:
<p id="p1"><b>Hello</b> world!</p>
代码:
var p = document.getElementById("p1");
var range = document.createRange();
range.selectNode(p);
range.collapse(true);
console.log(range.collapsed); //True
又如:
<ul id="list">
<li>thi is a list No.1</li>
<li>thi is a list No.2</li>
<li>thi is a list No.3</li>
<li>thi is a list No.4</li><li>thi is a list No.5</li>
</ul>
代码:
var list = document.querySelector("#list");
var range = document.createRange();
range.setStartAfter(list.getElementsByTagName("li")[1]);
range.setEndBefore(list.getElementsByTagName("li")[2]);
console.log(range.collapsed); //False 由于另有一个空缺节点在这里
var range2 = document.createRange();
range2.setStartAfter(list.getElementsByTagName("li")[3]);
range2.setEndBefore(list.getElementsByTagName("li")[4]);
console.log(range2.collapsed); //True 由于局限没有选中任何部份
比较DOM局限
comopareBoundaryPoints()
要领来比较
该要领涌来比较这些局限是不是有大众的边境。吸收两个参数:示意比较体式格局的常量值和要比较的局限。如:
Range.START_TO_START – 比较两个 Range 节点的最先点
Range.END_TO_END – 比较两个 Range 节点的完毕点
Range.START_TO_END – 用 sourceRange 的最先点与当前局限的完毕点比较
Range.END_TO_START – 用 sourceRange 的完毕点与当前局限的最先点比较
注重:《高等程序设计》一书中,对后两个的申明太隐约(不正确?);下面是w3school的诠释:
您能够以为,起首需要用参数 how 的局限常量指定当前局限的边境点,然后再用它指定 sourceRange 的边境点。但事实上,
常量 Range.START_TO_END 指定与当前局限的 end 点和 sourceRange 的 start 点举行比较。
常量 Range.END_TO_START 指定比较当前局限的 start 点和指定局限的 end 点。
假如第一个局限中的点位于第二个局限中的点之前,返回-1;假如相称返回0;假如第一个局限中的点位于第二个局限中的点以后,返回1
如:
<p id="p1"><b>Hello</b> world!</p>
代码:
var p = document.getElementById("p1");
var range1 = document.createRange();
var range2 = document.createRange();
range1.selectNodeContents(p);
range2.selectNodeContents(p);
range2.setEndBefore(p.lastChild);
console.log(range1.toString()); //Hello world!
console.log(range2.toString()); //Hello
console.log(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //0
console.log(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //1
又如:
<ul id="list">
<li>thi is a list No.1</li>
<li>thi is a list No.2</li>
<li>thi is a list No.3</li>
<li>thi is a list No.4</li><li>thi is a list No.5</li>
</ul>
代码:
var list = document.querySelector("#list");
var range1 = document.createRange();
var range2 = document.createRange();
range1.selectNodeContents(list);
range1.setStartAfter(list.firstChild.nextSibling);
range1.setEndBefore(list.lastChild.previousSibling);
range2.selectNodeContents(list);
console.log(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //1
console.log(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //-1
console.log(range1.compareBoundaryPoints(Range.START_TO_END, range2)); //1 注重这里是range1的END与range2的start对照;
console.log(range1.compareBoundaryPoints(Range.END_TO_START, range2)); //-1 注重这里是range1的START与range2的END对照;
复制DOM局限
cloneRange()
要领复制局限;
var newRange = range.cloneRange();
清算DOM局限
detach()
要领清算局限;
range.detach();
range = null;
上面的是从文档中星散局限;下面的是消除援用。
下节再议论IE8及更早版本中的局限