How to get selected text from a textbox control with JavaScript - javascript

I have a textbox and a link button.
When I write some text, select some of it and then click the link button, the selected text from textbox must be show with a message box.
How can I do it?
When I click the submit button for the textbox below, the message box must show Lorem ipsum. Because "Lorem ipsum" is selected in the area.
If I select any text from the page and click the submit button it is working, but if I write a text to textbox and make it, it's not. Because when I click to another space, the selection of textbox is canceled.
Now problem is that, when I select text from textbox and click any other control or space, the text, which is selected, must still be selected.
How is it to be done?

OK, here is the code I have:
function ShowSelection()
{
var textComponent = document.getElementById('Editor');
var selectedText;
if (textComponent.selectionStart !== undefined)
{ // Standards-compliant version
var startPos = textComponent.selectionStart;
var endPos = textComponent.selectionEnd;
selectedText = textComponent.value.substring(startPos, endPos);
}
else if (document.selection !== undefined)
{ // Internet Explorer version
textComponent.focus();
var sel = document.selection.createRange();
selectedText = sel.text;
}
alert("You selected: " + selectedText);
}
The problem is, although the code I give for Internet Explorer is given on a lot of sites, I cannot make it work on my copy of Internet Explorer 6 on my current system. Perhaps it will work for you, and that's why I give it.
The trick you look for is probably the .focus() call to give the focus back to the textarea, so the selection is reactivated.
I got the right result (the selection content) with the onKeyDown event:
document.onkeydown = function (e) { ShowSelection(); }
So the code is correct. Again, the issue is to get the selection on click on a button... I continue to search.
I didn't have any success with a button drawn with a li tag, because when we click on it, Internet Explorer deselects the previous selection. The above code works with a simple input button, though...

Here's a much simpler solution, based on the fact that text selection occurs on mouseup, so we add an event listener for that:
document.querySelector('textarea').addEventListener('mouseup', function () {
window.mySelection = this.value.substring(this.selectionStart, this.selectionEnd)
// window.getSelection().toString();
});
<textarea>
Select some text
</textarea>
<a href="#" onclick=alert(mySelection);>Click here to display the selected text</a>
This works in all browsers.
If you also want to handle selection via the keyboard, add another event listener for keyup, with the same code.
If it weren't for this Firefox bug filed back in 2001 (yes, 14 years ago), we could replace the value assigned to window.mySelection with window.getSelection().toString(), which works in IE9+ and all modern browsers, and also gets the selection made in non-textarea parts of the DOM.

function disp() {
var text = document.getElementById("text");
var t = text.value.substr(text.selectionStart, text.selectionEnd - text.selectionStart);
alert(t);
}
<TEXTAREA id="text">Hello, How are You?</TEXTAREA><BR>
<INPUT type="button" onclick="disp()" value="Select text and click here" />

For Opera, Firefox and Safari, you can use the following function:
function getTextFieldSelection(textField) {
return textField.value.substring(textField.selectionStart, textField.selectionEnd);
}
Then, you just pass a reference to a text field element (like a textarea or input element) to the function:
alert(getTextFieldSelection(document.getElementsByTagName("textarea")[0]));
Or, if you want <textarea> and <input> to have a getSelection() function of their own:
HTMLTextAreaElement.prototype.getSelection = HTMLInputElement.prototype.getSelection = function() {
var ss = this.selectionStart;
var se = this.selectionEnd;
if (typeof ss === "number" && typeof se === "number") {
return this.value.substring(this.selectionStart, this.selectionEnd);
}
return "";
};
Then, you'd just do:
alert(document.getElementsByTagName("textarea")[0].getSelection());
alert(document.getElementsByTagName("input")[0].getSelection());
for example.

I am a big fan of jQuery-textrange.
Below is a very small, self-contained, example. Download jquery-textrange.js and copy it to the same folder.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery-textrange</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="jquery-textrange.js"></script>
<script>
/* Run on document load */
$(document).ready(function() {
/* Run on any change of 'textarea' **/
$('#textareaId').bind('updateInfo keyup mousedown mousemove mouseup', function() {
/* The magic is on this line **/
var range = $(this).textrange();
/* Stuff into selectedId. I wanted to
store this is a input field so it
can be submitted in a form. */
$('#selectedId').val(range.text);
});
});
</script>
</head>
<body>
The smallest example possible using
<a href="https://github.com/dwieeb/jquery-textrange">
jquery-textrange
</a><br/>
<textarea id="textareaId">Some random content.</textarea><br/>
<input type="text" id="selectedId"></input>
</body>
</html>

// jQuery
var textarea = $('#post-content');
var selectionStart = textarea.prop('selectionStart');
var selectionEnd = textarea.prop('selectionEnd');
var selection = (textarea.val()).substring(selectionStart, selectionEnd);
// JavaScript
var textarea = document.getElementById("post-content");
var selection = (textarea.value).substring(textarea.selectionStart, textarea.selectionEnd);

Related

Programmatically change input value in Facebook's editable div input area

I'm trying to write a Chrome Extension that needs to be able to insert a character at the cursor location in an input field.
It's very easy when the input is an actual HTMLInputElement (insertAtCaretInput borrowed from another stack answer):
function insertAtCaretInput(text) {
text = text || '';
if (document.selection) {
// IE
this.focus();
var sel = document.selection.createRange();
sel.text = text;
} else if (this.selectionStart || this.selectionStart === 0) {
// Others
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
this.value = this.value.substring(0, startPos) + text + this.value.substring(endPos, this.value.length);
this.selectionStart = startPos + text.length;
this.selectionEnd = startPos + text.length;
} else {
this.value += text;
}
}
HTMLInputElement.prototype.insertAtCaret = insertAtCaretInput;
onKeyDown(e){
...
targetElement = e.target;
target.insertAtCaret(charToInsert);
...
}
But the moment an input is actually represented differently in the HTML structure (e.g. Facebook having a <div> with <span> elements showing up and consolidating at weird times) I can't figure out how to do it reliably. The new character disappears or changes position or the cursor jumps to unpredictable places the moment I start interacting with the input.
Example HTML structure for Facebook's (Chrome desktop page, new post or message input fields) editable <div> containing string Test :
<div data-offset-key="87o4u-0-0" class="_1mf _1mj">
<span>
<span data-offset-key="87o4u-0-0">
<span data-text="true">Test
</span>
</span>
</span>
<span data-offset-key="87o4u-1-0">
<span data-text="true">
</span>
</span>
</div>
Here's my most successful attempt so far. I extend the span element like so (insertTextAtCursor also borrowed from another answer):
function insertTextAtCursor(text) {
let selection = window.getSelection();
let range = selection.getRangeAt(0);
range.deleteContents();
let node = document.createTextNode(text);
range.insertNode(node);
for (let position = 0; position != text.length; position++) {
selection.modify('move', 'right', 'character');
}
}
HTMLSpanElement.prototype.insertAtCaret = insertTextAtCursor;
And since the element triggering key press events is a <div> that then holds <span> elements which then hold the text nodes with the actual input, I find the deepest <span> element and perform insertAtCaret on that element:
function findDeepestChild(parent) {
var result = { depth: 0, element: parent };
[].slice.call(parent.childNodes).forEach(function (child) {
var childResult = findDeepestChild(child);
if (childResult.depth + 1 > result.depth) {
result = {
depth: 1 + childResult.depth,
element: childResult.element,
parent: childResult.element.parentNode,
};
}
});
return result;
}
onKeyDown(e){
...
targetElement = findDeepestChild(e.target).parent; // deepest child is a text node
target.insertAtCaret(charToInsert);
...
}
The code above can successfully insert the character but then strange things happen when Facebook's behind-the-scenes framework tries to process the new value. I tried all kinds of tricks with repositioning the cursors and inserting <span> elements similar to what seems to be happening when Facebook manipulates the dom on inserts but in the end, all of it fails one way or another. I imagine it's because the state of the input area is held somewhere and is not synchronized with my modifications.
Do you think it's possible to do this reliably and if so, how? Ideally, the answer wouldn't be specific to Facebook but would also work on other pages that use other elements instead of HTMLInputElement as input fields but I understand that it might not be possible.
I had a similar problem with Whatsapp web
try to dispatch an input event
target.dispatchEvent(new InputEvent('input', {bubbles: true}));
I've made a Firefox extension that is able to paste a remembered note from context menu into input fields. However Facebook Messenger fields are heavly scripted divs and spans - not input fields. I've struggled to make them work and dispatching an event as suggested by #user9977151 helped me!
However it needs to be dispatched from a specific element and also you need to check if your Facebook Messenger input field is empty or not.
Empty field will look like that:
<div class="" data-block="true" data-editor="e1m9r" data-offset-key="6hbkl-0-0">
<div data-offset-key="6hbkl-0-0" class="_1mf _1mj">
<span data-offset-key="6hbkl-0-0">
<br data-text="true">
</span>
</div>
</div>
And not empty like that
<div class="" data-block="true" data-editor="e1m9r" data-offset-key="6hbkl-0-0">
<div data-offset-key="6hbkl-0-0" class="_1mf _1mj">
<span data-offset-key="6hbkl-0-0">
<span data-text="true">
Some input
</span>
</span>
</div>
</div>
The event needs to be dispatched from
<span data-offset-key="6hbkl-0-0">
It's simple when you add something to not empty field - you just change the innerText and dispatch the event.
It's more tricky for an empty field. Normally when the user writes something <br data-text="true"> changes into <span data-text="true"> with the user's input.
I've tried doing it programically (adding a span with innerText, removing the br) but it broke the Messenger input. What worked for me was to add a span, dispatch the event and then remove it! After that Facebook removed br like it normally does and added span with my input.
Facebook seems to somehow store user keypresses in it's memory and then input them itself.
My code was
if(document.body.parentElement.id == "facebook"){
var dc = getDeepestChild(actEl);
var elementToDispatchEventFrom = dc.parentElement;
let newEl;
if(dc.nodeName.toLowerCase() == "br"){
// attempt to paste into empty messenger field
// by creating new element and setting it's value
newEl = document.createElement("span");
newEl.setAttribute("data-text", "true");
dc.parentElement.appendChild(newEl);
newEl.innerText = message.content;
}else{
// attempt to paste into not empty messenger field
// by changing existing content
let sel = document.getSelection();
selStart = sel.anchorOffset;
selStartCopy = selStart;
selEnd = sel.focusOffset;
intendedValue = dc.textContent.slice(0,selStart) + message.content + dc.textContent.slice(selEnd);
dc.textContent = intendedValue;
elementToDispatchEventFrom = elementToDispatchEventFrom.parentElement;
}
// simulate user's input
elementToDispatchEventFrom.dispatchEvent(new InputEvent('input', {bubbles: true}));
// remove new element if it exists
// otherwise there will be two of them after
// Facebook adds it itself!
if (newEl) newEl.remove();
}else ...
where
function getDeepestChild(element){
if(element.lastChild){
return getDeepestChild(element.lastChild)
}else{
return element;
}
}
and message.content was a string that I wanted to be pasted into Messenger field.
This solution can change the content of Messenger field but will move the cursor to the beginning of the field - and I'm not sure if is possible to keep the cursor's position unchanged (as there's no selectionStart and selectionEnd that could be changed).
The answer of #raandremsil and #ATP mostly worked for me.
However, I had a case when it was not working.
My extension displays a list of texts that will be inserted in the input when the user clicks on an item. It was not working properly until I focused on the field before modifying the content and dispatching the event.
const myNewText = 'whatever text I get a click on my list';
elementToDispatchEventFrom.focus(); // <- I had to add this line, focus the field before editing (`elementToDispatchEventFrom` is from raandremsil's answer)
deepestChild.contextText = myNewText; // Edit the text
elementToDispatchEventFrom.dispatchEvent(new InputEvent('input', {bubbles: true})); // Dispatch event to simulate user input
UPDATE 27/02/2022:
This stopped working for some reason. Here is was I am doing now to replace a text in the input, assuming it is just before the cursor position.
const selection = window.getSelection()!;
const cursorPosition = selection.focusOffset;
const focusNode = selection.focusNode!;
const doc = focusNode.ownerDocument!;
const range = new Range();
range.setStart(focusNode, cursorPosition - textToReplace.length);
range.setEnd(focusNode, cursorPosition);
selection.removeAllRanges();
selection.addRange(range);
doc.execCommand('insertText', false, myNewText); // Careful, for some reason, this does not work if `myNewText` ends with the space.

Wrap an html tag after clicking a toolbar button using js or jquery

I want to do something similar to what this website and wordpress does. When a user highlights text on the screen, then clicks a button on the toolbar it will wrap an html tag around the text. In jquery I would probably use the .wrap class but how would I detect if the user highlighted something.
For example, when the user writes Hello World then clicks on the bold button it will say <b>Hello World</b>
This mainly requires (1) accessing the selectionStart and selectionEnd properties of the input/textarea element and (2) replacing the substring of the value property across that range with the same text, but wrapped in the desired start and end tags. Also, I think it makes sense to reselect the replaced text, which requires a couple of calls to select() and setSelectionRange(). Also, if there's no selection (meaning start equals end) it's probably a good idea to do nothing at all.
window.selWrapBold = function(id) { selWrap(id,'<b>','</b>'); };
window.selWrapItalic = function(id) { selWrap(id,'<i>','</i>'); };
window.selWrap = function(id,startTag,endTag) {
let elem = document.getElementById(id);
let start = elem.selectionStart;
let end = elem.selectionEnd;
let sel = elem.value.substring(start,end);
if (sel==='') return;
let replace = startTag+sel+endTag;
elem.value = elem.value.substring(0,start)+replace+elem.value.substring(end);
elem.select();
elem.setSelectionRange(start,start+replace.length);
} // end selWrap()
<input type="button" value="bold" onclick="selWrapBold('ta1');"/>
<input type="button" value="italic" onclick="selWrapItalic('ta1');"/>
<br/>
<textarea id="ta1"></textarea>
Get the text of the html element which is wrapping the text, then add as html the text embedded in the <b> tag.
See jQuery DOM Manipulation for tutorials.
I used this question to get the selected text. And this question to
get the element with selected text in it. I combined them in a single function.
function updateHighlightedText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
var node = $(window.getSelection().anchorNode.parentNode); //Get the selected node
node.html(node.text().replace(text, "<b>"+text+"</b>")); //Update the node
}

use javascript to dislay a form field as text until clicked on

I have got this working with the start point as a span, but I want to have the form still function if javascript is disabled in the browser this is how I had it working originally. I'm still very new to javascript, can someone lend a hand please.
window.onload = function() {
document.getElementById('container').onclick = function(event) {
var span, input, text;
// Get the event (handle MS difference)
event = event || window.event;
// Get the root element of the event (handle MS difference)
span = event.target || event.srcElement;
// If it's a span...
if (span && span.tagName.toUpperCase() === "SPAN") {
// Hide it
span.style.display = "none";
// Get its text
text = span.innerHTML;
// Create an input
input = document.createElement("input");
input.type = "text";
input.size = Math.max(text.length / 4 * 3, 4);
span.parentNode.insertBefore(input, span);
// Focus it, hook blur to undo
input.focus();
input.onblur = function() {
// Remove the input
span.parentNode.removeChild(input);
// Update the span
span.innerHTML = input.value;
// Show the span again
span.style.display = "";
};
}
};
};
Best way to do this would be to show the input first, then quickly swap it out when the page loads, then swap it back when the user clicks.
You might also consider using the form element the whole time, but just changing CSS classes on it to make it look like normal text. This would make your UI cleaner and easier to maintain in the future.
Then just put the input fields there from the start, and hide them with a script that runs when the form has loaded. That way all the fields will be visible if Javascript is not supported.
I think your best option would be to wrap a form with noscript tags which will fire when Javascript is disabled in a browser. If they display even while in the noscript tags then just set them as not visible with Javascript.
if you have jQuery, something like this should work.
function makeElementIntoClickableText(elm){
$(elm).parent().append("<div onClick='switchToInput(this);'>"+ elm.value +"</div>");
$(elm).hide();
}
function switchToInput(elm){
$(elm).prev().prev().show();
$(elm).hide();
}
makeElementIntoClickableText($("input")[0]);
use the readonly attribute in the input elements:
<input type="text" readonly />
And then remove that attribute with JavaScript in the onclick event handler, reassigning it on blur:
var inputs = document.getElementsByTagName('input');
for (i=0; i < inputs.length; i++) {
inputs[i].setAttribute('readonly',true);
inputs[i].onclick = function(){
this.removeAttribute('readonly');
};
inputs[i].onblur = function(){
this.setAttribute('readonly',true);
};
}
JS Fiddle demo.

Strange behavior of selection

My JS code:
function getSelectedText(){
if(window.getSelection){
select = window.getSelection().getRangeAt(0);
var st_span = select.startContainer.parentNode.getAttribute("id").split("_")[1];
var end_span = select.endContainer.parentNode.getAttribute("id").split("_")[1];
console.log(select.endContainer);
var ret_urn=[st_span,end_span];
return ret_urn
}
else if(document.getSelection){
return document.getSelection();
}
}
$(document).ready(function() {
$("div#check_button button").click(function () {
var loc = getSelectedText();
console.log(loc);
});
});
Here is my whole html file: http://pastebin.com/acdiU623
It is hard to explain it, so I prepared short movie: http://www.youtube.com/watch?v=tVk4K70JO80
In a few words: when I press left mouse button and hold it to select text/numbers and start selection from the half of letter/number, although this letter/number is not highlighted, it is added to selection. I have to start selection precisely. It is ok with wide letters, but hard with letters like i,j or l.
This is second example of my movie. I pressed left button on 3/4 of length of number 5, although 5 is not highlighted, it is selected.
Tested on FF and Opera.
Ok just tried this demo. and it works flawlessly. it even works on firefox. Just tested opera and safari and it works on both of them as well. Even if i select half a letter or number, it just returns the highlighted text which is what is expected when you make a selection.
try it out on a fresh webpage though just for testing purposes. then when it works and you are satisfied with the results then start making changes to your existing page.
Its a lot more simpler than your code. This is a cross-browser script to get text selected by the user
<script language=javascript>
function getSelText()
{
var txt = '';
if (window.getSelection)
{
txt = window.getSelection();
}
else if (document.getSelection)
{
txt = document.getSelection();
}
else if (document.selection)
{
txt = document.selection.createRange().text;
}
else return;
document.aform.selectedtext.value = txt;
}
</script>
<input type="button" value="Get selection" onmousedown="getSelText()">
<form name=aform >
<textarea name="selectedtext" rows="5" cols="20"></textarea>
</form>
http://www.codetoad.com/javascript_get_selected_text.asp
Hope this helps.
PK
There are multiple different boundary points for a selection that will look the same to the user. What you're seeing is probably the difference between the following, where | is a selection boundary:
<span>5</span><span>|6</span><span>7|</span><span>8</span>
and
<span>5|</span><span>6</span><span>7</span><span>|8</span>
In both cases, calling toString() on the selection will give you the same result ("67").

Use JavaScript to place cursor at end of text in text input element

What is the best way (and I presume simplest way) to place the cursor at the end of the text in a input text element via JavaScript - after focus has been set to the element?
There's a simple way to get it working in most browsers.
this.selectionStart = this.selectionEnd = this.value.length;
However, due to the *quirks of a few browsers, a more inclusive answer looks more like this
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
Using jQuery (to set the listener, but it's not necessary otherwise)
$('#el').focus(function(){
var that = this;
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='el' type='text' value='put cursor at end'>
Using Vanilla JS (borrowing addEvent function from this answer)
// Basic cross browser addEvent
function addEvent(elem, event, fn){
if(elem.addEventListener){
elem.addEventListener(event, fn, false);
}else{
elem.attachEvent("on" + event,
function(){ return(fn.call(elem, window.event)); });
}}
var element = document.getElementById('el');
addEvent(element,'focus',function(){
var that = this;
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
});
<input id='el' type='text' value='put cursor at end'>
Quirks
Chrome has an odd quirk where the focus event fires before the cursor is moved into the field; which screws my simple solution up. Two options to fix this:
You can add a timeout of 0 ms (to defer the operation until the stack is clear)
You can change the event from focus to mouseup. This would be pretty annoying for the user unless you still kept track of focus. I'm not really in love with either of these options.
Also, #vladkras pointed out that some older versions of Opera incorrectly calculate the length when it has spaces. For this you can use a huge number that should be larger than your string.
Try this, it has worked for me:
//input is the input element
input.focus(); //sets focus to element
var val = this.input.value; //store the value of the element
this.input.value = ''; //clear the value of the element
this.input.value = val; //set that value back.
For the cursor to be move to the end, the input has to have focus first, then when the value is changed it will goto the end. If you set .value to the same, it won't change in chrome.
I faced this same issue (after setting focus through RJS/prototype) in IE.
Firefox was already leaving the cursor at the end when there is already a value for the field. IE was forcing the cursor to the beginning of the text.
The solution I arrived at is as follows:
<input id="search" type="text" value="mycurrtext" size="30"
onfocus="this.value = this.value;" name="search"/>
This works in both IE7 and FF3 but doesn't work in modern browsers (see comments) as it is not specified that UA must overwrite the value in this case (edited in accordance with meta policy).
After hacking around with this a bit, I found the best way was to use the setSelectionRange function if the browser supports it; if not, revert to using the method in Mike Berrow's answer (i.e. replace the value with itself).
I'm also setting scrollTop to a high value in case we're in a vertically-scrollable textarea. (Using an arbitrary high value seems more reliable than $(this).height() in Firefox and Chrome.)
I've made it is as a jQuery plugin. (If you're not using jQuery I trust you can still get the gist easily enough.)
I've tested in IE6, IE7, IE8, Firefox 3.5.5, Google Chrome 3.0, Safari 4.0.4, Opera 10.00.
It's available on jquery.com as the PutCursorAtEnd plugin. For your convenience, the code for release 1.0 is as follows:
// jQuery plugin: PutCursorAtEnd 1.0
// http://plugins.jquery.com/project/PutCursorAtEnd
// by teedyay
//
// Puts the cursor at the end of a textbox/ textarea
// codesnippet: 691e18b1-f4f9-41b4-8fe8-bc8ee51b48d4
(function($)
{
jQuery.fn.putCursorAtEnd = function()
{
return this.each(function()
{
$(this).focus()
// If this function exists...
if (this.setSelectionRange)
{
// ... then use it
// (Doesn't work in IE)
// Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
var len = $(this).val().length * 2;
this.setSelectionRange(len, len);
}
else
{
// ... otherwise replace the contents with itself
// (Doesn't work in Google Chrome)
$(this).val($(this).val());
}
// Scroll to the bottom, in case we're in a tall textarea
// (Necessary for Firefox and Google Chrome)
this.scrollTop = 999999;
});
};
})(jQuery);
<script type="text/javascript">
function SetEnd(txt) {
if (txt.createTextRange) {
//IE
var FieldRange = txt.createTextRange();
FieldRange.moveStart('character', txt.value.length);
FieldRange.collapse();
FieldRange.select();
}
else {
//Firefox and Opera
txt.focus();
var length = txt.value.length;
txt.setSelectionRange(length, length);
}
}
</script>
This function works for me in IE9, Firefox 6.x, and Opera 11.x
It's 2019 and none of the methods above worked for me, but this one did, taken from https://css-tricks.com/snippets/javascript/move-cursor-to-end-of-input/
function moveCursorToEnd(id) {
var el = document.getElementById(id)
el.focus()
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
<input id="myinput" type="text" />
Move cursor to end
I've tried the following with quite great success in chrome
$("input.focus").focus(function () {
var val = this.value,
$this = $(this);
$this.val("");
setTimeout(function () {
$this.val(val);
}, 1);
});
Quick rundown:
It takes every input field with the class focus on it, then stores the old value of the input field in a variable, afterwards it applies the empty string to the input field.
Then it waits 1 milisecond and puts in the old value again.
el.setSelectionRange(-1, -1);
https://codesandbox.io/s/peaceful-bash-x2mti
This method updates the HTMLInputElement.selectionStart, selectionEnd,
and selectionDirection properties in one call.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
In other js methods -1 usually means (to the) last character. This is the case for this one too, but I couldn't find explicit mention of this behavior in the docs.
Simple. When editing or changing values, first put the focus then set value.
$("#catg_name").focus();
$("#catg_name").val(catg_name);
Still the intermediate variable is needed, (see var val=)
else the cursor behaves strange, we need it at the end.
<body onload="document.getElementById('userinput').focus();">
<form>
<input id="userinput" onfocus="var val=this.value; this.value=''; this.value= val;"
class=large type="text" size="10" maxlength="50" value="beans" name="myinput">
</form>
</body>
const end = input.value.length
input.setSelectionRange(end, end)
// 👇 scroll to the bottom if a textarea has long text
input.focus()
Try this one works with Vanilla JavaScript.
<input type="text" id="yourId" onfocus="let value = this.value; this.value = null; this.value=value" name="nameYouWant" class="yourClass" value="yourValue" placeholder="yourPlaceholder...">
In Js
document.getElementById("yourId").focus()
For all browsers for all cases:
function moveCursorToEnd(el) {
window.setTimeout(function () {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}, 1);
}
Timeout required if you need to move cursor from onFocus event handler
I like the accepted answer a lot, but it stopped working in Chrome. In Chrome, for the cursor to go to the end, input value needs to change. The solution is as follow:
<input id="search" type="text" value="mycurrtext" size="30"
onfocus="var value = this.value; this.value = null; this.value = value;" name="search"/>
document.querySelector('input').addEventListener('focus', e => {
const { value } = e.target;
e.target.setSelectionRange(value.length, value.length);
});
<input value="my text" />
In jQuery, that's
$(document).ready(function () {
$('input').focus(function () {
$(this).attr('value',$(this).attr('value'));
}
}
I just found that in iOS, setting textarea.textContent property will place the cursor at the end of the text in the textarea element every time. The behavior was a bug in my app, but seems to be something that you could use intentionally.
This problem is interesting. The most confusing thing about it is that no solution I found solved the problem completely.
+++++++ SOLUTION +++++++
You need a JS function, like this:
function moveCursorToEnd(obj) {
if (!(obj.updating)) {
obj.updating = true;
var oldValue = obj.value;
obj.value = '';
setTimeout(function(){ obj.value = oldValue; obj.updating = false; }, 100);
}
}
You need to call this guy in the onfocus and onclick events.
<input type="text" value="Test Field" onfocus="moveCursorToEnd(this)" onclick="moveCursorToEnd(this)">
IT WORKS ON ALL DEVICES AN BROWSERS!!!!
var valsrch = $('#search').val();
$('#search').val('').focus().val(valsrch);
Taking some of the answers .. making a single-line jquery.
$('#search').focus().val($('#search').val());
If the input field just needs a static default value I usually do this with jQuery:
$('#input').focus().val('Default value');
This seems to work in all browsers.
While this may be an old question with lots of answers, I ran across a similar issue and none of the answers were quite what I wanted and/or were poorly explained. The issue with selectionStart and selectionEnd properties is that they don't exist for input type number (while the question was asked for text type, I reckon it might help others who might have other input types that they need to focus). So if you don't know whether the input type the function will focus is a type number or not, you cannot use that solution.
The solution that works cross browser and for all input types is rather simple:
get and store the value of input in a variable
focus the input
set the value of input to the stored value
That way the cursor is at the end of the input element.
So all you'd do is something like this (using jquery, provided the element selector that one wishes to focus is accessible via 'data-focus-element' data attribute of the clicked element and the function executes after clicking on '.foo' element):
$('.foo').click(function() {
element_selector = $(this).attr('data-focus-element');
$focus = $(element_selector);
value = $focus.val();
$focus.focus();
$focus.val(value);
});
Why does this work? Simply, when the .focus() is called, the focus will be added to the beginning of the input element (which is the core problem here), ignoring the fact, that the input element already has a value in it. However, when the value of an input is changed, the cursor is automatically placed at the end of the value inside input element. So if you override the value with the same value that had been previously entered in the input, the value will look untouched, the cursor will, however, move to the end.
Super easy (you may have to focus on the input element)
inputEl = getElementById('inputId');
var temp = inputEl.value;
inputEl.value = '';
inputEl.value = temp;
Set the cursor when click on text area to the end of text...
Variation of this code is...ALSO works! for Firefox, IE, Safari, Chrome..
In server-side code:
txtAddNoteMessage.Attributes.Add("onClick", "sendCursorToEnd('" & txtAddNoteMessage.ClientID & "');")
In Javascript:
function sendCursorToEnd(obj) {
var value = $(obj).val(); //store the value of the element
var message = "";
if (value != "") {
message = value + "\n";
};
$(obj).focus().val(message);
$(obj).unbind();
}
If you set the value first and then set the focus, the cursor will always appear at the end.
$("#search-button").click(function (event) {
event.preventDefault();
$('#textbox').val('this');
$("#textbox").focus();
return false;
});
Here is the fiddle to test
https://jsfiddle.net/5on50caf/1/
I wanted to put cursor at the end of a "div" element where contenteditable = true, and I got a solution with Xeoncross code:
<input type="button" value="Paste HTML" onclick="document.getElementById('test').focus(); pasteHtmlAtCaret('<b>INSERTED</b>'); ">
<div id="test" contenteditable="true">
Here is some nice text
</div>
And this function do magic:
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
Works fine for most browsers, please check it, this code puts text and put focus at the end of the text in div element (not input element)
https://jsfiddle.net/Xeoncross/4tUDk/
Thanks, Xeoncross
I also faced same problem. Finally this gonna work for me:
jQuery.fn.putCursorAtEnd = = function() {
return this.each(function() {
// Cache references
var $el = $(this),
el = this;
// Only focus if input isn't already
if (!$el.is(":focus")) {
$el.focus();
}
// If this function exists... (IE 9+)
if (el.setSelectionRange) {
// Double the length because Opera is inconsistent about whether a carriage return is one character or two.
var len = $el.val().length * 2;
// Timeout seems to be required for Blink
setTimeout(function() {
el.setSelectionRange(len, len);
}, 1);
} else {
// As a fallback, replace the contents with itself
// Doesn't work in Chrome, but Chrome supports setSelectionRange
$el.val($el.val());
}
// Scroll to the bottom, in case we're in a tall textarea
// (Necessary for Firefox and Chrome)
this.scrollTop = 999999;
});
};
This is how we can call this:
var searchInput = $("#searchInputOrTextarea");
searchInput
.putCursorAtEnd() // should be chainable
.on("focus", function() { // could be on any event
searchInput.putCursorAtEnd()
});
It's works for me in safari, IE, Chrome, Mozilla. On mobile devices I didn't tried this.
Check this solution!
//fn setCurPosition
$.fn.setCurPosition = function(pos) {
this.focus();
this.each(function(index, elem) {
if (elem.setSelectionRange) {
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
});
return this;
};
// USAGE - Set Cursor ends
$('#str1').setCurPosition($('#str1').val().length);
// USAGE - Set Cursor at 7 position
// $('#str2').setCurPosition(7);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Set cursor at any position</p>
<p><input type="text" id="str1" value="my string here" /></p>
<p><input type="text" id="str2" value="my string here" /></p>
I took the best answers from here, and created a function that works well in Chrome.
You will need to wrap the logic in a timeout, because you have to wait for the focus to finish before accessing the selection
To place the cursor at the end, the selection start needs to be placed at the end
In order to scroll to the end of the input field, the scrollLeft needs to match the scrollWidth
/**
* Upon focus, set the cursor to the end of the text input
* #param {HTMLInputElement} inputEl - An HTML <input> element
*/
const setFocusEnd = (inputEl) => {
setTimeout(() => {
const { scrollWidth, value: { length } } = inputEl;
inputEl.setSelectionRange(length, length);
inputEl.scrollLeft = scrollWidth;
}, 0);
};
document
.querySelector('input')
.addEventListener('focus', (e) => setFocusEnd(e.target));
html, body {
width: 100%;
height: 100%;
margin: 0;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
input:focus {
background-color: hsla(240, 100%, 95%, 1.0);
}
<input
type="text"
placeholder="Search..."
value="This is some really, really long text">
<input id="input_1">
<input id="input_2" type="hidden">
<script type="text/javascript">
//save input_1 value to input_2
$("#input_2").val($("#input_1").val());
//empty input_1 and add the saved input_2 into input_1
$("#input_1").val("").val($("#input_2").val()).focus();
</script>

Categories