I'm trying to get the exact input change (what character and where) which comes from key press to an input field in HTML5 but I can't figure out how to do it "nicely".
My findings so far:
Event oninput(event) is too high-level, it basically says: "something" has changes. I don't know where and what exactly. Comparison of the original and current values sounds heavy for a big string.
Event onkeypress(event) is too low-level it does not care about where event.which goes into the input field.
Is there a way to get both what character user typed and where exactly?
It is a broad question, but I'll try to answer anyways. You can listen to onkeydown event and know what key has been pressed.
window.onkeydown = function(event) {
alert(String.fromCharCode(event.keyCode) + " was pressed");
}
};
After that you can get the position of where the key has been pressed.
var cursorPosition = $('#myTextarea').prop("selectionStart");
What you want to do with this basic information is up to you! You can build a little more intelligent code on top of this. Good luck!
Related
I know there are similar questions, but I could not find the answer, and I am trying to create an uncommon shortcut in order to execute action according to a specific combination of keys. I don't have an example, since I have not implemented it, I am trying to figure out if I can do it or not. I have a combination of Ctrl, shift, alt, meta keys, I can capture in javascript, my problem, is that I want to use a common key like "g" and make it behave like Ctrl, shift, alt, meta, etc, in order to combine with a key F1, F2, F3 to execute a javascript function with an specific visual component on screen. An Example, I intend to create a shortcut "Ctrl+1+F1" to perform an action in a specific table in a web page showing with more than one table on the html. Can Anyone answer me if this can be done? if someone can, How can I do it?
A broad overview of the algorithm would be as follows:
Keep a Set-type variable that will contain all currently pressed keys. Whenever you get a keydown/keyup event, update that set by adding/removing whatever key was pressed/released. Attach the event handlers as high as you can - for example, on the <body> tag, so that you can catch everything that happens in your page.
Then at the end of the keydown event you should check if the variable contains EXACTLY the keys that your keyboard shortcut requires. If they do, launch the action. In practice you'll probably have a long list of possible keyboard shortcuts. Check them all. Maybe you'll also need extra checks, like some shortcuts could only be active when a certain control is focused or when something is in the right state or whatever.
As a variation, you might want to launch the action not when the keys are pressed, but when they are released. In that case, don't launch the action immediately, but make some sort of note in another variable, that such-and-such combination was pressed. Then wait until all the keys are released (the set is empty), and THEN launch the action. If some other keys got pressed inbetween, clear that note and check if perhaps another combination should be activated instead. Store that in the note-variable and keep waiting.
Unfortunately, the Control keys and the Function keys seem to be mutually exclusive. You can set up key combos with any number of keys, as in the following example, but combining Control and Function doesn't work (on my system anyway).
const result = document.querySelector('#result')
const keys = {}
window.addEventListener('keydown', (ev) => {
keys[ev.key] = true
})
window.addEventListener('keyup', (ev) => {
if (keys['1'] && keys['Control'] && keys['F1']) {
console.log('This does not work on my system')
} else if (keys['1'] && keys['F1']) {
result.value = "F1 + 1 pressed!"
} else if (keys['Control'] && keys['o'] && keys['p']) {
result.value = "Control + o + p pressed!"
} else {
setTimeout(() => result.value = "", 500)
}
keys[ev.key] = false
})
<p>Click in the result pane and then press F1+1, or Control+o+p. Control+F1+1 does not work.</p>
<input id="result">
Thanks to everyone, compiling the answers given, i was able to solve the problem. i had to give the focus to the table (courtesy of kosh, who gave the straight answer i needed), and on the post(event) of the web page, i was capable to catch the active component. I can not post the solution i built, because the code belongs to the company, but i will try to build an example, and post on monday, in case someone else reaches this post after the same doubt (easter in brazil, and tomorrow i am travelling home, thats why the example i will show only on monday). Thanks to everyone again.
Background:
I am writing a script that does some stuff when a user clears an input type="search" (essentially the same as type=text) using backspace or delete. I want to address the case where user highlights original text and starts typing new text, and also pasting.
Because of this I cannot use keydown (fires before input value is changed). Cannot use keypress (need to fire when backspace/delete is pressed, and it fires too early as well). Using keyup is bad because I can't clear when value === 1 (might already be several characters in the field). I can build in some slop but then it won't clear right away which looks buggy.
Question:
So the DOM input event fires right when the value is updated, which is exactly what I want (tested using jQuery on 'input'). However, I cannot find the captured key (which I need to differentiate between deleting and entering content). I couldn't find great info on the spec. It seems like this is going to be implemented in the data section of the event, which does not yet have any browser support. Does that mean it is currently impossible to get the key from the oninput event? If so, how do most developers handle this? I imagine wanting the key immediately after it is entered is very common, surely there is a decent solution for this?
Current implementation for the curious:
For the time being I am grabbing the value right after keydown by using a setTimeout of 0. This gets me both the key and the updated value, but feels dirty and requires extra handlers for onpaste and such. While writing this it occurs to me I could probably use oninput by keeping track of the last value and comparing to current to differentiate between entering and deleting, but that doesn't seem all that much better, and would still require a separate paste handler since I want my event to fire every time a user pastes, and it doesn't seem to have any flags that would let me know the event was a paste.
I decided the last suggestion of dandavis was the best workaround. I used keydown to grab key info and triggered the action on paste, empty field, or 1 character and last character was not backspace/delete (on input does not fire on enter, modifier keys, etc. so those don't need to be accounted for).
The code looks like this:
var onClear = function(action){
var lastKey;
jQueryObject.keydown(function(e){
lastKey = e.which;
});
jQueryObject.on('input', function(){
if( !this.value.length || (this.value.length === 1 && lastKey !== 46 && lastKey !== 8) ){
action();
}
});
jQueryObject.on('paste', function(){
action();
});
}
I am trying to edit some existing JavaScript validation code.
Using the onkeydown event, the code checks that the value in a textbox does not go past a maximum length. I cannot use <input maxlength="value" /> as there may be some formatting characters in the string that I can safely exclude from the maximum length.
The code works fine apart from when the user has pressed the insert key to turn overtype on and they have reached the maximum length. When this occurs if they place the cursor before a character and try to overwrite it the validation thinks that this will go over the limit and doesn't realise that a character will actually be replaced.
This answer states that I cannot detect if overtype is on, but doesn't provide any references. So assuming that I cannot detect overtype, is there anyway in the onkeydown event to detect if a character is going to be replaced.
I am happy with an IE only solution.
Update: onblur is not appropriate as this will let them go many characters over the limit before warning them of the maximum length. I would like to prevent them from going over the limit.
Your handler should look at the entire value and check the length. If the length is legal, return. If not, you can update the value with a substring. You may have to use caret position to determine exactly how to manipulate the string which can be tricky as it's slightly different in IE and other browsers.
This is different from what you have now which is probably preventing keypress when max length is reached. Don't prevent keypress, just trim the resulting string.
I don't think your problem is with the onblur validation, but an event you calling on key press by the sounds of it (eg preventing the user to key any more once they reach the limit) or I have misunderstood.
IF your validation is indeed onblur, you shouldn't have to worry about things like insert/overwrite being enabled, you are only interested in what the value of the input element is once the user has completed their input.
IF you are trying to stop the user if they reach this limit as they type, I would write a function to compute the actual length you are testing. For eg,
function validateMyInput() {
var myInputField = document.getElementById('myInput');
var removeAllExcludedCharsResult = myInputField.value.replace('&','');//exclude &
var totalLength = removeAllExcludedCharsResult.length;
if(totalLength < 500) { //limit of this test is 500
return true;
}
else {
return false;
}
}
Obviously change this function to what you need and maybe make it more generic by passing in the element of the input, max length and array of excluded chars to make it reusable.
UPDATE
I have tested this problem is Chrome and the insert key seems to be ignored. IE on the other hand does overkey. However, it seems page specific, for eg, if i have enabled insert on Page A, it doesn't seem to affect Page B. I found this page which seems to be able to grab the keycode event even when insert has been pressed. It might be due to the following code?
if(window.event) {
event = window.event; //where event is the javascript key event.
}
Either way, the link above seems to have accounted for the problem, hopefully it will have the answer if the above is not correct.
Hope I haven't misunderstood what the problem was and this helped.
I am building a browser interface to a terminal. I need to catch both character (alphanumeric, dot, slash,...) and non-character key presses (arrows, F1-F12,...). Also, if the user holds some key down, it would be nice to get repeated keypresses (the function should be called repeatedly until key is released). The same goes for space key, characters,...
I want this to be as cross-browser as possible (jQuery keypress fails on that account). I have also tried using fork of jquery.hotkeys.js, but if I understand correctly, I can't catch both special and character keys in a single function (one should use keydown for former and keydown for the latter).
Is there a JS library that would allow me to catch both character and special keys?
I hope I'm not missing something obvious. :)
UPDATE To clarify: I am looking for the library that would hide the browser implementation details from me.
The onkeydown it exactly what you need. It captures all keys, even if you are holding a button it is fired repeatedly.
<input type='text' onkeydown='return myFunc(this,event)'>
<script>
function myFunc(Sender,e){
var key = e.which ? e.which : e.keyCode;
if(key == someKey){ // cancel event and do something
ev.returnValue = false;
if(e.preventDefault) e.preventDefault();
return false;
}
}
</script>
UPDATE try and test this with jQuery
$(document).ready(function(){
$('#in').keydown(fn);
});
var cnt = 0;
function fn(e){
var key = e.keyCode ? e.keyCode : e.which;
cnt++;
if(cnt == 10) {
alert('event was fired 10 times. Last time with key: '+key);
cnt = 0;
}
}
The DOM 3 Events spec includes key events, but it's still a working draft so likely not that widely supported yet but should be pretty helpful.
For turning key codes into characters, you might find Quriskmode helpful. Knowing which key was pressed and which modifiers should get you where you want to be. Note that you may have issues mapping all keyboards to the same character sets because some have keys that others don't (e.g. Microsoft "windows" key and Apple command key). A bit of trial and error might be required.
Oh, and you might find the article JavaScript Madness: Keyboard Events interesting.
I ended up using keycode.js, but am building a whole event-managing system around keydown, keypress and keyup events, because just one of the events (keydown) is not enough to determine which character was entered and which key was pressed if there is no corresponding character. Browser incompatibilities are an added bonus to this challenge. :)
Thank you both for your answers, it has helped me understand the problem fully.
I found this question. However, most of the answers intercept the key press, check the key code, and stop the event if it isn't an acceptable key code.
There are a some problems with that.
A common bug among all the answers is that shift key combinations are not prevented so users can enter stuff like "#" or "&".
Users can still paste in bad values from the clipboard.
When you start messing around with the key press event, the webpage starts doing weird, unexpected things. For example if the field has focus and the user tries to reload the page by pressing command-R it won't work. Or they can't tab out of the field.
I would like a solution that allows the keypress, then checks the entered value against a regex and removes unwanted characters.
I'm looking for a solution along these lines:
Doesn't intercept the keypress event.
Ideally uses a regex after the keypress.
OK if it uses jQuery.
Doesn't require installing a plug-in.
I tried this function:
$('input.numerals_only').keypress(function() {
var v = $(this).val();
var no_nonnumerals = v.replace( /[^0-9]/, '' );
$(this).val(no_nonnumerals);
});
But that doesn't work. I'm still able to type in letters.
Any info on why it doesn't work? How could I modify it so it works? Other suggestions?
If you use keyup and also blur you should handle most cases. Someone keys in text and also if they paste in a value into the text box. As the blur function will remove the bad values as well.
$('input.numerals_only').keyup(AllowOnlyNumber).blur(AllowOnlyNumber);
function AllowOnlyNumber()
{
var v = $(this).val();
var no_nonnumerals = v.replace(/[^0-9]/g, '');
$(this).val(no_nonnumerals);
}
Of course if html5 is an option you could always do:
<input type="number"/>
jsfiddle example.
The thing your regexp is missing, which is why it didn’t work for keypresses neither, is the g flag for a global regexp check.
Use var no_nonnumerals = v.replace( /[^0-9]/g, '' );
If you use keyup instead of keypress it will always remove the incorrect characters.
You can also use this to actually block the events:
$('input.numerals_only').keypress(function(event) {
if(event.keyCode < 48 || event.keyCode > 57){
return false;
}
});
Use the keyup event. It is triggered after the key is processed by the browser:
$('#txtInput')
.keyup(function(ev) {
var newValue = this.value.replace(/[^0-9]/, '');
$(this).val(newValue);
});
I wrote a jQuery plugin to do this. Demo and code here http://brianjaeger.com/process.php
It uses a regular expression to validate whatever you want.
There are a few issues:
it's a plugin (however, you could suck out the code and plunk it into your other JavaScript if you want. -its easier just to use as plugin)
Unfortunately there is no way to limit pasted information directly (across all browsers) - My solution to this was to add validation on focus change as well as keypress.