[javascript] Get contentEditable caret index position

As this took me forever to figure out using the new window.getSelection API I am going to share for posterity. Note that MDN suggests there is wider support for window.getSelection, however, your mileage may vary.

const getSelectionCaretAndLine = () => {
    // our editable div
    const editable = document.getElementById('editable');

    // collapse selection to end
    window.getSelection().collapseToEnd();

    const sel = window.getSelection();
    const range = sel.getRangeAt(0);

    // get anchor node if startContainer parent is editable
    let selectedNode = editable === range.startContainer.parentNode
      ? sel.anchorNode 
      : range.startContainer.parentNode;

    if (!selectedNode) {
        return {
            caret: -1,
            line: -1,
        };
    }

    // select to top of editable
    range.setStart(editable.firstChild, 0);

    // do not use 'this' sel anymore since the selection has changed
    const content = window.getSelection().toString();
    const text = JSON.stringify(content);
    const lines = (text.match(/\\n/g) || []).length + 1;

    // clear selection
    window.getSelection().collapseToEnd();

    // minus 2 because of strange text formatting
    return {
        caret: text.length - 2, 
        line: lines,
    }
} 

Here is a jsfiddle that fires on keyup. Note however, that rapid directional key presses, as well as rapid deletion seems to be skip events.

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to contenteditable

React.js: onChange event for contentEditable How to set caret(cursor) position in contenteditable element (div)? Get contentEditable caret index position contenteditable change events Set cursor position on contentEditable <div>

Examples related to caret

How to get the focused element with jQuery? Styling text input caret How to set caret(cursor) position in contenteditable element (div)? Get contentEditable caret index position How to get the caret column (not pixels) position in a textarea, in characters, from the start?

Examples related to cursor-position

Setting cursor at the end of any text of a textbox How to set caret(cursor) position in contenteditable element (div)? jQuery: Get the cursor position of text in input without browser specific code? Get contentEditable caret index position How to move screen without moving cursor in Vim? Set cursor position on contentEditable <div>