EllDoubleYew EllDoubleYew - 2 months ago 7
React JSX Question

How do I get the range offsets of an entire div in Javascript?

I am creating a range based on a user selection using the following method:

var selection = window.getSelection();
var beginsAt = selection.getRangeAt(0).startOffset;
var endsAt = selection.getRangeAt(0).endOffset;
return [beginsAt,endsAt];


The component that calls this function does the following:

let before = text.substring(0, range[0]);
let highlighted = text.substring(range[0], range[1]);
let after = text.substring(range[1], text.length);
return(
<div>
{before}
<span style={{
backgroundColor: 'yellow'
}}>
{highlighted}
</span>
{after}
</div>
)


Whenever I select my text, the range is always relative to where the highlighted span ends. So if my text is on a range between 0 and 50 and I select the range [25,26] then select the range [26,27], rather than highlighting the range [26,27] it highlights the range from [0,1] because the range was [0,1] relative to the text generated by {after}.

As long as I highlight any text rendered by {before} I have no issues, its only when I highlight something rendered in the {after} section.

How can I make these range values relative to the root of the entire text rather than relative to the blocks that they are rendered in? Is this a limitation of react or my implementation?

Answer

The issue is most certainly with the implementation and not a limitation of javascript or react (at least in the way that question is proposed here).

Rather than try and force the indexes to conform to a parent container it is much easier to simply offset them based on a previous selection.

The method that gets the selection can be modified to contain the following:

(relativityFlag) => {
    var selection = window.getSelection();
    var beginsAt = selection.getRangeAt(0).startOffset;
    var endsAt = selection.getRangeAt(0).endOffset;

    if(relativityFlag){
        beginsAt += endsAt;
        endsAt += endsAt;
    }
    return [beginsAt, endsAt]
}

Where the relativity flag is true if the selection is inside of the {after} render block.

This is one of many different ways to conform the index to a greater range but is of the simplest to implement.

Comments