Step4. 了解 Range 对象:
Range表示网页中的一块选择区域。
比如FireFox在页面中选取了3段文字,那么就会有相对应的3个Range对象
Range可以用 Document 对象的 createRange方法创建,也可以用Selection对象的getRangeAt方法取得。另外,可以通过构造函数 Range() 来获得一个 Range 。
详细参见 developer.mozilla.org Range
Range 的主要属性(只读
):
属性 | 用途 |
---|---|
Range.collapsed | 返回一个用于判断 Range 起始位置和终止位置是否相同的布尔值。 |
Range.commonAncestorContainer | 返回包含 startContainer 和 endContainer 的最深的节点。 |
Range.endContainer | 返回包含 Range 终点的节点。 |
Range.endOffset | 返回 endContainer 中表示Range终点位置的数字。 |
Range.startContainer | 返回包含 Range 开始的节点。 |
Range.startOffset | 返回 startContainer 中表示 Range 起始位置的数字。 |
他们之间的关系如下图:
Selection 的主要方法:
属性 | 参数 | 用途 |
---|---|---|
Range.setStart(startNode, startOffset) | dom,number | 设置 Range 的起点。 |
Range.setEnd(endNode, endOffset) | dom,number | 设置 Range 的终点。 |
Range.setStartBefore(referenceNode) | dom | 以其它节点 ( Node)为基准,设置 Range 的起点。 |
Range.setStartAfter(referenceNode) | dom | 以其它节点为基准,设置 Range 的始点。 |
Range.setEndBefore(referenceNode) | dom | 以其它节点为基准,设置 Range 的终点。 |
Range.setEndAfter(referenceNode) | dom | 以其它节点为基准,设置 Range 的终点。 |
Range.selectNode(referenceNode) | dom | 设定一个包含节点和节点内容的 Range 。 |
Range.selectNodeContents(referenceNode) | dom | 设定一个包含某个节点内容的 Range 。 |
Range.collapse(bool) | bool | 向指定端点折叠该 Range 。 |
--- | --- | --- |
Range.cloneContents() | dom | 返回 Range 当中节点的文档片段(DocumentFragment)。 |
Range.deleteContents() | 无 | 从文档(Document)中移除 Range 中的内容。 |
Range.extractContents() | 无 | 把 Range 的内容从文档树移动到文档片段中。 |
Range.insertNode(dom) | dom | 在 Range 的起点处插入节点。 |
Range.surroundContents(dom) | dom | 将 Range 的内容移动到一个新的节点中。 |
Range.cloneRange() | 无 | 返回拥有和原 Range 相同端点的克隆 Range 对象。 |
Range.toString() | 无 | 把Range内容作为字符串返回。 |
demo 点击下文按钮:
btn1.onclick = function() {
var select = document.getSelection();
if (select.rangeCount) {
var range = select.getRangeAt(0);
var frag = range.cloneContents();
txt.value = frag.textContent;
}
}
btn2.onclick = function() {
var select = document.getSelection();
var range = document.createRange();
select.removeAllRanges(); //chrome 只支持 一个区域
var spanTextNode = span1.childNodes[0];
range.setStart(spanTextNode, 0);
range.setEnd(spanTextNode, spanTextNode.length);
select.addRange(range);
}
btn3.onclick = function() {
var select = document.getSelection();
if (select.rangeCount) {
var range = select.getRangeAt(0);
var frag = range.extractContents();
var colorNode = document.createElement("color");
colorNode.style.color = "red";
colorNode.innerText = frag.textContent;
range.insertNode(colorNode);
}
}
selection 对象是对网页中所有选择区域的一个统筹管理者, 其实像collapse
deleteFromDocument
等方法是不应该放在 selection 中的
因为range对象已经很好地实现了这些功能(下篇 会介绍 range 对象) 因为FireFox允许多个 range 而 Chrome IE不允许.所以在这里 API的设计就产生了分歧.
为了互相兼容,所以现在 selection 也具备了 range的一些功能.
range.setStart(startNode, startOffset):
设置 Range 的起点
使用的时候要注意,如果 startNode 是一个文本节点则 则光标会停在这个文本节点从左往右数第 startOffset 那个字的位置那.,
如果 startNode 是一个一般dom节点 则光标会停在 parentNode.childNodes[startOffset] 那个节点的开头位置.
range.setEnd(endNode, endOffset):
设置 Range 的结束点
使用的时候要注意,如果 startNode 是一个文本节点则 则光标会停在这个文本节点从左往右数第 endOffset 那个字的位置那.,
如果 startNode 是一个一般dom节点 则光标会停在 parentNode.childNodes[endOffset] 那个节点的开头位置.
range.setStartBefore(dom) | range.setStartAfter(dom):
作用: 以其它节点(dom)为基准,设置 Range 的起点位置。
这个2个API很相似,他们都是用来设置一个选择区域的起始点的. 区别在于你想把开始位置放在dom的尖括号里面还是外面
setStartBefore是外边, setStartAfter是里面:
range.selectNode(dom):
作用:选中一个节点(参数 dom 全部, 相当于 range.setStartBefore(dom) + range.setEndAfter(dom))
range.selectNodeContents(dom):
作用:选中一个节点的内容 ,(参数 dom 的内容, 相当于 range.setStartAfter(dom) + range.setEndBefore(dom))
range.collapse(bool):
作用:折叠一段选中区域,(简单来说就是 定位光标到选中区域的开头或者结尾)
true 定位到开头.
false 定位到结尾.
range.cloneContents():
作用: 以DocumentFragment
形式返回你选中的区域内容.
比如你选中了以下区域:
则返回的是
o
<p>je</p>
range.deleteContents():
作用: 删除你选中的区域. 返回 undefined;
这个应该不需要解释...
range.extractContents():
作用: 和 range.deleteContents() 类似, 只不过他会把你选中的节点以 DocumentFragment
的形式 return 出来.
range.insertNode(dom):
作用: 在选择区域的开始的位置,插入dom节点.
range.insertNode(dom):
作用: 将 Range 的内容移动到一个新的节点中。 感觉比较少用.
range.cloneRange(dom):
作用: 返回拥有和原 Range 相同端点的克隆 Range 对象。
range.toString(dom):
作用: 把Range内容作为字符串返回。 即去除多余的 尖括号 等标记.