0

I need the selected text position area, This is how I was done in a textarea below:

//my textarea
let textarea = document.getElementById('textarea');

textarea.addEventListener('mouseup', function(){
  console.log(this.selectionStart); //return integer
})

This perfectly works on a textarea but not in a contentEditable div tag, instead of returning integer value it returns undefined, why and how to get selected text position in a contenteditable div tag?

//myDiv
<div id="textarea" contenteditable="true">
   <p> I am on </p>
</div>

I need a pure javascript solution, not in jquery.

Tahazzot
  • 1,224
  • 6
  • 27

3 Answers3

3

Get Selected Position

You can retrieve the selected position of a contenteditable div using the document's range observer. The API is slightly different from a texture element. Note: A similar (perhaps better) solution can be found here (credit: Tim Down).

// Step 1: Retrieve elements
let textarea = document.querySelectorAll('.textarea');

// Step 2: Bind events
textarea.forEach(txt=>{
  txt.addEventListener('mouseup', eventHandler) 
  txt.addEventListener('keyup', eventHandler)
})
function eventHandler(e){ getPosition(e.target) }


// Step 3: Determine cursor positions
function getPosition(el){
  let position = {start:0,end:0};
  let selection = document.getSelection();
  
  if (el.matches('textarea')){
    let offset = 1
    position.start = el.selectionStart + offset
    position.end = el.selectionEnd + offset
  }
  else {
    if (selection.rangeCount){
      let range = selection.getRangeAt(0);
      let range2 = range.cloneRange()  // don't mess with visible cursor
      range2.selectNodeContents(el)    // select content
      position.start = range.startOffset
      position.end = range.endOffset
    }
  }
  
  console.log(position.start, position.end)
}
<textarea class="textarea">
I am on
</textarea>

<div class="textarea" contenteditable="true">
   <p> I am on </p>
</div>

Retrieve Selected Text

This slightly deviates from the position, but does help to identify the selection. Note: the example requires selecting multiple characters, not only clicking on the elements.

//my textarea
let textarea = document.querySelectorAll('.textarea');

textarea.forEach(txt=>txt.addEventListener('mouseup', function(){
  let sel = document.getSelection()
  console.log(sel.toString())
}))
<textarea class="textarea">
I am on
</textarea>

<div class="textarea" contenteditable="true">
   <p> I am on </p>
</div>

Find Position of Selection

Once then selection text is found, search() can be used to find the position.

//my textarea
let textarea = document.querySelectorAll('.textarea');

textarea.forEach(txt=>txt.addEventListener('mouseup', function(e){
  let textbox = e.target;
  let selection = document.getSelection().toString()
  let position = textbox.textContent.search(selection)
  if(position)
    console.log(`"${selection}":`, position)
}))
<textarea class="textarea">
I am on
</textarea>

<div class="textarea" contenteditable="true">
   <p> I am on </p>
</div>
Mike
  • 1,279
  • 7
  • 18
  • Not sure the reason for the downvote, but I'll try to update (or delete) the answer with some more info. Otherwise, please allow me to address your concerns – Mike Mar 14 '20 at 02:46
  • Good solution @mike I am getting to add your ideas to my code. just as a note, the last part `Find Position` has a little issue, if the selected phrase is there in the element, more than once. the code always returns the first one's position. – Armin.G Dec 25 '21 at 11:55
0

try this :

<html>

<body>
    <div id="textarea" contenteditable="true">
        <p>I am on dsvsdvsdv vsdvdsvds sddvdsvds vdsdds sdvdsvdsv vdsvdsvds dsvdsvdsvdsv vsdvdsv sddvsdvds vdsvdsvdsv dsvdefwfs</p>
    </div>
    <script>
        function selection() {
            if (window.getSelection)
                return window.getSelection();
        }

        let textarea = document.getElementById('textarea');

        textarea.addEventListener('mouseup', function () {
            console.log(selection())
            console.log(textarea.innerText.indexOf(selection()))
        })
    </script>
</body>

</html>

this perfectly works : http://jsfiddle.net/xm0Lshdb/

Nilanka Manoj
  • 3,527
  • 4
  • 17
  • 48
-1

You can get any selected text in a page with the Selection API.

This API is curently in Working Draft status.

Here is an working example :

document.addEventListener('selectionchange', () => {
  console.log("Text :", document.getSelection().toString());
  console.log("Position:", document.getSelection().focusOffset);
});
Genosite
  • 359
  • 1
  • 8