JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://rangy.googlecode.com/svn/trunk/dev/rangy-core.js"></script>
<script src="http://rangy.googlecode.com/svn/trunk/dev/rangy-textrange.js"></script>
<p>
source:
<span contenteditable=true id="source" class="editable">testing...</span>
<p>
<span contenteditable=true id="foo" class="editable target"></span>
</p>
CSS
.red {color: red;}
.blue{color: blue;}
.editable {
border: 1px solid black;
border-radius: 5px;
padding: 5px;
}
.letter {
border: 1px solid #eee;
border-radius:2px;
padding: 1px;
}
JavaScript
function isAlpha(code) { return code>=65 && code<=90; }
function newLetterHTML(c) {
console.log("making letter for char " + c);
return "<span class='letter'>"+c+"</span>";
}
function newLetter(c) { return $(newLetterHTML(c)); }
function parentLetter(node) {
var letter = node;
while (letter.nodeType != 6
&& letter.tagName !== "SPAN"
&& letter.parentNode)
letter = letter.parentNode;
if (letter.className.split(' ').indexOf('letter')<0)
return null;
return letter;
}
function updateFields() {
var source = $('#source').text();
var lettersHTML = source.split('')
.map(newLetterHTML)
.join('');
$('.editable').empty().append(lettersHTML);
$('span:even',$('#foo')).addClass('red');
$('span:odd',$('#foo')).addClass('blue');
}
$('#source').keydown(function($e){
if ($e.which==13) {
updateFields();
$e.preventDefault();
}
});
var oldRange = null;
function oldRangeIsCollapsed() {
if (!oldRange) return true;
var r = oldRange[0].characterRange;
return (r.end - r.start == 0);
}
function saveRange(selection) {
if (!selection)
oldRange = null;
else
oldRange = selection.saveCharacterRanges($('#foo')[0]);
}
function loadRange(selection) {
if (!oldRange) return;
selection.restoreCharacterRanges($('#foo')[0],oldRange);
}
function downHandler(placeholder) { return function($e){
var sel = rangy.getSelection();
if (!isAlpha($e.which))
saveRange(sel);
else {
if (!!oldRange)
breakOutLastChar(sel);
else
saveRange(sel);
}
};}
function upHandler($e) {
if (!isAlpha($e.which))
saveRange(null);
else if (!!oldRange)
breakOutLastChar(rangy.getSelection());
}
function insertContentAtNode(c,node,before) {
var $newSpan = newLetter(c);
$parent = $(parentLetter(node));
if (!$parent.length) {
$('#foo').empty().append($newSpan);
...