【问题标题】:replace selected text in contenteditable div替换 contenteditable div 中的选定文本
【发布时间】:2011-04-29 04:47:49
【问题描述】:

我一直在寻找答案,但都失败了。

是否有跨浏览器解决方案来替换 contenteditable div 中的选定文本?
我只是希望用户突出显示一些文本并将突出显示的文本替换为xxxxx

【问题讨论】:

    标签: javascript contenteditable


    【解决方案1】:

    以下将在所有主要浏览器中完成这项工作:

    function replaceSelectedText(replacementText) {
        var sel, range;
        if (window.getSelection) {
            sel = window.getSelection();
            if (sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.deleteContents();
                range.insertNode(document.createTextNode(replacementText));
            }
        } else if (document.selection && document.selection.createRange) {
            range = document.selection.createRange();
            range.text = replacementText;
        }
    }
    

    【讨论】:

    • @DavidJeske:这在 Chrome 中确实适用于 contenteditable 元素,但不适用于输入或文本区域:在非 IE 浏览器中,此代码特定于常规内容中的选择。
    • @TimDown 我正在使用一些类似的rangy 代码(替换 iframe 上的文本节点)。使用sel.setSingleRange(range) 不选择replacementText 是否正常?
    • 不是 OP 要求的,只是提醒其他人,getSelection 在使用表单字段时不会在 Firefox 中捕获所选文本:bugzilla.mozilla.org/show_bug.cgi?id=85686
    • 此解决方案有一个错误:尝试撤消粘贴的文本。
    • @TimDown 是的,如果使用范围方法修改它,则不会处理撤消堆栈。所以最好添加一些这样的检查:if (document.queryCommandSupported('insertText')) { document.execCommand( 'insertText', false, replacementText ); } else { range.deleteContents(); range.insertNode(document.createTextNode(replacementText)); }
    【解决方案2】:

    我在how to add emoji in between the letters in contentEditable div? 上发布了一个工作示例,您可以使用它来替换内容可编辑 div 中所需的文本

      function pasteHtmlAtCaret(html) {
            let sel, range;
            if (window.getSelection) {
              // IE9 and non-IE
              sel = window.getSelection();
              if (sel.getRangeAt && sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.deleteContents();
    
                // Range.createContextualFragment() would be useful here but is
                // non-standard and not supported in all browsers (IE9, for one)
                const el = document.createElement("div");
                el.innerHTML = html;
                let frag = document.createDocumentFragment(),
                  node,
                  lastNode;
                while ((node = el.firstChild)) {
                  lastNode = frag.appendChild(node);
                }
                range.insertNode(frag);
    
                // Preserve the selection
                if (lastNode) {
                  range = range.cloneRange();
                  range.setStartAfter(lastNode);
                  range.collapse(true);
                  sel.removeAllRanges();
                  sel.addRange(range);
                }
              }
            } else if (document.selection && document.selection.type != "Control") {
              // IE < 9
              document.selection.createRange().pasteHTML(html);
            }
          }
    
          function addToDiv(event) {
            const emoji = event.target.value;
            const chatBox = document.getElementById("chatbox");
            chatBox.focus();
            pasteHtmlAtCaret(`<b>${emoji}</b>`);
          }
          function generateEmojiIcon(emoji) {
            const input = document.createElement("input");
            input.type = "button";
            input.value = emoji;
            input.innerText = emoji;
            input.addEventListener("click", addToDiv);
            return input;
          }
          const emojis = [
            {
              emoji: "?",
            },
            {
              emoji: "❤️",
            },
          ];
          emojis.forEach((emoji) => {
            document
              .getElementById("emojis")
              .appendChild(generateEmojiIcon(emoji.emoji));
          });
          #emojis span {
            cursor: pointer;
          }
          #chatbox {
            border: 1px solid;
          }
     <button
      type="button"
      onclick="document.getElementById('chatbox').focus(); 
      pasteHtmlAtCaret('<b>INSERTED</b>'); "
    >
      Paste HTML
    </button>
        <div id="emojis"></div>
        <div id="chatbox" contenteditable></div>

    【讨论】:

    • 为什么点击粘贴html后所有的文字都变粗了?又怎么能粘贴的文字只有粗体,其他的都是正常的呢?
    • @SAF 你可以用你喜欢的任何东西替换 js 中 &lt;b&gt;INSERTED&lt;/b&gt;&lt;b&gt;${emoji}&lt;/b&gt; 中的标签 b。您可以使用 innerText 代替它,只需对 sn-p 代码进行一些更改...
    • 关于后面的问题,我应该再探讨一下……
    【解决方案3】:

    我需要替换文本节点,并在粘贴时保留 html 实体。 这就是我解决问题的方法,不确定 textnodes 中的 data,也许最好使用 textContent 或其他的东西

    let selection = window.getSelection()
      , range = selection.getRangeAt(0)
      , fragment = range.extractContents();
    
    fragment.childNodes.forEach( e => e.data && (e.data = doSomething(e.data)) );
    range.insertNode(fragment);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2013-08-28
      • 2018-02-21
      • 2011-11-16
      • 2014-02-04
      • 1970-01-01
      • 2011-09-09
      相关资源
      最近更新 更多