javascriptcontenteditablecaretselection-api

Get contentEditable caret position


I'm finding tons of good, cross-browser answers on how to set the caret position in a contentEditable element, but none on how to get the caret position in the first place.

What I want to do is know the caret position within a div on keyup. So, when the user is typing text, I can, at any point, know the caret position within the contentEditable element.

<div id="contentBox" contentEditable="true"></div>

$('#contentbox').keyup(function() { 
    // ... ? 
});

Solution

  • The following code assumes:

    If you need a more general approach that will work content with nested elements, try this answer:

    https://stackoverflow.com/a/4812022/96100

    Code:

    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;
    }
    #caretposition {
      font-weight: bold;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <div id="contentbox" contenteditable="true">Click me and move cursor with keys or mouse</div>
    <div id="caretposition">0</div>
    <script>
      var update = function() {
        $('#caretposition').html(getCaretPosition(this));
      };
      $('#contentbox').on("mousedown mouseup keydown keyup", update);
    </script>