JSFiddle - React, Tailwind, and code Playground

by Aaron von Schassen

HTML

<pre contenteditable="true" id="editor">
line 1
line 2
line 3
line 4
line 5</pre>

CSS

#editor {
  border: 2px black solid;
  padding: 10px;
}

.bg-ed {
  background: red;
  width: 100%;
}

JavaScript

function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}

$('#editor').on("mouseup", function() {
  var caretpos = getCaretPosition(this);
  console.log(caretpos);

  var settext = $('#editor').text();
  $('#editor').html(settext);


  var sel = document.getSelection(),
    nd = sel.anchorNode,
    text = nd.textContent.slice(0, sel.focusOffset),
    array = nd.textContent.split("\n"),
    lineNum = text.split("\n").length,
    editline;

  editline = array;

  for (i = 0; i < array.length - 1; ++i) {
    array[i] = array[i] + "\n";
    editline[lineNum - 1] = "<div class='bg-ed'>" + editline[lineNum - 1] + "</div>";
  }

  $("#editor").html(editline);
});

$("#editor").keypress(function(e) {
  if (e.which == 13) {
    e.preventDefault();

    var str = "new line";
    elem = document.getElementById("editor");
    elem.innerHTML = elem.innerHTML + "\n" + str;
  }
});