Range对象
Range表示HTML文档的一部分内容,它可以在任何点开始和结束,最常见的Range就是用户选择的一段文本。通过Range对象,你可以找到开始点和结束点,你可以复制或者删除它,或者替换成另一段文本,甚至是一段HTML代码。
比如用户从下面的文本中选择了一段:
选中的这段文本跨越了好几个HTML元素,而且你会发现,这段选中的文本是极不规范的HTML代码,比如第一行没有<p>,最后一行没有</li>。
还好,所有浏览器都会自动补全:
获得用户选择区域
function getUserSelection(){ if (window.getSelection){ return window.getSelection(); } else if (document.selection){ return document.selection.createRange(); } } |
W3C:用户选择区域是Selection对象
IE:用户选择区域是TextRange对象
获得用户选择的内容
var userSelection = getUserSelection(), selectedText = userSelection.text || userSelection.toString(); |
通过Selection对象创建Range对象
function getRange(selection){ if (selection.getRangeAt){ return selection.getRangeAt(0); } else { //不支持getRangeAt的情况 var range = document.createRange(); range.setStart(selection.anchorNode, selection.anchorOffset); range.setEnd(selection.focusNode, selection.focusOffset); return range; } } |
IE调用getUserSelection()方法获得的就是一个TextRange对象,所以不需要再创建Range对象了。
通过编程的方式创建Range对象
如果浏览器不支持getRangeAt()方法,比如Safari1.3,我们需要先创建一个新的Range对象,而它必须包含用户当前选中的区域。
首先创建一个空的Range对象:
var range = document.createRange(); |
为了把它插进文档树中,我们需要设置开始点和结束点:
range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset); |
下面给出IE和W3C方法创建Range对象的差异:
IE6/7/8 | W3C |
---|
IE6/7/8 只有 TextRange,在指定的对象上创建一个 TextRange 需要使用 'object.createTextRange()'。 注意不是任何类型的对象都可以创建 TextRange,只有 body 对象、button 对象、textarea 对象和 type='text' 的 input 对象才可以。 还可以通过 'document.selection.createRange()' 从当前的文本 selection 中得到一个 TextRange。 |
在标准浏览器中有两种方式创建Range对象: 1. 使用 'window.getSelection().getRangeAt(index)' 获得一组 Range 中指定的 Range 2. var range = document.createRange(),然后设置range的开始位置(setStart())和结束位置(setEnd()) |
属性:
属性 | 说明 |
---|
collapsed | 返回一个boolean值,表示range的开始点和结束点是否为同一个位置。返回true表示没有包含任何内容,即DOM树中一个单独的点。这个属性是只读的,如需要操作它,请使用collapse方法。 |
commonAncestorContainer |
返回包含 startContainer 和 endContainer 的最深的节点,这个属性是只读的,如需要操作它,请重新设置range的开始位置和结束位置。 如果选择的是一段纯文本,如<span>1234</span>中的23,该属性为文本节点; 如果选区跨越了节点,比如123<span>456</span>中的34,该属性为二者的父节点; |
startContainer |
返回包含range开始点的节点。这个属性是只读的,如需要操作它,请使用setStart方法。 通常都是文本节点。 |
startOffset | 返回一个number值,表示range在startContainer中的开始位置。startOffset有两种意思:如果 startContainer 是Text节点、Comment节点或CDATASection节点,startOffset是指从startContainer的开始位置到range的开始位置的偏移量;如果是别的节点类型,startOffset是指从startContainer的开始位置到range的开始位置的子节点数量。这个属性是只读的,如需要操作它,请使用setStart方法。 |
endContainer | 返回包含range结束点的节点。这个属性是只读的,如需要操作它,请使用setEnd方法。 |
endOffset | 返回一个number值,表示range在endContainer中的结束位置。 |
方法:
定位方法(用于设置Range的开始点和结束点)
方法 | 说明 |
---|
collapse(toStart) | toStart是一个boolean值,true表示把Range collapse到开始位置,false表示把Range collapse到结束位置。 |
setStart(startNode, startOffset) | 设置Range的开始位置。如果 startNode 是Text节点、Comment节点或CDATASection节点,startOffset是指从 startNode 的开始位置到range的开始位置的偏移量;如果是别的节点类型,startOffset是指从 startNode 的开始位置到range的开始位置的子节点数量。这个属性是只读的,如需要操作它,请使用setStart方法。 |
setEnd(endNode, endOffset) | 设置Range的结束位置。 |
setStartBefore(referenceNode) | 把Range开始位置的父节点设置为referenceNode。 |
setStartAfter(referenceNode) | 把Range开始位置的父节点设置为referenceNode。 |
setEndBefore(referenceNode) | 把Range结束位置的父节点设置为referenceNode。 |
setEndAfter(referenceNode) | 把Range结束位置的父节点设置为referenceNode。 |
selectNode(referenceNode) | 使Range包含referenceNode和它的子节点,把Range的开始位置和结束位置的父节点设置为referenceNode。 |
selectNodeContents(referenceNode) | 使Range包含referenceNode的内容。startOffset 为 0, endOffset是子节点的数量 或者 referenceNode中的字符长度。 |
编辑方法(用于从Range中获取节点 和 修改Range的内容)
方法 | 说明 |
---|
cloneContents() | 复制Range的节点,返回一个文档碎片。用addEventListener之类绑定的事件不会被复制,而onclick这样的直接写在元素attribute上的事件会被复制,元素的ID也会被复制,这有可能导致两个相同的ID。Partially selected nodes include the parent tags necessary to make the document fragment valid。 |
deleteContents() | 删除Range的内容,这个方法不会返回包含删除内容的文档碎片。 |
extractContents() | 把Range的内容装入一个文档碎片,规则和cloneContents()相同。 |
insertNode(newNode) | 在Range的开始位置插入一个节点。如果 newNode 的插入位置是一个文本节点,这个文本节点会在插入位置进行分隔,也就是说最后是在两个文本节点之间进行插入。如果newNode是一个文档碎片,插入的是文档碎片的子节点。 |
surroundContents(newNode) | 把Range的内容装入一个新节点,并把这个新节点放在Range的开始位置。surroundContents 等价于 newNode.appendChild(range.extractContents()); range.insertNode(newNode)。 |
其他方法:
方法 | 说明 |
---|
compareBoundaryPoints(how, sourceRange) |
比较两个Range的边界点。 how:比较的方式,这是一个常量值: Range.END_TO_START -> 用 sourceRange 的结束点 与 当前Range的开始点 进行比较 Range.START_TO_END -> 用 sourceRange 的开始点 与 当前Range的结束点 进行比较 Range.START_TO_START -> 用 sourceRange 的开始点 与 当前Range的开始点进行比较 sourceRange:需要比较的Range 返回:-1, 0 或 1, 表示当前Range的边界点相对于sourceRange的边界点是在前,相等还是在后。 |
cloneRange() | 返回一个和当前Range边界点完全相同的Range对象,这是值拷贝,非引用,所以改变其中一个不会影响另一个。 |
detach() | 释放Range从而提高性能。调用 detach() 方法后,对这些属性的任何读操作都会抛出代码为 INVALID_STATE_ERR 的 DOMException 异常。 |
toString() | 返回Range的文本。 |
兼容之道
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架