如何在 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>
运行 代码并将任意两行纯文本复制并粘贴到框中。它会按照我想要的方式粘贴,每一行都有自己的 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>