首页 > 解决方案 > 如何在 contenteditable 元素中粘贴多行文本,以便每行始终位于自己的 div 中?

问题描述

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

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

还有更多不一致行为的例子。例如,删除所有内容并再次粘贴文本。现在,全选并粘贴到所选内容上。它会表现得像我想要的那样。现在,按 Enter 在现有的两个 div 下方创建一个新 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;
}
<div class="text_area" contenteditable="true"></div>

标签: javascripthtmlcontenteditable

解决方案


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

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

在“输入”上使用带有事件侦听器的 JavaScript,您可以测试 contenteditable 元素是否为空。您必须记住,<br>在该区域中将被视为非空。这就是导致您输入问题的原因。<br>在 s之前有一个<div>。如果您的 contenteditable 区域的 innerHTML 不包括<br>多余的空格,那么您需要将其附加div为 contenteditable 区域的子项。

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

// 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>


推荐阅读