代码之家  ›  专栏  ›  技术社区  ›  SeaBass

内容可编辑的粘贴修复

  •  4
  • SeaBass  · 技术社区  · 7 年前

    我正在运行一个脚本,用contenteditable清理div中粘贴的文本。

    它工作得很好,但是在FF中,如果文本被复制到同一个div或div之间,换行符就会被删除。

    有什么解决办法吗?
    如果我从不同的源粘贴文本,换行符将保持不变。
    我也愿意接受不同的解决方案。

    // Paste fix for contenteditable
    $(document).on('paste', '[contenteditable]', function (e) {
        e.preventDefault();
    
        if (window.clipboardData) {
            content = window.clipboardData.getData('Text');        
            if (window.getSelection) {
                var selObj = window.getSelection();
                var selRange = selObj.getRangeAt(0);
                selRange.deleteContents();                
                selRange.insertNode(document.createTextNode(content));
            }
        } else if (e.originalEvent.clipboardData) {
            content = (e.originalEvent || e).clipboardData.getData('text/plain');
            document.execCommand('insertText', false, content);
        }        
    });
    div {
      white-space: pre-wrap;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div contenteditable="true">Copy
    and
    paste
    this
    back in the same box or the one below. Where do they line-breaks go in FF?</div>
    <div contenteditable="true">Copy
    and
    paste
    this
    back in the same box or the one above. Where do they line-breaks go FF?</div>
    1 回复  |  直到 5 年前
        1
  •  5
  •   Giacomo Penuti    7 年前

    正如所承诺的那样,这里有一个工作解决方案,在讨论的评论中讨论了这种实施。

    使用选择和范围API时( https://developer.mozilla.org/en-US/docs/Web/API/Range ),我发现Range对象有一个toString()方法,我想测试它,看看这里、之前或之后是否修剪了换行符。

    幸运的是,我发现FF Range对象中的toString()方法没有修剪换行符。

    根据这一点,这里是我的代码和小提琴来覆盖默认的复制函数,覆盖(在复制事件中)剪贴板中的内容。

    $(document).on('copy', '[contenteditable]', function (e) {
      e = e.originalEvent;
      var selectedText = window.getSelection();
      console.log("original copied text\n--------\n", selectedText.toString());
      var range = selectedText.getRangeAt(0);
      var selectedTextReplacement = range.toString()
      console.log("replacement in clipboard\n--------\n", selectedTextReplacement);
      e.clipboardData.setData('text/plain', selectedTextReplacement);
      e.preventDefault(); // default behaviour is to copy any selected text
    });
    
    
    
    // Paste fix for contenteditable
    $(document).on('paste', '[contenteditable]', function (e) {
        e.preventDefault();
    
        if (window.clipboardData) {
            content = window.clipboardData.getData('Text');        
            if (window.getSelection) {
                var selObj = window.getSelection();
                var selRange = selObj.getRangeAt(0);
                selRange.deleteContents();                
                selRange.insertNode(document.createTextNode(content));
            }
        } else if (e.originalEvent.clipboardData) {
            content = (e.originalEvent || e).clipboardData.getData('text/plain');
            document.execCommand('insertText', false, content);
        }        
    });
    div {
      white-space: pre-wrap;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div contenteditable="true">Copy
    and
    paste
    this
    back in the same box or the one below. Where do they line-breaks go in FF?</div>
    <div contenteditable="true">Copy
    and
    paste
    this
    back in the same box or the one above. Where do they line-breaks go FF?</div>

    我还用edge和chrome做了一个粗略的测试,这个覆盖“不会把它们弄乱”,所以也许你可以让它控制它们在被复制时的行为。

    最后,我还有一个问题一直在我脑海中萦绕,那就是: 如果不想让html进入前端元素,为什么要使用contenteditable div而不是textarea?