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