Auto-scroll <textarea> with Javascript - javascript

I have this textarea that shows inputted text, but when the number of lines exceeds the size and width of the textarea, the user has to scroll down to see what they have last inputted.
I'd like the textarea to be set to the bottom everytime the enter button is pressed.
I've tried the following, but I can't get it to work:
function inputKeyDown(evt, input) {
if (evt.keyCode == 13) {
var textarea = document.getElementById("textarea");
textarea.value += "\n" + ">" + " " + input.value;
input.value = "";
return false;
}
var elem = document.getElementById('textarea');
elem.scrollTop = elem.scrollHeight;
}
and then I call the function keyDown in <input onKeyDown="return keyDown(event, this);" ...>
Any idea why no workie?

Try the following:
textarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;

It depends on what sort of input you are looking at, but forcing the cursor back to the bottom could potentially be a serious usability problem. If you need a textarea that automatically expands, have a look at existing solutions such as this jQuery plugin
I'm not really sure if this is what you want but have a look this: http://jsfiddle.net/yV76p/
var textarea = document.getElementById("textarea");
textarea.onkeyup = function(evt) {
this.scrollTop = this.scrollHeight;
}

Related

How to make a certain part of textarea read-only

I have a text area and I dynamically add data to it and it works fine. What I wanted to achieve was after the data is appended that data cant be altered (edited) but after the last element of the data user can start typing on the textarea. I was thinking of maybe calculating the length of string data the set read-only to that part. How can I achieve this? Any help is appreciated. Thanks in advance.
For a visual example take a look at the terminal of this website: https://www.online-python.com/
function test() {
x = 'this is a string to be appended to text area'
document.getElementById("textArea").value = x;
}
<textarea id="textArea"></textarea>
<button onclick="test()">Append</button>
You can add a keydown event listener that checks whether the selectionStart is smaller than the length of the textarea's value minus the length of the string appended:
let x = 'this is a string to be appended to text area'
var hasAppended = false;
function test() {
hasAppended = true
document.getElementById("textArea").value = x;
}
textArea.addEventListener('keydown', function(e) {
if (hasAppended) {
if (this.selectionStart > this.value.length - x.length && this.selectionStart != this.value.length) {
e.preventDefault()
e.stopPropagation()
}
}
})
<textarea id="textArea"></textarea><button onclick="test()">Append</button>
It is not possible to selectively mark parts of a <textarea> read-only, however, a similar effect can be achieved with contenteditable elements:
function test() {
const x = 'this is a string to be appended to text area'
const span = document.createElement('span')
span.appendChild(document.createTextNode(x))
span.setAttribute('contenteditable', 'false')
document.getElementById("textArea").appendChild(span);
}
#textArea{
border: 1px solid black;
height: 50px;
}
<div id="textArea" contenteditable="true"></div>
<button onclick="test()">Append</button>
However, this will still allow the user to delete the read-only block, or write before it.
This almost works.
EDIT:
Improved it a bit by changing keydown to keyup.
Now there is no need for space at the end of the read-only text and CTRL+a and then backspace will make the text come back almost instantly.
Maybe you can improve on it.
window.onload = function() {
document.getElementById('textArea').addEventListener('keyup', function (e){
var readOnlyLength = parseInt(document.getElementById("textArea").getAttribute('data-readOnlyLength') );
var currentLength = parseInt(document.getElementById("textArea").value.length );
if (readOnlyLength >= currentLength ) {
document.getElementById("textArea").value = document.getElementById("textArea").getAttribute('data-readonly') ;
}
}, false);
};
function test() {
x = 'this is a string to be appended to text area'
document.getElementById("textArea").value = x;
document.getElementById("textArea").setAttribute('data-readonly' , x);
document.getElementById("textArea").setAttribute('data-readOnlyLength' , x.length);
}
<textarea id="textArea"></textarea>
<button onclick="test()">Append</button>

textbox defocuses after pressing tab key followed by any character in Firefox

I am trying to make an in-browser HTML editor, similar to CodePen and JSfiddle.I included a test to allow tabs without defocusing the editor. It works fine, except in Firefox. In Firefox, it keeps focus after pressing tab only to lose focus after the next keystroke.
let textbox = document.getElementById("preview-textbox");//textbox used for inserting HTML into iframe
textbox.value = "";
let iframe = document.querySelector("iframe");//used to render user's code
textbox.addEventListener("input", (e)=>{//inserts html from textbox into the iframe
iframe.src = "data:text/html," + encodeURI(textbox.value);
});
textbox.addEventListener("keydown", (e)=>{//allows indentation with 'tab'
let cursor_position = textbox.selectionStart;
let is_tab = e.keyCode || e.which;
if(is_tab === 9){
textbox.value = textbox.value.substr(0, cursor_position) + '\t' + textbox.value.substr(cursor_position, textbox.value.length);
let focus_textbox = setInterval(()=>{
textbox.focus();//refocuses textbox
textbox.selectionEnd = ++cursor_position;//sets cursor position
clearInterval(focus_textbox);}, 30);//clear setInterval
}
});

Detecting that a textarea is focused during a button click

Explanation
I have a textarea and a button. When I click the button, I want to insert text into the textarea. However, the text that I insert depends upon the current focus of the texteara. Here are some cases:
Cases
(As of the time that the button is clicked)
Textarea focused
Insert text where the cursor is, as-is
Textarea unfocused
Insert text at the end of the textarea (ie add a newline to the inserted text)
Example / Attempt
Here is a fiddle with my example implementation:
https://jsfiddle.net/reL9ro6L/1/
$(document).ready(function() {
$('button').click(function() {
var $text = $('textarea');
var currentValue = $text.val(),
len = currentValue.length,
isTextAreaFocused = $text.is(':focus'),
optionalNewline = isTextAreaFocused ? '' : '\n';
var start = $text[0].selectionStart,
end = $text[0].selectionEnd,
beforeText = isTextAreaFocused ? currentValue.substring(0, start) : len,
afterText = isTextAreaFocused ? currentValue.substring(end) : len;
var insertedText = 'foo',
newValue = beforeText + insertedText + afterText + optionalNewline;
$text.val(newValue);
});
})
Problem
I believe that the button focuses before it has a chance to know if the textarea is focused. Is there a hook or way to handle the click event on the button such that I'll know (before it is focused) what is focused?
Off point: I'm using Ember as my framework. I'd really love to see a pure JS / jQuery solution, but I just wanted to place Ember on the table as well.
You'd have to use the mousedown event on the button, as it fires before the textarea loses focus.
By the time a click event fires, the mouse has been pressed down, and released, and the focus will have shifted to the button instead.
$(document).ready(function() {
$('button').on({
mousedown: function() {
var text = $('textarea').get(0),
currentValue = text.value,
isTextAreaFocused = text === document.activeElement,
insertedText = 'foo',
start = text.selectionStart,
end = text.selectionEnd,
beforeText = currentValue.substring(0, start) || "",
afterText = currentValue.substring(end) || "",
newValue = beforeText + insertedText + afterText;
text.value = isTextAreaFocused ? newValue : currentValue + insertedText + '\n';
$(this).data({'focus' : isTextAreaFocused, 'end' : end + insertedText.length});
},
mouseup: function() {
if ( $(this).data('focus') ) {
$('textarea').focus().get(0).setSelectionRange($(this).data('end'), $(this).data('end'));
}
}
});
});
textarea {
width: 20em;
height: 10em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<button>Insert text</button>

Clicking outside of textarea loses caret position

I created a textarea and a button. When the button is clicked, I want to add the letter 'a' at the current position of the cursor in the textarea. Below is my current code:
$('button.buttonA').click(function(){
var cursorPos = $('textarea.formInsideMenu').prop('selectionStart');
var textCurrent = $('textarea.formInsideMenu').val();
var textBefore = textCurrent.substring(0, cursorPos);
var textAfter = textCurrent.substring(cursorPos, textCurrent.length);
$('textarea.formInsideMenu').val(textBefore + 'a' + textAfter);
});
The above code works fine, (inserts an 'a' at the correct position), when the focus is on the textarea; but as soon as I click on the button, I lose focus of the textarea and the cursor is no longer showing. If I click on the button again after this, 'a' is appended at the very end of the text, (it seems like the cursor is moved to the end of the text). Is there anyway to keep track of where the cursor is inside the textarea even when something else has been clicked on and the textarea has lost focus?
Once you're done with the insert, you need to focus the textarea and set the caret position back:
$('button.buttonA').click(function() {
var area = $('textarea.formInsideMenu'),
curPos = area.prop('selectionEnd');// at the caret **or after selected text**
area.val( area.val().substring(0, curPos) + 'a' + area.val().substring(curPos) )
.focus()
.prop({'selectionStart': curPos+1, 'selectionEnd': curPos+1});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="buttonA">Add an a</button> <br>
<textarea class="formInsideMenu"></textarea>
This version uses javascript only after returning the dom object from jQuery:
$('button.buttonA').click(function(){
var text = $('textarea.formInsideMenu').get(0);
var start = text.selectionStart;
text.value = text.value.slice(0,start) + 'a' + text.value.slice(start);
text.setSelectionRange(start+1,start+1);
text.focus();
});
Fiddle here
Use setSelectionRange after inserting the 'a'.
$('button.buttonA').click(function(){
var cursorPos = $('textarea.formInsideMenu').prop('selectionStart');
var textCurrent = $('textarea.formInsideMenu').val();
var textBefore = textCurrent.substring(0, cursorPos);
var textAfter = textCurrent.substring(cursorPos, textCurrent.length);
$('textarea.formInsideMenu').val(textBefore + 'a' + textAfter);
var elem = document.getElementsByClassName("formInsideMenu")[0];
elem.setSelectionRange(cursorPos, cursorPos + 1);
});
https://jsfiddle.net/ny82n5kn/
You can make a change event on the textarea, where you sore the position of the cursor, like this:
var cursorPos;
$('textarea.formInsideMenu').on('change', function(){
cursorPos = $(this)).prop('selectionStart');
};
Now it will be avaiable in the clickhandler.

jQuery: add line break at cursor position when hitting Enter

I have a form with a textarea (id = details).
Is there a way I can insert the HTML code for a line break (<br />) at the cursor position when hitting Enter within this textarea ?
I would only need this to get to work in IE.
<textarea class="input height120 elastic span12" name="details" id="details" onkeyup="countCharLimit(event)" onpaste="countCharLimit(event)"></textarea>
Try this:
$('textarea').keypress(function (e){
if(e.keyCode == 13){
$('textarea').val($('textarea').val()+"<br />");
}
});
You could try and fiddle with it here
EDIT: I realized this is adding a <br /> at the end only, after some more research, I found this solution:
$('textarea').keypress(function (e){
if(e.keyCode == 13){
e.preventDefault();
this.value = this.value.substring(0, this.selectionStart)+"<br />"+"\n";
}
});
Here is a fiddle for this one
Source (mostly): Insert text into textarea with jQuery
EDIT AGAIN: Looks like the OP wanted the text at the end to also be cleared, so I updated my code accordingly (for other's seeing this: check out the first edit of my relevant fiddle for the case you'd want to keep the remaining text).
you will need to find the caret position first as follow:
var caretPos = function() {
var el = $("#details").get(0);
var pos = 0;
if('selectionStart' in el) {
pos = el.selectionStart;
} else if('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
taken from :here
then you do:
var textofDetails = $("#details").val();
jQuery("#detail").val(textofDetails.substring(0, caretPos) + "<br/>" + textofDetails.substring(caretPos) );
Major EDIT:
no need for all the above ; your function will be
function replaceNewLine(){
jQuery("#detail").val().replace(/\\n/g, "<br />");
}
source: so - here
Yes, sure. It seems to be so, that you need keydown event processing and, possible, setTimeout 0 hack, look here: Why is setTimeout(fn, 0) sometimes useful?

Categories