JSFiddle - React, Tailwind, and code Playground
HTML
<table>
<tr>
<td>
<textarea id="myTxt" onmouseup="getRange();" onkeyup="getRange();">
123456789
1234
123456789
</textarea>
</td>
<td>
<input type="button" value="<< Set Caret/Selection" onclick="setRange();" />
</td>
<td>
<div>
Start:
</div>
<input type="text" id="inpStart" /><br />
<div>
End:
</div>
<input type="text" id="inpEnd" />
<div>
Text To Insert:
</div>
<input type="text" id="insTxt" />
<br /><br />
<div>
Caret position after insertion:
</div>
<div>Before:<input type="radio" name="insPos" value="before" checked="on"></div>
<div>After:<input type="radio" name="insPos" value="after"></div>
<div>Select Insertion:<input type="radio" name="insPos" value="select"></div>
</td>
</tr>
<tr>
<td colspan="3">
<b>Note:</b>
Select text in textarea using keyboard/mouse, start & end position of selection should show up in fields.<br/>
Populate start and end fields and click the button to set caret position or select text.<br/>
Populate start,end, insert and position fields to replace selected text and place caret/selection as selected in radio button options.
Entering same value in both Start and End fields will set the caret position instead of highlighting a text selection.
</td>
</tr>
</table>
CSS
textarea
{
width: 300px;
height: 300px;
}
table
{
width: 600px;
}
JavaScript
$.fn.extend({
caretSelection : function(options)
{
if(options && !isNaN(options.start) && !isNaN(options.end))
{
this.setCaretSelection(options);
}
else
{
return this.getCaretSelection();
}
},
setCaretSelection : function(options)
{
var inp = this[0];
if(inp.createTextRange)
{
var selRange = inp.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', options.start);
selRange.moveEnd('character',options.end - options.start);
selRange.select();
}
else if(inp.setSelectionRange)
{
inp.focus();
inp.setSelectionRange(options.start, options.end);
}
},
getCaretSelection: function()
{
var inp = this[0], start = 0, end = 0;
if(!isNaN(inp.selectionStart))
{
start = inp.selectionStart;
end = inp.selectionEnd;
}
else if( inp.createTextRange )
{
var inpTxtLen = inp.value.length, jqueryTxtLen = this.val().length;
var inpRange = inp.createTextRange(), collapsedRange = inp.createTextRange();
inpRange.moveToBookmark(document.selection.createRange().getBookmark());
collapsedRange.collapse(false);
start = inpRange.compareEndPoints('StartToEnd', collapsedRange) > -1 ? jqueryTxtLen : inpRange.moveStart('character', -inpTxtLen);
end = inpRange.compareEndPoints('EndToEnd', collapsedRange) > -1 ? jqueryTxtLen : inpRange.moveEnd('character', -inpTxtLen);
}
return {start: Math.abs(start), end: Math.abs(end)};
},
replaceCaretSelection: function(options)
{
var pos = this.caretSelection();
this.val( this.val().substring(0,pos.start) + options.text + this.val().substring(pos.end) );
if(options.insPos == 'before')
{
...