skip to Main Content

Assume I have an editable div which contains these lines:

enter image description here

How to retrieve the position of ‘w’ in the text ?

I can’t use:

window.getSelection().anchorOffset;

Because this gets the position in the line, but not in text, that is 0 instead of 5.

I prefer not to use:

element.innerText.indexOf(selectedText);

Because it may retrieve similar texts.

2

Answers


  1. Chosen as BEST ANSWER
    function getOffset(event) {
        const anchorNode = window.getSelection().anchorNode;
        let totalLength = 0;
        let currentNode = anchorNode;
        let anchorOffset = window.getSelection().anchorOffset;
        while (currentNode && currentNode !== event.target) { // loop upwards / parents till the root 
            var lastNode = null;
            while (currentNode) {                             // loop sideways / siblings
                lastNode = currentNode; // save the last sibling for the outer loop (before currentNode gets null)
                currentNode = currentNode.previousSibling;
                if (currentNode) {
                    totalLength += currentNode.textContent.length;
                }
            }
            currentNode = lastNode.parentNode;
        }
        totalLength += anchorOffset;
        return totalLength;
    }
    

    You can see explanation for some of the terms on Laimonas answer


  2. Your anchor offset should be 6.

    Index Character
    0 H
    1 e
    2 l
    3 l
    4 o
    5 n
    6 w <- Here
    7 o
    8 r
    9 l
    10 d
    const el = document.querySelector('#test');
    const btn = document.querySelector('#btn');
    
    el.focus();
    selectText(el, 'w');
    btn.dispatchEvent(new MouseEvent('click')); // 6
    
    function getPos(event) {
      console.log(window.getSelection().anchorOffset);
    }
    
    function selectText(el, text) {
      const content = el.textContent;
      const startIndex = content.indexOf(text);
      if (startIndex === -1) return;
      const endIndex = startIndex + text.length;
      selectTextRange(el, startIndex, endIndex);
    }
    
    function selectTextRange(el, startIndex, endIndex) {
      const textNode = el.firstChild;
      const selection = window.getSelection();
      const range = document.createRange();
      range.setStart(textNode, startIndex);
      range.setEnd(textNode, endIndex);
      selection.removeAllRanges();
      selection.addRange(range);
    }
    <div id="test" style="white-space:pre;" contenteditable>Hello
    world</div>
    <br>
    <button id="btn" onClick="getPos(event)">Get Selection</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search