Refresh text input to show caret - javascript

I have the following fiddle: http://jsfiddle.net/sxAss/
By using the solution posted here I was able to move the caret to the end of the input. The problem that I have is that the input does not refresh to actually show the caret. Instead it shows the beginning of the input. What should I do to actually move the view to the end of the input. I am using Chrome.
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();
}
}

First focus your input element then call your moveCaretToEnd function
like
$('#button').click(function() {
$('#input').focus();
$('#input').val($('#input').val() + 'StackOverflowTest');
moveCaretToEnd(document.getElementById('input'));
});
Working fiddle

Related

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.

How to place cursor at the end of text after replacing HTML with jQuery?

I have a contenteditable div and trying to replace <font> tag with <span> tag but after replacing the html using jQuery replaceWith() function cursor defaults to the beginning of the text however I want it at the end of the replacing html.
Here is the DEMO to reproduce the issue. Let me know if there is any problem reproducing the issue.
Here is demo code gist
<div id="test" contenteditable=true>
<p> <font color="blue">Text to be replaced</font> </p>
</div>
<a id="replace" href="javascript:void(null);">replace</a>
JS code
$('#test').focus();
$('#replace').on({
mousedown: function (event) {
event.preventDefault();
},
click: function () {
$('#test').find('font').replaceWith(function () {
return '<span style="color:red">' + 'New Text' + '</span>'
});
}
});
EDIT: Here the problem may sound duplicate but it is indeed different as you see the content gets replaced. I might be replacing the part of that text selected by user and not the entire text. So I need to place the cursor at the end of the html which is replacing the original html.
You can use this function
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
call it as follows
placeCaretAtEnd( document.getElementById("content") );
EXAMPLE
If you create the <span> element by hand using document.createElement() and keep a reference to it, you can easily place the caret immediately after it.
Demo: http://jsfiddle.net/Gaqfs/10/
Code:
function placeCaretAfter(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.setStartAfter(el);
range.collapse(true);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
$('#test').focus();
$('#replace').on({
mousedown: function (event) {
event.preventDefault();
},
click: function () {
var span = document.createElement("span");
span.style.color = "red";
span.innerHTML = "New Text";
$('#test').find('font').replaceWith(span);
placeCaretAfter(span);
}
});

Setting focus to the end of a textarea

editor.focus();
Sets the focus fine in Chrome.
But in Firefox, the focus is set on the beginning on the line. I want it to be set on the end of the line. I tried this:
moveCaretToEnd(ed);
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();
}
}
And stupid FF doesn't work again. The focus is gone.
I used the following hack for firefox:
var value = editor.val();
editor.val("");
editor.focus();
editor.val(value);
Here is working fiddle: http://jsfiddle.net/vyshniakov/p37ax/

How to set cursor at the end in a textarea?

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);
}

jQuery: Trigger keydown only in specific div

I have a page with couple of DIV elements. When user presses the CTRL+ENTER button combo, I need to display (via alert()) the text, that user previously selected. I found the solution and it works like a charm, but there is still one thing left.
I need to make event trigger, only when selected text is inside a DIV with class "main_content". I've tried to assign keyup to $('DIV.main_content'), but it does not work.
Is there a way to make event trigger only if text inside $('DIV.main_content') selected?
Here is a working code that triggers on the whole document:
// Get user selection text on page
function getSelectedText() {
if (window.getSelection) {
return window.getSelection();
}
else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
$(document).ready(function(){
$(document).keydown(function(e) {
if(e.which == 13 && e.ctrlKey) {
alert(getSelectedText());
return false;
}
});
});
See the code with markup in jsFiddle
You have an error in the getSelectedText() function: window.getSelection() returns a Selection object, not a string. The fact you're passing the result of this to alert() is masking this, because alert() implicitly converts the argument passed to it into a string.
Here's some code to check whether the selection is completely contained within a <div> element with a particular class. It works in all major browsers.
Live example: http://www.jsfiddle.net/cVgsy/1/
// Get user selection text on page
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
}
else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
function isSelectionInDivClass(cssClass) {
var selContainerNode = null;
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
selContainerNode = sel.getRangeAt(0).commonAncestorContainer;
}
} else if (document.selection && document.selection.type != "Control") {
selContainerNode = document.selection.createRange().parentElement();
}
if (selContainerNode) {
var node = selContainerNode;
while (node) {
if (node.nodeType == 1 && node.nodeName == "DIV" && $(node).hasClass(cssClass)) {
return true;
}
node = node.parentNode;
}
}
return false;
}
$(document).ready(function(){
$(document).keydown(function(e) {
if(e.which == 13 && e.ctrlKey && isSelectionInDivClass("main_content")) {
alert(getSelectedText());
return false;
}
});
});
It is interesting question. I have the following idea: you need to catch mouseup event on div.
For example:
So, in your case you can do something like this:
var selectedText = "";
$(".yourdiv").mouseup(function(){
if (window.getSelection)
selectedText = window.getSelection();
else if (document.selection)
selectedText = document.selection.createRange().text;
alert(selectedText)
});
And variable selectedText will be store selected text.

Categories

Resources