Get contentEditable caret index position

后端 未结 10 880
暗喜
暗喜 2020-11-22 05:48

I\'m finding tons of good, crossbrowser anwers on how to SET the cursor or caret index position in a contentEditable element, but none on how to GET or find its

10条回答
  •  被撕碎了的回忆
    2020-11-22 06:35

    A few wrinkles that I don't see being addressed in other answers:

    1. the element can contain multiple levels of child nodes (e.g. child nodes that have child nodes that have child nodes...)
    2. a selection can consist of different start and end positions (e.g. multiple chars are selected)
    3. the node containing a Caret start/end may not be either the element or its direct children

    Here's a way to get start and end positions as offsets to the element's textContent value:

    // node_walk: walk the element tree, stop when func(node) returns false
    function node_walk(node, func) {
      var result = func(node);
      for(node = node.firstChild; result !== false && node; node = node.nextSibling)
        result = node_walk(node, func);
      return result;
    };
    
    // getCaretPosition: return [start, end] as offsets to elem.textContent that
    //   correspond to the selected portion of text
    //   (if start == end, caret is at given position and no text is selected)
    function getCaretPosition(elem) {
      var sel = window.getSelection();
      var cum_length = [0, 0];
    
      if(sel.anchorNode == elem)
        cum_length = [sel.anchorOffset, sel.extentOffset];
      else {
        var nodes_to_find = [sel.anchorNode, sel.extentNode];
        if(!elem.contains(sel.anchorNode) || !elem.contains(sel.extentNode))
          return undefined;
        else {
          var found = [0,0];
          var i;
          node_walk(elem, function(node) {
            for(i = 0; i < 2; i++) {
              if(node == nodes_to_find[i]) {
                found[i] = true;
                if(found[i == 0 ? 1 : 0])
                  return false; // all done
              }
            }
    
            if(node.textContent && !node.firstChild) {
              for(i = 0; i < 2; i++) {
                if(!found[i])
                  cum_length[i] += node.textContent.length;
              }
            }
          });
          cum_length[0] += sel.anchorOffset;
          cum_length[1] += sel.extentOffset;
        }
      }
      if(cum_length[0] <= cum_length[1])
        return cum_length;
      return [cum_length[1], cum_length[0]];
    }
    

提交回复
热议问题