ContentEditable Range test
HTML
<div id="edit-content" contenteditable="true">Type here something</div>
<div id="range-value"></div>
<div id="fake-caret"></div>
CSS
body {
margin: 0;
}
#fake-caret {
position: absolute;
top: 100px;
left: 0;
right: 0;
bottom: 0;
width: 20px;
height: 20px;
background: yellow;
}
#fake-caret:focus{
outline: none;
}
#range-value {
margin-top: 30px;
}
Babel + JSX
const editable = document.querySelector('#edit-content');
const rangeValue = document.querySelector('#range-value');
const fakeCaret = document.querySelector('#fake-caret');
const fakeCaretHeight = fakeCaret.offsetHeight;
editable.addEventListener("input", function () {
let windowSelection = window.getSelection();
if (windowSelection.rangeCount > 0) {
let range = windowSelection.getRangeAt(0);
range = range.cloneRange(); // this is hack for Chrome. Try it in Chrome without this line.
range.setStart(range.startContainer, 0); // hack for Safari
const rangeBounds = range.getBoundingClientRect();
rangeValue.innerText = getFormattedOutput(rangeBounds);
if (rangeBounds.top === 0) {
const editableHeight = editable.offsetHeight;
fakeCaret.style.top = editable.offsetHeight + 'px';
} else {
fakeCaret.style.top = rangeBounds.top + fakeCaretHeight + 'px';
}
fakeCaret.style.left = rangeBounds.right + 'px';
}
}, false);
function getFormattedOutput(clientRect) {
const { top, left, right, bottom } = clientRect;
return `top: ${top}; left: ${left}; right: ${right}; bottom: ${bottom}`;
}
editable.focus();