我正在寻找一些解决方案,帮助从带有突出显示功能的 html 字符串中搜索术语。我可以通过从字符串中删除 html 内容来做到这一点。但问题是我将无法看到它突出显示的原始内容。我确实有以下功能,可以在没有 html 标记的情况下搜索和突出显示字符串。
private static updateFilterHTMLValue(value: string, filterText: string): string
{
if (value == null) {
return value;
}
let filterIndex: number = value.toLowerCase().indexOf(filterText);
if (filterIndex < 0) {
return null;
}
return value.substr(0, filterIndex)
+ "<span class='search-highlight'>"
+ value.substr(filterIndex, filterText.length)
+ "</span>"
+ value.substr(filterIndex + filterText.length, value.length - (filterIndex + filterText.length));
}
因此,为了管理使用 html 对字符串的搜索,我创建了可以使用 html 搜索字符串的新函数。 (我在搜索正确的字符串匹配之前删除了 html 部分)
private static test(value: string, filterText: string): string {
if (value == null) {
return value;
}
// Check for raw data without html
let valueWithoutHtml = TextFilterUtils.removeTextHtmlTags(value);
let filterIndex: number = valueWithoutHtml.toLowerCase().indexOf(filterText);
if (filterIndex < 0) {
return null;
} else {
// TODO:
// just need to figure how we can highlight properly
// real issue is to identify proper index for warping <span class='search-highlight'> </span>
return "";
}
}
我们如何对 html 字符串进行扭曲?任何帮助或指导将不胜感激。
你可以使用的一件事是获取客户端矩形的方法Range目的:https://developer.mozilla.org/en-US/docs/Web/API/range/getClientRects
这允许您添加带有搜索坐标的 div,从而无需操作 DOM 即可突出显示文本。
查找节点并不是那么简单(特别是如果您有复杂的结构),但您可以迭代所有文本节点以匹配要搜索的元素的 textContent 中的搜索索引。
因此,首先将搜索结果与 DOM 进行匹配。在示例中,我使用递归生成器,但任何递归循环都可以。基本上,您需要做的是遍历每个文本节点以匹配搜索的索引。因此,您将遍历每个后代节点并计算文本长度,以便将搜索与节点相匹配。
完成此操作后,您可以创建一个Range从这些结果中,然后使用获得的矩形的坐标添加元素获取客户端矩形。通过给定 z-index 负值和绝对位置,它们将出现在文本下方的正确位置。因此,您将获得突出显示效果,但不会触及您正在搜索的 HTML。
像这样:
document.querySelector('#a').onclick = (e) => {
let topParent = document.querySelector('#b');
let s, range;
let strToSearch = document.querySelector('#search').value
let re = RegExp(strToSearch, 'g')
removeHighlight()
s = window.getSelection();
s.removeAllRanges()
// to handle multiple result you need to go through all matches
while (match = re.exec(topParent.textContent)) {
let it = iterateNode(topParent);
let currentIndex = 0;
// the result is the text node, so you can iterate and compare the index you are searching to all text nodes length
let result = it.next();
while (!result.done) {
if (match.index >= currentIndex && match.index < currentIndex + result.value.length) {
// when we have the correct node and index we add a range
range = new Range();
range.setStart(result.value, match.index - currentIndex)
}
if (match.index + strToSearch.length >= currentIndex && match.index + strToSearch.length < currentIndex + result.value.length) {
// when we find the end node, we can set the range end
range.setEnd(result.value, match.index + strToSearch.length - currentIndex)
s.addRange(range)
// this is where we add the divs based on the client rects of the range
addHighlightDiv(range.getClientRects())
}
currentIndex += result.value.length;
result = it.next();
}
}
s.removeAllRanges()
}
function* iterateNode(topNode) {
// this iterate through all descendants of the topnode
let childNodes = topNode.childNodes;
for (let i = 0; i < childNodes.length; i++) {
let node = childNodes[i]
if (node.nodeType === 3) {
yield node;
} else {
yield* iterateNode(node);
}
}
}
function addHighlightDiv(rects) {
for (let i = 0; i < rects.length; i++) {
let rect = rects[i];
let highlightRect = document.createElement('DIV')
document.body.appendChild(highlightRect)
highlightRect.classList.add('hl')
highlightRect.style.top = rect.y + window.scrollY + 'px'
highlightRect.style.left = rect.x + 'px'
highlightRect.style.height = rect.height + 'px'
highlightRect.style.width = rect.width + 'px'
}
}
function removeHighlight() {
let highlights = document.querySelectorAll('.hl');
for (let i = 0; i < highlights.length; i++) {
highlights[i].remove();
}
}
.hl {
background-color: red;
position: absolute;
z-index: -1;
}
<input type="text" id="search" /><button id="a">search</button>
<div id="b">
<h1>Lorem ipsum dolor sit amet</h1>, consectetur
<h2>adipiscing elit, sed do</h2> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <strong>exercitation <span>ullamco laboris</span> nisi ut aliquip ex ea commodo</strong> consequat. Duis aute irure dolor
in reprehenderit in voluptate velit <em>esse cillum dolore eu fugiat nulla pariatur.</em> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)