I have an input and on input change, I change it to the money format.
<input type="number" class="currency" step="0.01">
like this:
$('input[type="number"].currency').on('input', function(e) {
this.value = this.value.match(/^-?\d+\.?\d{0,2}/);
});
However, as this gets triggered on every keypress, it doesn't let me write "-" as first character; so it erases it as soon as I click "-"
What kind of regex can I use for allowing that?
https://jsfiddle.net/4zv9wLr3/ - Here is a fiddle, try to write a negative number, it won't allow you to write.
When "number" input triggers the input event, the value was received blank.
$('input[type="number"].currency').on('input', function(e) {
if (e.target.value.length !== 0) {
this.value = this.value.match(/^-?\d+\.?\d{0,2}/);
}
});
I added a guard like this and it worked.
Related
I am trying to get the text in a text box as the user types in it (jsfiddle playground):
function edValueKeyPress() {
var edValue = document.getElementById("edValue");
var s = edValue.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: " + s;
//var s = $("#edValue").val();
//$("#lblValue").text(s);
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>
The code runs without errors, except that the value of the input text box, during onKeyPress is always the value before the change:
Question: How do I get the text of a text box during onKeyPress?
Bonus Chatter
There are three events related to "the user is typing" in the HTML DOM:
onKeyDown
onKeyPress
onKeyUp
In Windows, the order of WM_Key messages becomes important when the user holds down a key, and the key begins to repeat:
WM_KEYDOWN('a') - user has pushed down the A key
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_KEYUP('a') - the user has released the A key
Will result in five characters appearing in a text control: aaaaa
The important point being that the you respond to the WM_CHAR message, the one that repeats. Otherwise you miss events when a key is pressed.
In HTML things are slightly different:
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyUp
Html delivers an KeyDown and KeyPress every key repeat. And the KeyUp event is only raised when the user releases the key.
Take aways
I can respond to onKeyDown or onKeyPress, but both are still raised before the input.value has been updated
I cannot respond to onKeyUp, because it doesn't happen as the text in the text-box changes.
Question: How do I get the text of a text-box during onKeyPress?
Bonus Reading
Getting a form value with jQuery
Get the value in an input text box
Keep it simple. Use both onKeyPress() and onKeyUp():
<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">
This takes care of getting the most updated string value (after key up) and also updates if the user holds down a key.
jsfiddle: http://jsfiddle.net/VDd6C/8/
Handling the input event is a consistent solution: it is supported for textarea and input elements in all contemporary browsers and it fires exactly when you need it:
function edValueKeyPress() {
var edValue = document.getElementById("edValue");
var s = edValue.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>
I'd rewrite this a bit, though:
function showCurrentValue(event)
{
const value = event.target.value;
document.getElementById("label").innerText = value;
}
<input type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="label"></span>
the value of the input text box, during onKeyPress is always the value before the change
This is on purpose: This allows the event listener to cancel the keypress.
If the event listeners cancels the event, the value is not updated. If the event is not canceled, the value is updated, but after the event listener was called.
To get the value after the field value has been updated, schedule a function to run on the next event loop. The usual way to do this is to call setTimeout with a timeout of 0:
$('#field').keyup(function() {
var $field = $(this);
// this is the value before the keypress
var beforeVal = $field.val();
setTimeout(function() {
// this is the value after the keypress
var afterVal = $field.val();
}, 0);
});
Try here: http://jsfiddle.net/Q57gY/2/
Edit: Some browsers (e.g. Chrome) do not trigger keypress events for backspace; changed keypress to keyup in code.
keep it Compact.
Each time you press a key, the function edValueKeyPress() is called.
You've also declared and initialized some variables in that function - which slow down the process and requires more CPU and memory as well.
You can simply use this code - derived from simple substitution.
function edValueKeyPress()
{
document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}
That's all you want, and it's faster!
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%; margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>
<script>
function isNumberKey(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
</script>
None of the answers so far offer a complete solution. There are quite a few issues to address:
Not all keypresses are passed onto keydown and keypress handlers (e.g. backspace and delete keys are suppressed by some browsers).
Handling keydown is not a good idea. There are situations where a keydown does NOT result in a keypress!
setTimeout() style solutions get delayed under Google Chrome/Blink web browsers until the user stops typing.
Mouse and touch events may be used to perform actions such as cut, copy, and paste. Those events will not trigger keyboard events.
The browser, depending on the input method, may not deliver notification that the element has changed until the user navigates away from the field.
A more correct solution will handle the keypress, keyup, input, and change events.
Example:
<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>
<script>
function UpdateDisplay()
{
var inputelem = document.getElementById("editvalue");
var s = inputelem.value;
var labelelem = document.getElementById("labelvalue");
labelelem.innerText = s;
}
// Initial update.
UpdateDisplay();
// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>
Fiddle:
http://jsfiddle.net/VDd6C/2175/
Handling all four events catches all of the edge cases. When working with input from a user, all types of input methods should be considered and cross-browser and cross-device functionality should be verified. The above code has been tested in Firefox, Edge, and Chrome on desktop as well as the mobile devices I own.
I normally concatenate the field's value (i.e. before it's updated) with the key associated with the key event. The following uses recent JS so would need adjusting for support in older IE's.
Recent JS example
document.querySelector('#test').addEventListener('keypress', function(evt) {
var real_val = this.value + String.fromCharCode(evt.which);
if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
alert(real_val);
}, false);
Support for older IEs example
//get field
var field = document.getElementById('test');
//bind, somehow
if (window.addEventListener)
field.addEventListener('keypress', keypress_cb, false);
else
field.attachEvent('onkeypress', keypress_cb);
//callback
function keypress_cb(evt) {
evt = evt || window.event;
var code = evt.which || evt.keyCode,
real_val = this.value + String.fromCharCode(code);
if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}
[EDIT - this approach, by default, disables key presses for things like back space, CTRL+A. The code above accommodates for the former, but would need further tinkering to allow for the latter, and a few other eventualities. See Ian Boyd's comment below.]
easy...
In your keyPress event handler, write
void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
var tb = sender as TextBox;
var startPos = tb.SelectionStart;
var selLen= tb.SelectionLength;
var afterEditValue = tb.Text.Remove(startPos, selLen)
.Insert(startPos, e.KeyChar.ToString());
// ... more here
}
So there are advantages and disadvantages to each event. The events onkeypress and onkeydown don't retrieve the latest value, and onkeypress doesn't fire for non-printable characters in some browsers. The onkeyup event doesn't detect when a key is held down for multiple characters.
This is a little hacky, but doing something like
function edValueKeyDown(input) {
var s = input.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: "+s;
//var s = $("#edValue").val();
//$("#lblValue").text(s);
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />
seems to handle the best of all worlds.
By using event.key we can get values prior entry into HTML Input Text Box. Here is the code.
function checkText()
{
console.log("Value Entered which was prevented was - " + event.key);
//Following will prevent displaying value on textbox
//You need to use your validation functions here and return value true or false.
return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />
Try to concatenate the event charCode to the value you get.
Here is a sample of my code:
<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>
js:
function cnum(event, str) {
var a = event.charCode;
var ab = str.value + String.fromCharCode(a);
document.getElementById('demo').innerHTML = ab;
}
The value in ab will get the latest value in the input field.
There is a better way to do this. Use the concat Method. Example
declare a global variable. this works good on angular 10, just pass it to Vanilla JavaScript. Example:
HTML
<input id="edValue" type="text" onKeyPress="edValueKeyPress($event)"><br>
<span id="lblValue">The text box contains: </span>
CODE
emptyString = ''
edValueKeyPress ($event){
this.emptyString = this.emptyString.concat($event.key);
console.log(this.emptyString);
}
I am very new to Javascript as I began self-learning just yesterday. I am trying to emulate a type racer game.
(spacebar) as the input will signify the completion of my attempt to type the current word, and I have functions to check if it is correct/incorrect, and then resets the input.
So if I type apple and then (space), the input field becomes reset.
However the problem is if the user types too quickly, then the first or more character of the next word is included in the input before the reset function.
Example:
words to type: apple lemon
user input: apple lemon
input field: apple le -> upon space, reset() is called and clears input but user already typed le once reset() is completed -> mon
So I am wondering if there is a way to speed up reset() such that it is called and completed before the next input from the user.
I initially had everything under 1 function "inputMatch", that was called upon keyup, but tried to separate the reset() and inputMatch() functions by having one being called upon keydown, and the other upon keyup.
This is the code I have. I can provide more context/the full code if needed, but since I am new here, I am unsure whether people prefer to read simplified pseudo code or actual code.
<input type="text" class="form-control" id="inputfield" value="" dir="ltr" placeholder="" onkeyup="reset()" onkeydown="inputMatch(event)">
<script>
const inputMatch = () => {
var current = word that I am currently attempting to type;
if(event.keyCode == 32){ //spacebar
change word that was typed to be either correct or incorrect
};
//once at end need to remove the first (current.wordnr - 1) words
}
const reset = () => {
if(event.keyCode == 32){ //spacebar
document.getElementById('inputfield').value = ""; //clear input field
}
}
</script>
Welcome to Stack Overflow! My recommendation would be to use the oninput event handler instead of onkeyup/onkeydown. See the following code:
const handle = (input) => {
if (input.charAt(input.length - 1) === ' ') // If the last character is a space
reset()
else // otherwise, handle your input (in your case, use it in your type racing game)
console.log("Partial word: " + input)
}
const inputField = document.getElementById("inputfield")
const reset = () => {
console.log("Entered word: " + inputField.value.trimRight())
inputField.value = ""
}
<input type="text" id="inputfield" value="" dir="ltr" placeholder="" oninput="handle(this.value)">
oninput runs synchronously, meaning that it's impossible for the user to type too quickly. It also makes the code a lot simpler.
I am trying to reproduce in my app a UX similar to Microsoft Excel / Google Sheets when you type of formula and you have an autocomplete dropdown for the different formulas and variables you have at your disposal.
For that purpose, after having validated the autocomplete, I want to be able to control the position of the cursor.
For exemple, if I type =sum(variable1, variable2), on autocomplete of variable2, cursor should be before the last parenthesis and not at the very end.
I understand how to set the position of the cursor with javascript, the problem is since at the same time I modify the value of the input and set the cursor position, the latter doesn't work.
I reproduced on fiddle the problem with a simpler context:
https://jsfiddle.net/joparisot/j8ourfa1/31/
My html:
<div id="app">
<autocomplete v-model="selection"></autocomplete>
</div>
<template id="autocomplete">
<div>
<h2>gernerogrnio</h2>
<input id="my-input"
class="form-control"
type="text"
:value="value"
#keydown.enter="updateValue($event.target.value)">
<p>{{ value }}</p>
</div>
</template>
My script:
Vue.component('autocomplete', {
template: '#autocomplete',
props: {
value: {
type: String,
required: true
}
},
methods: {
updateValue (value) {
var new_value = ''
if (value.length < 4) {
new_value = 'Inferior'
} else {
new_value = 'Superior'
}
this.$emit('input', new_value)
var myInput = document.getElementById('my-input');
this.setCaretPosition(myInput, 5)
},
setCaretPosition(ctrl, pos) {
ctrl.focus();
ctrl.setSelectionRange(pos, pos);
}
}
});
new Vue({
el: '#app',
data: {
selection: 'test'
}
});
I don't bother there with the autocomplete, but depending on what you type, when you press enter, the input will be filled with a new value. You can see that if you comment lines 11 to 16 and just set new_value to value, then setting the cursor position will work.
I can't seem to be able to do both things at the same time. Any thoughts?
Thanks to Roy J's comment, I was able to find the solution.
Add the following in the updateValue function:
this.$nextTick(() => {
this.setCaretPosition(myInput, 5)
});
I learned about setSelectionRange from this question, and I used it to handle credit card number input:
template:
<input
ref="input"
v-model="value"
#input="handleChange"
>
instance methods:
data() {
return {
lastValue: '',
}
},
methods: {
setCursorPosition(el, pos) {
el.focus();
el.setSelectionRange(pos, pos);
},
handleChange() {
// handle backspace event
if (this.value.length < this.lastValue.length) {
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle value-edit event
if (this.$refs.input.selectionStart < this.value.length) {
const startPos = this.$refs.input.selectionStart;
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.$nextTick(() => this.setCursorPosition(this.$refs.input, startPos));
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle everything else
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.lastValue = this.value;
this.$emit('input-changed', this.value);
},
},
The goal with the above code is to add spaces into a credit card input, so 1234123412341234 is automatically reformatted to 1234 1234 1234 1234. A person venturing into this territory will notice that problems arise when editing the input value.
You can see there are three conditions in my sample above. The last one is the default which simply reformats the current value with a 2-step combo: remove all spaces then adds a space every 4th character.
If you comment out the two if blocks, you can watch the problems emerge.
The first if block handles the backspace event. As you can see, every time the input changes, the value is captured as this.lastValue. When you press backspace, the goal of the first condition is to NOT run the regex. In my opinion, this is better UX. If you comment out that condition, you can see.
The second if block handles the editing events. A good way to test it, is to enter a valid CC but omit the 3rd character, so that everything is off by one. Then add the character in. Everything should be good. Likewise if you backspace multiple characters out. The goal of the second condition is to properly manage the cursor position (or caret position if you prefer that nomenclature).
You can safely delete the first condition and all references to lastValue and the code will still work. This is arguably simpler but worse UX.
I found an easy way to fix this issue, Tested in IE and Chrome 100%
Call this function in each key press
function setCaret(eleId)
{
var mousePosition = $(elemId)[0].selectionStart;
var elem = document.getElementById(elemId);
elem.setSelectionRange(mousePosition + 1, mousePosition + 1);
}
Pass text box id to this function, the function will find the mouse position and place the caret for each key press
In an input box I used e.preventDefault(); to stop text input after inputValue.length > 10. However text input always stops at 11 characters instead of 10. I can't understand why it doesn't stop accepting characters at 10. Why is this? Thanks so much!
'use strict';
document.querySelectorAll('.input_style')[0].addEventListener('keydown', pressKey);
document.querySelectorAll('.input_style')[0].addEventListener('keyup', releaseKey);
function pressKey(e) {
let inputValue = e.target.value;
if (inputValue.length > 10) {
e.preventDefault();
}
}
function releaseKey(e) {
let inputValue = e.target.value;
console.log(inputValue.length);
if (inputValue.length > 10 ) {
e.preventDefault();
}
}
.input_style {
font-size: 2rem;
font-family: arial;
}
<input class="input_style">
The length of the string has to be 11 for the condition > 10 to be true. If you want to stop at 10, do >= 10.
Your condition waits until it's bigger than 10, so that condition is only met when it's 11.
The issue here is that new values are added to the input on keydown, not keyup, and your keydown handler pressKey(e) is checking for the current value of the input box, before adding the new value. Therefore, you need to check for your length >= 10 rather than >10.
The keyup handler in this case is completely unnecessary, since it does not stop a new value from being added.
Another thing you should consider is checking for the input keycode values 8 ("backspace") and 46 ("delete"), and allow those to be handled. As it stands now, once your input box is full, it is impossible to change it in any way, as you can't use backspace or delete to remove a wrong character.
This Javascript which uses functions from jQuery is quite handy but getting feedback on it there is some limitations which I was hoping you guys could help me overcome.
The function basically creates a textbox with a formatted time (HH:MM:SS) so that it is easy for users to enter in times rather than have to use a date time picker which involves lots of clicks.
Code:
//global variable for keeping count on how many times the function is called
var i = 0;
//for adding formatted time fields
function timemaker()
{
//creates an input field of text type formatted with a value of "00:00:00"
var input = $("<input>",
{
name: 'time'+i, // e.g. time0, time1, time2, time3
value: '00:00:00',
maxlength: '8',
size: '6'
});
//this function which uses jquery plugin causes the cursor in the field to goto position zero
//when selected making it easier for the user to enter times and not need to select the correct position
input.click(function()
{
$(this).prop({
selectionStart: 0,
selectionEnd: 0
});
//this child function moves the cursor along the text field
//when it reaches the first ":" it jumps to the next "00"
}).keydown(function() {
if (event.keyCode == 9)
{
return;
}
else
{
var sel = $(this).prop('selectionStart'),
val = $(this).val(),
newsel = sel === 2 ? 3: sel;
newsel = sel === 5 ? 6: newsel;
$(this).val(val.substring(0, newsel) + val.substring(newsel + 1))
.prop({
selectionStart: newsel,
selectionEnd: newsel
});
}
});
//this appends the text field to a divved area of the page
input.appendTo("#events");
i++;
return;
}
00:00:00
Limitations I need help with
Say for example you wanted to enter a time of 12:45:00 , you
obviously don't need to enter the seconds part (last "00") as they
are already there. So you then decide to tab out of that text field
but the javascript interprets your "Tab" keypress as an entry and
deletes a zero from the field causing the value to be like 12:45:0
Does not validate inputs for 24 hour format- do you think it will be
possible to do that? e.g. first number you enter is "2" therefore the
only options you have are "0,1,2,3"
If you make a mistake in the 4th digit and reselect the text field
you have to enter everything again.
I think the main thing you're missing that would allow you to implement all those requirements is the argument that jQuery passes to you in your keydown event handler. So, change that line to this:
.keydown(function(event){
if (event.keyCode == 9) { return; }
... the rest of your code ...
and then you can use event.keyCode to identify what was pressed and take actions accordingly. So for example, if event.keyCode == 9 then the user pressed TAB.
This is a slightly out-of-the-box solution, but you might consider it if things don't work out with your filtered textbox:
http://jsfiddle.net/YLcYS/4/