Reputation:
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
What has been tried & ideas:
Right now I am getting the cursor selected text using var text = window.getSelection().toString();
Using functions such as indexOf
and lastIndexOf
doesn't appear to be an option as the cursor selected term can be arbitrary and thus there is no pattern, and there is no guarantee that it will be unique.
I recently posted a very similar question which was marked as a duplicate, because there is a solution to this problem (using selectionStart
and selectionEnd
), but for that to work you have to use a <textarea>
which isn't possible for this use case.
I feel as though perhaps the odd use of <span>
tags could be utilised in some way; particularly because it's an option to add any id
s (or other attributes) as necessary.
Restriction:
<textarea>
instead of a <div>
is not an option for this scenario.Upvotes: 1
Views: 756
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 onanchorOffset
- the index of the character within anchorNode
the selection began atfocusNode
- the element the selection ended onfocusOffset
- the index of the character within focusNode
the selection ended atIt'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);
Upvotes: 4