【问题标题】:Selection to word boundaries, but excluding punctuation signs选择单词边界,但不包括标点符号
【发布时间】:2014-05-29 09:07:05
【问题描述】:

我尝试将用户所做的选择修改为始终是完整的单词。例如,鉴于文本“报告:奥巴马总统寻求在阿富汗保留 9,800 名美军……消息人士称,今年之后”,如果用户只选择“fghanist”,我希望选择修改为“阿富汗”。经过一番搜索,我在 Stackoverflow 上偶然发现了 here,得到了以下解决方案:

snapSelectionToWord : function() {
  var sel;
  if (window.getSelection && (sel = window.getSelection()).modify) {
    sel = window.getSelection();
    if (!sel.isCollapsed) {
        // Detect if selection is backwards
        var range = document.createRange();
        range.setStart(sel.anchorNode, sel.anchorOffset);
        range.setEnd(sel.focusNode, sel.focusOffset);

        var backwards = range.collapsed;
        range.detach();

        // modify() works on the focus of the selection
        var endNode = sel.focusNode, endOffset = sel.focusOffset;
        sel.collapse(sel.anchorNode, sel.anchorOffset);

        var direction = [];
        if (backwards) {
            direction = ['backward', 'forward'];
        } else {
            direction = ['forward', 'backward'];
        }

        sel.modify("move", direction[0], "character");
        sel.modify("move", direction[1], "word");
        sel.extend(endNode, endOffset);
        sel.modify("extend", direction[1], "character");
        sel.modify("extend", direction[0], "word");
    }
  } else if ( (sel = document.selection) && sel.type != "Control") {
      var textRange = sel.createRange();
      if (textRange.text) {
        textRange.expand("word");
        // Move the end back to not include the word's trailing space(s), if necessary
        while (/\s$/.test(textRange.text)) {
            textRange.moveEnd("character", -1);
        }
        textRange.select();
    }
  }
},

原则上,它工作得很好。然而,也有一些病态的案例。例如,选择“fghanistan..”它会捕捉到“Afghanistan...after”(我想要“Afghanistan”)。我选择“.afte”得到的结果相同(这里的期望结果:“after”)。主要问题似乎是粒度word 只考虑空格而不考虑其他标点符号。

我现在的想法是将粒度从 word 更改为 character 并将其放入循环中,直到达到标点符号。这对于sel.modify("extend", ...); 行非常有效,但对于sel.modify("move", ...); 行却不是(如预期的那样)。在collapse 和第一个move 修改之后,sel.toString() 都是空的。因此,我不能循环第一个/最后一个字符来逐个字符移动。在sel.extend(endNode, endOffset);之后,再次设置sel.toString(),使用循环的方法就可以了。

我根本无法理解这一点。

【问题讨论】:

  • 自动选择整个单词的应用程序让我发疯。请注意,有些用户会非常讨厌这一点。 :-)
  • RobG,同意!我也不喜欢被光顾:)。但是,我的目标是用户注释文本 sn-ps 的系统。也就是说,他们首先选择一个 sn-p,然后可以对其进行注释。我认为在这种情况下对齐单词边界是合理的。

标签: javascript html dom selection


【解决方案1】:

我偶然发现了rangy,它很好地解决了我的问题。使用这个库将我的功能减少到:

snapSelectionToWord : function() {
  rangy.getSelection().expand("word");
},

感谢开发者让我的生活变得如此轻松!

【讨论】:

    猜你喜欢
    • 2020-06-03
    • 2016-05-08
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    相关资源
    最近更新 更多