Copy output of a JavaScript variable to the clipboard - javascript

I have no knowledge of JavaScript, but I managed to put this code together using bits and bolts from various Stack Overflow answers. It works OK, and it outputs an array of all selected checkboxes in a document via an alert box.
function getSelectedCheckboxes(chkboxName) {
var checkbx = [];
var chkboxes = document.getElementsByName(chkboxName);
var nr_chkboxes = chkboxes.length;
for(var i=0; i<nr_chkboxes; i++) {
if(chkboxes[i].type == 'checkbox' && chkboxes[i].checked == true) checkbx.push(chkboxes[i].value);
}
return checkbx;
}
And to call it I use:
<button id="btn_test" type="button" >Check</button>
<script>
document.getElementById('btn_test').onclick = function() {
var checkedBoxes = getSelectedCheckboxes("my_id");
alert(checkedBoxes);
}
</script>
Now I would like to modify it so when I click the btn_test button the output array checkbx is copied to the clipboard. I tried adding:
checkbx = document.execCommand("copy");
or
checkbx.execCommand("copy");
at the end of the function and then calling it like:
<button id="btn_test" type="button" onclick="getSelectedCheckboxes('my_id')">Check</button>
But it does not work. No data is copied to clipboard.

function copyToClipboard(text) {
var dummy = document.createElement("textarea");
// to avoid breaking orgain page when copying more words
// cant copy when adding below this code
// dummy.style.display = 'none'
document.body.appendChild(dummy);
//Be careful if you use texarea. setAttribute('value', value), which works with "input" does not work with "textarea". – Eduard
dummy.value = text;
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
}
copyToClipboard('hello world')
copyToClipboard('hello\nworld')

OK, I found some time and followed the suggestion by Teemu and I was able to get exactly what I wanted.
So here is the final code for anyone that might be interested. For clarification, this code gets all checked checkboxes of a certain ID, outputs them in an array, named here checkbx, and then copies their unique name to the clipboard.
JavaScript function:
function getSelectedCheckboxes(chkboxName) {
var checkbx = [];
var chkboxes = document.getElementsByName(chkboxName);
var nr_chkboxes = chkboxes.length;
for(var i=0; i<nr_chkboxes; i++) {
if(chkboxes[i].type == 'checkbox' && chkboxes[i].checked == true) checkbx.push(chkboxes[i].value);
}
checkbx.toString();
// Create a dummy input to copy the string array inside it
var dummy = document.createElement("input");
// Add it to the document
document.body.appendChild(dummy);
// Set its ID
dummy.setAttribute("id", "dummy_id");
// Output the array into it
document.getElementById("dummy_id").value=checkbx;
// Select it
dummy.select();
// Copy its contents
document.execCommand("copy");
// Remove it as its not needed anymore
document.body.removeChild(dummy);
}
And its HTML call:
<button id="btn_test" type="button" onclick="getSelectedCheckboxes('ID_of_chkbxs_selected')">Copy</button>

For general purposes of copying any text to the clipboard, I wrote the following function:
function textToClipboard (text) {
var dummy = document.createElement("textarea");
document.body.appendChild(dummy);
dummy.value = text;
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
}
The value of the parameter is inserted into value of a newly created <textarea>, which is then selected, its value is copied to the clipboard and then it gets removed from the document.

Very useful. I modified it to copy a JavaScript variable value to clipboard:
function copyToClipboard(val){
var dummy = document.createElement("input");
dummy.style.display = 'none';
document.body.appendChild(dummy);
dummy.setAttribute("id", "dummy_id");
document.getElementById("dummy_id").value=val;
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
}

When you need to copy a variable to the clipboard in the Chrome dev console, you can simply use the copy() command.
https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference#copyobject

I managed to copy text to the clipboard (without showing any text boxes) by adding a hidden input element to body, i.e.:
function copy(txt){
var cb = document.getElementById("cb");
cb.value = txt;
cb.style.display='block';
cb.select();
document.execCommand('copy');
cb.style.display='none';
}
<button onclick="copy('Hello Clipboard!')"> copy </button>
<input id="cb" type="text" hidden>

Use Clipboard API
text = "HEllo World";
navigator.clipboard.writeText(text)
It works on Chrome 66+, Edge 79+, Firefox 63+ & doesn't work on I.E.
Read More About Clipboard API At MDN Docs

Nowadays there is a new(ish) API to do this directly. It works on modern browsers and on HTTPS (and localhost) only. Not supported by IE11.
IE11 has its own API.
And the workaround in the accepted answer can be used for unsecure hosts.
function copyToClipboard (text) {
if (navigator.clipboard) { // default: modern asynchronous API
return navigator.clipboard.writeText(text);
} else if (window.clipboardData && window.clipboardData.setData) { // for IE11
window.clipboardData.setData('Text', text);
return Promise.resolve();
} else {
// workaround: create dummy input
const input = h('input', { type: 'text' });
input.value = text;
document.body.append(input);
input.focus();
input.select();
document.execCommand('copy');
input.remove();
return Promise.resolve();
}
}
Note: it uses Hyperscript to create the input element (but should be easy to adapt)
There is no need to make the input invisible, as it is added and removed so fast. Also when hidden (even using some clever method) some browsers will detect it and prevent the copy operation.

At the time of writing, setting display:none on the element didn't work for me. Setting the element's width and height to 0 did not work either. So the element has to be at least 1px in width for this to work.
The following example worked in Chrome and Firefox:
const str = 'Copy me';
const el = document.createElement("input");
// Does not work:
// dummy.style.display = "none";
el.style.height = '0px';
// Does not work:
// el.style.width = '0px';
el.style.width = '1px';
document.body.appendChild(el);
el.value = str;
el.select();
document.execCommand("copy");
document.body.removeChild(el);
I'd like to add that I can see why the browsers are trying to prevent this hackish approach. It's better to openly show the content you are going copy into the user's browser. But sometimes there are design requirements, we can't change.

I just want to add, if someone wants to copy two different inputs to clipboard. I also used the technique of putting it to a variable then put the text of the variable from the two inputs into a text area.
Note: the code below is from a user asking how to copy multiple user inputs into clipboard. I just fixed it to work correctly. So expect some old style like the use of var instead of let or const. I also recommend to use addEventListener for the button.
function doCopy() {
try{
var unique = document.querySelectorAll('.unique');
var msg ="";
unique.forEach(function (unique) {
msg+=unique.value;
});
var temp =document.createElement("textarea");
var tempMsg = document.createTextNode(msg);
temp.appendChild(tempMsg);
document.body.appendChild(temp);
temp.select();
document.execCommand("copy");
document.body.removeChild(temp);
console.log("Success!")
}
catch(err) {
console.log("There was an error copying");
}
}
<input type="text" class="unique" size="9" value="SESA / D-ID:" readonly/>
<input type="text" class="unique" size="18" value="">
<button id="copybtn" onclick="doCopy()"> Copy to clipboard </button>

function CopyText(toCopy, message) {
var body = $(window.document.body);
var textarea = $('<textarea/>');
textarea.css({
position: 'fixed',
opacity: '0'
});
textarea.val(toCopy);
body.append(textarea);
textarea[0].select();
try {
var successful = document.execCommand('copy');
if (!successful)
throw successful;
else
alert(message);
} catch (err) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", toCopy);
}
textarea.remove();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<button type="button" onClick="CopyText('Hello World', 'Text copped!!')">Copy</button>

Related

How to copy a variable into the clipboard

How do I copy a variable into the clipboard?
It always return:
Uncaught TypeError: copyText.select is not a function
Code
function copy() {
var allDesCode2 = document.getElementsByClassName("desCode2");
var copyText = "ABC";
for(var i=0; i<allDesCode2.length; i++) {
copyText += allDesCode2[i].innerHTML;
}
copyText.select();
document.execCommand("copy");
}
The copy() function below can help to copy a string from a variable. You can use this method in pure JavaScript without the help of any libraries, such as jQuery.
function copy() {
var copyText = "Hooray ! I will be copied";
var el = document.createElement('textarea');
el.value = copyText;
el.setAttribute('readonly', '');
el.style = {
position: 'absolute',
left: '-9999px'
};
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
}
<button onclick="copy()">Copy</button>
I assume you were using this article as a reference. But in this example .select() was used on <input> element, and you're trying to execute this method on a variable.
You can look at this question (your question is a possible duplicate of this). It has a plenty of useful answers which will help you.
You just try to select text without any input. That's mistake one. Also I just read the copy event must be inside the click event (maybe there are more events to copy - reference).
I attached the copy function on your div, put its HTML content into the input, and then copy it.
function copy() {
var allDesCode2 = document.getElementsByClassName("desCode2");
var copyText = "ABC";
for (var i = 0; i < allDesCode2.length; i++) {
copyText += allDesCode2[i].innerHTML;
}
$('input').val(copyText).select();
document.execCommand('copy');
}
$('.desCode2').on('click', copy);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="desCode2">123123123123</div>
<input>

Copy current URL to clipboard

Not sure why this has been so difficult for me today, but for some reason I cannot seem to get it to copy the current URL to the clipboard. Overall, I'm looking for a way to do it without needing to create some hidden text elements.
This is what I'm trying so far:
var shareBtn = document.querySelector(".share-button");
shareBtn.addEventListener('click', function(event) {
var cpLink = window.location.href;
cpLink.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copy command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
event.preventDefault;
});
When I try to go about it using the .select() I get this error:
t.select is not a function
So I'm not 100% sure what the best way to go about this. Again, without using jQuery (or any other JS library) and not using some sort of hidden textfield.
You can create a temporary DOM element to hold the URL
Unfortunately there is no standard API for clipboard operations, so we're left with the hacky way of using a HTML input element to fit our needs. The idea is to create an input, set its value to the URL of the current document, select its contents and execute copy.
We then clean up the mess instead of setting input to hidden and polluting the DOM.
var dummy = document.createElement('input'),
text = window.location.href;
document.body.appendChild(dummy);
dummy.value = text;
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
2021 update: you can use the Clipboard API like so:
navigator.clipboard.writeText(window.location.href);
ppajer's answer is indeed all that's needed when the browser handles the copying, without any custom handling of clipboard events being involved.
But if you or some library hook into the copy event (say, window.addEventListener('copy', ...) and then if that handler relies on using window.getSelection(), then a 19 year old Firefox issue will bite you. Like MDN says:
It is worth noting that currently getSelection() doesn't work on the content of <textarea> and <input> elements in Firefox, Edge (Legacy) and Internet Explorer.
So, getSelection() returns a non-null result after HTMLInputElement#select, but without providing the actual selected content. Easily fixed by using a non-input element to temporarily hold the URL:
function copyUrl() {
if (!window.getSelection) {
alert('Please copy the URL from the location bar.');
return;
}
const dummy = document.createElement('p');
dummy.textContent = window.location.href;
document.body.appendChild(dummy);
const range = document.createRange();
range.setStartBefore(dummy);
range.setEndAfter(dummy);
const selection = window.getSelection();
// First clear, in case the user already selected some other text
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
document.body.removeChild(dummy);
}
(The above will also work when no custom handler hooks into the copy event.)
this might be one of the simpler ways to do it
window.navigator.clipboard.writeText(textToCopy);
var $temp = $("<input>");
var $url = $('.copy').attr('href');
$('.clipboard').on('click', function() {
$("body").append($temp);
$temp.val($url).select();
document.execCommand("copy");
$temp.remove();
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
})
Toast.fire({
icon: 'success',
title: 'URL copied! '
})
})

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
}

get selected/highlighted text html in gmail compose mail area

I am designing an chrome extension for Gmail. In this I want to get selected/highlighted text. I tried following code:
if (!window.x) {
x = {};
}
x.Selector = {};
x.Selector.getSelected = function() {
var t = '';
if($('.compose-container').getSelection){
t = $('.compose-container').getSelection();
alert(t);
} else if (window.getSelection) {
t = window.getSelection();
} else if (document.getSelection) {
t = document.getSelection();
} else if (document.selection) {
t = document.selection.createRange().text;
}
return t;
}
It is not giving me selected text in compose mail.
Please help me out.
You would need to use the copy command to achieve this.
var copyText = document.execCommand('copy');
Basically it will copy any text selection in the browser.
You can check out this link on how it was fully utilized
As per gRenzFries answer, I code same as link provided by him. But slight addition in code to paste it in textbox.
Code to Copy text :
var emailLink = document.querySelector('.gmail_default');
var range = document.createRange();
range.selectNode(emailLink);
window.getSelection().addRange(range);
try {
// Now that we've selected the anchor text, execute the copy command
var successful = document.execCommand('copy', true);
} catch(err) {
}
Code to paste it in textbox:
$('#text-to-display').val(""); //reset textbox value
$('#text-to-display').focus(); //set focus to textbox
document.execCommand("Paste");
This code works just as expected.

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