css 停止在contenteditable div中粘贴html样式,只粘贴纯文本

7tofc5zh  于 2023-03-09  发布在  其他
关注(0)|答案(5)|浏览(407)

我正在使用contenteditable div,当我尝试粘贴带有样式的内容时,它应该只复制纯文本,但它也获得了样式,有人知道在我粘贴时如何强制它转换为纯文本吗?或者有人有更好的解决方案吗
下面是我的代码:

<div contenteditable="true">   
      This text can be edited by the user. 
    </div>

第一节第一节第一节第一节第一次

yxyvkwin

yxyvkwin1#

当你粘贴富格式内容时,它将显示为富格式内容,所以你需要捕获粘贴事件,阻止默认操作,并从剪贴板读取文本。

var ce = document.querySelector('[contenteditable]')
ce.addEventListener('paste', function (e) {
  e.preventDefault()
  var text = e.clipboardData.getData('text/plain')
  document.execCommand('insertText', false, text)
})
[contenteditable] {
    background-color: black;
    color: white;
    width: 400px;
    height: 200px;
  }
<div contenteditable="true"></div>

<div>
  <h1>Test content</h1>
  <p style="color:red">Copy <em>this</em> <u>underlined</u></p>
</div>
p3rjfoxz

p3rjfoxz2#

以下解决方案适用于要粘贴到的字段中已有文本的情况,并且不使用已弃用的document.execCommand()函数。

// Edited from https://htmldom.dev/paste-as-plain-text/

const editable_div = document.getElementById('editable_div');

// Handle the paste event
editable_div.addEventListener('paste', function (e) {
    // Prevent the default action
    e.preventDefault();

    // Get the copied text from the clipboard
    const text = e.clipboardData
        ? (e.originalEvent || e).clipboardData.getData('text/plain')
        : // For IE
        window.clipboardData
        ? window.clipboardData.getData('Text')
        : '';

    // Insert text at the current position of caret
    const range = document.getSelection().getRangeAt(0);
    range.deleteContents();

    const textNode = document.createTextNode(text);
    range.insertNode(textNode);
    range.selectNodeContents(textNode);
    range.collapse(false);

    const selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
});
<div id="editable_div" contenteditable="true">
    You can only paste plain text into me!
</div>
xsuvu9jc

xsuvu9jc3#

您可以拦截“paste”事件并替换目标的内容。

/* Derrived from: https://stackoverflow.com/a/6035265/1762224 */
const onPastePlainText = (e) => {
  var pastedText = undefined;
  if (window.clipboardData && window.clipboardData.getData) { // IE
    pastedText = window.clipboardData.getData('Text');
  } else if (e.clipboardData && e.clipboardData.getData) {
    pastedText = e.clipboardData.getData('text/plain');
  }
  e.target.textContent = pastedText;
  e.preventDefault();
  return false;
}

document.querySelector('.ediatable-div').addEventListener('paste', onPastePlainText);
.ediatable-div {
  border: 2px inset #EEE;
  height: 25vh;
}

/* Placeholder - Derrived from: https://stackoverflow.com/a/20300212/1762224 */
[contentEditable=true]:empty:not(:focus):before {
  content: attr(data-text);
  color: #AAA;
}
<div class="ediatable-div" contenteditable="true" data-text="Paste copied HTML here"></div>
<div>
  <p style="text-decoration:underline">Copy <strong>me</strong>, I have <em>style</em>!</p>
</div>
zazmityj

zazmityj4#

当contenteditable元素可能被动态添加到DOM时,有一个文档级处理程序是很有用的,一旦添加到DOM,它将检测未来的示例以及现有的示例。

// 1. Paste plain text only into contenteditable elements
document.addEventListener("paste", function (e) {
    if (e.target.isContentEditable) {
        e.preventDefault();
        var text = e.clipboardData.getData('text/plain')
        document.execCommand('insertText', false, text)
    }
});

// 2. Prevent any paste into contenteditable elements
document.addEventListener("paste", function (e) {
    if (e.target.isContentEditable) {
        e.preventDefault();
        return false;
    }
});
oaxa6hgo

oaxa6hgo5#

WebKit-based browsers支持一个非标准user-modify CSS属性:

-webkit-user-modify: read-write-plaintext-only;

这样就不需要使用过时的execCommand API或容易出错的步骤来正确定位插入符号。
x一个一个一个一个x一个一个二个x
有一个奇怪的行为:通过双击选择的复制粘贴文本可能会引入额外的前导和/或尾随空格(至少在macOS上)。
要支持非WebKit浏览器,您仍然需要侦听paste事件,例如:

someEditableElement.addEventListener("paste", function (e) {
  e.preventDefault();
  const text = e.clipboardData ? e.clipboardData.getData("text/plain") : "";

  if (document.queryCommandSupported?.("insertText")) {
    return document.execCommand("insertText", false, text);
  }

  const selection = document.getSelection();
  if (!selection) return;
  const range = selection.getRangeAt(0);
  range.deleteContents();
  range.insertNode(new Text(text));
  range.collapse(); // select nothing
  selection.removeAllRanges(); // position caret after inserted text
  selection.addRange(range); // show caret
});

这两种方法是有区别的,请自行判断。

相关问题