代码之家  ›  专栏  ›  技术社区  ›  Seungho Lee

如何检查web上的选定文本是否仅由JavaScript中的单词组成?

  •  4
  • Seungho Lee  · 技术社区  · 7 年前

    在vanilla Javascript中,我试图确定用户在网页上选择的文本是否全部由单词组成(不包括符号)。

    举个例子,,

    假设我们在网页的某个地方有如下文本。

    您好,以文本为例! (选择“全部”时)

    应该导致 ['Hello', 'a', 'text', 'for', 'the', 'example']

    然而,

    赫尔 lo,以文本为例!

    应该导致 ['a', 'text', 'for', 'the', 'example'] 自从 Hello 未完全选定为单词。

    getSelectionText 函数,用于显示所有选定文本。

    function getSelectionText() {
        var text = "";
        if (window.getSelection) {
            text = window.getSelection().toString();
        } else if (document.selection && document.selection.type !== "Control") {
            text = document.selection.createRange().text;
        }
        return text;
    }
    
    // Just adding the function as listeners.
    document.onmouseup = document.onkeyup = function() {
        console.log(getSelectionText());
    };
    

    1 回复  |  直到 7 年前
        1
  •  5
  •   nem035    7 年前

    一种方法是有一本包含所有英语单词的完整词典。

    const setOfAllEnglishWords = new Set([
      "Hello",
      "a",
      "text",
      "for",
      "the",
      "example"
      // ... many many more
    ]);
    
    const selection = "lo, a text for the example!";
    const result = selection
      .replace(/[^A-Za-z0-9\s]/g, "") // remove punctuation by replacing anything that is not a letter or a digit with the empty string
      .split(/\s+/)                   // split text into words by using 1 or more whitespace as the break point
      .filter(word => setOfAllEnglishWords.has(word));
    
    console.log(result);

    218632 话。平均字长为 4.5 信件和JS商店 2 218632 * (4.5 * 2) = 1967688 B = 1.967 MB ,在慢速3G连接上下载可能需要1分钟。

    function getSetOfWordsOnPage() {
      const walk = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_TEXT
      );
    
      const dict = new Set();
      let n;
      while ((n = walk.nextNode())) {
        for (const word of n.textContent
          .replace(/[^A-Za-z0-9\s]/g, "")
          .split(/\s+/)
          .map(word => word.trim())
          .filter(word => !!word)) {
          dict.add(word);
        }
      }
      return dict;
    }
    
    const setOfWordsOnThePage = getSetOfWordsOnPage();
    
    function getSelectionText() {
      if (window.getSelection) {
        return window.getSelection().toString();
      } else if (document.selection && document.selection.type !== "Control") {
        return document.selection.createRange().text;
      }
      return "";
    }
    
    // Just adding the function as listeners.
    document.querySelector("#button").addEventListener("click", () => {
      const result = getSelectionText()
        .replace(/[^A-Za-z0-9\s]/g, "") // remove punctuation
        .split(/\s+/) // split text into words
        .filter(word => setOfWordsOnThePage.has(word));
      console.log(result);
    });
    <button id="button">Show result</button>
    <p>this is some text</p>
    <p>again this is a text!!!!!</p>
    <p>another,example,of,a,sentence</p>

    也许我们可以更进一步。我们甚至需要记住单词吗?“单词是由空格包围的文本”的定义似乎已经足够了。

    为了减少记住页面上单词的不必要开销,并解决部分选择有效单词的错误,我们可以在选择后立即检查所选区域最左侧(锚定)和最右侧(焦点)节点的内容,如果它们包含其他未选择的文本,则忽略它们。

    我们在这里做的假设是,对于任意选择的文本,我们最多可以有2个部分选择的单词,每个选择端一个。

    注: 下面的方法还通过假设 THIS tHiS ,及 this 都是同一个词。

    function removePunctuation(string) {
      return string.replace(/[^A-Za-z0-9\s]/g, " ");
    }
    
    function splitIntoWords(string) {
      return removePunctuation(string)
        .split(/\s+/)
        .map(word => word.toLowerCase().trim())
        .filter(word => !!word);
    }
    
    function getSelectedWords() {
      const selection = window.getSelection();
      const words = splitIntoWords(selection.toString());
    
      if (selection.anchorNode) {
        const startingsWords = splitIntoWords(selection.anchorNode.textContent);
        if (words[0] !== startingsWords[0]) {
          words.shift(); // remove the start since it's not a whole word
        }
      }
    
      if (selection.focusNode) {
        const endingWords = splitIntoWords(selection.focusNode.textContent);
        if (words[words.length - 1] !== endingWords[endingWords.length - 1]) {
          words.pop(); // remove the end since it's not a whole word
        }
      }
    
      return words;
    }
    
    // Just adding the function as listeners.
    document.querySelector("#button").addEventListener("click", () => {
      console.log(getSelectedWords());
    });
    <button id="button">Show result</button>
    <p><div>this is</div> <div>some text</div></p>
    <p><span>again</span><span> </span><span>this</span><span> </span><span>is</span><span> </span><span>a</span> <span>text</span><span>!!!!!</span></p>
    <p>another,example,of,a,sentence</p>

    注: 如果您将单词分解为多个html元素,则此代码仍然会中断 <span>w</span><span>o</span><span>r</span><span>d</span>