user9467747
user9467747

Reputation:

Getting index of cursor-selected text

Given the following HTML:

<div>
    <span>This </span>
    <span>is </span>
    <span>plain </span>
    <span>text </span>
    <span>and </span>
    <span>this </span>
    <span>is </span>
    <span>more </span>
    <span>plain </span>
    <span>text </span>
    <span>and </span>
    <span>this </span>
    <span>is </span>
    <span>the </span>
    <span>final </span>
    <span>plain </span> 
    <span>text</span>
</div>

That displays as:

This is plain text and this is more plain text and this is the final plain text

Pleas note: the <span> tags are being used for another purpose.

I want to be able to highlight (cursor select) any part of the above text and get both the start & end index of the cursor selected text. For example, the following cursor selection (cursor-selecting the second occurence of the term "plain text") would output startIndex = 35 and endIndex = 44

enter image description here

What has been tried & ideas:

Restriction:

Upvotes: 1

Views: 756

Answers (1)

Mitya
Mitya

Reputation: 34556

You need to interrogate the various properties of the selection object returned by getSelection().

Of particular interest to you are:

  • anchorNode - the element the selection began on
  • anchorOffset - the index of the character within anchorNode the selection began at
  • focusNode - the element the selection ended on
  • focusOffset - the index of the character within focusNode the selection ended at

It's then a case of doing DOM iteration and some maths.

Putting it together:

let div = document.querySelector('div'),
    text = div.innerText;
div.addEventListener('mouseup', evt => {
    let sel = getSelection(),
        result = {start: null, end: null};
    if (!sel) return;
    ['start', 'end'].forEach(which => {
        let counter = 1,
            tmpNode = div.querySelector('span'),
            node = which == 'start' ? 'anchor' : 'focus';
        while(tmpNode !== sel[node+'Node'].parentElement) {
            result[which] += tmpNode.innerText.length;
            counter++;
            tmpNode = div.querySelector('span:nth-child('+counter+')')
        }
        result[which] += sel[node+'Offset'] + (which == 'start' ? 1 : 0);
    });
    alert('Selection starts at '+result.start+' and ends at '+result.end);
}, false);

Fiddle

Upvotes: 4

Related Questions