Currently, I listen on the Enter key to start sending a message.
But for multi-byte characters, the Enter key is supposed to choose a certain character.
The problem is that I've no idea how to detect whether a user is in the middle of inputting a multi-byte character, and even if he's in that process, the message will be sent the first time he presses the Enter key.
So the user experience is really strange.
Does anyone have a solution to this?
If you don't get what I mean above, can try to chat here, and once you started a conversation, switching to multi-byte mode, then you'll know what I mean.
The link is here:
http://maishudi.com/OMegle.php
I'm assuming your reference to multibyte input is a reference to "Input Methods" (or "Input Method Editors" on Windows).
Unfortunately, there isn't any real solution at the moment -- DOM3 was going to add mechanisms for this but it seems to have dropped this due to the complexity.
Part of the complexity comes from the vastly different behaviour of individual input methods before you even consider the behaviour discrepancy between browsers. A good example is to just check what key events you receive for a set of behaviour with Japanese, Korean, and (traditional and simplified) Chinese. The browsers cannot avoid this as they are responding to events fired directly by the input editors.
The only things you can really rely on are keyDown events, and even then not so much in opera and Firefox -- Safari and IE both provide keyDown events during IME composition, with a charCode of 229, and a keyUp event with a charCode corresponding to the actual key that was pressed.
There is a textInput event, but that is only supported by Safari (and by proxy Chrome should support it as well), but it's not substantially better than standard events anyway :-/
Related
This is a more specific question of Is it possible to simulate key press events programmatically? Every answer is missing the following information in one way or another, reducing the question's value. I've tried three things on there already that didn't work in modern browsers, or were advised against by official sources.
Here is what I'm looking for:
At the time of answering, every example should work in modern versions of Firefox and Chrome.
No examples include deprecated objects, fields, properties, or functions.
Every answer should include a way of typing a printable character in a textfield and textarea. As mentioned in a comment below, this can't be done.
Every answer should include a way to type an alphanumeric character when an input does not have focus. e.g., "a", "b", "c", etc.
Every answer should include a way to type a non-printable character. e.g., page down, left arrow, the F1 key (if this isn't possible, it's okay to state so), Enter, etc.
Every answer should include a link to all the "codes" needed to simulate alphanumeric characters and non-printable characters, or even better, embed that info into the answer. I'm using the term "codes" loosely here: I mean whatever term is appropriate to to satisfy the 2nd point.
This solution fills all of the criteria:
This example works in modern versions of chrome and firefox (https://caniuse.com/dispatchevent) (https://caniuse.com/keyboardevent-key)
This example does not include anything deprecated
N/A
Alphanumeric characters are supported
This is possible with this solution
You can set key equal to one of these values https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values (I would embed this, however, there are a lot of codes)
Ctrl: Use the ctrlKey option (boolean)
Alt: Use the altKey option (boolean)
Shift: Use the shiftKey option (boolean)
Meta Key/Command Key: use the metaKey option (boolean)
function simulateKeypress(target, options) {
target.dispatchEvent(new KeyboardEvent('keydown', options));
}
document.addEventListener("keydown", event => {
console.log(event.key);
});
setTimeout(() => {
simulateKeypress(document, {
key: "F1"
});
}, 1000);
(As already stated on the linked original question, it is unclear what "simulate" means here. However:)
We maintain a package for simulating user events for testing at #testing-library/user-event.
This includes userEvent.type() API for conveniently simulating keyboard input to input elements as well as userEvent.keyboard() API for simulating keyboard events anywhere.
The library simulates the common browser behavior. It will dispatch the key events, change element values, move selection and focus - dependent on the pressed keys and possibly custom event handler that e.g. stop propagation.
The primary target audience for the library is testing with jest and jsdom, but other environments including testing in real browsers are also supported.
(For examples and further explanations see the linked docs. For missing features, bugs, etc.: Issues and PRs are always welcome at the linked Github repo :) )
Is there any way to detect the current keyboard layout using JavaScript? I found this,
but it only detects if the visitor is on the english layout. I need to know the exact layout as a string, e.g.de-ch, fr or en.
I know this question is old, but for those of you who have been stymied by the fact that some keys map to different characters in other locales, here is an approach you can use to deal with it.
Most likely, you have your keyboard event handler tied to a keyup or keydown event; the results of the event.which or event.keyCode property in this case is tied to which key the user pressed. For instance, the same key you use to type ';' in an EN layout is the key used to type 'ж' in an RU layout, and the event reports 186 as the code for both of them.
However, if you're more interested in the character that resulted from the key press, you should use the 'keypress' event instead. This event fires after keydown/up, and it reports the actual unicode codepoint of the character that was typed inside event.which or event.charCode, which in the example above is decimal 1078 or U+0436.
So, if you'd prefer not to guess at keyboard layouts and you don't need to differentiate between keyup/keydown, keypress may be a viable alternative for you. It's not perfect (most browsers don't consistently report keypress events on keys that don't print characters, like modifier keys, function keys and navigation keys), but it's better than guessing at keycodes when dealing with printable characters.
Keyboard layouts do not have standardized identifiers. They have names assigned to them by the layout creator. They may have a language association as one defined property.
The Keyboard layouts should not be confused with language or locale identifiers. In particular there is no single “English layout” but dozens of layouts that may be used for English.
I don’t think systems normally make their current layout settings readable via JavaScript.
So whatever problem you are trying solve by detecting the keyboard layout, a different approach is needed.
You can now use the Keyboard object returned by the Navigator interface.
This object provides access to functions that retrieve keyboard layout maps and toggle capturing of key presses from the physical keyboard.
See https://developer.mozilla.org/en-US/docs/Web/API/Keyboard
At this moment this feature is experimental and working only on some major browsers.
All what I know about this topic and already implemented a solution for it, is to detect non English layout keyboard, i.e Languages that uses any alphabet other than that used in English. The solution is depend on regular expression to match any word character \w, any digit character \d and a range of predefined English keyboard special characters, so any other characters, such as Arabic, Japanese, etc, will not match, all this uses keydown event and I am using this solution to restrict and notify usernames and passwords fields entry in login form. I packaged it in a function like the following:
function checkKeyboard(ob,e){
re = /\d|\w|[\.\$#\*\\\/\+\-\^\!\(\)\[\]\~\%\&\=\?\>\<\{\}\"\'\,\:\;\_]/g;
a = e.key.match(re);
if (a == null){
alert('Error 2:\nNon English keyboard layout is detected!\nSet the keyboard layout to English and try to fill out the field again.');
ob.val('');
return false;
}
return true;
}
Then call the function from the event as the following:
$("#textFieldId").keydown(function(e){
if (!checkKeyboard($(this),e)){
return false;
}
});
This is Working DEMO for unknown down voters!
Notice:
In the regex pattern, re you are able to add any missing special characters such as #,`,|, etc
You are looking for is how to detect their Locale. In the HTTP headers this is stored in the Accept-Language header, but thats not available to the browser through pure JS.
There's a jQuery plugin called 'Browser Language' that might get you going on the right path.
you can use event.code to determine the actual keyposition from any layout, try it http://keycode.info/
Quick background:
when a key is pressed in a browser, three events are generated: keyDown, keyPress and keyUp.
keyDown and keyUp have a keyCode property which is approximately the physical key pressed.
keyPress also has charCode property set which takes into account modifier keys and keyboard layout (A and a have same keyCode but a different charCode).
all three events have properties that indicate which modifier keys were pressed during those events.
I'm the main noVNC developer and I have a tough problem: noVNC needs the translated charCode value without using the keyPress event for the following reasons:
noVNC needs to send the keyDown and keyUp events separately to the VNC server (otherwise it's not a completely functional VNC client).
more importantly, noVNC needs to prevent the default keyboard actions while connected which means calling the preventDefault() method of the keyDown event. This has the side-effect of also preventing the keyPress event from firing.
Due to differences in keyboard layouts (i.e. different keyCode to charCode mappings) I've determine that noVNC will need a lookup table for different keyboard layouts.
But here is the real problem: on alternate layouts, some different physical keys have the SAME keyCode. For example, with an azerty (French) keyboard layout the '-' (dash) and '_' underscore keys both generate keyCode 189. Ack!!!
So ... how do I get proper keyCode to charCode mapping and prevent default browser actions at the same time?
BTW, I suspect the solution to this will be applicable to other interactive web applications and HTML5 games since you often want to be able to know full information about the key pressed without triggering any additional browser response to that keypress.
Useful links:
Here is an useful test page that show the three events and some other useful properties.
Summary of the crazy state of key events in Javascript (thanks #Tim)
Quirksmode Detecting keystrokes
Quirksmode Events - key events
noVNC issue with more discussion of the problem.
Solution: see my post below.
I have solved my own question. It's not a 100% solution but it should cover most of what is needed. Hopefully there will be a cleaner solution when browser vendors start integrating DOM Level 3 Events.
Just to re-iterate the main constraints:
The key down and key up events should be reported/sent at the time they actually happen. I.e. sending a key down and key up together during the keyPress event is insufficient.
Many key combinations must be fully handled during the keyDown event either because they never trigger a keyPress event (i.e. Ctrl key) or because the default action must be stopped in keyDown (WebKit) and doing so prevents the keyPress event from happening.
The key down and key events should report the translated character code and not keyCode value.
Without some out-of-the-box epiphany, the current browser implementations appear to prevent all three constraints from being fulfilled completely. So I have decided to relax constraint #3 just a bit.
On browser keyDown event add the event to a key down list and check to see if it is a safe (no undesirable browser default behavior) key combination:
Safe: do nothing until the keyPress.
Unsafe: report/send a key down event immediately. This is where constraint #3 is relaxed because these limited key combinations are not translated to a character code (many of them don't have them though anyways).
On browser keyPress event (which happens immediately after the keyDown event) check to see if it is a safe key combination:
Safe: report/send a key down event. Update the key down list using the translated character code (event.which).
Unsafe: do nothing since it was already reported/sent during keyDown.
On browser keyUp event, find and remove the matching event from the key down list and use the translated code to report/send the key up event.
Some additional links for those interesting:
The noVNC commit with the change.
Some wiki notes on the issues as related to noVNC.
This solution has been adopted in RedHat's Broadway project (HTML5 GTK+ backend).
This is an absolute minefield and I would urge you not to attempt this if you can possibly avoid it. Not only is there a long and tangled history of browser manufacturers not agreeing on key event behaviour, there is also the fact that they still don't agree and are still regularly changing the key behaviour of their browsers.
The following is the best I can offer and the definitive resource on browser key events: http://unixpapa.com/js/key.html
If you have to do this, I think you're going to end up with loads of key code mapping tables that will go out of date very quickly. Good luck.
I'm not asking this because I need a work-a-around. I have one that works fine, but I want to know WHY it doesn't. Is this bug in Javascript (or JQuery because I was using the JQuery .keypress handler) or is there a specific reason why this is so?
The keypress event is designed for handling a character typed by the user rather than detecting keyboard activity and the delete and backspace keys do not generate characters. Some browsers blur this line somewhat but the general principle is that the keyup and keydown events are there to detect any key being pressed and telling you about which key it is while keypress is for detecting an actual character being typed.
The short answer is that the onkeypress event is not fired for all key types in all browsers. Check the manual for your browser.
Why?
Probably not a comprehensive answer, but consider Shift, when it goes down and when it comes up relative to other keys is significant. And different keyboard hardware has different key rollover characteristics which you might want to know about in detail.
How do you find out what the user typed or pasted into a textarea? For example, if they typed in B (or β) at index 1, or if they pasted hello world\n at index 23. I've searched a fair bit but can't find anything. Here's what I have so far, uses jQuery:
$("textarea").keydown(function(evt){
var index= getCaret(this); // this.selectionStart doesn't work in IE
var key = evt.keyCode; // Wrong.
}
See this question for getCaret. The problem with event.keyCode is non-english keyboard layouts. I'm entirely stuck as far pasting is concerned.
If possible, I'd like to know the values before the textarea is changed - that is, from within the keydown event. I'm not sure if this can be done for pasting.
(Deletion is easier - detect keyCode==8 for backspace and keyCode==46 for del. If selection.length > 0, then the selection is removed; otherwise the character before or after is removed. In theory. There's also the case of pasting on top of a selection.)
Anything that gets any part of this closer to working in any browser is greatly appreciated. That is, how do you know:
the unicode string value of the typed character?
when a paste occurred?
what the text content of the paste is?
I'm not quite sure what your ultimate goal is here, so it's difficult to advise. However, here's some information:
When the user types a character, getting what they typed is easy enough using the keypress event and (assuming your event object is stored in a a variable called evt) using String.fromCharCode(evt.keyCode || evt.which).
For pasting, things are a bit trickier. The simplest thing would be to detect the paste before it has happened, store the textarea's value and after a very short time (using window.setTimeout) compare the new value with the old. As for detecting the paste, a lot of browsers now have the paste event: IE since version 5, Firefox since version 3 and WebKit browsers for a while (not sure exactly when), so you can use that for those browsers. As a fallback for other browsers you could detect Ctrl-V and Shift-Insert in a keydown event handler, though this is by no means foolproof since it won't fire when the user pastes using the Edit menu or the context menu in their browser.