Fix buggy autocomplete behaviour for non-US keyboards

This change moves the code for actually entering data from the keydown handler to the
keypress handler, which can reliably catch the character entered (rather than
the key pressed).

This is my second attempt at
https://meta.discourse.org/t/typing-shows-on-non-us-keyboard-layouts/20449
without doing dangerous refactoring.

This does not fix the issue reported in
https://meta.discourse.org/t/overly-aggresive-emoji-autocomplete/20691/7
as that is a different bug.
This commit is contained in:
Martin Meyerhoff 2014-10-11 14:49:06 +02:00
parent b736fb7016
commit 97b60e6422

View File

@ -6,44 +6,32 @@
export var CANCELLED_STATUS = "__CANCELLED"; export var CANCELLED_STATUS = "__CANCELLED";
var shiftMap = []; var keys = {
shiftMap[192] = "~"; backSpace: 8,
shiftMap[49] = "!"; tab: 9,
shiftMap[50] = "@"; enter: 13,
shiftMap[51] = "#"; shift: 16,
shiftMap[52] = "$"; ctrl: 17,
shiftMap[53] = "%"; alt: 18,
shiftMap[54] = "^"; esc: 27,
shiftMap[55] = "&"; space: 32,
shiftMap[56] = "*"; leftWindows: 91,
shiftMap[57] = "("; rightWindows: 92,
shiftMap[48] = ")"; pageUp: 33,
shiftMap[109] = "_"; pageDown: 34,
shiftMap[107] = "+"; end: 35,
shiftMap[219] = "{"; home: 36,
shiftMap[221] = "}"; leftArrow: 37,
shiftMap[220] = "|"; upArrow: 38,
shiftMap[59] = ":"; rightArrow: 39,
shiftMap[222] = "\""; downArrow: 40,
shiftMap[188] = "<"; insert: 45,
shiftMap[190] = ">"; deleteKey: 46,
shiftMap[191] = "?"; zero: 48,
shiftMap[32] = " "; a: 65,
z: 90,
};
function mapKeyPressToActualCharacter(isShiftKey, characterCode) {
if ( characterCode === 27 || characterCode === 8 || characterCode === 9 || characterCode === 20 || characterCode === 16 || characterCode === 17 || characterCode === 91 || characterCode === 13 || characterCode === 92 || characterCode === 18 ) { return false; }
// Lookup non-letter keypress while holding shift
if (isShiftKey && ( characterCode < 65 || characterCode > 90 )) {
return shiftMap[characterCode];
}
var stringValue = String.fromCharCode(characterCode);
if ( !isShiftKey ) {
stringValue = stringValue.toLowerCase();
}
return stringValue;
}
export default function(options) { export default function(options) {
var autocompletePlugin = this; var autocompletePlugin = this;
@ -271,17 +259,22 @@ export default function(options) {
}); });
$(this).keypress(function(e) { $(this).keypress(function(e) {
var caretPosition = Discourse.Utilities.caretPosition(me[0]),
term;
if (!options.key) return; if (!options.key) return;
// keep hunting backwards till you hit a the @ key // keep hunting backwards till you hit a the @ key
if (e.which === options.key.charCodeAt(0)) { if (e.which === options.key.charCodeAt(0)) {
var caretPosition = Discourse.Utilities.caretPosition(me[0]);
var prevChar = me.val().charAt(caretPosition - 1); var prevChar = me.val().charAt(caretPosition - 1);
if (!prevChar || /\s/.test(prevChar)) { if (!prevChar || /\s/.test(prevChar)) {
completeStart = completeEnd = caretPosition; completeStart = completeEnd = caretPosition;
updateAutoComplete(options.dataSource("")); updateAutoComplete(options.dataSource(""));
} }
} else if ((completeStart !== null) && (e.charCode !== 0)) {
term = me.val().substring(completeStart + (options.key ? 1 : 0), caretPosition);
term += String.fromCharCode(e.charCode);
updateAutoComplete(options.dataSource(term));
} }
}); });
@ -313,8 +306,8 @@ export default function(options) {
if (!options.key) { if (!options.key) {
completeStart = 0; completeStart = 0;
} }
if (e.which === 16) return; if (e.which === keys.shift) return;
if ((completeStart === null) && e.which === 8 && options.key) { if ((completeStart === null) && e.which === keys.backSpace && options.key) {
c = Discourse.Utilities.caretPosition(me[0]); c = Discourse.Utilities.caretPosition(me[0]);
next = me[0].value[c]; next = me[0].value[c];
c -= 1; c -= 1;
@ -339,7 +332,7 @@ export default function(options) {
} }
// ESC // ESC
if (e.which === 27) { if (e.which === keys.escape) {
if (completeStart !== null) { if (completeStart !== null) {
closeAutocomplete(); closeAutocomplete();
return false; return false;
@ -358,9 +351,9 @@ export default function(options) {
// Keyboard codes! So 80's. // Keyboard codes! So 80's.
switch (e.which) { switch (e.which) {
case 13: case keys.enter:
case 39: case keys.rightArrow:
case 9: case keys.tab:
if (!autocompleteOptions) return true; if (!autocompleteOptions) return true;
if (selectedOption >= 0 && (userToComplete = autocompleteOptions[selectedOption])) { if (selectedOption >= 0 && (userToComplete = autocompleteOptions[selectedOption])) {
completeTerm(userToComplete); completeTerm(userToComplete);
@ -370,14 +363,14 @@ export default function(options) {
} }
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
case 38: case keys.upArrow:
selectedOption = selectedOption - 1; selectedOption = selectedOption - 1;
if (selectedOption < 0) { if (selectedOption < 0) {
selectedOption = 0; selectedOption = 0;
} }
markSelected(); markSelected();
return false; return false;
case 40: case keys.downArrow:
total = autocompleteOptions.length; total = autocompleteOptions.length;
selectedOption = selectedOption + 1; selectedOption = selectedOption + 1;
if (selectedOption >= total) { if (selectedOption >= total) {
@ -388,12 +381,10 @@ export default function(options) {
} }
markSelected(); markSelected();
return false; return false;
default: case keys.backSpace:
// otherwise they're typing - let's search for it!
completeEnd = caretPosition; completeEnd = caretPosition;
if (e.which === 8) { caretPosition--;
caretPosition--;
}
if (caretPosition < 0) { if (caretPosition < 0) {
closeAutocomplete(); closeAutocomplete();
if (isInput) { if (isInput) {
@ -404,25 +395,14 @@ export default function(options) {
} }
return true; return true;
} }
term = me.val().substring(completeStart + (options.key ? 1 : 0), caretPosition); term = me.val().substring(completeStart + (options.key ? 1 : 0), caretPosition);
if (e.which >= 48 && e.which <= 90) {
term += mapKeyPressToActualCharacter(e.shiftKey, e.which);
} else if (e.which === 187) {
term += "+";
} else if (e.which === 189) {
term += (e.shiftKey) ? "_" : "-";
} else if (e.which === 220) {
term += (e.shiftKey) ? "|" : "]";
} else if (e.which === 222) {
term += (e.shiftKey) ? "\"" : "'";
} else if (!e.which) {
/* fake event */
} else if (e.which !== 8) {
term += ",";
}
updateAutoComplete(options.dataSource(term)); updateAutoComplete(options.dataSource(term));
return true; return true;
default:
completeEnd = caretPosition;
return true;
} }
} }
}); });