根据textContent中的索引突出显示文本

wiz*_*zz4 11 javascript text dom highlight offset

赏金

正如jsPerf所展示的那样,赏金将在测试时通过最新版本的Firefox,Chrome和Internet Explorer获得最快的解决方案,或者在我自行决定创建此类解决方案最有用的答案.Mwahahaha!

我将主要满足的是通吃的溶液偏移 S和未处理<span>,并添加突出显示的是,让parent.textContent = parent.textContent后面运行的偏移将重新的更新列表上的解决方案的亮点,但这不利的时间复杂度所以不是首选.


相关问题


我有一个只包含文本的元素,我想强调一下.我也有一个数组[startline, startcol, endline, endcol],知道每行的长度.textContent,我可以标准化为[startoffset, endoffset].如何在每对偏移 s 之间突出显示

这个问题比看起来更难,因为:

  • 内容不保证没有重复(所以没有查找/替换),和
  • 必须最终对已经突出显示的文本执行突出显示,有时与已突出显示的文本相交,并且
  • 必须根据父元素.textContent属性的索引执行突出显示.

定义

  • 亮点:放置文本的子集从一个元素的textContent一个或多个<span class="highlighted">而不改变父元素的textContent值,即突出显示的n倍为n嵌套内,使得文本<span class="highlighted">元素.
  • offset:一个非负整数,表示某个点之前的字符数(在两个字符之间).
  • character:一个JavaScript给你的实例,作为.textContent字符串给定索引(包括空格)的值.

MCVE

function highlight(parent, startoff, endoff) {
  // Erm...
  parent.textContent;
}

// Test cases

var starts = [
  5,  44, 0, 50, 6,  100, 99,  50, 51, 52
];
var ends = [
  20, 62, 4, 70, 10, 100, 101, 54, 53, 53
];
for (var i = 0; i < 10; i += 1) {
  highlight(document.getElementById("target"),
            starts[i], ends[i]);
}
Run Code Online (Sandbox Code Playgroud)
#target {
  white-space: pre-wrap;
}
Run Code Online (Sandbox Code Playgroud)
<span id="target">
'Twas brillig, and the slithy toves
  Did gyre and gimble in the wabe:
All mimsy were the borogoves,
  And the mome raths outgrabe.

"Beware the Jabberwock, my son!
  The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
  The frumious Bandersnatch!"

He took his vorpal sword in hand:
  Long time the manxome foe he sought --
So rested he by the Tumtum tree,
  And stood awhile in thought.

And, as in uffish thought he stood,
  The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
  And burbled as it came!

One, two! One, two! And through and through
  The vorpal blade went snicker-snack!
He left it dead, and with its head
  He went galumphing back.

"And, has thou slain the Jabberwock?
  Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!'
  He chortled in his joy.

'Twas brillig, and the slithy toves
  Did gyre and gimble in the wabe;
All mimsy were the borogoves,
  And the mome raths outgrabe.
</span>
Run Code Online (Sandbox Code Playgroud)

sky*_*yer 5

对开始/结束位置进行标准化以避免重叠。

  1. 将起始位置和结束位置合并到具有相反值的单个列表(例如,-1 和 1)
  2. 按位置值排序列表,然后 - 按标记值(基于二级排序,您可以区分顺序范围合并它们)
  3. 查看位置列表并将当前位置的值标记添加到当前总和;一旦它是“0”——这意味着你刚刚找到了一些嵌套/相交部分的结尾;

这样,您将获得没有嵌套/重叠范围的突出显示位置。

用文本节点和 HTML 元素(如<span>)的混合替换文本节点documentFragment.replaceChild()将有助于:

let starts = [
    5,  44, 0, 50, 6,  100, 99,  50, 51, 52
];
let ends = [
    20, 62, 4, 70, 10, 100, 101, 54, 53, 53
];

let positions = [];
let normalizedPositions = [];
starts.forEach(function(position) {
    positions.push({position, value: 1});
});
ends.forEach(function(position) {
    positions.push({position, value: -1});
});
positions = positions.sort(function(a, b) {
    return a.position - b.position || 
        b.value - a.value
});

var currentSection = {from: 0, counter: 0};

for(position of positions) {
    if (!currentSection.counter) {
        if (position.value === -1) {
            throw `inconsistent boundaries: closing before opening ${position.position}`;
        }
        currentSection.from = position.position;  
    }
    currentSection.counter += position.value;

    if (!currentSection.counter) { 
        normalizedPositions.push({
            from: currentSection.from, 
            to: position.position
        });
    }
}
if (currentSection.counter) {
    throw "last section has not been closed properly";   
}


let parentNode = document.querySelector('p');
let textNodeToReplace = parentNode.childNodes[0];
let sourceText = textNodeToReplace.nodeValue;

let documentFragment = document.createDocumentFragment();
let withoutHighlightingStart = 0;

normalizedPositions.forEach(function (highlightRange) {
    if (highlightRange.from> withoutHighlightingStart) {
      let notHighlighted = createTextNode(sourceText.slice(withoutHighlightingStart, highlightRange.from));
      documentFragment.appendChild(notHighlighted);
    }
    let highlighted = createHighlighted(sourceText.slice(highlightRange.from, highlightRange.to));
    documentFragment.appendChild(highlighted);
    withoutHighlightingStart = highlightRange.to;
});
let lastNotHighlighted = createTextNode(sourceText.slice(withoutHighlightingStart));
documentFragment.appendChild(lastNotHighlighted);

parentNode.replaceChild(documentFragment, textNodeToReplace);

function createTextNode(str) {
   return document.createTextNode(str);
}

function createHighlighted(str) {
   let span = document.createElement('span');
   span.classList.add('highlight');
   span.appendChild(createTextNode(str));
   return span;
}
Run Code Online (Sandbox Code Playgroud)
.highlight {
    background-color: yellow;
    color: dark-blue;
}
Run Code Online (Sandbox Code Playgroud)
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
Run Code Online (Sandbox Code Playgroud)