JSFiddle - React, Tailwind, and code Playground

by Nico D

HTML

<b>Click with mouse or simply move with arrows inside text:</b>
<div id="test" contenteditable="true">Hello, some <b>bold</b> and <i>italic and <b>bold</b></i> text</div>
<br>
    <b>OUTPUT</b><br>
    <div id="output"></div>

CSS

span {
    background: #0c0;
    display: inline-block;
    height: 1em;
    width: 1em;
}

JavaScript

// Character offset in a Text Box

function getCharacterOffsetWithin(range, node) {
    var treeWalker = document.createTreeWalker(
        node,
        NodeFilter.SHOW_TEXT,
        function(node) {
            var nodeRange = document.createRange();
            nodeRange.selectNodeContents(node);
            return nodeRange.compareBoundaryPoints(Range.END_TO_END, range) < 1 ?
                NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
        },
        false
    );

    var charCount = 0;
    while (treeWalker.nextNode()) {
        charCount += treeWalker.currentNode.length;
    }
    if (range.startContainer.nodeType == 3) {
        charCount += range.startOffset;
    }
    return charCount;
}

var test = function(e) {
    var output;
    var el = document.getElementById("test");
    var range = window.getSelection().getRangeAt(0);
    var positionToUse = document.caretRangeFromPoint(e.clientX, e.clientY);
    
    output = "Caret char pos: " + getCharacterOffsetWithin(range, el) + "<br>Position Pixels: " + e.clientX + " " + e.clientY
    + "<br>Position Pixels 2: " + e.target.offsetLeft + " " + e.target.offsetTop;
    
    document.getElementById("output").innerHTML = output;
    //positionToUse.insertNode(document.createElement('span'));
};

window.onclick = test;

// On Typing caretRangeFromPoint has not clientX or clientY
window.onkeyup = test;
//jQuery("#test").keyup(test);