JSFiddle - React, Tailwind, and code Playground
by waxwing
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/rangy/1.2.3/rangy-core.js"></script>
<div id="auto" contenteditable="true" class="text">
This is a ​<span class="keyword" contenteditable="false">Keyword</span>. And also here is another ​<span class="keyword" contenteditable="false">one</span>.
</div>
CSS
.text {
border: 1px solid black;
padding: 10px;
white-space: pre-wrap;
}
.keyword {
background-color: #aaaaff;
border: 1px solid #333399;
border-radius: 2px;
}
JavaScript
rangy.init();
$.fn.allowUneditableContent = function () {
var KEY_ENTER = 9;
$(this).keypress(function (event) {
var sel, node, offset, text, textBefore, textAfter, range;
sel = rangy.getSelection();
// the node that contains the caret
node = sel.anchorNode;
// if ENTER was pressed while the caret was inside the input field
if (node.parentNode === this && event.which === 13) {
// prevent br/div element
event.preventDefault();
// the caret position inside the node
offset = sel.anchorOffset;
// insert a '\n' character at that position
text = node.textContent;
textBefore = text.slice( 0, offset );
textAfter = text.slice( offset ) || ' ';
node.textContent = textBefore + '\n' + textAfter;
// position the caret after that new-line character
range = document.createRange();
range.setStart( node, offset + 1 );
range.setEnd( node, offset + 1 );
// update the selection
sel.removeAllRanges();
sel.addRange(range);
}
});
};
$("#auto").allowUneditableContent();