在节点上选择多个单词并存储相对于根元素的textContent

时间:2019-03-22 00:14:33

标签: javascript browser selection textselection rangy

我正在开发一个电子学习应用程序。在一个练习中,我想让我们的学生阅读课文,标记我输入的错误并评估他们的回答。

使用Rangy,我解决了一些与文本选择有关的问题(假设有一个<p id='myText'>包含要纠正的文本):

  • 用户可以在点击时在myText中标记文本。我之所以说 mark 是因为尽管我在过程中确实使用了Selection API,但最终它还是一种更持久的选择。
  • 标记始终扩展到单词级别。每次点击都标记一个单词。
  • 可以标记介于0到n之间的任何单词数(其中 n myText.innerText中的单词数)。
  • 每个标记的单词都使用highlight类的跨度来设置样式。

我用几行代码使用Vue来完成所有这些工作。每当我点击myText时,就会触发此功能:

highlight: function() {
    // Get Selection
    let selection = this.$rangy.getSelection();

    // Some RegEx checking omitted

    // Expand selection to word boundaries
    selection.expand('word');

    // Some more RegEx checking omitted

    // A range represents a continuous part of selected text
    let range = selection.getRangeAt(0);

    // Highlight text or remove marking
    let applier = this.$rangy.createClassApplier('highlight');
    applier.toggleRange(range);
}

我需要将标记的单词与实际包含错误的单词列表进行比较,因此我尝试存储每个选定范围的索引。但是似乎任何浏览器API或Rangy中都没有任何函数可以为我提供相对于文本本身的索引,我只能在myText中获得相对于 HTML 的索引-这正在发生变化每个标记或取消标记都会随着Rangy插入跨度而突出显示用户选择的单词。

我的问题是否有很好的解决方案?我可以将每个标记的单词及其左,右邻居(单词与myText的边界之间的文本)存储起来,并将其与myText内容的纯文本版本进行比较,但这似乎相当笨拙。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我认为有一个highlighter module in Rangy听起来像您想要的。 Rangy还具有各种API,用于返回相对于页面内文本的范围和选择。希望文档会有所帮助,我可以回答出现的问题。