How to set cursor at the end in a textarea? - javascript

Is there a way to set the cursor at the end in a textarea element? I'm using Firefox 3.6 and I don't need it to work in IE or Chrome. It seems all the related answers in here use onfocus() event, which seems to be useless because when user clicks on anywhere within the textarea element Firefox sets cursor position to there. I have a long text to display in a textarea so that it displays the last portion (making it easier to add something at the end).
No frameworks or libraries.

There may be many ways, e.g.
element.focus();
element.setSelectionRange(element.value.length,element.value.length);
http://jsfiddle.net/doktormolle/GSwfW/

selectionStart is enough to set initial cursor point.
element.focus();
element.selectionStart = element.value.length;

It's been a long time since I used javascript without first looking at a jQuery solution...
That being said, your best approach using javascript would be to grab the value currently in the textarea when it comes into focus and set the value of the textarea to the grabbed value. This always works in jQuery as:
$('textarea').focus(function() {
var theVal = $(this).val();
$(this).val(theVal);
});
In plain javascript:
var theArea = document.getElementByName('[textareaname]');
theArea.onFocus = function(){
var theVal = theArea.value;
theArea.value = theVal;
}
I could be wrong. Bit rusty.

var t = /* get textbox element */ ;
t.onfocus = function () {
t.scrollTop = t.scrollHeight;
setTimeout(function(){
t.select();
t.selectionStart = t.selectionEnd;
}, 10);
}
The trick is using the setTimeout to change the text insertion (carat) position after the browser is done handling the focus event; otherwise the position would be set by our script and then immediately set to something else by the browser.

Here is a function for that
function moveCaretToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
[Demo][Source]

textarea.focus()
textarea.value+=' ';//adds a space at the end, scrolls it into view

(this.jQuery || this.Zepto).fn.focusEnd = function () {
return this.each(function () {
var val = this.value;
this.focus();
this.value = '';
this.value = val;
});
};

#Dr.Molle answer is right. just for enhancement, U can combine with prevent-default.
http://jsfiddle.net/70des6y2/
Sample:
document.getElementById("textarea").addEventListener("mousedown", e => {
e.preventDefault();
moveToEnd(e.target);
});
function moveToEnd(element) {
element.focus();
element.setSelectionRange(element.value.length, element.value.length);
}

Related

Prevent default cursor placement

Here's the code I use to set caret position before third symbol of input value. It works fine, with one exception — the function setCaretPosition() executes a moment after the default script fires while I want it happen immediately. Is there any chance to avoid default cursor placement without adding an overlay element?
function setCaretPosition(elemId, caretPos) {
var el = document.getElementById(elemId);
el.value = el.value;
// ^ this is used to not only get "focus", but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
}
else {
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
else { // fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
}
}
}
var inputId = 'test';
document.getElementById(inputId).addEventListener('click', function() {
setCaretPosition(inputId, 2);
},false)
https://jsfiddle.net/82fnpmf6/
Yes there is a way to avoid this abrupt change of position. We can change the perception by doing some trickery. You can clone the input and make it overlap over the original as soon as you click on the input field. Use a timeout to change the order of fields again so that the non blinking clone goes behind the original again. So basically the user sees a non selected input for a few milliseconds which should be enough time to position your cursor where it belongs.
Since the change of position happens within less than a second I dont think it will be bother the user.

What do selectionStart and selectionEnd signify for textarea?

I came across following code snippet to insert enter into the the text in a textarea where ctrl + enter is pressed.
$("#txtChatMessage").keydown(MessageTextOnKeyEnter);
function MessageTextOnKeyEnter(e) {
console.log(this.selectionEnd);
if (e.keyCode == 13) {
if (e.ctrlKey) {
var val = this.value;
if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") {
var start = this.selectionStart;
this.value = val.slice(0, start) + "\n" + val.slice(this.selectionEnd);
this.selectionStart = this.selectionEnd = start + 1;
} else if (document.selection && document.selection.createRange) {
this.focus();
var range = document.selection.createRange();
range.text = "\r\n";
range.collapse(false);
range.select();
}
}
return false;
}
}
What I don't understand is what do selectionStart and selectionEnd mean here ? According to documentation that I read, selectionStart-End contain the start-end of selected text in the input element. However, here no text is explicitly selected. On doing console.log I could see that both these properties always have some value even when the text is not selected. Why is that?
selectionStart specifies the index of the selection/highlighted text within the <textarea>. Similarly, selectionEnd specifies the index where the selection ends. Initially, they are set to 0, and if the <textarea> is focused but no text is selected, the selectionStart and selectionEnd values will be the same, and reflect the position of the caret within the value of the <textarea>. On un-focus or blur of the <textarea>, they will remain at the last value that they were set to before the blur event.
Here's a fiddle you can play with:
http://jsfiddle.net/5vd8pxct/
The if block in question appears to handle cross-browser compatibility. document.selection is for IE. selectionStart and selectionEnd seem to work elsewhere. I don't have IE on my machine to experiment with it, and I'm using Chrome. It appears from my fiddle that the default start/end are 0 when the page loads. If you click into/select in the box, the start end will be as expected. If you click outside the box, the positions within the box are remembered.
document.selection is undefined in Chrome.
Your code does not work. You mix regular JavaScript and JQuery. I would suggest to start with plain JavaScript. Generally, in JavaScript this is a reference to the object on which the code will be executed.
Take a look at the following example:
<html>
<head>
<script type="text/javascript">
window.addEventListener("load", function () {
var chat = document.getElementById('txtChatMessage'); // get textarea
chat.addEventListener('keydown', function (event) { //add listener keydown for textarea
event = event || window.event;
if (event.keyCode === 13) { //return pressed?
event.preventDefault();
if (this.selectionStart != undefined) {
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var selectedText = this.value.substring(startPos, endPos);
alert("Hello, you've selected " + selectedText);
}
}
})
});
</script>
</head>
<body>
<textarea id="txtChatMessage" cols="40" rows="10"></textarea>
</body>
</html>
At first an event listener "onLoad" has been registered. Within this function we get a reference to the textarea object. On this object a new event listener "onKeyDown" has been registered. Within this function this refers to the textarea (chat) object. With the help of the event object, we can ask for the pressed key event.keyCode === 13. With this (textarea) and its attributes selectionStart and selectionEnd we get the selected text.

window.getselection is not working in android

I am new to use html+javascript+jQuery. I am trying to use window.getSelection to get selected text but this is not working.
Can any one suggest solution for this.
Thanks in advance.
Just need simple line of code in java script which done your job
//I am using below line of code which works in both android and web browsers.
function getSelectedText() {
var selection = null;
if (window.getSelection) {
selection = window.getSelection();
} else if (typeof document.selection != "undefined") {
selection = document.selection;
}
var selectedRange = selection.getRangeAt(0);
console.log(selectedRange.toString());
}
NOTE : Don't call this method in post or inside any runnable interface as post or any runnable interface make delay in calling this method(Method call happens after browser selection release). Just call this method like
webView.loadUrl("javascript:getSelectedText()");
I know this is a very old question, but I get this as a first search result when I had tried to resolve the same or similar issue. I didn't find a solution here but after some time I realized that sometimes for phones there should be a short timeout between click and selection to make getSelection() work properly.
So e.g. instead this:
document.getElementById("element").addEventListener('click', function (event) {
window.getSelection().selectAllChildren(this)
});
You should use somethink like this:
document.getElementById("element").addEventListener('click', function (event) {
setTimeout(function(passedThis) {
window.getSelection().selectAllChildren(passedThis)
}, 10, this);
});
Maybe it save some time to somebody.
If you want to call a function right after a text selection, you can use the "selectionchange" event:
document.addEventListener("selectionchange", handleSelection);
It's working for android chrome and iOS safari.
Try
function getSelected() {
var text = "";
if (window.getSelection && window.getSelection().toString() && $(window.getSelection()).attr('type') != "Caret") {
text = window.getSelection();
return text;
} else if (document.getSelection && document.getSelection().toString() && $(document.getSelection()).attr('type') != "Caret") {
text = document.getSelection();
return text;
} else {
var selection = document.selection && document.selection.createRange();
if (!(typeof selection === "undefined") && selection.text && selection.text.toString()) {
text = selection.text;
return text;
}
}
return false;
}

Invoke a function after right click paste in jQuery

I know we can use bind paste event as below:
$('#id').bind('paste', function(e) {
alert('pasting!')
});
But the problem is, that it will call before the pasted text paste. I want a function to be triggered after the right click -> paste text pasted on the input field, so that I can access the pasted value inside the event handler function.
.change() event also doesn't help. Currently I use .keyup() event, because I need to show the remaining characters count while typing in that input field.
Kind of a hack, but:
$("#id").bind('paste', function(e) {
var ctl = $(this);
setTimeout(function() {
//Do whatever you want to $(ctl) here....
}, 100);
});
Why not use the "input" event?
$("#id").bind('input', function(e) {
var $this = $(this);
console.log($this.val());
});
This will stop user from any pasting, coping or cutting with the keyboard:
$("#myField").keydown(function(event) {
var forbiddenKeys = new Array('c', 'x', 'v');
var keyCode = (event.keyCode) ? event.keyCode : event.which;
var isCtrl;
isCtrl = event.ctrlKey
if (isCtrl) {
for (i = 0; i < forbiddenKeys.length; i++) {
if (forbiddenKeys[i] == String.fromCharCode(keyCode).toLowerCase()) {
return false;
}
}
}
return true;
});
This one will do the same for the mouse events:
$("#myField").bind("cut copy paste",function(event) {
event.preventDefault();
});
Even though the above one will not prevent right clicks, the user will not be able to paste, cut or copy from that field.
To use it after the event, like you wondered on your question, you must use JavaScript Timing Event
setTimeout(function() {
// your code goes here
}, 10);
I had the same issue, I opted to replicate the paste action through javascript and use that output instead:
var getPostPasteText = function (element, pastedData) {
// get the highlighted text (if any) from the element
var selection = getSelection(element);
var selectionStart = selection.start;
var selectionEnd = selection.end;
// figure out what text is to the left and right of the highlighted text (if any)
var oldText = $(element).val();
var leftPiece = oldText.substr(0, selectionStart);
var rightPiece = oldText.substr(selectionEnd, oldText.length);
// compute what the new value of the element will be after the paste
// note behavior of paste is to REPLACE any highlighted text
return leftPiece + pastedData + rightPiece;
};
See IE's document.selection.createRange doesn't include leading or trailing blank lines for source of the getSelection function.
No need to bind :
$(document).on('keyup input', '#myID', function () {
//Do something
});

Performance issues in javascript onclick handler

I have written a game in java script and while it works, it is slow responding to multiple clicks. Below is a very simplified version of the code that I am using to handle clicks and it is still fails to respond to a second click of 2 if you don't wait long enough. Is this something that I need to just accept or is there a faster way to be ready for the next click?
BTW, I attach this function using AddEvent from the quirksmode recoding contest.
var selected = false;
var z = null;
function handleClicks(evt) {
evt = (evt)?evt:((window.event)?window.event:null);
if (selected) {
z.innerHTML = '<div class="rowbox a">a</div>';
selected = false;
} else {
z.innerHTML = '<div class="rowbox selecteda">a</div>';
selected = true;
}
}
The live code may be seen at http://www.omega-link.com/index.php?content=testgame
You could try to only change the classname instead of removing/adding a div to the DOM (which is what the innerHTML property does).
Something like:
var selected = false;
var z = null;
function handleClicks(evt)
{
var tmp;
if(z == null)
return;
evt = (evt)?evt:((window.event)?window.event:null);
tmp = z.firstChild;
while((tmp != null) && (tmp.tagName != 'DIV'))
tmp = tmp.firstChild;
if(tmp != null)
{
if (selected)
{
tmp.className = "rowbox a";
selected = false;
} else
{
tmp.className = "rowbox selecteda";
selected = true;
}
}
}
I think your problem is that the 2nd click is registering as a dblclick event, not as a click event. The change is happening quickly, but the 2nd click is ignored unless you wait. I would suggest changing to either the mousedown or mouseup event.
I believe your problem is the changing of the innerHTML which changes the DOM which is a huge performance problem.
Yeah you may want to compare the performance of innerHTML against document.createElement() or even:
el.style.display = 'block' // turn off display: none.
Profiling your code may be helpful as you A/B various refactorings:
http://www.mozilla.org/performance/jsprofiler.html
http://developer.yahoo.com/yui/profiler/
http://weblogs.asp.net/stevewellens/archive/2009/03/26/ie-8-can-profile-javascript.aspx

Categories

Resources