I am trying to display a div
that is using white-space: pre
style and allows for editing.
However, every time a new line is inserted from the keyboard, and then the contents is read back from the div using innerText
2 new lines are obtained instead of 1. I understand the browser is implicitly wrapping lines in <div>
's and inserting <br>
's. However, I am not sure how to obtain a textual representation of the div
that is accurate.
E.g. to demonstrate. in the following, after entering 1<return>2<return><return>3
in the editable div, the following is obtained (where the second is a direct innerText
copy between two div
s and the third is the actual innerHTML
shown):
I have put together a simple fiddle showing this: https://jsfiddle.net/mv2h4Lnp/1/
Possible Solution
It sounds very much like the issue experienced when FireFox changed from using br
to div
in generated markup. However, the solution presented in that article is FireFox specific and essentially makes FireFox behave like before it was changed to wrap lines in div
s.
I also noticed the following SO questions `contenteditable` with `white-space: pre-wrap` - newline insertion and https://stackoverflow.com/a/54926262/5660642 that give a suggestion that its best to handle the onkeydown
event and deal with the new lines instead of leaving to the browser.
Reusing that as a basis, I updated the fiddle to use ideas from the above articles as: https://jsfiddle.net/mv2h4Lnp/2/
Essentially, the following code has been used to intercept the return key:
document.getElementById('ss').addEventListener("keydown", e => {
if (e.which == 13) {
e.stopPropagation();
e.preventDefault();
document.execCommand('insertHTML', false, '<br>');
}
});
While this mostly works. I notice that when there is already a <br>
where the caret is when the return key is pressed it does not insert another <br>
and simply moves the caret forward one character. This is not what I am looking for, and I dont really understand why another <br>
is not inserted as the insertHTML
is called.
Instead, if the above JavaScript is updated to insert a \n
instead of a <br>
it works in the fiddle perfectly, but when running outside of the fiddle in Chrome it still generates spurious newlines as it still tries to wrap lines in <div>
's - so the <br>
is probably the way to go.
Is there any better way of getting the text back from a div
that has the same number of new lines as it displays? I really dont care how its structured in the div
, just that I can access the plain text again. I feel like I am missing something obvious.
Update: FireFox
Just testing in FF80, it works fine with document.execCommand('insertHTML', false, '<br>');
so maybe its Chrome (tested at version 85) this does not work properly with.