这是东西:
Contenteditables不好。 Firefox 使用类似div1
的东西来处理它,而 Chrome 做类似div2
的东西。
两者的文本内容相同(从用户的角度来看),但是它们的结构不同。
当我同时使用innerText
获得两个文本内容时,由于它们的结构方式,我会得到不同的结果。
有没有办法获取这些文本并返回相同的字符串(因为它们在屏幕上产生的文本完全相同)?
类似的东西:
div1 = div2 = "Line1\nLine2\n\nLine3\n\n\nLine4"
(实际上是div1
的结果,因为它仅由文本和中断组成)。在这种情况下,div2
是问题。
我需要的伪代码:
“根据屏幕上显示的内容,获取带有中断次数的div
的文本内容。”
最终目标:
要在两种结构中始终粘贴新文本,我需要一种以相同方式处理它们的方法。
const div1 = document.getElementById('div1');
const div2 = document.getElementById('div2');
const p1 = document.getElementById('p1');
const p2 = document.getElementById('p2');
p1.innerText = JSON.stringify(div1.innerText);
p2.innerText = JSON.stringify(div2.innerText);
#div1 {
border: 1px dotted blue;
}
#div2 {
margin-top: 40px;
border: 1px dotted red;
}
<div id="div1" contenteditable>
Line1
<br>
Line2
<br>
<br>
Line3
<br>
<br>
<br>
Line4
</div>
<p><b>Div1 innerText:</b></p>
<p id="p1"></p>
<div id="div2" contenteditable>
<div>Line1</div>
<div>Line2</div>
<div><br></div>
<div>Line3</div>
<div><br></div>
<div><br></div>
<div>Line4</div>
</div>
<p><b>Div2 innerText:</b></p>
<p id="p2"></p>
答案 0 :(得分:1)
我建议您在评论中将<div>
的内容转换为<textarea>
元素。此解决方案避免了Firefox和Chrome之间的行为差异。
下面是一个有关如何实现的简单示例。我想您将能够根据自己的实际需求进行调整(例如将<p>
切换为<div>
)。
const contentEditable = document.querySelector('#content-editable'),
htmlPreview = document.querySelector('#html-preview');
htmlPreview.innerText = contentEditable.innerHTML;
contentEditable.addEventListener('click', contentEditableHtmlToTextarea);
/**
* Converts HTML of #content-editable into <textarea>.
*/
function contentEditableHtmlToTextarea() {
const textarea = document.createElement('textarea'),
height = contentEditable.offsetHeight;
// Converts <p> tags to \r\n.
textarea.value = this.innerHTML
.replace(/^\s*/gm, '')
.replace(/<p>(.*?)<\/p>/g, '$1\r\n')
.trim();
// Updates #content-editable HTML.
this.innerHTML = '';
this.appendChild(textarea);
textarea.style.height = `${height}px`;
htmlPreview.style.display = 'none';
this.removeEventListener('click', contentEditableHtmlToTextarea);
// A bit tricky, but without timeout, the callback is directly called.
setTimeout(() => {
document.addEventListener('click', contentEditableTextareaToHtml);
}, 0);
}
/**
* Converts <textarea>'s value into HTML for #content-editable.
*/
function contentEditableTextareaToHtml(e) {
const textarea = contentEditable.querySelector('textarea'),
// Converts lines into <p> tags.
html = textarea.value.replace(/^(.+?)$/gm, '<p>$1</p>');
// Checks if the mouse click is outside the <textarea>.
if (e.target !== textarea) {
// Updates #content-editable HTML.
textarea.remove();
contentEditable.innerHTML = html;
htmlPreview.innerText = contentEditable.innerHTML;
htmlPreview.style.display = 'block';
document.removeEventListener('click', contentEditableTextareaToHtml);
contentEditable.addEventListener('click', contentEditableHtmlToTextarea);
}
}
div {
padding: 3px;
border: 1px solid #000;
}
textarea {
margin: 0 auto;
display: block;
width: 98%;
}
<div id="content-editable">
<p>Line 1</p>
<p>Line 2</p>
<p>Line 3</p>
</div>
<pre id="html-preview"></pre>