JavaScript DOM2和DOM3——“局限”的注重要点

“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 的边境点。但事实上,

  1. 常量 Range.START_TO_END 指定与当前局限的 end 点和 sourceRange 的 start 点举行比较。

  2. 常量 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及更早版本中的局限

    原文作者:JS菌
    原文地址: https://segmentfault.com/a/1190000004270980
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞