5

Using jQuery 1.7.2 and jQueryUI 1.8.12, I'm trying to implement an autocomplete field with the following behavior:

  • If an autocomplete suggestion is selected (with the mouse or keyboard), call function A
  • If there are no matches (hence no suggestion was selected) and ENTER was pressed, call function B

The problem I'm having is, when I select a suggestion with the keyboard, my check for ENTER is also fired, and that would make me call function B when I shouldn't. Here is a simple example (also on jsfiddle):

$('input').autocomplete({
    source: ['foo', 'bar', 'baz' ],
    select: function(event, ui) {
      console.log('suggestion selected');   
    }
}).keydown(function(e) {
    if(e.keyCode == 13) console.log('ENTER (keydown)');
}).keyup(function(e) {
    if(e.keyCode == 13) console.log('ENTER (keyup)');
});

According to the console, the keyup/keydown handlers are firing after the autocomplete select event (which is weird), so I tried to prevent it (by either trying to top bubbling, preventing the default, or both). I also traversed the event object's originalEvent properties up to the topmost parent (the original KeyboardEvent), but that seems unstoppable either.

Does anyone know a simple solution to what I'm trying to accomplish, preferably avoiding flags to indicate that the select event was fired? I'd like to avoid that, as such a flag would have to be cleared somewhere else, which seems error-prone.

Community
  • 1
  • 1
bfavaretto
  • 71,580
  • 16
  • 111
  • 150

3 Answers3

4

How about this. Before keydown event registry, just bind an autocomplete.keydown event. This is guaranteed to execute before your keydown. Note the order of event registration also matter.

http://jsfiddle.net/zFPZH/

$('input')
    .autocomplete({
        source: ['foo', 'bar', 'baz' ],
        select: function(event, ui) {
            console.log('suggestion selected');         
        }
    }).bind("keydown.autocomplete", function() {
        if(event.keyCode == 13){ 
            console.log('keydown.autocomplete (keyup)'); 
        };
    }).keydown(function(e) {
        if(e.keyCode == 13){ 
            console.log('ENTER (keydown)');
        };
    }).keyup(function(e) {
        if(e.keyCode == 13){ 
            console.log('ENTER (keyup)');
        };
    });
DutGRIFF
  • 5,103
  • 1
  • 33
  • 42
PSL
  • 123,204
  • 21
  • 253
  • 243
  • That looks promising! If I combine it with a check for class `ui-state-hover` [as D. Strout suggested](http://stackoverflow.com/a/16112644/825789), it should work. I'll test it now. – bfavaretto Apr 19 '13 at 20:32
1

It seems that when the suggestion list has appeared and a suggestion is highlighted, it has the class ui-state-hover. When checking the keyCode in your keydown event, you could also check for the presence of an element with that class in the suggestion menu to see if, when enter is pressed, it is to confirm the suggestion.

Ashley Strout
  • 6,107
  • 5
  • 25
  • 45
  • Just tried that. When I focus the suggestion, the class is there, but when the keyup/keydown handlers fire, it's already gone. – bfavaretto Apr 19 '13 at 20:06
  • I ended up combining your suggestion with PSCoder's, and was able to avoid resorting to flags. Not sure if I should have been so stubborn about this, but it's good to know there is a way! :) – bfavaretto Apr 19 '13 at 20:55
0

This is an old question, but none of the given answers worked out for me.

I ended up with this workaround:

$('input')
    .autocomplete({
        source: ['foo', 'bar', 'baz' ],
        select: function(event, ui) {
            $(this).data("stopPropagation", true);            // <----- turn off
            console.log('suggestion selected');         
        }
    }).keydown(function(e) {
        if ($(this).data("stopPropagation")) {
            $(this).data("stopPropagation", false);           // <----- turn on
            return;
        }
        if (e.keyCode == 13){ 
            console.log('ENTER (keyup)');
        };
    });
mirko
  • 3
  • 1
  • 1
  • 6