如何在 contenteditable 元素中粘贴多行文本,以便每行始终在其自己的 div 中?

How to paste multiline text in a contenteditable element so that each line is always in its own div?

运行 代码并将任意两行纯文本复制并粘贴到框中。它会按照我想要的方式粘贴,每一行都有自己的 div.

现在删除所有内容并按回车键创建一个空 div,然后将文本粘贴到 div 中。将看到不需要的行为。

还有更多不一致行为的例子。 例如,删除所有内容并重新粘贴文本。现在,select 全部粘贴到 selection 上。它会像我想要的那样表现。现在,按回车键在现有的两个 div 下方创建一个新的 select 所有文本并再次粘贴。将看到不需要的行为。

有些问题似乎与生成的中断标记有关。我试图解决它,但一个修复破坏了其他东西。

.text_area {
  width: 200px;
  height: 100px;
  border: 1px solid;
  padding: 2em 2em 2em 3em;
  overflow: auto;
}

.text_area>div {
  border: 1px solid lightgray;
  margin: 0.33em 0;
  min-height: 1.2em;
}
<div class="text_area" contenteditable="true"></div>

如果您总是希望每一行都在 div 中,则必须确保始终有一个 div 来让内容进入。

使用内部 div 初始化您的 contenteditable 元素。这可确保当用户单击时,他们已经处于正确的环境中。

将 JavaScript 与 'input' 上的事件侦听器结合使用,您可以测试 contenteditable 元素是否变为空。您必须记住,该区域中的 <br> 将被视为非空。这就是导致您输入问题的原因。在 <div> 之前有一个 <br>。如果您的 contenteditable 区域的内部 HTML,不包括 <br> 和多余的空格,那么您需要将 div 作为 contenteditable 区域的子项追加回来。

最后,您在复制和粘贴时遇到了 div 嵌套。这是因为粘贴到可编辑区域的默认行为是使用 HTML 格式。因此,如果您复制 <div>a</div><div>b</div> 并将其粘贴到 <div></div> 中,就会出现嵌套。您可以通过仅从剪贴板获取 'text/plain' 来避免这种情况。

// Ensure Text is copied as plain text not as HTML (Fixes Nested Divs Problem)
document.querySelector('[contenteditable]').addEventListener('paste', (event) => {
  event.preventDefault();
  document.execCommand('inserttext', false, event.clipboardData.getData('text/plain'));
});

document.querySelector('[contenteditable]').addEventListener('input', (event) => {
  // Remove All BR
  if (event.target.childNodes.length > 0) {
    for (let br of event.target.querySelectorAll('br')) {
      br.remove();
    }
  }

  // If DIV is ever made empty after removal of BRs
  if (event.target.innerHTML.trim().length === 0) {
    // Re-populate the initial DIV
    event.target.innerHTML = '';
    event.target.appendChild(document.createElement('div'));
  }
});
.text_area {
  width: 200px;
  height: 100px;
  border: 1px solid;
  padding: 2em 2em 2em 3em;
  overflow: auto;
}

.text_area>div {
  border: 1px solid lightgray;
  margin: 0.33em 0;
  min-height: 1.2em;
}
<!-- Prime Your Content Editable Area With a DIV -->
<div class="text_area" contenteditable="true">
  <div></div>
</div>