Get caret index in contenteditable div including tags

前端 未结 2 1855
遥遥无期
遥遥无期 2020-11-27 05:41

I have a contentEditable div in which I have multiple tags (br, b, u, i) and text.

I need

相关标签:
2条回答
  • 2020-11-27 06:07

    Have you tried this? Get a range's start and end offset's relative to its parent container

    Direct link to the jsfiddle: https://jsfiddle.net/TjXEG/1/

    Function code:

    function getCaretCharacterOffsetWithin(element) {
        var caretOffset = 0;
        if (typeof window.getSelection != "undefined") {
            var range = window.getSelection().getRangeAt(0);
            var preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(element);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            caretOffset = preCaretRange.toString().length;
        } else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
            var textRange = document.selection.createRange();
            var preCaretTextRange = document.body.createTextRange();
            preCaretTextRange.moveToElementText(element);
            preCaretTextRange.setEndPoint("EndToEnd", textRange);
            caretOffset = preCaretTextRange.text.length;
        }
        return caretOffset;
    }
    
    function showCaretPos() {
        var el = document.getElementById("test");
        var caretPosEl = document.getElementById("caretPos");
        caretPosEl.innerHTML = "Caret position: " + getCaretCharacterOffsetWithin(el);
    }
    
    document.body.onkeyup = showCaretPos;
    document.body.onmouseup = showCaretPos;
    
    0 讨论(0)
  • 2020-11-27 06:14

    just had to do this so there is some working solution (some testing may be required)

    basic idea is to:

    1. get textContent position using this method: Get caret (cursor) position in contentEditable area containing HTML content

    2. iterate through innerHTML of an element to the textContent position

    3. if html tag or entity is encountered, iterate through it until normal char, then continue

    sample code here:

    function getCaretPosition (node) {
        var range = window.getSelection().getRangeAt(0),
            preCaretRange = range.cloneRange(),
            caretPosition,
            tmp = document.createElement("div");
    
        preCaretRange.selectNodeContents(node);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        tmp.appendChild(preCaretRange.cloneContents());
        caretPosition = tmp.innerHTML.length;
        return caretPosition;
    }
    
    function getHTMLCaretPosition(element) {
    var textPosition = getCaretPosition(element),
        htmlContent = element.innerHTML,
        textIndex = 0,
        htmlIndex = 0,
        insideHtml = false,
        htmlBeginChars = ['&', '<'],
        htmlEndChars = [';', '>'];
    
    
    if (textPosition == 0) {
      return 0;
    }
    
    while(textIndex < textPosition) {
    
      htmlIndex++;
    
      // check if next character is html and if it is, iterate with htmlIndex to the next non-html character
      while(htmlBeginChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) {
        // console.log('encountered HTML');
        // now iterate to the ending char
        insideHtml = true;
    
        while(insideHtml) {
          if (htmlEndChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) {
            if (htmlContent.charAt(htmlIndex) == ';') {
              htmlIndex--; // entity is char itself
            }
            // console.log('encountered end of HTML');
            insideHtml = false;
          }
          htmlIndex++;
        }
      }
      textIndex++;
    }
    
    //console.log(htmlIndex);
    //console.log(textPosition);
    // in htmlIndex is caret position inside html
    return htmlIndex;
    }
    
    0 讨论(0)
提交回复
热议问题