文本搜索后如何设置选择?

How do I setSelection after a text search?

我正在尝试向 Quill 添加搜索功能,并希望突出显示它找到的文本。我在获取它找到的文本的范围索引时遇到问题,很可能我没有使用正确的方法。

到目前为止,我使用 getContents() 获取文本并且可以通过遍历行找到匹配项。但是,我无法找到 setSelection() 的正确索引位置。第二个问题是我希望 window 滚动到找到选择的位置,但它没有滚动到视图中。

...
myKeyPhrases = ['obvious', 'orange', 'apple'];

var myDelta = editor.getContents();
myDelta.eachLine((line, attributes, i) => {

    mytext = line.filter((op) => typeof op.insert === 'string').map((op) => op.insert).join('');
    mytext = mytext.toLowerCase();

    ndx = isKeyPhraseFound(mytext, myKeyPhrases); 
    if (ndx >= 0){
        // The code finds the matches OK to here.
        // The next 4 lines don't get the correct range and scroll.
        index = i;
        editor.focus();
        editor.setSelection(index, 1, Quill.sources.USER); 
        editor.scrollIntoView();
        return index;
    }
});

我想要的结果是选择找到的文本匹配项,然后滚动 window 以便显示选择。实际结果是选择了错误的文本,window 没有滚动查看选择。

你基本上就在那里。我怀疑你的问题是你过滤掉了块元素,这类似于 Quill 的 getText 方法。根据文档:

Non-string content are omitted, so the returned string’s length may be shorter than the editor’s as returned by getLength.

这是因为非文本元素的长度通常为 1,因此对于您省略的每一个元素,您的索引都会漂移 1。

一个简单的解决方法是用换行符替换任何非文本元素,换行符的长度为 1,还有导致搜索失败的额外好处(除非您让用户使用换行符搜索 - 也许然后你可以选择另一个特殊字符,如控制字符)。

以下方法应该 return 长度匹配 quill.getLength 的 Quill 内容的纯文本表示,因此应该能够使用任何 JavaScript 文本搜索方法进行搜索您想要(例如 indexOf 用于简单搜索)。

function textContents() {
  return quill.getContents().ops
    .reduce((text, op) => {
      if (typeof op.insert === 'string') {
        // If the op is a string insertion, just concat
        return text + op.insert;
      } else {
        // Otherwise it's a block. Represent this as a newline,
        // which will preserve the length of 1, and also prevent
        // searches matching across the block
        return text + '\n';
      }
    }, '');

}

这是一个粗略的例子:https://codepen.io/alecgibson/pen/GLVzPb