Skip to content

Instantly share code, notes, and snippets.

@lawvs
Created March 2, 2018 01:54
Show Gist options
  • Save lawvs/fc579107acd203b2775fca4582070c99 to your computer and use it in GitHub Desktop.
Save lawvs/fc579107acd203b2775fca4582070c99 to your computer and use it in GitHub Desktop.
高亮HTMLElement
/**
* Highlights text within a dom element.
*
* Specifically this is designed to work with the output
* positions of terms returned from a lunr search.
*
* @param {HTMLElement} element - the element that contains text to highlight.
* @param {MatchLocation[]} matches - the list of matches to highlight.
*/
module.exports = function (element, matches) {
var nodeFilter = {
acceptNode: function (node) {
if (/^[\t\n\r ]*$/.test(node.nodeValue)) {
return NodeFilter.FILTER_SKIP
}
return NodeFilter.FILTER_ACCEPT
}
}
var index = 0,
matches = matches.sort(function (a, b) { return a[0] - b[0] }).slice(),
previousMatch = [-1, -1]
match = matches.shift(),
walker = document.createTreeWalker(
element,
NodeFilter.SHOW_TEXT,
nodeFilter,
false
)
while (node = walker.nextNode()) {
if (match == undefined) break
if (match[0] == previousMatch[0]) continue
var text = node.textContent,
nodeEndIndex = index + node.length;
if (match[0] < nodeEndIndex) {
var range = document.createRange(),
tag = document.createElement('mark'),
rangeStart = match[0] - index,
rangeEnd = rangeStart + match[1];
tag.dataset.rangeStart = rangeStart
tag.dataset.rangeEnd = rangeEnd
range.setStart(node, rangeStart)
range.setEnd(node, rangeEnd)
range.surroundContents(tag)
index = match[0] + match[1]
// the next node will now actually be the text we just wrapped, so
// we need to skip it
walker.nextNode()
previousMatch = match
match = matches.shift()
} else {
index = nodeEndIndex
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment