I was given an unusual request recently that I'm having the most difficult time addressing that involves capturing all display-characters when typed into a text box. The set up is as follows:
I have a text box that has a maxlength of 10 characters. When the user attempts to type more than 10 characters, I need to notify the user that they're typing beyond the character count limit.
The simplest solution would be to specify a maxlength of 11, test the length on every keyup, and truncate back down to 10 characters but this solution seems a bit kludgy. What I'd prefer to do is capture the character before keyup and, depending on whether or not it is a display-character, present the notification to the user and prevent the default action.
A white-list would be challenging since we handle a lot of international data.
I've played around with every combination of keydown, keypress, and keyup, reading event.keyCode, event.charCode, and event.which, but I can't find a single combination that works across all browsers. The best I could manage is the following that works properly in >=IE6, Chrome5, FF3.6, but fails in Opera:
NOTE: The following code utilizes jQuery.
$(function(){
$('#textbox').keypress(function(e){
var $this = $(this);
var key = ('undefined'==typeof e.which?e.keyCode:e.which);
if ($this.val().length==($this.attr('maxlength')||10)) {
switch(key){
case 13: //return
case 9: //tab
case 27: //escape
case 8: //backspace
case 0: //other non-alphanumeric
break;
default:
alert('no - '+e.charCode+' - '+e.which+' - '+e.keyCode);
return false;
};
}
});
});
I'll grant that what I'm doing is likely over-engineering the solution but now that I'm invested in it, I'd like to know of a solution.
The simplest solution would be to specify a maxlength of 11, test the length on every keyup, and truncate back down to 10 characters but this solution seems a bit kludgy.
It is also easily defeated by cut/paste, drag/drop, right-click-undo/redo, etc. There's no reliable way to get every potential bit of input short of polling.
Why not set maxlength to 10, to let the browser enforce the limit properly, and just show a warning if there is another attempted keypress? You don't need to prevent any default action because the browser is already taking care of the length, so the amount of key checking you have to do is lower.
<input id="x" maxlength="10"/>
<div id="x-warning" style="display: none;">can't type any more!</div>
<script type="text/javascript">
function LengthMonitor(element, warning) {
element.onkeypress= function(event) {
if (event===undefined) event= window.event;
var code= 'charCode' in event? event.charCode : 'which' in event? event.which : event.keyCode;
var full= element.value.length===element.maxLength;
var typed= !(code<32 || event.ctrlKey || event.altKey || event.metaKey);
warning.style.display= (full & typed)? 'block' : 'none';
};
element.onblur= function() {
warning.style.display= 'none';
};
}
LengthMonitor(document.getElementById('x'), document.getElementById('x-warning'));
</script>
Since you're using JQuery already, .validate() is terrific for forms. Just set a rule of maxlength for your field, and you're good to go. E.g.
$("form[name='myform']").validate({
rules: {
myfield: {required:true, maxlength:10}
}
});
I had a vaguely similar situation come up in a web-app I am working on where I needed to give feedback to the user, live, as they entered data into an input.
Honestly, the best solution I came up with was just to use a setTimeout to poll the input box periodically. I did a few tests to find a nice balance between responsiveness and efficiency (I think ~400ms).
It works great, and is much better than trying to kludge together event handlers for every scenario (key-down, on-change, etc etc).
It's not as elegant as I would like, but it works.
If you really want to do this, I would watch the input in real time, checking it's length. If it's over the limit, chop it and alert the user.
This would not be a replacement for other validation of course.
I would also consider that this may be unnecessary. I suppose it's nice, but most websites get by with a hard limit and validation-on-submission.
How about presenting a message to the user when they go over the limit, but not truncating their input? You can prevent submission using the onsubmit event and the user will never have the poor experience of a maxlength or a transient input. You can highlight the box in red or display an icon as well to really drive the point home.
However, this is all client-side, so if you really need to validate the input, that must be built into the submission target's server-side logic (in the case of a form).
Alternatively, if this is happening in real-time, link the logic to a variable that is set by the key-up event. If the length limit is exceeded, present an error message, do not truncate, and do not update the private variable.
Related
I'm creating an input field where some data should be fetched (by AJAX) and displayed every time the user enters data into that field. However, if the user types several characters, say he types "test" to get all records who contain the string "test", it would not be necessary to do 4 queries after every character pressed, but one query after he stopped typing. I can think of several solutions with a global variable where I check if the same event has been fired again, but is there a really elegant way to do this? Maybe check if there is something in the keyboard buffer and only proceed if it is empty? Or is there an event that is only fired once the keyboard buffer is empty and all characters are in the input field?
The elegant way is to use a timeout, and to keep clearing the previous timeout with each key press
var tID;
function keyUp (e) {
if (tID) clearTimeout(tID);
tID = setTimeout(function() {
... // make web call
}, 2000);
}
This will ensure that the web call is only called after the last key is pressed (you may want to adjust the timeout value)
There are ways to achieve this that I can think of:
Use timeout, from the last keyup event. This is not always the best and not that precise with users that have low typing speed.
Use space character do regconize if the user has finished typing a word. Based on changes in length and total word count, you can decide if you would want to send AJAX or not.
Depends on the type of input you are working with, you may choose the most suitable method for you. The first one is somewhat quite rigid. The second method requires user to press space every time he finishs typing. A little bit of both could be a sweet spot perhaps. In modern day, I don't think sending request every keyup will cause huge performance effect though.
I have gone through answers and came across two ways which can help in distinguishing between scanner and keyboard inputs. It can be done through:
Time Based: Scanner inputs are faster than manual keyboard inputs.
Prefix Based: Append a prefix to barcodes or scanners (inbuilt in scanner devices) and use it to identify the scanner inputs.
Here are the links: link 1, link 2 which I have used for the references.
The problem which I have run into is that whenever the user manually types some keyboard keys while the scanning event is being fired it gets added to scanner input and leads to inconsistent results.
Here is the code which I am using:
var BarcodeScannerEvents = function(){
this.initialize.apply(this, arguments);
};
BarcodeScannerEvents.prototype = {
initialize: function() {
$(document).on({
keypress: $.proxy(this._keypress, this)
});
},
_timeoutHandler: 0,
_inputString: '',
_keypress: function (e){
if(this._timeoutHandler){
clearTimeout(this._timeoutHandler);
}
this._inputString += String.fromCharCode(e.which);
//CHECKS FOR VALID CHARACTERS WHILE SCANNING
this._timeoutHandler = setTimeout($.proxy(function(){
if(this._inputString.length <= 10){
this._inputString = '';
return;
}
$(document).trigger('barcodescanned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
new BarcodeScannerEvents();
The format for my barcode is: ~xxx-xxx-xxxxxx where x can be any number between 0-9. If a character which is a number is appended to the barcode it leads to wrong inserts in the database.
I have tried comparing the events from keyboard inputs and scanner inputs but to no avail. I have given a thought of appending extra characters before each digit and then invalidate the scanned barcode if consecutive numbers appear. But I don't feel this is best way to approach this problem. Can someone help me out here?
It is not necessary to judge from keyboard/barcode scanner.
If you decide the Enter(Carriage Return) key notification as input completion on any device, you can use it as simplest trigger to execute Price Look Up/input value verification.
Most scanners can add suffix code to the scanned barcode data for notification.
The most commonly used is the Enter key, but the Tab key may also be used.
By sending the suffix code by the barcode scanner, the possibility that the scanner notification and the key input are mixed is much lower than the timeout detection.
You can do as follows.
Using the setting barcode, it is set to inform that keys such as Enter, Tab etc. which are not normally included in the barcode as a suffix.
Bind an event listener for the corresponding suffix key to the text input field.
The key code is judged in the event listener, and if it is the suffix key, it assumes that the input of the barcode data is complete, carries out processing such as Price Look Up/input value verification, and moves the input focus to the next field.
For example see this article.
execute function on enter key
In Addition:
Your worries seem to be overwhelmed by situations that do not occur often.
If it really happens to be a problem, you should give up dealing with JavaScript.
Please acquire scanner data with another program by the following method. Please notify it to the application in some way.
If you want to continue keyboard input emulation, it is better to capture data before the browser or application is notified.
SetWindowsHookExW function / LowLevelKeyboardProc callback function
EasyHook / Indieteur/GlobalHooks
hook into linux key event handling / uinput-mapper
The Linux keyboard driver / LKL Linux KeyLogger / kristian/system-hook
system wide keyboard hook on X under linux / Error when trying to build a Global Keyboard Hook in Ubuntu Linux / 10.5.2 Keyboard and Pointer Events
Alternatively, set the scanner to serial port mode and have a dedicated program to receive it.
Serial API
JavaScript/JQuery communicate with SerialPort/COM1
Questions tagged opos / Questions tagged pos-for-.net / Questions tagged javapos
My first answer would be to train the users not to touch the keyboard while scanning. However, the tone of your responses to answers and comments makes it sound like you're thinking more of malicious, intentional attempts to corrupt the data.
Beyond kunif's very thorough answer, you're not going to find a solution to the problem you're envisioning or running into. The reason is that JavaScript is only going to receive from the operating system's input buffer; JS will not (cannot! for OS security reasons) distinguish how the input buffer is filled. If keystrokes and scan data are simultaneously being put into the buffer, that is an issue to try to address at the OS or hardware level. JavaScript is just not equipped to deal with it.
I've been looking at the jQuery Validation Plugin and it seems like overkill (my site's script requirements are ballooning), and also not quite what I want.
Let me define some terminology: an <input type="text"> field's status is VALID if it matches both RegEx 1 and RegEx 2, PARTIAL if it matches RegEx 1 but not RegEx 2, and INVALID if it doesn't match RegEx 1.
For example, RegEx 1 could be /^[A-Z_]*$/ and RegEx 2 could be /^[A-Z]+(_[A-Z]+)*$/.
The requirements are:
any key press which would lead to an INVALID status is ignored, without interfering with focus or the caret position, and without the value ever being seen to change,
otherwise the status is updated after every key press to be either VALID or PARTIAL, and
whenever an input's status changes, a callback is invoked.
Seems pretty straightforward. This is basically the QStringValidator model.
I have jQuery core but I'm new to it. How can I implement this? Thanks.
P.S. if the best solution lies outside of jQuery, IE support is not required.
if (this.value.match(this.getAttribute('data-regex1')) {
if (this.value.match(this.getAttribute('data-regex2')) {
do_whatever_for_full();
} else {
do_whatever_for_partial();
}
} else {
do_whatever_for_invalid();
}
Put your regexes into the element as custom attributes (data-regex1, data-regex2) then check the data as it changes (not sure how many events you want to check but you probably have to check with onkeydown ignoring enter and tab, or you could create a timer onfocus and just check every half second or so).
I have an input like this
<input id="guestCard" name="guestCard" onkeypress="transform(event)" type="text" value="" />
and I want to transform the key pressed on a keyboard regardless of which language settings to english character. E.g. when I press on czech keyboard + (with keycode 43) , I want to get 1 (with keycode 49).
Is there some standard way to do this? How would the function transform look like?
Alternatively I want the same functionality but using ajax (on asp.net mvc). Any ideas there?
Thanks in advance.
As far as I am aware, JavaScript is not locale aware - so you would need to somehow detect or have the user pick the appropriate transform mapping (in this case, perhaps a radio button for czech as the source and U.S. ASCII as the destination). Once that is taken care of, your function could be something like:
function transform(event) {
var code = (event.charCode) ? event.charCode : event.keyCode; // cross-browser happy
switch (code) {
case 43 : return "1";
}
}
There is a great test page to see how keyCode/charCode properties and the onKeyDown/Press/Up events behave in different browsers. http://asquare.net/javascript/tests/KeyCode.html
I doubt there is one but to create it, create an associative array, add some JS to a text field which saves the two values in the array and then press every key on the keyboard. After that, you can dump the array somewhere and use this as a constant in your code.
But be warned: Almost all users will have problems when they don't get the character on the screen which they've typed on the keyboard.
Trimack -
I think you are using the wrong event. You need onkeydown, and use the keyCode property of event.
I have a textbox that must have a MIN number of characters as well as a MAX number of characters. What is the best way, using jQuery, to make sure that the input is within the range (while displaying status messages to the user) before allowing the user to submit the form?
Update: the code below works to some degree, however I am getting issues when deleting text. Since it is using 'keypress' to capture events in the textbox, the 'length' variable gets falsely incremented when hitting backspace for example. It seems like the issue is that the length of the text is retrieved before the fact i.e. a keypress will always result in a length of what was there before plus 1. What is the proper way around this?
Update: I think i solved the previous issue by using the keyup function instead of keypress
If this is the only client side validation in your app (always validate on the server too!) then it'd look something like this:
$("#your_textbox").keypress(function() {
var length = this.value.length;
if(length >= MIN && length <= MAX) {
$("#your_submit").removeAttr("disabled");
$("#your_validation_div").hide();
} else {
$("#your_submit").attr("disabled", "disabled");
$("#your_validation_div").show();
}
});
If you need a lot of validation in your application you might want to consider the validation plugin.
Setting the maxlength attribute:
<input type='text' maxlength="30" />