When you hit Enter on a contentEditable element every browser is handling the resulting code differently: Firefox inserts a BR tag, Chrome inserts a DIV tag while Internet Explorer inserts a P tag.
I was desperately looking for a solution to at least use a BR or P for all browsers and the most common answer was this:
inserting BR tag :
$("#editableElement").on("keypress", function(e){
      if (e.which == 13) {
        if (window.getSelection) {
          var selection = window.getSelection(),
              range = selection.getRangeAt(0),
              br = document.createElement("br");
          range.deleteContents();
          range.insertNode(br);
          range.setStartAfter(br);
          range.setEndAfter(br);
          selection.removeAllRanges();
          selection.addRange(range);
          return false;
        }
      }
    });
But this doesn't work because it seems that browsers don't know how to set the caret after <br> which means the following is not doing anything useful (especially if you hit enter when the caret is placed at the end of text):
range.setStartAfter(br);
range.setEndAfter(br);
Some people would say: use double <br><br> but this results in two line breaks when you hit enter inside a text node.
Others would say always add an additional <br> at the end of contentEditable, but if you have a <div contenteditable><p>text here</p></div> and you place the cursor at the end of text then hit enter, you will get the wrong behavior.
So I said to myself maybe we can use P instead of BR, and the common answer is:
inserting P tag:
document.execCommand('formatBlock', false, 'p');
But this doesn't work consistently either.
As you can see, all these solutions leave something to be desired. Is there another solution that solves this issue?
One possible solution: append a text node with a zero-width space character after the <br> element. This is a non-printing zero-width character that's specifically designed to:
...indicate word boundaries to text processing systems when using scripts that do not use explicit spacing, or after characters (such as the slash) that are not followed by a visible space but after which there may nevertheless be a line break.
(Wikipedia)
Tested in Chrome 48, Firefox 43, and IE11.
$("#editableElement").on("keypress", function(e) {
  //if the last character is a zero-width space, remove it
  var contentEditableHTML = $("#editableElement").html();
  var lastCharCode = contentEditableHTML.charCodeAt(contentEditableHTML.length - 1);
  if (lastCharCode == 8203) {
    $("#editableElement").html(contentEditableHTML.slice(0, -1));
  }
  // handle "Enter" keypress
  if (e.which == 13) {
    if (window.getSelection) {
      var selection = window.getSelection();
      var range = selection.getRangeAt(0);
      var br = document.createElement("br");
      var zwsp = document.createTextNode("\u200B");
      var textNodeParent = document.getSelection().anchorNode.parentNode;
      var inSpan = textNodeParent.nodeName == "SPAN";
      var span = document.createElement("span");
      
      // if the carat is inside a <span>, move it out of the <span> tag
      if (inSpan) {
        range.setStartAfter(textNodeParent);
        range.setEndAfter(textNodeParent);
      }
      // insert the <br>
      range.deleteContents();
      range.insertNode(br);
      range.setStartAfter(br);
      range.setEndAfter(br);
      
      // create a new span on the next line
      if (inSpan) {
        range.insertNode(span);
        range.setStart(span, 0);
        range.setEnd(span, 0);
      }
      // add a zero-width character
      range.insertNode(zwsp);
      range.setStartBefore(zwsp);
      range.setEndBefore(zwsp);
      
      // insert the new range
      selection.removeAllRanges();
      selection.addRange(range);
      return false;
    }
  }
});#editableElement {
  height: 150px;
  width: 500px;
  border: 1px solid black;
}<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable=true id="editableElement">
  <span>sample text</span>
</div>If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With