Eu recomendaria dar uma olhada no widget de preenchimento automático da UI do jQuery. Eles lidaram com a maioria dos casos lá, já que sua base de código é mais madura do que a maioria dos outros por aí.
Abaixo está um link para uma página de demonstração para que você possa verificar se funciona. http://jqueryui.com/demos/autocomplete/#default
Você obterá o maior benefício ao ler a fonte e ver como eles a resolveram. Você pode encontrá-lo aqui: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .
Basicamente, eles fazem tudo, se vinculam input, keydown, keyup, keypress, focus and blur. Então eles têm um tratamento especial para todos os tipos de chaves, como page up, page down, up arrow key and down arrow key. Um cronômetro é usado antes de obter o conteúdo da caixa de texto. Quando um usuário digita uma chave que não corresponde a um comando (tecla para cima, tecla para baixo e assim por diante), existe um timer que explora o conteúdo após cerca de 300 milissegundos. Parece com isso no código:
// switch statement in the
switch( event.keyCode ) {
//...
case keyCode.ENTER:
case keyCode.NUMPAD_ENTER:
// when menu is open and has focus
if ( this.menu.active ) {
// #6055 - Opera still allows the keypress to occur
// which causes forms to submit
suppressKeyPress = true;
event.preventDefault();
this.menu.select( event );
}
break;
default:
suppressKeyPressRepeat = true;
// search timeout should be triggered before the input value is changed
this._searchTimeout( event );
break;
}
// ...
// ...
_searchTimeout: function( event ) {
clearTimeout( this.searching );
this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
// only search if the value has changed
if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
this.selectedItem = null;
this.search( null, event );
}
}, this.options.delay );
},
O motivo para usar um timer é para que a interface do usuário tenha a chance de ser atualizada. Quando o Javascript está em execução, a interface do usuário não pode ser atualizada; portanto, a chamada para a função de atraso. Isso funciona bem para outras situações, como manter o foco na caixa de texto (usada por esse código).
Portanto, você pode usar o widget ou copiar o código em seu próprio widget se não estiver usando a interface do usuário do jQuery (ou, no meu caso, desenvolvendo um widget personalizado).