Onkeypress update input is 1 step behind - javascript

I am trying to update an input with 2 other inputs. For example
Amount : (user inputs value)
Fee: (value is already set -- disabled value: 0.0002)
Total: (amount - fee) worked out via javascript below
$('#amount').keypress(function() {
var total = $('#amount').val() - $('#fee').val();
if(typeof total != 'undefined'){ $('#total').val(total) }});
When I 'keypress' on my input with a number, it is one step behind updating the input with total.
Say for an example if I type 1 in the input amount, the total will be -0.0002(the fee) when I press 1 again, it will be 0.9998 (even though the amount input is now 11 so on so forth.)

It's cause of you're using keypress which consists of 2 events keydown and keyup, so your function launches on the first one - keydown, so you get your values, as you said "one step behind", cause when the keydown event is fired your input field didn't recieve the pressed key value yet. Use keyup and you will get your result:
$('#amount').keyup(function() {
var total = $('#amount').val() - $('#fee').val();
if(typeof total != 'undefined') $('#total').val(total)
});
Fiddle

The posted answers are good answers, but the best event to use here is the oninput event, because it's faster.
$('#amount').on('input', function() {
var total = $('#amount').val() - $('#fee').val();
if(typeof total != 'undefined'){
$('#total').val(total);
}
});
Supported by all browsers: browser support. It's actually better supported than onchange and other events like onkeyup. You can compare that on https://caniuse.com/.
You can even use this event for other input elements as well. Like checkboxes, radio buttons and the select element.
It's fast. So you can combine this with search queries to make your search results return faster.
Please note: since this is not a keyboard event, there won't be a keyCode or any other keyboard related value in the event.
Read more
Event Reference
Global Event Handler

True, because when function is called the field is not updated with the value
The event is called in this steps
Keydown
Keypress
updateview
Keypress
updateview
keyup
So if you can change this event to keyup then you will get the latest value.

Related

Debounce search only if search term changes [duplicate]

This question already has answers here:
Throttle event calls in jQuery
(7 answers)
Closed 5 years ago.
I'm working on a live ajax search field. So we have:
<input type="search" id="search">
And I want to trigger the search once the user has stopped typing for 500ms.
I got it working like this:
function throttle(f, delay){
var timer = null;
return function(){
var context = this, args = arguments;
clearTimeout(timer);
timer = window.setTimeout(function(){
f.apply(context, args);
},
delay || 500);
};
}
$('#search').keyup(throttle(function(){
// do ajax
}));
The problem is: if user holds shift key and releases it, the search will trigger regardless. So no new keys are added and the same search term was submitted.
How can I make it so that it triggers only if a new character has been added/removed?
Simply keep track of the state:
var currentSearch = "";
Then whenever a keyup happens, check if the input changed, if not stop updating:
if($("#search").val() === currentSearch) return;
//updated so:
currentSearch = $("#search").val();
Sidenote: as DOM lookup is time intensive you may cache $("#search") ...
You could also use the keyup event, and check if the keycode matches the keys on which you want to act on. Please refer this answer
Adapting that answer to your case:
$('#search').keyup(
function(event) {
var isWordCharacter = event.key.length === 1;
var isBackspaceOrDelete = (event.keyCode == 8 || event.keyCode == 46);
if (isWordCharacter || isBackspaceOrDelete) {
(throttle(function(){
// do ajax
})))();
}
})
You should use input event instead of keyup, which will be triggered only when the value will change.
$('#search').on('input', throttle(function(){
// do ajax
}));
The DOM input event is fired synchronously when the value of an <input>, <select>, or <textarea> element is changed. (For input elements with type=checkbox or type=radio, the input event does not fire when a user clicks the control, because the value attribute does not change.)
But be aware that this event has some problems in IE9/10/11 (and is not supported in previous IE versions at all):
[2] IE 9 does not fire an input event when the user deletes characters from an input (e.g. by pressing Backspace or Delete, or using the "Cut" operation).
[3] IE 10 and 11 has a bug, input event fires on placeholder attribute changes.
But the IE10/11 problem is kind of ok, so it depends on if you need to support IE9.
https://developer.mozilla.org/en-US/docs/Web/Events/input
EDIT: unfortunately change is not a suitable solution as it occurres only after blur (loosing focus of the input). Correct solution is to use input event.

Allow use special commands on input validating

I have a little problem with validating an input field.
Here is my validation code:
_validateInput: function(e) {
var value = e.currentTarget.value;
var key = e.which || e.keyCode;
var re = /[^0-9\.]/gi;
if (re.test(value + String.fromCharCode(key))) {
return value;
} else {
return value + String.fromCharCode(key);
}
},
The logic is the next. If user input non-digital characters, the function return current value of the input, without the last symbol.
If user type digit or dot, function return current input value + entered number.
What is my problem:
1) It not allows user to enter dot.
2) String.fromCharCode for dot character returns "¾" symbol.
3) Special symbols like backspace, tab, etc... doesn`t work.
4) Commands like Ctrl+V, Ctrl+A also does not work
Could someone help me to solve this problems? What is wrong with my RegEx?
Thanks!
P.S. Function fired on the keydown event
Unless you need to support older browsers listen for oninput instead of onkeydown and a lot of the processing will have been done for you.
http://www.w3schools.com/jsref/event_oninput.asp
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. The other difference is that the onchange event also works on <keygen> and <select> elements.
Whenever oninput is triggered then check the value in the text area is valid and if it isn't then correct it. This will also let you check for multiple dots being entered (if you need to do that). For example 231.21.23 is not a valid number.

Input value onkeydown returns incorrect value (one less)

I'm working on a script for our client's project that autotabs you onto the next input field when you've hit the maximum character count for a particular input. For some reason the input value is returning one less than it should be, and therefore tabs to the 'next' input when an extra character is entered above the 'threshold'.
Here's my script to watch the inputs value - ofc, if there is a better way please advise :) -
var watchLength = function (watch) {
watch.onkeypress = function () {
var nextInput = getNextSibling(this);
console.log(this.getAttribute('data-autotab-length'));
console.log(this.value.length);
if (this.value.length == this.getAttribute('data-autotab-length')) {
nextInput.focus();
console.log('Limit reached here');
}
};
};
And a jsFiddle to the working input. The first input is limited to '2' characters, but when you type in 3 it jumps to the next input. I think this is something to do with the keypress/keydown event not reading the initial value, but I'm at a loss of how to fix it. Any help really appreciated.
I'm logging the results in the Console:
http://jsfiddle.net/qdnCZ/
The Problem is, that onkeypress will fire before you want it to. You can simply replace onkeypress by onkeyup, that way you make sure that the <input> elements value is set correctly the time you check it.
See: http://jsfiddle.net/qdnCZ/1/
Yes it will return one less, simply use +1 on the length check. This is beacuse onkeypress event is executed before the field is updated, which means using e.preventDefault() the letter will not appear in the field. You could use onkeyup otherwise.
Use onkeyup instead onkeypress
onkeyup gets fired after field gets updated
if (this.value.length == this.getAttribute('data-autotab-length')) {
nextInput.focus();
console.log('Limit reached here');
return false; // this is prevent the third value being entered
}
Updated fiddle

jQuery - How to restrict input values for text box

I want to restrict input in TextBox to be either 'Y' or 'N' (any case).
How can this be done in jQuery.
I'm pretty sure that if keydown returns false, then the input is not allowed. You can do this by grabbing the key code from the event object. This doesn't prevent doing things like copy/pasting a value into the text box, though. So a better option would be a select or radio button if you want to restrict the user's input.
$("#some-selector").bind("keydown", function (e) {
return e.keyCode == 89 || e.keyCode == 78
});
As you said this does not take care of the case of copy/paste a better alternative would be to attach a change event handler and then check if its an allowed char else flag an error
$("some-selector").change( function () {
var textBoxVal=$(this).val();
if(textBoxVal!=='y' || textBoxVal!=='n')
alert("Error");
});
Note:alerts jsut an example- add a different style to the textbox or however u r handling error on ur page.

Why do I get wrong, doubled input value on keyup when typing fast?

$("#input").keyup(function(){
console.log($(this).val());
})
When one is typing slowly "a" & "b" the above code will result in "a", "b" in the console log. But the problem is when somebody does it quickly. The result then is "ab", "ab". It's easier to repeat this situation with letters which are near on a keyboard e.g. "e" & "r". How to avoid it?
Events keydown and keypress does not suffer from this problem of quick-typist, but they are also fire to early. Result: returned value of an input does not contain the last typed letter when they occur. Or maybe there is a way to get this last letter somehow?
Well, the problem is not really fast typing, but actually when the key up event happens. Consider this:
a is pressed
b is pressed
a is released
b is released
No matter how slowly this is done, you will not get the key up event until the first key is released. There is obviously no way around this, you can't cause the key up event before the key is released.
If you just want the key that is pressed in a key press event, you can get it from the event object. Example:
$('#input').keypress(function(e){
console.log(e.which);
});
I had a similar problem and found a workaround. Basically, I created an array with the timeStamp of the event (e.timeStamp) for every time the keyup fired. Then I compared the last two values in the array (the two most recent) and stopped the event if the difference in time wasn't at least 100ms.
This is my code inside the function called by the keyup listener:
timeArray.push(e.timeStamp); // add new timeStamp to array
if (timeArray.length >= 2) {
var diff = (timeArray[timeArray.length - 1] - timeArray[timeArray.length - 2]);
if (diff > 100) { // 1 second
// perform desired action
} else { return false; }
} else {
// still perform desired action if array only has one timestamp
}

Categories