JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html>
<head>
<style>
#cursor {
border-left: 1px solid red;
background-color: #acf;
animation: blink 1s;
margin-left: -1px;
animation-iteration-count: infinite;
}
span:not(#cursor) {
color: green;
}
span:not(#cursor):before {
content: "5";
vertical-align: super;
font-size: smaller;
}
@keyframes blink {
50% { border-color: #ffffff00; } }
</style>
</head>
<body>
<textarea id="ta" style="height:150px">The top element is a textarea and the div at the bottom a pseudo editable field. Try to type in the div below and to select text with the mouse. Type a dollar sign to insert a span.</textarea>
<div id="mydiv" onclick="let pos = getSelectionPosition(event); ta.setSelectionRange(...pos.sort()); ta.focus()"></div>
<script>
function getSelectionPosition(e) {
if (document.caretRangeFromPoint) {
// edge, chrome, android
range = document.caretRangeFromPoint(e.clientX, e.clientY)
nodeA = range.startContainer
posA = range.startOffset
var node = range.endContainer
var pos = range.endOffset
} else {
// firefox
var node = e.rangeParent
var pos = e.rangeOffset
}
while (nodeA = nodeA.previousSibling)
posA += (nodeA.nodeType == Node.TEXT_NODE ? nodeA : nodeA.innerText).length
while (node = node.previousSibling)
pos += (node.nodeType == Node.TEXT_NODE ? node : node.innerText).length
return [posA, pos]
}
function parse(t) {
return t.replace(/\$/g, '<span>XX</span>')
}
function update() {
// insert pseudo caret
selA = ta.selectionStart
selB = ta.selectionEnd
mydiv.innerHTML = parse(ta.value.slice(0, selA))+"<span id='cursor'>"+parse(ta.value.slice(selA, selB))+"</span>"+parse(ta.value.slice(selB))
}
var mouse = false
mydiv.onmousedown = function(e) {
mouse = true
if (!document.caretRangeFromPoint) {
// firefox, remember start selection
nodeA = e.rangeParent
...