Set input value in keyup, stops change event from firing - javascript

NEW Fiddle: http://jsfiddle.net/martinnormark/jBZfs/14/ - new isolated example. See how the change event is not fired for Amount 2! **
I have a jQuery plugin for formatting a number in a currency format, as you type.
You can see it in action in this fiddle: http://jsfiddle.net/martinnormark/Rv4Ug/1/
The problem is, if you enter a value of at least 4 digits (causing the need to thousand separator: 1178 becomes 1,178), the change event dies. As long as you stay below 4 digits, not causing a new format, the change event is fired.
In the fiddle, try to enter 12, then 123. You should see a text reading 'change event raised'. And then enter 1234 - and the change event is not fired.
This will have something to do with the manipulation of the input element's value in a keyup event handler:
$this.on("keyup.autoformatcurrency", function(event) {
if ($.inArray(event.keyCode, keyCodes) > -1) {
formatCurrency($(this), true);
}
});
And the formatCurrency function:
function formatCurrency($this, setCaretPosition) {
var rawValue = $this.val(),
floatValue = Globalize.parseFloat(rawValue);
if ($.isNumeric(floatValue)) {
var formattedValue = Globalize.format(floatValue, settings.formatString),
caretPosition = 0;
if (setCaretPosition) {
caretPosition = $this.caret().end + (formattedValue.length - rawValue.length);
}
$this.val(formattedValue);
if (setCaretPosition) {
$this.caret(caretPosition, caretPosition);
}
}
}
(for full source, see the file on Github: https://github.com/martinnormark/jquery-format-currency/blob/master/src/jquery.formatcurrency.js )
The question is, if there's a way to make sure the change event will be fired?
UPDATE - Current state in browsers
Chrome: Change event fired, if number is below 4 digits.
Safari, IE: Change event is never fired, as long the value is set programmatically. Enter letters instead of numbers will trigger the change event.
Firefox: Works!
Opera: Works!

The easiest way would be, to trigger the change event from within the keyup function:
$this.on("keyup.autoformatcurrency", function(event) {
if ($.inArray(event.keyCode, keyCodes) > -1) {
formatCurrency($(this), true);
$(this).change();
}
});

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

Does focus trigger a keyup event?

I made 3 input boxes for time input (hh, mm, ss)
When the user type in 2 digits in hh, it will automatically focus the next (mm) field. Same for mm and ss.
I am using the 'keyup' event to bind my input boxes. However the behaviour is strange:
If I type 2 digits SLOWLY, it works.
If I type FASTER, it will jump twice.
I suspect the 'focus' event triggers the keyup event, and I dont know how to deal with it. I have tried to .preventDefault on the focus event. But no luck.
Here is the code:
$('#hh').on('keyup', function (e) {
var hh = $('#hh').val().toString();
if (hh.length >= 2) {
$('#mm').focus();
}
});
$('#mm').on('keyup', function (e) {
var mm = $('#mm').val().toString();
if (mm.length >= 2) {
$('#ss').focus();
}
});
Here is a demo:
jsfiddle (http://jsfiddle.net/ch3ksuwa)
To reproduce: type in 2 digits quickly in hh field, and it will jump to ss instead of mm
I tried on Chrome and Firefox, same issue
It looks like $('#hh').val() is happening after the second key press but I'm not sure why the second 'keyup' event's target is #mm.
You could try using the 'input' event instead of the 'keyup' event. This event triggers when the input's value is changing. It is more semantic for this purpose and avoids any problems with keyboard events firing at the wrong time.
$('#hh').on('input', function (e) {
var hh = $('#hh').val().toString();
if (hh.length >= 2) {
$('#mm').focus();
}
});
$('#mm').on('input', function (e) {
var mm = $('#mm').val().toString();
if (mm.length >= 2) {
$('#ss').focus();
}
});
I haven't checked which browsers support this yet. It's working on Chrome for me.
It's pretty straight forward. The event is triggering twice, if you type fast, because you set "value" to a 2 digit number. Test this by doing this: Type '23', while holding both keys. Then release the 2, it will jump to the second input, then release the 3 and it will jump to the last.
So once you typed two digits in the first input and release one key, the event will be triggered once, and on the second keyup, the next event keyup will be triggered instantly, because the value of the second input is already 2 digits long.
If you replace this with a placeholder, then it works. Check this out:
<input type="text" id="ss" class="chained" placeholder="30">
http://jsfiddle.net/ch3ksuwa/4/
Edit: The first solution I posted fixes this problem in a way, that the second time someone wants to change a value, the same error will occur.
So I have added a variable called "comesFromFirst" which is initially false and will be true, once the keyup event triggers the .focus on the second input. Then, the first time a keyup event is triggered in the second input, it will set the value to false. Now you can also use "value", instead of a placeholder(placeholder is in most cases nicer, tho). Check it out here:
http://jsfiddle.net/ch3ksuwa/5/
Relevant jQuery:
var comesFromFirst = false;
$('#hh').on('keyup', function (e) {
var hh = $('#hh').val().toString();
comesFromFirst = true;
if (hh.length >= 2) {
$('#mm').focus();
}
});
$('#mm').on('keyup', function (e) {
var mm = $('#mm').val().toString();
console.log(comesFromFirst);
if (mm.length >= 2 && comesFromFirst == false) {
$('#ss').focus();
}
else{
comesFromFirst = false;
}
});

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

Detect Textbox Field Change jQuery

I have a text box that accepts integers, and I need it to run a function that will use the text box's input, as soon as a user inputs numbers into the field.
The problem here is that keyUp() will detect each and every input. So if I type 23, it will fire once for 2 and once for 3. I only need it to run when the input is complete.
Is there a way to do this, without losing focus and without using a timer that will keep checking the text box input every while using setInterval?
Look like you want to be notified when the user stops typing. The following code can be used as a starting point, it calls bufferedKeyUp 300 ms after the user stops typing. http://jsfiddle.net/mendesjuan/VTMEe/
$(function() {
// Creates a handler that will wait until the event hasn't fired for a period
// before it fires the actual event handler
function createBuffered(fun, delay) {
var timer;
return function() {
clearTimeout(timer);
var args = arguments;
var me = this;
timer = setTimeout(function() {
fun.apply(me, args);
}, delay);
}
}
$('#in').keyup( createBuffered(function(){
console.log('change');
}, 300));
});​
Ext-JS has a nice simple way to do this http://jsfiddle.net/mendesjuan/DYkmU/1/
Ext.get('myid').on('keyup', function() {
console.log('change');
}, null, {buffer: 300});
Why not test the textbox contents after they're changed, after all that's when input is complete isn't it?
If the result is not okay, you can always clear and focus the textbox so the user has to enter valid data.
Something like:
$("textbox").change( function () {
if (someTestForGoodData) {
handleTheGoodData();
} else {
$(this).focus();
alert($(this) + " has bad data!");
}
})
$('input').on('input propertychange', function() {
$('#output').html($(this).val().length + ' characters');
});
From this answer.

Differentiate between focus event triggered by keyboard/mouse

I'm using jquery ui autocomplete and want to decipher between focus events triggered by keyboard interaction and mouse interaction. How would I go about this?
$('input').autocomplete({
source: function(request, response) {
...
},
focus: function(event, ui) {
// If focus triggered by keyboard interaction
alert('do something');
// If focus event triggered by mouse interaction
alert('do something else');
}
});
Thanks
The only way I can think of doing this is to have a handler listen in on the keypress and click events, and toggle a boolean flag on/off. Then on the focus handler of your input, you can just check what the value of your flag is, and go from there.
Probably something like
var isClick;
$(document).bind('click', function() { isClick = true; })
.bind('keypress', function() { isClick = false; })
;
var focusHandler = function () {
if (isClick) {
// clicky!
} else {
// tabby!
}
}
$('input').focus(function() {
// we set a small timeout to let the click / keypress event to trigger
// and update our boolean
setTimeout(focusHandler,100);
});
Whipped up a small working prototype on jsFiddle (don't you just love this site?). Check it out if you want.
Of course, this is all running off a focus event on an <input>, but the focus handler on the autocomplete works in the same way.
The setTimeout will introduce a bit of lag, but at 100ms, it might be negligible, based on your needs.
You should actually be able to determine this from the event-Object that is passed into the focus-event. Depending on your code structure this might be different, but there is usually a property called originalEvent in there, which might be nested to some depth. Examine the event-object more closely to determine the correct syntax. Then test on mousenter or keydown via regular expression. Something like this:
focus: function(event, ui){
if(/^key/.test(event.originalEvent.originalEvent.type)){
//code for keydown
}else{
//code for mouseenter and any other event
}
}
The easiest and most elegant way I've found of achieving this is to use the "What Input?" library. It's tiny (~2K minified), and gives you access to the event type both in scripts:
if (whatInput.ask() === 'mouse') {
// do something
}
...and also (via a single data attribute that it adds to the document body) styles:
[data-whatinput="mouse"] :focus,
[data-whatinput="touch"] :focus {
// focus styles for mouse and touch only
}
I particularly like the fact that where you just want a different visual behaviour for mouse / keyboard it makes it possible to do that in the stylesheet (where it really belongs) rather than via some hacky bit of event-checking Javascript (though of course if you do need to do something that's not just purely visual, the former approach lets you handle it in Javascript instead).
The first thing that comes to mind is that you can find the position of the mouse and check to see if its within the position of the element
Use this to store the position of the element:
var input = $('#your_autocompleted_element_id'),
offset = input.offset(),
input_x = offset.top,
input_y = offset.left,
input_w = input.outerWidth(),
input_h = input.outerHeight();
Then use this to find absolute position of the mouse within the window:
var cur_mx, cur_my;
$(document).mousemove(function(e){
cur_mx = e.pageX;
cur_my = e.pageY;
});
Then in your autcomplete setup:
focus: function(event, ui) {
// mouse is doing the focus when...
// mouse x is greater than input x and less than input x + input width
// and y is greater than input y and less than input y + input height
if (cur_mx >= input_x && cur_mx <= input_x + input_w && cur_my >= input_y && cur_my <= input_y + input_h) {
// do your silly mouse focus witchcraft here
} else {
// keyboard time!
}
}
This can be handled using mousedown event, see my example below.
this.focusFrom = 'keyboard' =>
onFocus = () => {
if (this.focusFrom === 'keyboard') {
// do something when focus from keyboard
}
}
handleMouseDown = () => {
this.focusFrom = 'mouse';
}
handleOnClick = () => {
this.focusFrom = 'keyboard';
}

Categories

Resources