介绍
1、const selection = window.getSelection();
说明:
1、用于获取用户当前文档选择的对象;
2、它返回一个 Selection 对象,该对象代表了用户选择的文本范围(可以包含一个或多个范围,因为用户可以同时选择多个不相邻的文本部分);
基本属性:
- anchorNode:表示选择范围的起始节点;
- anchorOffset:表示选择范围的起始偏移量(字符数或子元素的索引);
- focusNode:表示选择范围的结束节点;
- focusOffset:表示选择范围的结束偏移量;
- baseNode:表示选择范围的起始节点。这通常是一个 DOM 元素或文本节点;
- baseOffset:表示选择范围的起始偏移量。它表示从 baseNode 的开始位置(0)开始的字符偏移量或子元素的索引;
- extentNode:表示选择范围的结束节点。这也通常是一个 DOM 元素或文本节点;
- extentOffset:表示选择范围的结束偏移量。它表示从 extentNode 的开始位置(0)开始的字符偏移量或子元素的索引;
- isCollapsed:: 一个布尔值,指示选择范围是否是折叠的(即起点和终点相同);
说明:
1、折叠的情况:在折叠的选择范围中,起点和终点的节点是相同的,偏移量也相同,因为用户只是设置了插入点(光标)而没有选择文本范围。
2、非折叠的情况:在非折叠的选择范围中,起点和终点的节点可以相同,也可以不同,但偏移量一定不同。这表示用户已经选择了一段文本范围,起点和终点指向所选择文本范围的开始和结束位置。
- rangeCount:表示当前选择中的范围数量;
- type: 属性是只读的,表示选择范围的类型,可以是 “Caret”(插入符号,即折叠的选择范围),“Range”(实际的文本选择范围)或其他类型,具体取决于用户的选择操作,“None”(还没有选择范围,即没有任何焦点信息);
基本方法:
- addRange(range): 向选择中添加一个范围对象。可以使用这个方法将自定义的范围添加到用户的文本选择中。
- removeRange(range): 从选择中移除一个范围对象。如果您需要删除之前添加的范围,可以使用这个方法。
- removeAllRanges(): 从选择中移除所有范围对象。这将清空当前选择中的所有范围,将选择重置为空。
- getRangeAt(index): 获取指定索引位置的范围对象。如果用户的选择包含多个不相邻的范围,您可以使用这个方法来访问它们。
- toString(): 返回选择范围中的文本内容。这是一个便捷的方法,用于获取用户选择的文本。(相当于所有选中范围是一段dom,然后获取dom的innerText)
- selectAllChildren(container): 选择指定容器元素的所有子元素。这将把选择范围设置为指定容器的所有内容。
- collapse(node, offset): 折叠选择范围到指定节点的指定偏移量。这用于创建折叠的选择(插入符号)。【即移动光标位置,offset从0开始,没传就是0】
- extend(node, offset): 扩展选择范围到指定节点的指定偏移量。这用于扩展文本范围选择。
2、const range = document.createRange()
说明:
1、是用于创建新的文本范围(Range)对象的方法,它是 Document Object Model (DOM) 的一部分,通常用于处理文档中的文本和元素选择。通过调用 document.createRange(),可以创建一个新的、空的文本范围对象 range。然后,您可以使用该范围对象来定义其起始点和终点,以便操作文档中的文本和元素。
2、使用 Range 对象,您可以执行各种操作,如高亮文本、插入新文本、删除文本等。它对于富文本编辑器、文本操作和选择性处理非常有用
基本属性:
- startContainer:范围的起始节点(通常是一个 DOM 元素或文本节点);
- startOffset:起始节点内的偏移量,表示从起始节点的开头(通常是字符或子元素的索引);
- endContainer:范围的终点节点;
- endOffset:终点节点内的偏移量;
基本方法:
- setStart(node, offset):设置范围的起始点;
- setEnd(node, offset):设置范围的终点;
- selectNode(node):选择一个特定的节点及其所有子节点;
- selectNodeContents(node):选择一个节点的所有子节点;
- deleteContents():用于删除文本范围内的内容,包括文本节点、元素节点等。它会从文档中移除所选择的内容,但不会删除文档结构;
- insertNode(node):用于在文本范围的起始位置插入节点,可以是文本节点、元素节点或其他类型的节点;
- collapse(toStart):用于将文本范围折叠到起始点或终点,取决于 toStart 参数的值。如果 toStart 为 true,则折叠到起始点,如果为 false,则折叠到终点;
- cloneRange():用于创建当前文本范围的副本。这是一个非常有用的方法,允许您在不影响原始范围的情况下创建一个新范围,以便进行独立的操作;
- setStartAfter(refNode):用于设置文本范围的起始点为 refNode 元素之后。这是一个很有用的方法,可以在文档中定位文本范围的起始位置;
运用
1、JS选中一段文本或节点或元素。
const selection = window.selection();
const range = document.createRange();
// 其中node为具体的元素
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
2、聚焦在节点的首部
const selection = window.selection();
const range = document.createRange();
// 其中node为具体的元素
range.selectNode(node);
selection.removeAllRanges();
selection.addRange(range);
node.focus();
3、聚焦在节点的尾部
const selection = window.selection();
const range = document.createRange();
let len = temp1.childNodes.length;
// 其中node为具体的元素
range.selectNode(temp1);
range.setStart(temp1, len);
range.setEnd(temp1, len);
selection.removeAllRanges();
selection.addRange(range);
node.focus();
4、控制输入长度(比如:可编辑DIV的输入框;注意:这里的长度是指文本长度)
- 场景1:input键盘输入
// 获取光标所在节点
const selection = window.selection();
// 获取当前聚焦节点的range
const range = selection.getRangeAt(0);
// 获取range的开始节点
const startDom = range.startContainer;
const endDom = range.endContainer;
let endOffset = range.endOffset;
// 输入框的当前内容长度:10
let contentLen = 10;
// 最大输入长度
let maxLength = 10;
if (contentLen > maxLength) {
let startOffset = endOffset - (contentLen - maxLength);
startOffset = startOffset < 0 ? 0 : startOffset;
// 改变选取范围
range.setStart(startDom, startOffset);
range.setEnd(endDom, endOffset);
range.deleteContents();
}
- 场景2:复制黏贴
思路:监听paste事件,获取其中的copy内容,然后在手动插入其中的内容,阻断事件的默认事件执行。
代码:
// 黏贴事件
function pasteEvent(event) {
// 获取剪切对象
const clipboardData =
event.clipboardData || event.originalEvent.clipboardData;
// 判断剪切对象是否存在
if (!clipboardData) {
return false;
}
// 获取剪贴板的内容,通过text获取纯文本,通过text/html获取html结构
let html = "";
let copytext = "";
// 根据需要判断是获取纯文本还是富文本,此处以获取富文本为例
// copytext = clipboardData.getData("text");
copytext = clipboardData.getData("text/html") || clipboardData.getData("text");
// 判断剪贴板内容的结构,是否为纯文本
if (copytext.indexOf("<!--StartFragment-->") >= 0) {
// html
copytext = copytext
.split("<!--StartFragment-->")[1]
.split("<!--EndFragment-->")[0];
}
html = copytext;
// 插入元素节点
insertHtml(html);
// Prevent the default behavior of the paste event
event.preventDefault();
return false;
}
// 将富文本转换为节点数据并插入
function insertHtml(html) {
// 将修改后的富文本内容转换为元素节点数据
const dom = new DOMParser().parseFromString(html, "text/html");
const eleNodes = [...dom.body.childNodes];
// 获取当前选择文本的长度(指选中内容的文本长度)
const selectedContentLen = getSelectedTextLength();
// 记录一下当前的光标位置信息
// ...
// 遍历循环元素节点信息,一一插入
for (let i = 0; i < eleNodes.length; i++) {
// ...
}
}
5、获取选中内容的文本长度
function getSelectedRangeTextLength() {
let selectedText = "";
let selectedTextLength = 0;
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const selectedRange = selection.getRangeAt(0);
selectedText = selectedRange.toString();
selectedTextLength = selectedText.length;
}
return selectedTextLength;
}