show different keyboard character from the typed one in google chrome
google-chrome, javascript
Solution
It would be easier not to create a new event, which as you observed is not universally supported, and instead cancel the event and insert the mapped character corresponding to the character typed.
Assuming the user is typing into a textarea with id "ta", the following will handle keyboard input for that textarea in all the major browsers, mapping `q` to `ɛ` and all other characters to "X" for illustrative purposes.
Be aware that there are issues in IE <= 8 with the code for finding the selection to do with line breaks that the following code doesn't handle for the sake of brevity. You can get my cross browser function for handling this correctly here: Is there an Internet Explorer approved substitute for selectionStart and selectionEnd?
var charMap = {
"q": "ɛ"
};
document.getElementById("ta").onkeypress = function(evt) {
var val = this.value;
evt = evt || window.event;
// Ensure we only handle printable keys, excluding enter and space
var charCode = typeof evt.which == "number" ? evt.which : evt.keyCode;
if (charCode && charCode != 13 && charCode != 32) {
var keyChar = String.fromCharCode(charCode);
// Get the mapped character (default to "X" for illustration purposes)
var mappedChar = charMap[keyChar] || "X";
var start, end;
if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") {
// Non-IE browsers and IE 9
start = this.selectionStart;
end = this.selectionEnd;
this.value = val.slice(0, start) + mappedChar + val.slice(end);
// Move the caret
this.selectionStart = this.selectionEnd = start + 1;
} else if (document.selection && document.selection.createRange) {
// For IE up to version 8
var selectionRange = document.selection.createRange();
var textInputRange = this.createTextRange();
var precedingRange = this.createTextRange();
var bookmark = selectionRange.getBookmark();
textInputRange.moveToBookmark(bookmark);
precedingRange.setEndPoint("EndToStart", textInputRange);
start = precedingRange.text.length;
end = start + selectionRange.text.length;
this.value = val.slice(0, start) + mappedChar + val.slice(end);
start++;
// Move the caret
textInputRange = this.createTextRange();
textInputRange.collapse(true);
textInputRange.move("character", start - (this.value.slice(0, start).split("\r\n").length - 1));
textInputRange.select();
}
return false;
}
};
Problem
I'm working on a javascript keyboard that seeks to enable users to type in various African languages.Currently, this works fine in IE8 and firefox but not google chrome, and I'm actually stuck on this one.What I want to accomplish is for example, to type(on my physical keyboard) 'q'(keyCode=113) and get 'ɛ'(keyCode=603) as the output but currently, my code does nothing in google chrome. The relevant portion of my code is as follows: ``` var k_layouts = {}; k_layouts.Akan = {88:390,113:603};//keyCode mappings for Akan language k_layouts.Ga = {120:596,81:400};//keyCode mappings for Ga language var current_layout = ""; //function that maps the keyCode of a **typed** key to that of the **expected** key function map_key_code(keycode){ if(k_layouts[current_layout] && k_layouts[current_layout][keycode]) return k_layouts[current_layout][keycode]; return keycode; } //function that actually changes the keyCode of a **typed** key to the **expected** value function handle_keypress(ev){ var ev = ev || window.event; if(ev.bubbles != null ||!ev.bubbles) return true; var target = ev.target || ev.srcElement; var keyCode = window.event? ev.keyCode: ev.which; if(keyCode == 0) return true; var newKeyCode = map_key_code(keyCode); if(newKeyCode == keyCode) return true; if(target.addEventListener){ //for chrome and firefox //cancel event ev.preventDefault(); ev.stopPropagation(); //create new event with the keycode changed var evt = document.createEvent("KeyboardEvent"); try{//for firefox(works fine) evt.initKeyEvent("keypress",false,true,document.defaultView,ev.ctrlKey,ev.altKey,ev.shiftKey,ev.metaKey,newKeyCode,newKeyCode); } catch(e){// for google chrome(does not work as expected) evt.initKeyboardEvent("keydown",false,true,document.defaultView,ev.ctrlKey,ev.altKey,ev.shiftKey,ev.metaKey,newKeyCode,newKeyCode); } //dispatch new event target.dispatchEvent(evt); } else if(target.attachEvent){// works for IE ev.keyCode = newKeyCode; } } ``` Is there a way of achieving what I seek to do in chrome?Or, is there something I'm missing in my approach?I'd be glad for any help, and any thoughts.