Merge pull request #2871 from mamhoff/autocomplete-again

Fix buggy autocomplete behaviour for non-US keyboards
This commit is contained in:
Sam 2014-10-16 17:35:48 +11:00
commit 737be5e151
1 changed files with 47 additions and 66 deletions

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,23 @@ export default function(options) {
}); });
$(this).keypress(function(e) { $(this).keypress(function(e) {
var caretPosition, 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]); 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)) {
caretPosition = Discourse.Utilities.caretPosition(me[0]),
term = me.val().substring(completeStart + (options.key ? 1 : 0), caretPosition);
term += String.fromCharCode(e.charCode);
updateAutoComplete(options.dataSource(term));
} }
}); });
@ -313,8 +307,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 +333,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 +352,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 +364,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 +382,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 +396,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;
} }
} }
}); });