Rangy:range.selectCharacters()返回的索引更改取决于HTML结构

时间:2019-06-22 15:03:06

标签: javascript html rangy

我需要在文本中突出显示一些逗号。为此,我首先获取所有逗号的索引:

for (let i = 0; i < text.length; i++) {
      if (text[i] == ',')
          commaIndexes.push(i);
}

好吧,我想这里缺少一些逗号了,对吧?,这些索引分别是4和42。

然后将这段文本包装在我从diff算法获得的跨度中:

<span>Well</span>
<span>,</span>
<span> I guess there's a few commas missing</span>
<span>,</span>
<span> right?</span>

我想使用Rangy通过索引选择逗号:

// Create a Rangy range at the index that should contain a comma
let range = rangy.createRange();

// I'd expect the range to include the comma and only the comma.
range.selectCharacters(fragment, index, index + 1);

这仅适用于文本中的第一个逗号。将文本换成跨度似乎可以改变索引,我可以弄清楚一个系统:对于每个逗号,我需要在每个其他逗号的索引中加上2:

for (let i = 0; i < text.length; i++) {
    if (text[i] == ',')
        commaIndexes.push(i + 2 * commaIndexes.length);
}

我的代码现在可以正常工作,但是我想了解发生了什么。据我了解,Rangy的range.selectCharacters方法应根据可见文本的索引选择字符,而文本是否用跨距包裹也没关系。

编辑:我的第二个代码示例中有换行符。我从Chrome的开发人员工具复制了此内容。换行符可能会引起我的问​​题,但是,我不确定是DOM的一部分还是仅显示在开发工具中。这是我要做的所有将文本换成跨距的操作:

// Create new span to host the segment
let span = document.createElement('span');

// Set text and append span
span.innerText = 'some text';
fragment.appendChild(span); 

第二次修改:代码段

rangy.init();

// A sample text. Commas should be at (zero-based) indexes 4 and 42.
let text = "Well, I guess there's a few commas missing, right?";

// Store zero-based comma indexes
let commaIndexes = [];

for (let i = 0; i < text.length; i++) {
      if (text[i] == ',')
          commaIndexes.push(i);
}

// Simulate diff output
let substrings = [
  'Well',
  ',',
  " I guess there's a few commas missing",
  ',',
  ' right?'
];

// Create a DOM fragment to hold all spans created in the next step
let fragment = document.createDocumentFragment();

// Create new span for each substring
substrings.forEach(substring => {
    let span = document.createElement('span');

    // Set text and append span
    span.innerText = substring;
    fragment.appendChild(span);
});

commaIndexes.forEach(index => {
    // Create a Rangy range
    let range = rangy.createRange();

    // I guess selectCharacters is one-based, left index including, right index excluding?
    range.selectCharacters(fragment, index + 1, index + 2);

    // I get the first comma and the 'g' preceding the second one
    console.log(range.text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-selectionsaverestore.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.js"></script>

0 个答案:

没有答案