Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

innerText on content editable doubling some line breaks

Tags:

javascript

dom

I am trying to read multi line user input on a content editable div, and I don't get the right number of line breaks when I read the input with contentEditableDiv.innerText.

I tried textContent, but it doesn't return any line break, while innerText returns too many sometimes. innerHTML doesn't seem appropriate since I don't want any HTML code, just text.

If my div contains:

a
b

It returns "a↵b" (97 10 98 in the example)

But if my <div> contains:

a

b

innerText returns a↵↵↵b (one too many ↵, 97 10 10 10 98 in the example)

var input = document.getElementById("input");
var button = document.getElementById("button");
var result = document.getElementById("result");
button.addEventListener("click", (event) => {
  var charCodes = "";
  for (var i = 0; i < input.innerText.length; ++i) {
    charCodes += input.innerText.charCodeAt(i) + " ";
  }
  result.innerText = charCodes;
});
<div id="input" contenteditable="true" spellcheck="true" style="border:1px #000 solid"></div>
<button id="button">check</button>
<div id="result"></div>
like image 792
Carlo Avatar asked Jun 11 '19 01:06

Carlo


1 Answers

The standard is a bit vague:

UAs should offer a way for the user to request an explicit line break at the caret position without breaking the paragraph, e.g. as the default action of a keydown event whose identifier is the "Enter" key and that has a shift modifier set. Line separators are typically found within a poem verse or an address. To insert a line break, the user agent must insert a br element.

If the caret is positioned somewhere where phrasing content is not allowed (e.g. in an empty ol element), then the user agent must not insert the br element directly at the caret position. In such cases the behavior is UA-dependent, but user agents must not, in response to a request to insert a line separator, generate a DOM that is less conformant than the DOM prior to the request.

To conform this definition, it is safe to wrap the <br> element into <div>, which Chrome does, but it is UA dependent, so you should not rely on this. The side effect on this behavior and the cause of your problem is that both div and br elements produces line break in the innerText property.

The innerHTML of a↵↵b looks like this in Chrome:

a
<div>
  <br>
  <div>
    <br>
    <div>
      b
    </div>
  </div>
</div>

But if you paste it (instead of typing char by char) it looks like this

<div>a</div>
<div>
  <br>
</div>
<div>
  <br>
</div>
<div>b</div>

To reduce the line breaks, you need to further process the innerHTML and treat <div><br></div> after every input change as a single line-break and then read the innerText (with caution on places where phrasing content like br is not allowed, but in real life browsers can handle them well).

like image 144
Jan Turoň Avatar answered Nov 11 '22 14:11

Jan Turoň