Prevent text keyboard input on Android/chrome mobile [web] - javascript

I have a textarea with keyDown listener
<textarea onKeyDown={handleKeyDown}></textarea>
And the handleKeyDown function:
const handleKeyDown = event => event.preventDefault()
When I typing from windows PC, Chrome Version 90.0.4430.212 (Official Build) (64-bit) everything works perfect: text is not appearing in textarea.
When I typing from mac, chrome 90 everything works perfect too.
But when I grab my Android Phone (Samsung, Android 11), open Mobile Chrome (90.0.4430.210) and start typing, text IS appearing in textarea. And the worst thing is that the only mention about this bug I found is this question, which will be referenced by bots when marking my question as duplicate. There is no answer: maxlength attribute not working anymore.
This is the list of things I tried to prevent mobile chrome from input:
Maxlength = 0 (no effect at all)
readOnly (=disabled, I need focus and selection)
blocking onKeyUp, onKeyPress, onPaste, onCut, onInput
I also tried to manually set value of textarea to '' but if I set a listener which does this, my textarea become completely broken: each time I press key on keyboard, it duplicates all previous content.
My question is how to prevent input, maybe there is a hack or trick? Please don't send me to android report forums where this bug may be discussed or another questions...

I would first check to see if the events are working when adding eventlisteners. There must be a way to handle key events on Android:
<textarea id="mytextarea"></textarea>
let mytextarea = document.getElementById('mytextarea');
mytextarea.addEventListener('keydown', (event) => {
console.log(event.code);
});
If this is not working; you asked for a hack or trick: try the focus and blur events, then you could run a function on interval that clears the textarea. Note that this blocking trick is something that goes against good user experience conventions, so should be considered a hack/trick for sure ;-)
<textarea id="mytextarea"></textarea>
let int1;
let mytextarea = document.getElementById('mytextarea');
mytextarea.addEventListener('focus', () => {
clearInterval(int1);
int1 = setInterval(() => {
mytextarea.value = '';
}, 10)
});
mytextarea.addEventListener('blur', () => {
clearInterval(int1);
});

Instead of using event.key or event.code properties of keypress (keyup, keydown) event, I have used event.inputType, event.data of update event and added few restricting attributes to the input tag to overcome 'smartness' of mobile keyboard app. It is an ugly hack but worked for my purpose.
HTML:
<textarea id="inpt" autocapitalize="none" autocomplete="off" autocorrect="off" spellcheck="false" ></textarea>
</div>
JS:
var inpt = document.getElementById('inpt');
inpt.addEventListener('input', do_on_input);
function do_on_input(e) {
if( e.inputType == "insertText"){
console.log( e.data );
}
if( e.inputType == "deleteContentBackward"){
console.log('Backspace');
}
if( e.inputType == "insertCompositionText"){
// without restrictive attribbutes you will need to deal with this type events
}
}

Related

Firefox issue when focusing textarea element in keypress event handler

The following snippet works great in chrome/edge/safari. In Firefox the textarea gets focused, but the pressed character isn't being added to the textarea - the first character will be always missing.
document.addEventListener('keypress', (event) => {
document.querySelector('#input').focus();
});
<textarea id="input"></textarea>
How can I make this behave consistently across all browsers?
Here's how you can make it work without browser sniffing: When the keypress happens, bind a handler to the input event on the textarea, and also set a 0-ms timeout.
If the browser accepted the pressed key for the textarea, the input handler will run before the timeout (because the input event fires synchronously). If that happens, you know the browser has handled the keypress correctly, and you can cancel the timeout.
Then, if the timeout fires, you know that the input event hasn't fired and thus the character hasn't been added to the textarea, and you do it programmatically.
In both the event handler and the timeout handler, you unbind the event handler – it should run at most once (per key press).
var textarea = document.getElementById("input");
document.addEventListener("keypress", function (event) {
if (event.target === textarea) {
return;
}
var eventHandler = function () {
textarea.removeEventListener("input", eventHandler);
clearTimeout(timeoutId);
console.log("input event");
}
var timeoutHandler = function () {
var character = ("char" in event) ? event.char : String.fromCharCode(event.charCode);
textarea.value += character;
textarea.removeEventListener("input", eventHandler);
console.log("timeout fired");
}
timeoutId = setTimeout(timeoutHandler, 1);
textarea.addEventListener("input", eventHandler);
textarea.focus();
});
<textarea id="input"></textarea>
<p style="background: #ccc">
<b>Click here</b> to make sure the document is focused, but the textarea is not. Then press a key.
</p>
If you try the above snippet in Firefox, the console will say "timeout fired". In all other browsers it will say "input event". In either case, your pressed key is added to the textarea.
Some notes:
Technically, for consistent behavior you'd need to do more than just append the character to the end; you'd also have to look at things like cursor position and text selection. This may be overkill however.
If you need to support really old browsers, you might want to do a feature check for availability of the input event.
If you have other code that relies on the textarea changing synchronously upon keypress, you'll probably have to make updates there.
While this code will not work if any other browsers share the same behavior as Firefox, the following code will add any key input, given that it is a character whose string length is 1, when the code is run on Firefox:
var mozFocused = false;
document.addEventListener('keypress', (event) => {
document.querySelector('#input').focus();
var isFirefox = typeof InstallTrigger !== 'undefined';
if (isFirefox && !mozFocused && event.key.length === 1) {
mozFocused = true;
document.querySelector('#input').value += event.key;
}
});
document.querySelector('#input').addEventListener('blur', (event) => {
mozFocused = false;
});
<textarea id="input"></textarea>
Again, note that this does not guarantee it to work across all browsers, as this was a fix for Firefox specifically, but, if you see the same behavior occurring in other browsers, I used the answer from this SO post to detect the current browser the client is using (assuming it is in the list of the browsers that this post discusses): How to detect Safari, Chrome, IE, Firefox and Opera browser?

How to enforce maxlength on textarea in Opera but allow modification

I want to limit the number of characters in a textarea to 255 but still allow keys like Backspace, Delete, arrow keys, Home, End, PgUp, etc. I also want to allow Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+A shortcuts inside a textarea. The number of characters should never be more than 255 even when text was pasted by Ctrl+C or right click > paste. With browsers other than Opera, I can simply use the maxlength property, but it is unfortunately not supported in Opera.
I looked at some of the solutions of SO, but none of them seems to complelety implement what I want. And those solutions are somewhat ugly because some of them hard code many keyCodes. (Maybe that is the only approach.)
How should I approach this to solve this problem?
Concerning Opera, you can just handle the input event:
$('textarea').on('input', function() {
if (this.value.length > 255) this.value = this.value.substring(0, 255);
});
Fiddle
Note: No IE<=8 support. This can technically be shimmed with MS's propertychange event, but that's rather buggy when pasting on IE8 textarea, figures.
Just made this slightly crude snippet to automatically shim textareas' maxLength:
$(function() {
var helper = document.createElement('textarea');
//if (!('maxLength' in helper)) {
var supportsInput = 'oninput' in helper,
ev = supportsInput ? 'input' : 'propertychange paste keyup',
handler = function() {
var maxlength = +$(this).attr('maxlength');
if (this.value.length > maxlength) {
this.value = this.value.substring(0, maxlength);
}
};
$('textarea[maxlength]').on(ev, supportsInput ? handler : function() {
var that = this;
setTimeout(function() {
handler.call(that);
}, 0);
});
//}
});
Demo
Tested in Opera 12.10 and IE8.
This will automatically patch textareas that have a maxlength attribute on DOM ready. You may obviously delegate the event (in case there are dynamically generated textareas) by attaching it to an ancestor and using textarea[maxlength] as a descendant selector, e.g.:
$(document).on(ev, 'textarea[maxlength]', ...)
And finally, the feature detection is commented out because Opera does have a maxLength property on textareas, it parses the value the html to the DOM maxLength property as well as having the default value (-1) for textareas without maxLength, it is just that it apparently has no effect in Opera.
I can't find a way to properly feature detect this Opera bug so the feature detection part is commented out, that is, the code above attaches listeners to textareas independently of whether the browser supports maxLength. Feel free to edit the answer in case you manage to feature detect Opera's bug. Though this seems to be a very localized bug that shall be fixed soon enough.

Do not allow Paste any non alphanumeric characters

I don’t want user to allow pasting of any non Alphanumeric characters on a text box.
How do I restrict this in Javascript?
Thanks!!
Using jQuery, this is one way to do it:
HTML:
​<form name='theform' id='theform' action=''>
<textarea id='nonumbers' cols='60' rows='10'> </textarea>
</form>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
JavaScript:
$().ready(function(){
$("textarea#nonumbers").keyup(removeextra).blur(removeextra);
});
function removeextra() {
var initVal = $(this).val();
outputVal = initVal.replace(/[^0-9a-zA-Z]/g,"");
if (initVal != outputVal) {
$(this).val(outputVal);
}
};
Try it out here.
EDIT: As remarked in the comments, the original (using the .keyup() event) would have left open the possibility of pasting via the mouse context menu, so I've added a .blur() event. .change() would have been possible too, but there are reports of bugginess. Another option is using .focusout(). Time to experiment...
You can use the onblur event of text box.
function remove()
{
var otxt=document.getElementById('txt1');
var val=otxt.value;
for(i=0;i<val.length;i++)
{
var code=val.charCodeAt(i);
if(!(code>=65 && code<=91) && !(code >=97 && code<=121) && !(code>=48 && code<=57))
{ otxt.value=""; return ; }
}
}
<input type="text" id="txt1" onblur="remove();" />
It will remove all value of text box when you input non alphanumeric value.
Why has no one suggested using the OnPaste event? That is fully supported in IE, Safari and Chrome.
Docs for using OnPaste in IE
Docs for using OnPaste in Webkit
In JQuery, that would look like this:
$(input).bind("paste", function(e){ RemoveNonAlphaNumeric(); })
That covers 75% of the browser market.
If you use JQuery, OnPaste is automatically normalized in Firefox so that it works there too. If you can't use JQuery, there is an OnInput event that works.
The working solution is to use a fast setTimeout value to allow the input's value property to be filled.
Basically like this:
$("input").bind("paste", function(e){RemoveAlphaChars(this, e);});
function RemoveAlphaChars(txt, e)
{
setTimeout(function()
{
var initVal = $(txt).val();
outputVal = initVal.replace(/[^0-9]/g,"");
if (initVal != outputVal)
$(txt).val(outputVal);
},1);
}
I have tested this in IE, Chrome and Firefox and it works well. The timeout is so fast, you can't even see the characters that are being removed.
I'm not sure how you can prevent pasting, but you can filter the contents either on the submit or on the change event.
It's better to validate form - check this great jQuery's plugin - http://docs.jquery.com/Plugins/Validation/ and you can use the "number" rule : http://docs.jquery.com/Plugins/Validation/Methods/number. Really simple and easy to tune thing!
Assuming:
<textarea id="t1"/>
You could modify the onchange event handler for the textarea to strip out anything not alphanumeric:
document.getElementById('t1').onchange = function () {
this.value = this.value.replace(/\W/,'');
}

Textarea onchange detection

How do I detect change event on textarea using javascript?
I'm trying to detect how many characters left is available as you type.
I tried using the onchange event, but that seems to only kick in when focus is out.
The best way to do this, cross-browser: use a combination of the input and onpropertychange events, like so:
var area = container.querySelector('textarea');
if (area.addEventListener) {
area.addEventListener('input', function() {
// event handling code for sane browsers
}, false);
} else if (area.attachEvent) {
area.attachEvent('onpropertychange', function() {
// IE-specific event handling code
});
}
The input event takes care of IE9+, FF, Chrome, Opera and Safari, and onpropertychange takes care of IE8 (it also works with IE6 and 7, but there are some bugs).
The advantage of using input and onpropertychange is that they don't fire unnecessarily (like when pressing the Ctrl or Shift keys); so if you wish to run a relatively expensive operation when the textarea contents change, this is the way to go.
Now IE, as always, does a half-assed job of supporting this: neither input nor onpropertychange fires in IE when characters are deleted from the textarea. So if you need to handle deletion of characters in IE, use keypress (as opposed to using keyup / keydown, because they fire only once even if the user presses and holds a key down).
Source: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/
EDIT: It seems even the above solution is not perfect, as rightly pointed out in the comments: the presence of the addEventListener property on the textarea does not imply you're working with a sane browser; similarly the presence of the attachEvent property does not imply IE. If you want your code to be really air-tight, you should consider changing that. See Tim Down's comment for pointers.
You will need to use onkeyup and onchange for this. The onchange will prevent context-menu pasting, and the onkeyup will fire for every keystroke.
See my answer on How to impose maxlength on textArea for a code sample.
For Google-Chrome, oninput will be sufficient (Tested on Windows 7 with Version 22.0.1229.94 m).
For IE 9, oninput will catch everything except cut via contextmenu and backspace.
For IE 8, onpropertychange is required to catch pasting in addition to oninput.
For IE 9 + 8, onkeyup is required to catch backspace.
For IE 9 + 8, onmousemove is the only way I found to catch cutting via contextmenu
Not tested on Firefox.
var isIE = /*#cc_on!#*/false; // Note: This line breaks closure compiler...
function SuperDuperFunction() {
// DoSomething
}
function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
if(isIE) // For Chrome, oninput works as expected
SuperDuperFunction();
}
<textarea id="taSource"
class="taSplitted"
rows="4"
cols="50"
oninput="SuperDuperFunction();"
onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>
I know this isn't exactly your question but I thought this might be useful.
For certain applications it is nice to have the change function fire not every single time a key is pressed. This can be achieved with something like this:
var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);
text.onkeyup = function(){
var callcount = 0;
var action = function(){
alert('changed');
}
var delayAction = function(action, time){
var expectcallcount = callcount;
var delay = function(){
if(callcount == expectcallcount){
action();
}
}
setTimeout(delay, time);
}
return function(eventtrigger){
++callcount;
delayAction(action, 1200);
}
}();
This works by testing if a more recent event has fired within a certain delay period. Good luck!
I know this question was specific to JavaScript, however, there seems to be no good, clean way to ALWAYS detect when a textarea changes in all current browsers. I've learned jquery has taken care of it for us. It even handles contextual menu changes to text areas. The same syntax is used regardless of input type.
$('div.lawyerList').on('change','textarea',function(){
// Change occurred so count chars...
});
or
$('textarea').on('change',function(){
// Change occurred so count chars...
});
You can listen to event on change of textarea and do the changes as per you want. Here is one example.
const textArea = document.getElementById('my_text_area');
textArea.addEventListener('input', () => {
var textLn = textArea.value.length;
if(textLn >= 100) {
textArea.style.fontSize = '10pt';
}
})
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>
Keyup should suffice if paired with HTML5 input validation/pattern attribute. So, create a pattern (regex) to validate the input and act upon the .checkValidity() status. Something like below could work. In your case you would want a regex to match length. My solution is in use / demo-able online here.
<input type="text" pattern="[a-zA-Z]+" id="my-input">
var myInput = document.getElementById = "my-input";
myInput.addEventListener("keyup", function(){
if(!this.checkValidity() || !this.value){
submitButton.disabled = true;
} else {
submitButton.disabled = false;
}
});
Code I have used for IE 11 without jquery and just for a single textarea:
Javascript:
// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{
if (internalChange == 1)
{
internalChange= 0;
return;
}
internalChange= 1;
// <form> and <textarea> are the ID's of your form and textarea objects
<form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}
and html:
<TEXTAREA onpropertychange='limit_char(5)' ...
Try this one. It's simple, and since it's 2016 I am sure it will work on most browsers.
<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea>
<div><span id="spn"></span> characters left</div>
function check(){
var string = document.getElementById("url").value
var left = 15 - string.length;
document.getElementById("spn").innerHTML = left;
}
The best thing that you can do is to set a function to be called on a given amount of time and this function to check the contents of your textarea.
self.setInterval('checkTextAreaValue()', 50);

Javascript textbox call event when value changes

I have a textbox, and whenever the value of the box changes, I want to check and see if 20 digits have been entered.
I thought that I would use the onChange event, but this seems to be interpreted as the onBlur event on IE.
So then I thought I would use onKeyDown, but the problem comes in if the user wants to paste a value into the field, then the function never gets called.
There are no other form boxes so I can't rely on onBlur or expect that they will change focus ever.
How do I do this?
I just want to evaluate the value of the textbox every time the value of the textbox changes.
<input type="text" onKeyDown="myfunction()">
An effective way is to use a combination of onkeydown and onpaste, which will work in IE, Firefox, Chrome and Safari. Opera is the odd one out here because it doesn't support onpaste so you may have to fall back to onchange for Opera or use the DOMAttrModified mutation event, see example below.
Internet Explorer also supports onpropertychange, which will fire every time a property changes on an element -- including value. I have read that DOMAttrModified is supported by Opera and Safari (not sure about Firefox), so you could use that in combination with IE's onpropertychange (untested):
if ("implementation" in document &&
document.implementation.hasFeature('MutationEvents','2.0'))
myInput.addEventListener("DOMAttrModified", valueChanged, false);
else if ("onpropertychange" in myInput)
myInput.onpropertychange = valueChanged;
function valueChanged (evt)
{
var attr;
evt = evt || window.event;
attr = evt.attrName || evt.propertyName;
if (attr == "value")
validate();
}
use onKeryPress event
<input type="text" onKeyDown="CountText(this,200)" onpaste="return false;">
function CountText(field, maxlimit)
{
if (field.value.length < maxlimit) // if too long...trim it!
{
return true;
}
else
return false;
}
check my full article on : http://www.codeproject.com/KB/validation/MyTextBox.aspx
<script>
function multy(val)
{
alert(val.value+"--"+val.id);
}
</script>
</head>
<body>
<input id="txtdemo" type="text" onchange="multy(this);"></br>
<input id="txtdemo" type="text" onchange="multy(this);">
</input>
</body>
Thanks... :)

Categories