javascript prevent copy/pasting beyond character limit in textarea - javascript

I have the following code (pulled from this question) for setting a character limit on textareas.
function maxLength(el) {
if (!("maxLength" in el)) {
var max = el.attributes.maxLength.value;
el.onkeypress = function () {
if (this.value.length >= max) return false;
};
}
}
var maxtext = document.getElementsByClassName("maxtext");
for (var i = 0; i < maxtext.length; i++) {
maxLength(maxtext[i]);
}
And an example of my html for textareas:
<textarea maxlength="150" class="maxtext"></textarea>
This all works just fine in Firefox and Chrome. In IE7+, it will stop me if I type up to the limit, but I'm then able to copy/paste text without restriction.
Any way to modify this script to prevent copy/pasting beyond the max character limit?

Listen for the onpaste event. Once the event fires, grab the text from the clipboard and manipulate it how you like.
HTML
<textarea id="test" maxlength="10" class="maxtext"></textarea>
JAVASCRIPT
var test = document.getElementById("test");
test.onpaste = function(e){
//do some IE browser checking for e
var max = test.getAttribute("maxlength");
e.clipboardData.getData('text/plain').slice(0, max);
};
EXAMPLE

You could listen to the onchange event to check the content length, if exceeds the limit then subtract it.

Related

Feature detection for text area maxlength with newlines

It's well-documented that different browsers treat newlines in text areas differently with regards to maxlength. For example, the snippet below will behave differently in Chrome versus Firefox if you use newlines.
My problem is that I need to allow users to enter newlines and I need to show them how many characters they have left. I could detect their browser type, but that's brittle and is a known antipattern. Is there a way to use feature detection to do this properly? Or should I still just avoid maxlength? Note that my question is not jQuery-specific, I just used jQuery in my examples for the sake of simplicity in showing what was happening. Note that I have an example already of a workaround without maxlength (see below), but it doesn't translate well across frameworks like ember where you want to avoid using jquery hacks.
Maxlength issue (try with Firefox, Chrome, and type at least one newline
$('.t').on('input',function(){
$('.x').html($('.t').val().length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="t" rows=3 maxlength=10></textarea>
<br>
chars typed: <span class="x"></span>
Without maxlength workaround (gross)
$('.t').on('input', function(){
let maxLength = 10;
let val = $('.t').val();
$('.t').val((val && val.length) ? val.substring(0,maxLength) : val);
$('.x').html($('.t').val().length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="t" rows=3></textarea>
Chars typed: <span class='x'></span>
You can use keydown and keyup events and regular expression which will replace all new lines characters with empty string. Than in the keydown event suppress type-in new character when the maxLength is reached, and in the keyup event display the number of characters left:
var maxLength = 10;
var navKeys = [8,46,27,38,40,33,34,13,37,39];
$(".x").html(maxLength);
$("textarea")
.on("keydown", function(e){
// Get value without new lines
var val = $(this).val().replace(/\n|\r/g, "");
// Allow nav keys
if(navKeys.indexOf(e.keyCode) !== -1) {
return true;
}
// Do not allow type in another char
if(val.length >= maxLength) {
e.preventDefault();
return;
}
})
.on("keyup", function(e) {
// Get value without new lines
var val = $(this).val().replace(/\n|\r/g, "");
$(".x").html(maxLength - val.length);
// Check the max length
if(val.length > maxLength) {
$(this).val(val.substr(0,maxLength));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<br/>
chars typed: <span class="x"></span>
This worked for me in FF and also in Chrome.
I think the best choice is that you implement your own maxLength.
Something like this:
var element = document.getElementById('textarea'),
maxLength = 10;
var trim = function() {
if(element.value.length >= maxLength) {
element.value = element.value.substring(0, maxLength);
}
};
// for older IE
element.onkeydown = function() {
setTimeout(trim, 1);
};
// browser support: CH, IE 9+, FF 4.0, SF 5.0, OP
element.oninput = trim;
<textarea rows="3" id="textarea"></textarea>

Capture keys typed on android virtual keyboard using javascript

I have a web page with a textarea, and I need to capture the keys typed by the user (so that I can substitute different unicode characters for the keys typed). My current code is as follows:
$("#myTextArea").bind('keypress', function(event) {
var keyInput = event.which;
// call other functions
});
This above code works on PCs, and iPhone/Safari. However, it fails when using Chrome on an android (samsung) tablet. For some reason when I type on the android virtual (soft) keyboard, the "keypress" event is not triggered. The android version is 5.0.2.
If I try using "keyUp" or "keyDown", it always returns 229 for all characters (except for return key, space, backspace, etc).
Even though the keyCode is always 229, the textarea displays the correct characters typed by the user. Which means the device knows which key was entered, but somehow I'm unable to get a handle on this event (and the key code) using javascript.
Here are the alternatives that I have tried so far, and their outcomes:
$("#mainTextArea").on("keydown keyup", function(event) {
// event.which and event.keyCode both return 229
$(document).on('keypress', function(event) {
// function is not triggered
$('#myTextArea').bind('input keypress', function(event) {
// comes inside function, but keyCode and which are undefined
Any help regarding this issue is appreciated..
Unfortunately it seems you cannot do much here.
Keypress event is deprecated, thus not fired.
229 on keyup and keydown indicates the keyboard buffer is busy. The reason - when you press a key - the input is still not guaranteed to be what the user pressed, because of auto suggest and other events that may follow immediately and invalidate the event.
Although in my opinion it would have been better to send the key first, then fire another event perhaps on auto suggest so you can act upon it separately...
The only thing that I currently know of is to attach to both - keydown and keyup, store the value on keydown, get the value on keyup and find the delta, which is what user pressed. Unfortunately this will not work for non-input controls (e.g. - the body or something like that).
Maybe not what you want to hear as answer but still.
I came across this discussion while doing research for a project I was working on. I had to create input masks for a mobile app, and Pavel Donchev's answer got me thinking about what could work to capture keys in Android. In my specific project, keydown and keyup would not be enough because keyup event is only triggered after a key is released, so it would imply in a late validation, so I did some more research (and lots of trial and error) with input events and got it working.
var input = document.getElementById('credit-card-mask'),
oldValue,
newValue,
difference = function(value1, value2) {
var output = [];
for(i = 0; i < value2.length; i++) {
if(value1[i] !== value2[i]) {
output.push(value2[i]);
}
}
return output.join("");
},
keyDownHandler = function(e) {
oldValue = input.value;
document.getElementById("onkeydown-result").innerHTML = input.value;
},
inputHandler = function(e) {
newValue = input.value;
document.getElementById("oninput-result").innerHTML = input.value;
document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue);
}
;
input.addEventListener('keydown', keyDownHandler);
input.addEventListener('input', inputHandler);
<input type="text" id="credit-card-mask" />
<div id="result">
<h4>on keydown value</h4>
<div id="onkeydown-result"></div>
<h4>on input value</h4>
<div id="oninput-result"></div>
<h4>typed value</h4>
<div id="typedvalue-result"></div>
</div>
The oninput event is triggered right after the keydown event, which is the perfect timing for my validations.
I compiled the whole thing in an article. If you're curious, you can read about it here.
I ran into the same issue. Several explanations are out there but anyhow it seems strange that no solution is offered.
For the moment I solved it by capturing the oninput event.
"This event is similar to the onchange event. The difference is that the oninput event occurs immediately after the value of an element has changed, while onchange occurs when the element loses focus, after the content has been changed"
This event support inserted text too, from pasting text or from corrections & suggestions.
it doesn't give me the perfect solution cause I can only manipulate the text AFTER it has been entered, but for the moment it is the best I have.
If anyone has a better solution I will be glad to hear about it.
just check your input characters keyCode, if it is 0 or 229 then here is the function getKeyCode() which uses charCodeAt of JS to return the KeyCode which takes input string a parameter and returns keycode of last character.
<script>
var getKeyCode = function (str) {
return str.charCodeAt(str.length);
}
$('#myTextfield').on('keyup',function(e){
//for android chrome keycode fix
if (navigator.userAgent.match(/Android/i)) {
var inputValue = this.value;
var charKeyCode = e.keyCode || e.which;
if (charKeyCode == 0 || charKeyCode == 229) {
charKeyCode = getKeyCode(inputValue);
alert(charKeyCode+' key Pressed');
}else{
alert(charKeyCode+' key Pressed');
}
}
});
</script>
There is a textInput event that gives you the entered character
const inputField = document.getElementById('wanted-input-field');
inputField.addEventListener('textInput', function(e) {
// e.data will be the 1:1 input you done
const char = e.data; // In our example = "a"
// If you want the keyCode..
const keyCode = char.charCodeAt(0); // a = 97
// Stop processing if "a" is pressed
if (keyCode === 97) {
e.preventDefault();
return false;
}
return true;
});
I recently implemented a "mentions" feature in the latest version of our Astro AI assisted Email app. Basically you type "#" in our compose web view and you get a list of autocomplete suggestions. We, like most other people, had problems trying to solve this in the Javascript. What eventually worked was a native solution. If you #Override the WebView's onCreateInputConnection() method, you can wrap the super.onCreateInputConnection() result (which is just an InputConnection interface) with a custom class. Then in your wrapper implementation, you can trap input via commitText() or setComposingText() or maybe some other method specific to what you are looking for...like deletes. I don't know if you would get any callbacks on control characters like up and down arrows but maybe this can be a place to start to solve your specific problem.
You can approach it from a different perspective by using the selectionstart property:
Returns / Sets the beginning index of the selected text. When nothing
is selected, this returns the position of the text input cursor
(caret) inside of the <input> element [also applies to <textarea>].
Source: MDN
I do something like this in my own app and it has worked reliably...
document.querySelector('textarea').addEventListener('input', (e) => {
const elInput = e.target;
// Get start of selection (caret offset when typing)
const nSelStart = elInput.selectionStart;
// Get last typed character (modify for your own needs)
const sLastTyped = elInput.value.substr(nSelStart-1, 1);
console.log('Last typed character:', sLastTyped);
});
textarea {
width: 99%;
height: 4rem;
}
<textarea placeholder="Enter something using Android soft keyboard"></textarea>
Codepen: https://codepen.io/thdoan/full/dymPwVY
I FIGURED IT OUT!
Here's a 100% working solution that works EVERYWHERE with EVERY feature, including even emoji suggestions on iOS and any pasted content. I'm using substring comparison to find actual stuff that changed from onInput to onInput.
Points from which to which text is deleted and from which to which it's inserted are pointed out.
Rating and selecting as an answer is appreciated.
var x = document.getElementById("area"),
text = x.value,
event_count = 0
function find_Entered_And_Removed_Substrings(
previous_string, current_string, pos
) {
let
right_pos = pos,
right_boundary_of_removed =
previous_string.length -
(
current_string.length -
pos
),
left_max_pos = Math.min(
pos,
right_boundary_of_removed
),
left_pos = left_max_pos
for (
let x = 0; x < left_max_pos; x++
) {
if (
previous_string[x] !==
current_string[x]
) {
left_pos = x
break
}
}
return {
left: left_pos,
right: pos,
removed_left: left_pos,
removed_right: right_boundary_of_removed
}
}
x.oninput =
(e) => {
// debugger;
let
cur_text = x.value,
positions =
find_Entered_And_Removed_Substrings(
text, cur_text, Math.max(
x.selectionStart, x.selectionEnd
)
)
console.log(positions)
let
entered =
cur_text.substring(
positions.left, positions.right
),
removed =
text.substring(
positions.removed_left, positions.removed_right
)
if (
entered.length >
0 ||
removed.length >
0
) {
document.getElementById("entered")
.innerHTML +=
entered
document.getElementById("removed")
.innerHTML +=
removed
document.getElementById("events")
.innerHTML =
event_count++
}
text = cur_text
}
<textarea id="area"></textarea>
<br/>
<pre id="entered"></pre>
<br/>
<div id="events"></div>
<pre id="removed"></pre>

Why isn't my regex returning the correct value for my text input?

So basically, I have a large form with more than 50 text inputs.
I am applying a function via onKeyPress to all of them to make sure that they are numbers only with the use of one decimal point.
This is my regex function:
function pointAndNumbersOnly(inputString)
{
return inputString.match(/^[0-9]*\.?[0-9]*$/);
}
This is an example of one of my text inputs:
<input type="text" pattern="\d*" class="form-main" name="priceGST" id="priceGST" placeholder="Enter GST without % sign" value="10" onkeypress="return pointAndNumbersOnly(this.id);">
What is my mistake here?
PS. I am receiving no errors in my console.
After seeing all other answers and looking into your problem I think this is what you want.
HTML:
<input type="text" pattern="\d*" class="form-main" name="priceGST" id="priceGST" placeholder="Enter GST without % sign" value="10"/>
Attach the events in JavaScript, and prevent the default behavior if the input is not valid. By using keypress event you can read the current character accurately, append it to the value that was read (which excludes the character you just typed) and then pass the validation.
JavaScript:
function isValidNumber(str) {
return /^\d*\.?\d*$/.test(str);
}
document.getElementById('priceGST').addEventListener('keypress', function(e) {
var char = String.fromCharCode(e.which);
if (! isValidNumber(this.value + char)) {
e.preventDefault();
}
});
DEMO: http://jsbin.com/oCobAfUJ/1/edit
Let's begin with the usage of your regex, you should be doing it like this:
var inputString = document.getElementById('priceGST').value;
var regex = /^[0-9]*\.?[0-9]*$/;
var valid = regex.test(inputString);
So this should work just fine for you:
function pointAndNumbersOnly(inputString)
{
var regex = /^[0-9]*\.?[0-9]*$/;
var valid = regex.test(inputString);
return valid;
}
var inputString = document.getElementById('priceGST').value;
var valid = pointAndNumbersOnly(inputString);
There are other options though:
function pointAndNumbersOnly(inputString)
{
var regex = /^[0-9]*\.?[0-9]*$/;
var valid = regex.exec(inputString);
return valid;
}
var inputString = document.getElementById('priceGST').value;
var valid = pointAndNumbersOnly(inputString);
Let's make your function even better by only requiring elements to be pushed down, not their values:
function pointAndNumbersOnly(inputElement)
{
var inputString = inputElement.value;
var regex = /^[0-9]*\.?[0-9]*$/;
var valid = regex.test(inputString);
return valid;
}
var inputElement = document.getElementById('priceGST');
var valid = pointAndNumbersOnly(inputElement);
Now another matter:
Using html-attributes such as onkeypress, click, etc... is bad practice since we want to separate our HTMLand JavaScript. Besides, onkeypress is a problem maker to begin with because it doesn't always do what you think it does. It's better to use change, keyup and keydown to detect changes.
Instead of using onkeypress="return pointAndNumbersOnly(this.id);we want to use event delegation to detect changes in the dom, using our new change events:
function pointAndNumbersOnly(inputElement)
{
var inputString = inputElement.value;
var regex = /^[0-9]*\.?[0-9]*$/;
var valid = regex.test(inputString);
return valid;
}
inputElement.addEventListener("change, keyup, keydown", function(e)
{
var inputElement = document.getElementById('priceGST'); // Makes more sense to use this
var valid = pointAndNumbersOnly(inputElement );
// ...
});
You can also add event listeners to a set of elements by referencing to their class.
Finally:
Make sure the JavaScript is defined AFTER your DOM is ready, that is, make sure the JavaScript is added at the bottom of your body so that the HTML exists OR you have functionality such as jQuery's .ready function, that detects when the DOM is loaded and the JavaScript within is allowed to execute, otherwise it won't know the HTML ids' such as id="priceGST".
If you define your JavaScript and try to reference HTML ids' then you'll see that they are undefined, or just null, because they don't exist at that specific point.
Change the way you pass the parameter to the pointAndNumbersOnly function and it should work:
onkeypress="return pointAndNumbersOnly(this.val());"
Edit: as mentioned, the above solution is JQuery. With Javascript is should be:
onkeypress="return pointAndNumbersOnly(this.value);"
Firstly,use onkeyup instead of onkeypress because when use onkeyup,you can get this.value as what you've just input,and onkeypress will get your input value before.
For example,the inputbox has current value 10 and you want to input 101.
onkeyup will get this.value = 101,
onkeypress will get this.value = 10.
As I will do,I will set a preValue,if the current value is invalid,set this.value to preValue.
Just like this:
//html
<input onkeyup="return pointAndNumbersOnly(this);" type="text" pattern="\d*" class="form-main" name="priceGST" id="priceGST" placeholder="Enter GST without % sign" value="10">
//js
function pointAndNumbersOnly(obj){
var key = 'price'+obj.id;
//.2 will be valid here. If not,use /^[0-9]+\.?[0-9]*$|^$/ instead
if(obj.value.match(/^[0-9]*\.?[0-9]*$/) !== null) {
window[key] = obj.value;
return true;
}else {
obj.value = window[key];
return false;
}
}

How to impose maxlength on textArea in HTML using JavaScript

I would like to have some functionality by which if I write
<textarea maxlength="50"></textarea>
<textarea maxlength="150"></textarea>
<textarea maxlength="250"></textarea>
it will automatically impose the maxlength on the textArea. If possible please do not provide the solution in jQuery.
Note: This can be done if I do something like this:
<textarea onkeypress="return imposeMaxLength(event, this, 110);" rows="4" cols="50">
function imposeMaxLength(Event, Object, MaxLen)
{
return (Object.value.length <= MaxLen)||(Event.keyCode == 8 ||Event.keyCode==46||(Event.keyCode>=35&&Event.keyCode<=40))
}
Copied from What is the best way to emulate an HTML input “maxlength” attribute on an HTML textarea?
But the point is I don't want to write onKeyPress and onKeyUp every time I declare a textArea.
window.onload = function() {
var txts = document.getElementsByTagName('TEXTAREA');
for(var i = 0, l = txts.length; i < l; i++) {
if(/^[0-9]+$/.test(txts[i].getAttribute("maxlength"))) {
var func = function() {
var len = parseInt(this.getAttribute("maxlength"), 10);
if(this.value.length > len) {
alert('Maximum length exceeded: ' + len);
this.value = this.value.substr(0, len);
return false;
}
}
txts[i].onkeyup = func;
txts[i].onblur = func;
}
};
}
I know you want to avoid jQuery, but as the solution requires JavaScript, this solution (using jQuery 1.4) is the most consise and robust.
Inspired by, but an improvement over Dana Woodman's answer:
Changes from that answer are: Simplified and more generic, using jQuery.live and also not setting val if length is OK (leads to working arrow-keys in IE, and noticable speedup in IE):
// Get all textareas that have a "maxlength" property. Now, and when later adding HTML using jQuery-scripting:
$('textarea[maxlength]').live('keyup blur', function() {
// Store the maxlength and value of the field.
var maxlength = $(this).attr('maxlength');
var val = $(this).val();
// Trim the field if it has content over the maxlength.
if (val.length > maxlength) {
$(this).val(val.slice(0, maxlength));
}
});
EDIT: Updated version for jQuery 1.7+, using on instead of live
// Get all textareas that have a "maxlength" property. Now, and when later adding HTML using jQuery-scripting:
$('textarea[maxlength]').on('keyup blur', function() {
// Store the maxlength and value of the field.
var maxlength = $(this).attr('maxlength');
var val = $(this).val();
// Trim the field if it has content over the maxlength.
if (val.length > maxlength) {
$(this).val(val.slice(0, maxlength));
}
});
Update Use Eirik's solution using .live() instead as it is a bit more robust.
Even though you wanted a solution that wasn't using jQuery, I thought I'd add one in for anyone finding this page via Google and looking for a jQuery-esque solution:
$(function() {
// Get all textareas that have a "maxlength" property.
$('textarea[maxlength]').each(function() {
// Store the jQuery object to be more efficient...
var $textarea = $(this);
// Store the maxlength and value of the field.
var maxlength = $textarea.attr('maxlength');
var val = $textarea.val();
// Trim the field if it has content over the maxlength.
$textarea.val(val.slice(0, maxlength));
// Bind the trimming behavior to the "keyup" event.
$textarea.bind('keyup', function() {
$textarea.val($textarea.val().slice(0, maxlength));
});
});
});
Hope that is useful to you Googlers out there...
HTML5 adds a maxlength attribute to the textarea element, like so:
<!DOCTYPE html>
<html>
<body>
<form action="processForm.php" action="post">
<label for="story">Tell me your story:</label><br>
<textarea id="story" maxlength="100"></textarea>
<input type="submit" value="Submit">
</form>
</body>
</html>
This is currently supported in Chrome 13, FF 5, and Safari 5. Not surprisingly, this is not supported in IE 9. (Tested on Win 7)
This solution avoids the issue in IE where the last character is removed when a character in the middle of the text is added. It also works fine with other browsers.
$("textarea[maxlength]").keydown( function(e) {
var key = e.which; // backspace = 8, delete = 46, arrows = 37,38,39,40
if ( ( key >= 37 && key <= 40 ) || key == 8 || key == 46 ) return;
return $(this).val().length < $(this).attr( "maxlength" );
});
My form validation then deals with any issues where the user may have pasted (only seems to be a problem in IE) text exceeding the maximum length of the textarea.
This is some tweaked code I've just been using on my site. It is improved to display the number of remaining characters to the user.
(Sorry again to OP who requested no jQuery. But seriously, who doesn't use jQuery these days?)
$(function() {
// Get all textareas that have a "maxlength" property.
$("textarea[maxlength]").each(function() {
// Store the jQuery object to be more efficient...
var $textarea = $(this);
// Store the maxlength and value of the field
var maxlength = $textarea.attr("maxlength");
// Add a DIV to display remaining characters to user
$textarea.after($("<div>").addClass("charsRemaining"));
// Bind the trimming behavior to the "keyup" & "blur" events (to handle mouse-based paste)
$textarea.on("keyup blur", function(event) {
// Fix OS-specific line-returns to do an accurate count
var val = $textarea.val().replace(/\r\n|\r|\n/g, "\r\n").slice(0, maxlength);
$textarea.val(val);
// Display updated count to user
$textarea.next(".charsRemaining").html(maxlength - val.length + " characters remaining");
}).trigger("blur");
});
});
Has NOT been tested with international multi-byte characters, so I'm not sure how it works with those exactly.
Also add the following event to deal with pasting into the textarea:
...
txts[i].onkeyup = function() {
...
}
txts[i].paste = function() {
var len = parseInt(this.getAttribute("maxlength"), 10);
if (this.value.length + window.clipboardData.getData("Text").length > len) {
alert('Maximum length exceeded: ' + len);
this.value = this.value.substr(0, len);
return false;
}
}
...
The maxlength attribute is supported in Internet Explorer 10, Firefox, Chrome, and Safari.
Note: The maxlength attribute of the <textarea> tag is not supported in Internet Explorer 9 and earlier versions, or in Opera.
from HTML maxlength Attribute w3schools.com
For IE8 or earlier versions you have to use the following
//only call this function in IE
function maxLengthLimit($textarea){
var maxlength = parseInt($textarea.attr("maxlength"));
//in IE7,maxlength attribute can't be got,I don't know why...
if($.browser.version=="7.0"){
maxlength = parseInt($textarea.attr("length"));
}
$textarea.bind("keyup blur",function(){
if(this.value.length>maxlength){
this.value=this.value.substr(0,maxlength);
}
});
}
P.S.
The maxlength attribute of the <input> tag is supported in all major browsers.
from HTML maxlength Attribute w3schools.com
You can use jQuery to make it easy and clear
JSFiddle DEMO
<textarea id="ta" max="10"></textarea>
<script>
$("#ta").keypress(function(e){
var k = e.which==0 ? e.keyCode : e.which;
//alert(k);
if(k==8 || k==37 || k==39 || k==46) return true;
var text = $(this).val();
var maxlength = $(this).attr("max");
if(text.length >= maxlength) {
return false;
}
return true;
});
</script>
It is tested in Firefox, Google Chrome and Opera
Better Solution compared to trimming the value of the textarea.
$('textarea[maxlength]').live('keypress', function(e) {
var maxlength = $(this).attr('maxlength');
var val = $(this).val();
if (val.length > maxlength) {
return false;
}
});
Small problem with code above is that val() does not trigger change() event, so if you using backbone.js (or another frameworks for model binding), model won't be updated.
I'm posting the solution worked great for me.
$(function () {
$(document).on('keyup', '.ie8 textarea[maxlength], .ie9 textarea[maxlength]', function (e) {
var maxLength = $(this).attr('maxlength');
if (e.keyCode > 47 && $(this).val().length >= maxLength) {
$(this).val($(this).val().substring(0, maxLength)).trigger('change');
}
return true;
});
});
I implemented maxlength behaviour on textarea recently, and run into problem described in this question: Chrome counts characters wrong in textarea with maxlength attribute.
So all implementations listed here will work little buggy. To solve this issue I add .replace(/(\r\n|\n|\r)/g, "11") before .length. And kept it in mind when cuting string.
I ended with something like this:
var maxlength = el.attr("maxlength");
var val = el.val();
var length = val.length;
var realLength = val.replace(/(\r\n|\n|\r)/g, "11").length;
if (realLength > maxlength) {
el.val(val.slice(0, maxlength - (realLength - length)));
}
Don't sure if it solves problem completely, but it works for me for now.
Try this jQuery which works in IE9, FF, Chrome and provides a countdown to users:
$("#comments").bind("keyup keydown", function() {
var max = 500;
var value = $(this).val();
var left = max - value.length;
if(left < 0) {
$(this).val( value.slice(0, left) );
left = 0;
}
$("#charcount").text(left);
});
<textarea id="comments" onkeyup="ismaxlength(this,500)"></textarea>
<span class="max-char-limit"><span id="charcount">500</span> characters left</span>
Try to use this code example:
$("#TextAreaID1").bind('input propertychange', function () {
var maxLength = 4000;
if ($(this).val().length > maxLength) {
$(this).val($(this).val().substring(0, maxLength));
}
});
2022 Update
You can set the HTML attribute for "maxlength" with the property maxLength (note the uppercase L). You might end up on this page if you were trying to use maxlength (all lowercase) and it wasn't working.
textareaElement1.maxLength = 50;
textareaElement2.maxLength = 150;
textareaElement3.maxLength = 250;
If you wanted to programmatically do it to all existing textareas, you could just iterate over a getElementsByTagName result:
const textAreas = document.getElementsByTagName('textarea');
for (const element of textAreas) {
element.maxLength = 150;
}
This is much easier:
<textarea onKeyPress="return ( this.value.length < 1000 );"></textarea>

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