javascript - 突出显示句子中单击时的单词

标签 javascript

在 Javascript 中,我编写了一个脚本,用于在用户单击某个单词时突出显示该单词。

这个问题在某些地方已经得到了回答。我已经利用这些解决方案中的答案来创建这个运行得很好的脚本。

$(".clickable").click(function(e){
      var selectedVocabPhrase = null
      var matchedVocabPhrase = null
      var selection = window.getSelection()

      if (selection.anchorNode.parentNode.nodeName === 'STRONG') {
        selectedVocabPhrase = selection.anchorNode.parentNode.innerText
      }
      if (!selection || selection.rangeCount < 1) return true;
      var range = selection.getRangeAt(0);
      var node = selection.anchorNode;

      var word_regexp = /^\w*$/;

      // Extend the range backward until it matches word beginning
      while ((range.startOffset > 0) && range.toString().match(word_regexp)) {
        range.setStart(node, (range.startOffset - 1));
      }
      // Restore the valid word match after overshooting
      if (!range.toString().match(word_regexp)) {
        range.setStart(node, range.startOffset + 1);
      }

      // Extend the range forward until it matches word ending
      while ((range.endOffset < node.length) && range.toString().match(word_regexp)) {
        range.setEnd(node, range.endOffset + 1);
      }
      // Restore the valid word match after overshooting
      if (!range.toString().match(word_regexp)) {
        range.setEnd(node, range.endOffset - 1);
      }
  console.log(range.toString().trim());
});

JSBIN 链接在这里...

https://jsbin.com/faxibolebu/edit?html,js,console,output

但是,存在问题/例如,如果一个单词有 hypth - 例如 co-worker,那么如果单击 co,则只会突出显示 co。如果单击“worker”,则仅突出显示“worker”。类似的问题也发生在包含撇号的单词上,例如不能。这个词被 split 了。

我无法解决这个问题。如有任何帮助,我们将不胜感激。

最佳答案

不要匹配 \w* - 仅匹配单词字符 - 考虑匹配 \S*,它匹配任何非空格字符。

为了排除尾随 .,,请将 (?![.,])\S 添加到末尾 (向前查找除 ., 之外的任何内容,然后匹配任何非空格字符)。

此外,如果用户故意单击并拖动来选择文本,您可能会考虑按原样保留现有的突出显示(这对用户更加友好,并避免奇怪和/或模棱两可的行为,例如当选择多个单词时)。通过检查 startOffset 是否等于 endOffset 来执行此操作:

$(".clickable").click(function(e) {
  var selectedVocabPhrase = null
  var matchedVocabPhrase = null
  var selection = window.getSelection()

  if (selection.anchorNode.parentNode.nodeName === 'STRONG') {
    selectedVocabPhrase = selection.anchorNode.parentNode.innerText
  }
  if (!selection || selection.rangeCount < 1) return true;
  var range = selection.getRangeAt(0);
  if (range.startOffset !== range.endOffset) {
    // User selected at least one character themselves; don't change anything
    return;
  }
  var node = selection.anchorNode;

  var word_regexp = /^(?:|\S*(?![.,])\S)$/;

  // Extend the range backward until it matches word beginning
  while ((range.startOffset > 0) && range.toString().match(word_regexp)) {
    range.setStart(node, (range.startOffset - 1));
  }
  // Restore the valid word match after overshooting
  if (!range.toString().match(word_regexp)) {
    range.setStart(node, range.startOffset + 1);
  }

  // Extend the range forward until it matches word ending
  while ((range.endOffset < node.length) && range.toString().match(word_regexp)) {
    range.setEnd(node, range.endOffset + 1);
  }
  // Restore the valid word match after overshooting
  if (!range.toString().match(word_regexp)) {
    range.setEnd(node, range.endOffset - 1);
  }
  console.log(range.toString().trim());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="clickable">
  <div>
    <div>
      <div class="v-popover">
        <span aria-describedby="popover_8k4slo118o" tabindex="-1" class="trigger" style="display: inline-block;">
            <span>When office worker Laura Garzón visited a butcher's shop in Bogota, she <strong>couldn't believe her eyes</strong>.
            </span>
        </span>
      </div>
      <div class="v-popover">
        <span aria-describedby="popover_tb8xft1vhg" tabindex="-1" class="trigger" style="display: inline-block;">
            <span> Standing behind the counter was her co-worker, Jorge Castro.
            </span>
        </span>
      </div>
      <div class="v-popover"><span aria-describedby="popover_1b3s8fw9ee" tabindex="-1" class="trigger" style="display: inline-block;">
          <span style="cursor: pointer; display: inline !important;"> But instead of wearing a suit and tie, he was wearing a bloodstained butcher's apron and white cap.
          </span>
        </span>
      </div>
    </div>
  </div>
</div>

关于javascript - 突出显示句子中单击时的单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60199437/

相关文章:

javascript - 如何在同一页面中添加 2 个 signature_pad

javascript - typescript 错误 : Property 'log' does not exist on type {. ..} - Console.log()

javascript - 如何在Javascript中将数字作为字符串创建关联数组

javascript - 使用 JavaScript 隐藏/删除 ul 类中的文本

javascript - php foreach 循环中的隐藏输入值未正确传递给 JQuery

javascript - 无法捕获fabricjs中的拖动事件

javascript - 在 Angular 插值中使用 Array.map

javascript - 我需要使用用户的输入动态更新 iframe

javascript - 访问包含从右到左文本的元素时出现奇怪问题

javascript - (向后/向前)按键时的 DOM 导航