提问人:Abreham 提问时间:8/10/2022 最后编辑:Abreham 更新时间:9/6/2022 访问量:272
在 HTML 中的特定元素中搜索文本并返回其 Range 对象
Search text in a particular element in the HTML and return the Range object for it
问:
我想在 HTML 元素中搜索文本并返回文本的 Range 对象。我想使用范围进行一些操作,例如突出显示和替换文本。类似于 Grammarly 的错误突出显示功能。
到目前为止,我尝试过:
- 遍历元素的子元素以查找文本并构造 Range。但这种方法有 2 个问题。
a. 它非常慢(350 毫秒)和
b.找不到一些文本
const getRangeofText = (text:string) => {
const children = document.activeElement;
let finalNode;
let parent = children;
let i = 12;
let isFound = false;
while (parent.children.length > 0 && i > 0) {
i--;
console.log("I: ", i);
console.log("traversing through: ", parent.childNodes);
for (const item of Array.from(parent.childNodes)) {
console.log("item: ", item);
if (item.nodeType === 3 && item.textContent.includes(text)) {
console.log("found in TEXT NODE");
finalNode = item;
isFound = true;
}
if (item.nodeType === 1 && item.textContent.includes(text)) {
console.log("found in ELEMENT NODE");
parent = item as Element;
finalNode = item;
isFound = true;
}
}
}
console.log("final node: ", finalNode);
// console.log("node type: ", finalNode.nodeType);
const range = new Range();
let startNode;
let endNode;
let arr = text.split(" ");
let startWord = arr[0];
let endWord = arr[arr.length - 1];
if (finalNode) {
if (finalNode.nodeType === 1) {
let childNodes = finalNode.childNodes;
for (const item of Array.from(childNodes)) {
if (item.textContent.includes(startWord)) {
startNode = item;
}
if (item.textContent.includes(endWord)) {
endNode = item;
}
}
range.setStart(startNode, 0);
range.setEndAfter(endNode);
} else {
range.setStart(finalNode, 0);
range.setEnd(finalNode, text.length);
}
window.getSelection().addRange(range);
}
};
下面是上述代码的 Codesandbox。
- 使用 Rangy 的 findText() 方法。这种方法也很慢(200ms)
我还有什么其他选择?或者如何优化这些功能?
答:
0赞
Abreham
9/6/2022
#1
function getRanges(a) {
let ranges = [];
const scrollTop = document.documentElement.scrollTop;
while (window.find(a)) {
var rng = window.getSelection().getRangeAt(0);
ranges = [...ranges, rng];
document.documentElement.scrollTop = scrollTop;
}
return ranges;
}
const getRangeElements = (str) => {
window.getSelection().removeAllRanges();
const ranges = getRanges(str);
window.getSelection().removeAllRanges();
return ranges;
};
getRangeElements("Text to search for")
这是有效的,但它模糊了页面,并且作为焦点的任何元素(例如文本输入)都会变得模糊。有什么方法可以避免模糊吗?
评论