How to avoid keydown delay with jQuery? - javascript

GOAL:
When a user types character in a text box, make a button appear. When the user clears the text box using the backspace key but holds down that key for a few extra seconds, hide the button instantly.
ISSUE:
If a user types in a single character, and uses the backspace to remove it—by holding down the backspace key a few extra seconds—there is a delay before the button is hidden. This only happens when the user typed only one character and then held down the the backspace key without letting go. If instead the user typed multiple characters, and then held down the backspace key until the textbox was empty, there was no delay in hiding the button.
<input type="text" id="tbox"></text>
<button type="button" id="btn" style="display:none;">push me</button>
$('#tbox').on('keydown keypress keyup',function(){
if($('#tbox').val() !== '') {
$('#btn').css({'display':'block'});
} else {
$('#btn').css({'display':'none'});
}
});
JSFIDDLE:
http://jsfiddle.net/odkut0dh/

A little walkthrough the situation :
Assuming that <input> value is "x" and you type backspace :
- When the keydown event fires the input's value is still "x".
- When the keypress fires, it still "x".
If you don't release the key :
__ keydown fires again, after some delay, depending on os I guess value is now "".
__ keypress fires again, value is still "".
__ When you release the key, keyup fires, value is "".
If you do release the key :
__ keypress fires directly, value is "".
The solution For IE10+ is to use the input event which will fire when the textEditable element's content has changed or, as suggested by #Mayhem, the change event, which won't even listen for key inputs and has a better browser support than input
$('#tbox').on('input change',function(e){
if($('#tbox').val() !== '') {
$('#btn').css({'display':'block'});
} else {
$('#btn').css({'display':'none'});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="tbox"></text>
<button type="button" id="btn" style="display:none;">push me</button>

As i've aleady made comments on this one, did a quick google and came across this post which might make it a little easier.. Detect all changes to a <input type="text"> (immediately) using JQuery
So i put it into a fiddle here for you to test: Slight Modded Version
The HTML
<input type="text" value="Some Value" id="text1" />
<button id="btn1">Click Me</button>
The JS
$('#text1').each(function() {
var elem = $(this);
elem.data('oldVal', elem.val());
elem.bind("propertychange change click keyup input paste", function(event){
if (elem.data('oldVal') != elem.val()) {
if (elem.val().length == 0 ) {
$("#btn1").hide();
} else {
$("#btn1").show();
}
elem.data('oldVal', elem.val());
}
});
});
As i dont have to much time to break this code down into sections... By the looks of it.. You dont need the elem.data... Just the bind event...
... ah seems i decided to shorten the code for you...
http://jsfiddle.net/z2ew3fqz/3/
Using the same HTML...
Shortest version i could make from the example given above
The HTML
<input type="text" value="Some Value" id="text1" />
<button id="btn1">Click Me</button>
The JS
$('#text1').bind("propertychange change click keyup input paste", function(event){
if ($(this).val().length == 0 ) {
$("#btn1").hide();
} else {
$("#btn1").show();
}
});
I've quickly tested this on chrome.. mouse/function keys all seem to affect it correctly... Other browsers i'll leave upto the OP to test.. Let me know if any issues in a particular browser..
IE10 seems to be the min support for this .. IE9 might be able to have a js prototype done.. But how important is this for support in your project? to support IE<10?

The Problem is that $('#tbox').val(); is not empty ('') when backspace is pressed. So You have to delay the value check.
When you press down the key, the first thing what happend is that the keydown event is fired, then after that the key action will be performed on the input field.
$('#tbox').on('keydown keypress keyup',function(){
setTimeout(function () {
if($('#tbox').val() !== '') {
$('#btn').css({'display':'block'});
} else {
$('#btn').css({'display':'none'});
}
},0);
});

You can prevent repeating keydown by control it on key up by an global variable:
var allow = true;
$(document).on('keydown', function(e) {
if (e.repeat != undefined) {
allow = !e.repeat;
}
if (!allowed) return;
allowed = false;
if($('#tbox').val() !== '') {
$('#btn').css({'display':'block'});
} else {
$('#btn').css({'display':'none'});
}
});
$(document).keyup(function(e) {
allowed = true;
});

Related

HTML Spinbutton up/down arrows event [duplicate]

I want to be able to listen to <input type="number" /> step UP (increment) and step down events with jQuery. (currently I can only understand how to listen to change event)
For input type="number", you can use the change event, but will possibly have more cases to handle and create some clutter. I broke it down, I recommend using the "mouseup" event for the increment feature (which will mainly be used from pc) But if the user uses a device instead, I would use the event 'keyup' since the increment feature will not appear and the user will have an on-screen keyboard instead. The change event will listen for both.
For example :
$(".counter").bind('mouseup', function () {
if($(this).val() == undefined || $(this).val() == "")
return; /* Exit dont bother with handling this later, if its not needed leave. */
/* Important Check against integers and not strings. */
/* Comparing against arrays will give unexecpted behavior, size is different then the value. */
var newVal = parseInt($(this).val());
var oldVal = parseInt($(this).data('old-value'));
if (oldVal < newVal) {
alert('incrementing');
}
else{
alert('decrementing');
}
$(this).data('old-value', $(this).val());
});
$(".counter").bind('keyup', function () {
/* Similar logic */
});
I use "bind" instead of "on" or the by method "change" since "on" is a shorthand for bind.
JSFiddle Demo
There is no event for up and down. You can use change event
$(".counter").change(function () {
alert($(this).val());
})
DEMO
You can try something like, You can store previous value and compare with currently value and identify up or down
$(".counter").change(function () {
if ($(this).data('old-value') < $(this).val()) {
alert('Alert up');
} else {
alert('Alert dowm');
}
$(this).data('old-value', $(this).val());
})
DEMO
I'm not sure if there is a listener of the stepUp and StepDown but you can externalize the PLUS and LESS buttons of the input number using:
document.getElementById("myNumber").stepUp(5); //increase the value +5
document.getElementById("myNumber").stepDown(5); // decrease the value -5
So you can finally achieve your objective!
Reference: https://www.w3schools.com/jsref/met_number_stepup.asp
NOTE: Be aware that IE11 and EDGE doesn't implement stepUp / stepDown. On my case I just remove the + and - icon and leave only the input number field. Hope EDGE die soon...
I know this is a relatively old question but, came across it in my search.
In case anyone comes here looking for the answer to this on a custom element triggering the stepUp() or stepDown() like me and not wanting to use jQuery, the below should help:
On the element handling the click to trigger the stepUp()/stepDown(), add this (and change the elements to whatever relation they have to each other):
onclick="this.elementToStepDown.stepDown();this.elementToStepDown.dispatchEvent(new Event('change'))"
Fuller example:
<input class="input--hide_controls" id="number_of_ducks" type="number" value="7" step="1"/>
<div class="increment" onclick="this.parentNode.querySelector('input').stepUp();this.parentNode.querySelector('input').dispatchEvent(new Event('change'))"><i class="im im-plus"></i></div>
Or, extract it out and put it in a JS function that does the same and call that onclick:
let increment = (element) => {
element.stepUp();
element.dispatchEvent(new Event('change'))
}
let decrement = (element) => {
element.stepDown();
element.dispatchEvent(new Event('change'))
}
Then listen out for the 'change' event on the input.
There's no specific event for up and down. Your closest bet is to use the change event. You might also take a look at the oninput event but I am not sure it is supported by all browsers:
$('#myinput').on('input', function() {
});
You should do this:
var $counter = $("your_counter");
var number = $counter.val();
$counter.change(function () {
if($counter.val() > number)
alert('up');
else
alert('down');
number = $counter.val();
});
Here is the demo: http://jsfiddle.net/6bb8S/
html
<input type="number" data-number="0" class="counter" value="0" />
you need to put the same value in the data-number and in the value
jquery
$(document).on('change', '.counter', function() {
//get number of input
var number = $(this).attr("data-number");
//console.log(number);
if($(this).val() > number){
alert('up');
}else{
alert('down');
}
//set number of input for the next step
$(this).attr("data-number", $(this).val());
});
https://jsfiddle.net/maicon_card/46hdm8pj/
works with multiple inputs

Why submit button is not enabled immediately on change to textfield?

With this code The button will become enabled only after:
I type something in textfield
I change the focus out of the textfield.
How can I get the button to enable as soon as something is typed in?
function validateAmount(){
if ($('#parlay-amount-textfield').val().length > 0) {
$("#parlay-submit-button").prop("disabled", false);
}
else {
$("#parlay-submit-button").prop("disabled", true);
}
}
$(document).ready(function(){
validateAmount();
$('#parlay-amount-textfield').change(validateAmount);
});
The change event doesn't fire until focus leaves the input field.
You can use the input event instead on modern browsers, which fires immediately. Or a combination of events to support slightly older browsers: input change paste click which you can respond to immediately and then keydown which you need to respond to after a very brief delay. But I think input's support is very good these days, with the notable exception of IE8 which doesn't support it.
Example with just input:
function validateAmount() {
if ($('#parlay-amount-textfield').val().length > 0) {
$("#parlay-submit-button").prop("disabled", false);
} else {
$("#parlay-submit-button").prop("disabled", true);
}
}
$(document).ready(function() {
validateAmount();
$('#parlay-amount-textfield').on("input", validateAmount);
});
<input type="text" id="parlay-amount-textfield">
<input type="button" id="parlay-submit-button" value="Send">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Example with input change paste click handled immediately and keydown after a very brief delay:
function validateAmount() {
if ($('#parlay-amount-textfield').val().length > 0) {
$("#parlay-submit-button").prop("disabled", false);
} else {
$("#parlay-submit-button").prop("disabled", true);
}
}
$(document).ready(function() {
validateAmount();
$('#parlay-amount-textfield')
.on("input change paste click", validateAmount)
.on("keydown", function() {
setTimeout(validateAmount, 0);
});
});
<input type="text" id="parlay-amount-textfield">
<input type="button" id="parlay-submit-button" value="Send">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Side note: FWIW, validateAmount can be a bit shorter:
function validateAmount() {
$("#parlay-submit-button").prop("disabled", $('#parlay-amount-textfield').val().length == 0);
}
And if just spaces isn't a valid value, you might consider throwing a $.trim() around $('#parlay-amount-textfield').val() (or on modern browsers, using $('#parlay-amount-textfield').val().trim()).
Since we are using the change event the input fields focus tends to say that user has not yet ended up his field with data.so only after the focus is moved the button gets enabled u can use the above Link for further clarifications
[1]"https://jsfiddle.net/MuthuramanNagarajan/gs2sff6j/"

How do I listen for step up event for input type="number"

I want to be able to listen to <input type="number" /> step UP (increment) and step down events with jQuery. (currently I can only understand how to listen to change event)
For input type="number", you can use the change event, but will possibly have more cases to handle and create some clutter. I broke it down, I recommend using the "mouseup" event for the increment feature (which will mainly be used from pc) But if the user uses a device instead, I would use the event 'keyup' since the increment feature will not appear and the user will have an on-screen keyboard instead. The change event will listen for both.
For example :
$(".counter").bind('mouseup', function () {
if($(this).val() == undefined || $(this).val() == "")
return; /* Exit dont bother with handling this later, if its not needed leave. */
/* Important Check against integers and not strings. */
/* Comparing against arrays will give unexecpted behavior, size is different then the value. */
var newVal = parseInt($(this).val());
var oldVal = parseInt($(this).data('old-value'));
if (oldVal < newVal) {
alert('incrementing');
}
else{
alert('decrementing');
}
$(this).data('old-value', $(this).val());
});
$(".counter").bind('keyup', function () {
/* Similar logic */
});
I use "bind" instead of "on" or the by method "change" since "on" is a shorthand for bind.
JSFiddle Demo
There is no event for up and down. You can use change event
$(".counter").change(function () {
alert($(this).val());
})
DEMO
You can try something like, You can store previous value and compare with currently value and identify up or down
$(".counter").change(function () {
if ($(this).data('old-value') < $(this).val()) {
alert('Alert up');
} else {
alert('Alert dowm');
}
$(this).data('old-value', $(this).val());
})
DEMO
I'm not sure if there is a listener of the stepUp and StepDown but you can externalize the PLUS and LESS buttons of the input number using:
document.getElementById("myNumber").stepUp(5); //increase the value +5
document.getElementById("myNumber").stepDown(5); // decrease the value -5
So you can finally achieve your objective!
Reference: https://www.w3schools.com/jsref/met_number_stepup.asp
NOTE: Be aware that IE11 and EDGE doesn't implement stepUp / stepDown. On my case I just remove the + and - icon and leave only the input number field. Hope EDGE die soon...
I know this is a relatively old question but, came across it in my search.
In case anyone comes here looking for the answer to this on a custom element triggering the stepUp() or stepDown() like me and not wanting to use jQuery, the below should help:
On the element handling the click to trigger the stepUp()/stepDown(), add this (and change the elements to whatever relation they have to each other):
onclick="this.elementToStepDown.stepDown();this.elementToStepDown.dispatchEvent(new Event('change'))"
Fuller example:
<input class="input--hide_controls" id="number_of_ducks" type="number" value="7" step="1"/>
<div class="increment" onclick="this.parentNode.querySelector('input').stepUp();this.parentNode.querySelector('input').dispatchEvent(new Event('change'))"><i class="im im-plus"></i></div>
Or, extract it out and put it in a JS function that does the same and call that onclick:
let increment = (element) => {
element.stepUp();
element.dispatchEvent(new Event('change'))
}
let decrement = (element) => {
element.stepDown();
element.dispatchEvent(new Event('change'))
}
Then listen out for the 'change' event on the input.
There's no specific event for up and down. Your closest bet is to use the change event. You might also take a look at the oninput event but I am not sure it is supported by all browsers:
$('#myinput').on('input', function() {
});
You should do this:
var $counter = $("your_counter");
var number = $counter.val();
$counter.change(function () {
if($counter.val() > number)
alert('up');
else
alert('down');
number = $counter.val();
});
Here is the demo: http://jsfiddle.net/6bb8S/
html
<input type="number" data-number="0" class="counter" value="0" />
you need to put the same value in the data-number and in the value
jquery
$(document).on('change', '.counter', function() {
//get number of input
var number = $(this).attr("data-number");
//console.log(number);
if($(this).val() > number){
alert('up');
}else{
alert('down');
}
//set number of input for the next step
$(this).attr("data-number", $(this).val());
});
https://jsfiddle.net/maicon_card/46hdm8pj/
works with multiple inputs

jQuery: clone input field without losing keyCode functionality

Been trying to build jQuery support into a text input where pressing return duplicates the div container into the space right below it. What I can't figure out is how to focus on the input field inside the newly-created div automatically, and, even more frustrating, why that new input field loses the functionality to duplicate. In other words, pressing return only duplicates if you are in the originally-created input field.
$(document).ready(function(){
textboxes = $("input.data-entry");
if ($.browser.mozilla) {
$(textboxes).keypress (checkForAction);
}
else {
$(textboxes).keydown (checkForAction);
}
});
function checkForAction (event) {
if (event.keyCode == 13) {
$(this).clone().val('').appendTo('#form_container');
return false;
}
}
HTML
<div id="form_container">
<input name="firstrow" type="text" class="data-entry">
</div>
use .clone(true) to copy event handlers. see the docs for more info.
$(textboxes).live('keypress', function(checkForAction));

Proper handling of input change event

It may be a correct behavior of change event, but the below behavior is bit annoying. When the value is updated from the field history (see explanation below), the event is not triggered.
Please see example code below. the result input field is updated with the change in input field 'input1'. The form and submit button is not fully relevant, but needed to submit a form to make the browser keep the history of field values.
To test:
enter any input in the field (say ABC)
Submit the form
enter first character of input from 1 (A)
use the down arrow to select the previous value + Enter
or use the mouse to select the previous value from the history
No input change is detected.
Which event/ how should this code should modify so that an event is generated whenever the input value is changed.
thanks.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
Result:<input type="text" id="result" readonly></input>
<form method="post" action="">
<input type="text" id="input1" />
<button type=submit>Submit</button>
</form>
<script >
$(document).ready(function() {
$('#input1').change(
function(){
$('#result').val($('#input1').val());
});
});
</script>
</body>
</html>
I think this has nothing to do with jQuery.
A change event should be dispatched when the content of a control has changed and the control loses focus. In practice, the implementation of the change event is inconsistent in browsers, e.g. Firefox dispatches a change event when radio buttons are clicked on rather then when they lose focus. Also in IE, selecting a value from a list of previous values then causing a blur event doesn't fire a change event.
Note that for form controls to be successful, they must have a name attribute with a value. A simple test case is:
<form action="#">
<input type="text" name="input1" onchange="alert('changed');">
<input type="submit">
</form>
One solution is to use the blur event instead and compare the control's current value to its defaultValue - if they're different, perform whatever it is you were going to do for the change event. If the value may be changed a number of times, after the first time you need to compare with the last value onblur rather than the defaultValue.
Anyhow, here's a function that can be called onblur to see if a text input has changed. It needs a bit of work if you want to use it with other types of form control, but I don't think that's necessary.
<form action="#">
<input type="text" name="input1" onblur="
var changed = checkChanged(this);
if (changed[0]) {
alert('changed to: ' + changed[1]);
}
">
<input type="submit">
</form>
<script type="text/javascript">
// For text inputs only
var checkChanged = (function() {
var dataStore = [];
return function (el) {
var value = el.value,
oValue;
for (var i=0, iLen=dataStore.length; i<iLen; i+=2) {
// If element is in dataStore, compare current value to
// previous value
if (dataStore[i] == el) {
oValue = dataStore[++i];
// If value has changed...
if (value !== oValue) {
dataStore[i] = value;
return [true, value];
// Otherwise, return false
} else {
return [false, value];
}
}
}
// Otherwise, compare value to defaultValue and
// add it to dataStore
dataStore.push(el, value);
return [(el.defaultValue != value), value];
}
}());
</script>
Try the keyup event:
$(document).ready(function() {
$('#input1').keyup(
function(){
$('#result').val($('#input1').val());
});
});
http://jsfiddle.net/kaptZ/7/
It seems like it's definitely a browser bug. Not much you can do besides implement your own change handler with focus and blur. This example is not very reusable, but it solved the problem and can be used as inspiration for something reusable.
http://jsfiddle.net/kaptZ/9/
var startValue;
var input1 = $('#input1');
input1.focus(function(){
startValue = this.value;
});
input1.blur(function(){
if (this.value != startValue) {
$('#result').val(this.value);
}
});
A dirty alternative is to use autocomplete="off"
It looks like this bug which was supposed to be fixed in November 2009.
In modern browsers you can use the input event and update as you type. It can be bound either to the text input:
$('#input1').bind('input', function(){
$('#result').val($('#input1').val());
});
Or to the form:
$('#input1').closest('form').bind('input', function(){
$('#result').val($('#input1').val());
});

Categories

Resources