User Tools

Site Tools


javascript:position:get_caret_position_in_contenteditable

JavaScript - Position - Get caret position in contentEditable

The Range instance returned by various Selection methods – most commonly window.getSelection().getRangeAt(0) – does not provide enough information to determine the total offset of the caret (or selection start/end).

Here’s how:

var SelectionUtils = {};
 
/**
 * Returns an object with 2 properties: a boolean value indicating if #child was found in the currently iterating
 * set of child nodes, and an integer value representing how many characters of textContent were examined in that same
 * iteration.
 * @private
 * @param {Node} child
 * @param {Node} container
 * @returns {{offset: number, found: boolean}}
 */
SelectionUtils.getCharacterCountToNodeRecursive = function(child, container){
  var response = {
    offset : 0,
    found : false
  };
  var current = container.firstChild;
  loop: while(current){
    if(current == child){
      response.found = true;
      break;
    }
    switch(current.nodeType){
      case 3 :
        response.offset += current.textContent.length;
        break;
      case 1 :
        var childResponse = arguments.callee(child, current);
        response.offset += childResponse.offset;
        if(childResponse.found){
          response.found = true;
          break loop;
        }
        break;
    }
    current = current.nextSibling;
  }
  return response;
};
 
/**
 * Returns the number of characters of text content preceding #child, in #container.
 * @param {Node} child
 * @param {Node} container
 * @returns {number}
 */
SelectionUtils.getCharacterCountToNode = function(child, container){
  container = container || document.body;
  if(!container.contains(child)){
    throw new Error('child must be descendant of container');
  }
  return SelectionUtils.getCharacterCountToNodeRecursive(child, container).offset;
};
 
/**
 * Convenience method to count the number of characters of text content to the start of the current selection.
 * @param range
 * @param container
 * @returns {number}
 */
SelectionUtils.getSelectionStartOffset = function(range, container){
  return range.startOffset + SelectionUtils.getCharacterCountToNode(range.startContainer, container);
};
 
/**
 * Convenience method to count the number of characters of text content to the end of the current selection.
 * @param range
 * @param container
 * @returns {number}
 */
SelectionUtils.getSelectionEndOffset = function(range, container){
  return range.endOffset + SelectionUtils.getCharacterCountToNode(range.endContainer, container);
};
<div id="editable" contenteditable="true">
  <form>
    <fieldset>
      <p>
        This is a paragraph.
      </p>
      <p>
        <strong>This</strong> is also a paragraph.
      </p>
    </fieldset>
  </form>
</div>

javascript/position/get_caret_position_in_contenteditable.txt · Last modified: 2020/07/15 09:30 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki