Inserting a text where cursor is using Javascript/jquery
JavascriptJqueryJavascript Problem Overview
I have a page with a lot of textboxes. When someone clicks a link, i want a word or two to be inserted where the cursor is, or appended to the textbox which has the focus.
For example, if the cursor/focus is on a textbox saying 'apple' and he clicks a link saying '[email]', then i want the textbox to say, 'apple [email protected]'.
How can I do this? Is this even possible, since what if the focus is on a radio/dropdown/non textbox element? Can the last focused on textbox be remembered?
Javascript Solutions
Solution 1 - Javascript
Use this, from here:
function insertAtCaret(areaId, text) {
var txtarea = document.getElementById(areaId);
if (!txtarea) {
return;
}
var scrollPos = txtarea.scrollTop;
var strPos = 0;
var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
"ff" : (document.selection ? "ie" : false));
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart('character', -txtarea.value.length);
strPos = range.text.length;
} else if (br == "ff") {
strPos = txtarea.selectionStart;
}
var front = (txtarea.value).substring(0, strPos);
var back = (txtarea.value).substring(strPos, txtarea.value.length);
txtarea.value = front + text + back;
strPos = strPos + text.length;
if (br == "ie") {
txtarea.focus();
var ieRange = document.selection.createRange();
ieRange.moveStart('character', -txtarea.value.length);
ieRange.moveStart('character', strPos);
ieRange.moveEnd('character', 0);
ieRange.select();
} else if (br == "ff") {
txtarea.selectionStart = strPos;
txtarea.selectionEnd = strPos;
txtarea.focus();
}
txtarea.scrollTop = scrollPos;
}
<textarea id="textareaid"></textarea>
<a href="#" onclick="insertAtCaret('textareaid', 'text to insert');return false;">Click Here to Insert</a>
Solution 2 - Javascript
Maybe a shorter version, would be easier to understand?
jQuery("#btn").on('click', function() {
var $txt = jQuery("#txt");
var caretPos = $txt[0].selectionStart;
var textAreaTxt = $txt.val();
var txtToAdd = "stuff";
$txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />
I wrote this in response to https://stackoverflow.com/questions/15976574/how-to-add-a-text-to-a-textbox-from-the-current-position-of-the-pointer-with-jqu
Solution 3 - Javascript
The approved answer from George Claghorn worked great for simply inserting text at the cursor position. If the user had selected text though, and you want that text to be replaced (the default experience with most text), you need to make a small change when setting the 'back' variable.
Also, if you don't need to support older versions of IE, modern versions support textarea.selectionStart, so you can take out all of the browser detection, and IE-specific code.
Here is a simplified version that works for Chrome and IE11 at least, and handles replacing selected text.
function insertAtCaret(areaId, text) {
var txtarea = document.getElementById(areaId);
var scrollPos = txtarea.scrollTop;
var caretPos = txtarea.selectionStart;
var front = (txtarea.value).substring(0, caretPos);
var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
txtarea.value = front + text + back;
caretPos = caretPos + text.length;
txtarea.selectionStart = caretPos;
txtarea.selectionEnd = caretPos;
txtarea.focus();
txtarea.scrollTop = scrollPos;
}
Solution 4 - Javascript
The code above didn't work for me in IE. Here's some code based on this answer.
I took out the getElementById
so I could reference the element in a different way.
function insertAtCaret(element, text) {
if (document.selection) {
element.focus();
var sel = document.selection.createRange();
sel.text = text;
element.focus();
} else if (element.selectionStart || element.selectionStart === 0) {
var startPos = element.selectionStart;
var endPos = element.selectionEnd;
var scrollTop = element.scrollTop;
element.value = element.value.substring(0, startPos) +
text + element.value.substring(endPos, element.value.length);
element.focus();
element.selectionStart = startPos + text.length;
element.selectionEnd = startPos + text.length;
element.scrollTop = scrollTop;
} else {
element.value += text;
element.focus();
}
}
input{width:100px}
label{display:block;margin:10px 0}
<label for="in2copy">Copy text from: <input id="in2copy" type="text" value="x"></label>
<label for="in2ins">Element to insert: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="insertAtCaret(document.getElementById('in2ins'),document.getElementById('in2copy').value)">Insert</button>
EDIT: Added a running snippet, jQuery is not being used.
Solution 5 - Javascript
using @quick_sliv answer:
function insertAtCaret(el, text) {
var caretPos = el.selectionStart;
var textAreaTxt = el.value;
el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
};
Solution 6 - Javascript
How to insert some Text to current cursor position of a TextBox through JQuery and JavaScript
Process
- Find the Current Cursor Position
- Get the Text to be Copied
- Set the Text Over there
- Update the Cursor position
Here I have 2 TextBoxes and a Button. I have to Click on a certain position on a textbox and then click on the button to paste the text from the other textbox to the the position of the previous textbox.
Main issue here is that getting the current cursor position where we will paste the text.
//Textbox on which to be pasted
<input type="text" id="txtOnWhichToBePasted" />
//Textbox from where to be pasted
<input type="text" id="txtFromWhichToBePasted" />
//Button on which click the text to be pasted
<input type="button" id="btnInsert" value="Insert"/>
<script type="text/javascript">
$(document).ready(function () {
$('#btnInsert').bind('click', function () {
var TextToBePasted = $('#txtFromWhichToBePasted').value;
var ControlOnWhichToBePasted = $('#txtOnWhichToBePasted');
//Paste the Text
PasteTag(ControlOnWhichToBePasted, TextToBePasted);
});
});
//Function Pasting The Text
function PasteTag(ControlOnWhichToBePasted,TextToBePasted) {
//Get the position where to be paste
var CaretPos = 0;
// IE Support
if (document.selection) {
ControlOnWhichToBePasted.focus();
var Sel = document.selection.createRange();
Sel.moveStart('character', -ctrl.value.length);
CaretPos = Sel.text.length;
}
// Firefox support
else if (ControlOnWhichToBePasted.selectionStart || ControlOnWhichToBePasted.selectionStart == '0')
CaretPos = ControlOnWhichToBePasted.selectionStart;
//paste the text
var WholeString = ControlOnWhichToBePasted.value;
var txt1 = WholeString.substring(0, CaretPos);
var txt2 = WholeString.substring(CaretPos, WholeString.length);
WholeString = txt1 + TextToBePasted + txt2;
var CaretPos = txt1.length + TextToBePasted.length;
ControlOnWhichToBePasted.value = WholeString;
//update The cursor position
setCaretPosition(ControlOnWhichToBePasted, CaretPos);
}
function setCaretPosition(ControlOnWhichToBePasted, pos) {
if (ControlOnWhichToBePasted.setSelectionRange) {
ControlOnWhichToBePasted.focus();
ControlOnWhichToBePasted.setSelectionRange(pos, pos);
}
else if (ControlOnWhichToBePasted.createTextRange) {
var range = ControlOnWhichToBePasted.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
</script>
Solution 7 - Javascript
Adding text to current cursor position involves two steps:
- Adding the text at the current cursor position
- Updating the current cursor position
Demo: https://codepen.io/anon/pen/qZXmgN
Tested in Chrome 48, Firefox 45, IE 11 and Edge 25
JS:
function addTextAtCaret(textAreaId, text) {
var textArea = document.getElementById(textAreaId);
var cursorPosition = textArea.selectionStart;
addTextAtCursorPosition(textArea, cursorPosition, text);
updateCursorPosition(cursorPosition, text, textArea);
}
function addTextAtCursorPosition(textArea, cursorPosition, text) {
var front = (textArea.value).substring(0, cursorPosition);
var back = (textArea.value).substring(cursorPosition, textArea.value.length);
textArea.value = front + text + back;
}
function updateCursorPosition(cursorPosition, text, textArea) {
cursorPosition = cursorPosition + text.length;
textArea.selectionStart = cursorPosition;
textArea.selectionEnd = cursorPosition;
textArea.focus();
}
HTML:
<div>
<button type="button" onclick="addTextAtCaret('textArea','Apple')">Insert Apple!</button>
<button type="button" onclick="addTextAtCaret('textArea','Mango')">Insert Mango!</button>
<button type="button" onclick="addTextAtCaret('textArea','Orange')">Insert Orange!</button>
</div>
<textarea id="textArea" rows="20" cols="50"></textarea>
Solution 8 - Javascript
I think you could use the following JavaScript to track the last-focused textbox:
<script>
var holdFocus;
function updateFocus(x)
{
holdFocus = x;
}
function appendTextToLastFocus(text)
{
holdFocus.value += text;
}
</script>
Usage:
<input type="textbox" onfocus="updateFocus(this)" />
<a href="#" onclick="appendTextToLastFocus('textToAppend')" />
A previous solution (props to gclaghorn) uses textarea and calculates the position of the cursor too, so it may be better for what you want. On the other hand, this one would be more lightweight, if that's what you're looking for.
Solution 9 - Javascript
This question's answer was posted so long ago and I stumbled upon it via a Google search. HTML5 provides the HTMLInputElement API that includes the setRangeText() method, which replaces a range of text in an <input>
or <textarea>
element with a new string:
element.setRangeText('abc');
The above would replace the selection made inside element
with abc
. You can also specify which part of the input value to replace:
element.setRangeText('abc', 3, 5);
The above would replace the 4th till 6th characters of the input value with abc
. You can also specify how the selection should be set after the text has been replaced by providing one of the following strings as the 4th parameter:
'preserve'
attempts to preserve the selection. This is the default.'select'
selects the newly inserted text.'start'
moves the selection to just before the inserted text.'end'
moves the selection to just after the inserted text.
Browser compatibility
The MDN page for setRangeText doesn't provide browser compatibility data, but I guess it'd be the same as HTMLInputElement.setSelectionRange(), which is basically all modern browsers, IE 9 and above, Edge 12 and above.
Solution 10 - Javascript
This jQuery plugin gives you a pre-made way of selection/caret manipulation.
Solution 11 - Javascript
The accepted answer didn't work for me on Internet Explorer 9. I checked it and the browser detection was not working properly, it detected ff (firefox) when i was at Internet Explorer.
I just did this change:
if ($.browser.msie)
Instead of:
if (br == "ie") {
The resulting code is this one:
function insertAtCaret(areaId,text) {
var txtarea = document.getElementById(areaId);
var scrollPos = txtarea.scrollTop;
var strPos = 0;
var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
"ff" : (document.selection ? "ie" : false ) );
if ($.browser.msie) {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart ('character', -txtarea.value.length);
strPos = range.text.length;
}
else if (br == "ff") strPos = txtarea.selectionStart;
var front = (txtarea.value).substring(0,strPos);
var back = (txtarea.value).substring(strPos,txtarea.value.length);
txtarea.value=front+text+back;
strPos = strPos + text.length;
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart ('character', -txtarea.value.length);
range.moveStart ('character', strPos);
range.moveEnd ('character', 0);
range.select();
}
else if (br == "ff") {
txtarea.selectionStart = strPos;
txtarea.selectionEnd = strPos;
txtarea.focus();
}
txtarea.scrollTop = scrollPos;
}
Solution 12 - Javascript
you can only focus required textbox an insert the text there. there is no way to find out where focus is AFAIK (maybe interating over all DOM nodes?).
check this stackoverflow - it has a solution for you: https://stackoverflow.com/questions/497094/how-do-i-find-out-which-javascript-element-has-focus
Solution 13 - Javascript
Content Editable, HTML or any other DOM element Selections
If you are trying to insert at caret on a <div contenteditable="true">
, this becomes much more difficult, especially if there are children within the editable container.
I have had really great luck using the Rangy library:
It has a ton of great features such as:
- Save Position or Selection
- Then later, Restore the Position or Selection
- Get selection HTML or Plaintext
- Among many others
The online demo was not working last I checked, however the repo has working demos. To get started, simple download the Repo from Git or NPM, then open ./rangy/demos/index.html
It makes working with caret pos and text selection a breeze!