I'm capturing input from a barcode scanner (which acts like keyboard input) and it works great, but I don't have access to a barcode scanner at the moment and need to test my code, so I need to simulate the barcode scanner (keyboard) input.
I thought triggering keypress events for each character would work, but it doesn't. Here's my test code:
var barcodeScannerTimer;
var barcodeString = '';
// capture barcode scanner input
$('body').on('keypress', function (e) {
barcodeString = barcodeString + String.fromCharCode(e.charCode);
clearTimeout(barcodeScannerTimer);
barcodeScannerTimer = setTimeout(function () {
processBarcode();
}, 300);
});
function processBarcode() {
console.log('inside processBarcode with barcodeString "' + barcodeString + '"');
if (!isNaN(barcodeString) && barcodeString != '') { // #todo this check is lame. improve.
alert('ready to process barcode: ' + barcodeString);
} else {
alert('barcode is invalid: ' + barcodeString);
}
barcodeString = ''; // reset
}
window.simulateBarcodeScan = function() {
// simulate a barcode being scanned
var barcode = '9781623411435';
for (var i = 0; i < barcode.length; i++) {
var e = jQuery.Event("keypress");
e.which = barcode[i].charCodeAt(0);
$("body").focus().trigger(e);
}
}
JSFIDDLE
If you type in a number quickly (like 1234), you'll see the input is captured fine. However, click the button to run my test code, and the input is not captured. The event is triggered because an alert box pops up, but barcodeString is empty!
Why isn't this working? Should I be triggering some event other than keypress?
The handler is reading the charCode but you are only setting which on the event. Set charCode, or read from which. https://jsfiddle.net/mendesjuan/bzfeuezv/1/
barcodeString = barcodeString + String.fromCharCode(e.which);
Firing Synthetic events
This is a reminder that firing synthetic events is tricky business and typically requires you to have intimate knowledge of the handlers (which is bad) so that you don't have to construct a full event object. Also, beware that not all events triggered by jQuery will actually trigger the native events and cause its default action to apply.
Simply put, triggering keypress does not actually type a character into a text field or fires event handlers not set with jQuery.
document.querySelector('input').addEventListener('keypress', function() {
console.log('standard input key press handler');
});
var e = jQuery.Event("keypress");
e.which = "a".charCodeAt(0);
$('input').keypress(function(){
console.log('jQuery input key press handler');
}).trigger('keypress', e);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input value="yo" />
Related
I need to archieve 2 objectives but I archive one at time, never both of them.
First I have an input field that should fires an event when a key is pressed and I need to catch the field value. I use letters, number and the TAB key. So if I use keyup it fires at the first char. If I use keydown it takes 2 char to fire because when it fires the first time the char is not pressed yet. So when I press for the second time it fires with the first letter and so on.
Said that, it is clear that what I need is the keyup event that put the value in the field then the event is fired. But TAB has a special meaning in my case and it is not the default behavior and with TAB key I am unable to catch e.which, e.charCode nor e.keyCode! Only with keydown I am able to get those value!
Now I don´t have a clue what to do. How could I catch TAB key or make keydown catch the value of a field?
P.S keypress also working as keydown. Event is fired before I have the value in the field
EDIT 1:
Here is the code:
$('input[data-action="keyupNome"]').each(function () {
$(this).on("keypress", function(e) {
//Se o campo não estiver vazio
if($(this).val() != '') {
if(key != 9) // the tab key code
{
limpaCamposBusca('nome');
var width = $('#nomeBusca').width();
$('.nomeContainer').css('width', width);
$('.displayNomeTbl').css('width', width);
buscaEndereco('Controller/Dispatcher.php?classe=Buscas&acao=buscaEnderecoPorNome', 'nome');
}//if key == 9
else {
alert('here');
e.preventDefault();
}
}// val == ''
else {
clearFields();
clearBuscaCliente();
reactivateFields();
}
});
});
The trick is to use keydown and to combine actual value of the field with the char currently pressed OR to catch TAB in keydown and set an external variable to be used in keyup as in my example.
EDIT :
In fact, I realized that not preventing default behavior of TAB in keydown doesn't fire keyup. So, no variable is needed, but only preventing TAB on keydown. Anyhow, this version always work if the glitch you talked about exist in some circumstances.
(function() {
var tabKeyPressed = false;
$("#t").keydown(function(e) {
tabKeyPressed = e.keyCode == 9;
if (tabKeyPressed) {
e.preventDefault();
return;
}
});
$("#t").keyup(function(e) {
if (tabKeyPressed) {
$(this).val("TAB"); // Do stuff for TAB
e.preventDefault();
return;
}
//Do other stuff when not TAB
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="t" value="">
I'm trying to fire a function whenever the value of an input field changes. The input field is in a lightbox so I have to delegate the event:
var validateDonation = function(elem) {
var msg,
value = elem.value;
if (value == '') { msg = 'Please enter an amount'; }
else if(parseInt(value, 10) < 1) { msg = 'Please enter an amount greater than 1'; }
else if(parseInt(value, 10) > 100) { msg = 'Please enter an amount less than 100'; }
else { msg = ''; }
if(msg != '') {
console.log(msg);
}
}
and
$('body').delegate('#donation_amount', 'change', function(event) {
validateDonation(this);
});
If I use keyup instead of change the console log works just fine. But not on change. Why?
https://msdn.microsoft.com/en-us/library/ms536912(v=vs.85).aspx
onchange: This event is fired when the contents are committed and not while the value is changing. For example, on a text box, this event is not fired while the user is typing, but rather when the user commits the change by leaving the text box that has focus. In addition, this event is executed before the code specified by onblur when the control is also losing the focus.
If you want the change to be instantly updated then you would want to use the oninput event
oninput: The DOM input event is fired synchronously when the value of an <input> or <textarea> element is changed. Additionally, it fires on contenteditable editors when its contents are changed.
For IE less than IE9 i believe you need to use the onpropertychange event as well as oninput to accommodate modern browsers.
Here is a fiddle to show you the event fires immediately
http://jsfiddle.net/SeanWessell/9jfkcapp/
Try this...
$('body').delegate('#donation_amount', 'input propertychange', function (event) {
validateDonation(this);
});
In the following code I have "input" event handler that changes the value of the input as the user types. I also have "change" event handler to keep track of any changes made to this field. For some reason "change" event doesn't fire in Chrome and IE when the user leaves the field. Why is that and how to make it work in all major browsers?
Also note that it's not acceptable to trigger "change" event manually every time "input" event fires.
EDIT: "change" event seems to fire in Chrome only if transform function does not change the resulting string in any way. So if I type lower case letters and focus out after every character, "change" fires only for indexes 0, 2, 4 ...
Link to fiddle: http://jsfiddle.net/3hqxx2pr/
function transform(s) {
var r = "";
for (var i = 0; i < s.length; i++) {
r += i & 1 ? s[i].toUpperCase() : s[i];
}
return r;
}
$(document).ready(function(){
$("#in").on("change", function() {
console.log("changed"); // works only in ff
});
$("#in").on("input propertychange", function() {
$("#in").val(transform($("#in").val()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<input id="in"/>
Trigger change yourself
$("#in").val(transform($("#in").val())).change();
or
$("#in").val(transform($("#in").val())).trigger("change");
Based on a edit and restriction you made:
$("#in").on("input propertychange", function() {
var inp = $(this);
var orgVal = inp.val();
var transVal = transform(orgVal);
if (orgVal !== transVal) {
inp.val(transVal).trigger("change");
}
});
I try to manually trigger key-up event in qunit test but it fails since manually trigger key-up event will not change the input value.
http://jsfiddle.net/Re9bj/4/
$('input').on('keyup', function (event) {
$('div').html($('input').val());
});
var e = $.Event('keyup', {
keycode: 68
});
$('input').trigger(e); //this trigger will not change the input value
This trigger will work but the problem is that input value never change.
You can't add a character with a simple trigger. Trigger will only fire events, but not the default behavior. You need to simulate it.
To do that, you can use this code :
if(event.isTrigger && event.keycode) this.value += String.fromCharCode(event.keycode);
It will check if the event is triggered and then print the value.
Final code :
$('input').on('keyup', function (event) {
if(event.isTrigger && event.keycode) this.value += String.fromCharCode(event.keycode);
$('div').html($('input').val());
});
var e = $.Event('keyup', {
keycode: 68
});
$('input').trigger(e);
Fiddle : http://jsfiddle.net/Re9bj/9/
I'm using jquery tagsInput plugin where I need to dynamically modify the query(deleting the query or entering the new query) without actually typing in the search box connected with tagsInput plugin.
My problem here is I want to trigger backspace event at first then enter event next. Here is the code.
function triggering_events() {
$(".tag").each(function() {
var e = jQuery.Event("keydown");
e.keyCode = 8;
e.which = 8;
$("#input-search_tag").trigger(e); //triggering backspace event
});
var input = $("#input-search_tag");
input.val("food");
input.trigger(e); //triggering enter event
}
But only the backspace event is triggering from the above code. How can I make that enter event work?
Could anyone point out the mistake I've done?
Thanks!
you can try use the methods removeTag and addTag for remove and add tag's:
function triggering_events() {
var
idInput = 'input-search',
input = $("#" + idInput);
$("#"+idInput+"_tagsinput .tag").each(function() {
var tag = $.trim($(this).find('span:eq(0)').text());
input.removeTag(tag);
});
input.addTag("food");
}
run
There is an issue here:
$("#input-search_tag").val("food").trigger(e); //triggering enter event
.val() returns you a string value of the jquery Element, it is not a chainable method. strings do not have a trigger method.
You could fix this by splitting it into two calls:
var input = $("#input-search_tag");
input.val("food");
input.trigger(e); // triggering enter event
Or using .end():
$("#input-search_tag").val("food").end().trigger(e); //triggering enter event
Edit: putting it all together, along with reusing one event instead of creating multiples:
function triggering_events() {
var e = jQuery.Event("keydown");
e.which = 8;
$(".tag").each(function() {
$("#input-search_tag").trigger(e); // triggering backspace event
});
e.which = 13;
$("#input-search_tag").val("food").end().trigger(e); // triggering enter event
}