Search code examples
javascriptjquerytwitter-typeahead

Twitter Typeahead differentiate between events


I'm designing a system that allows users to annotate elements with either strings or terms from a vocabulary. I use Twitter typeahead for autocompletion and want to distinguish between an entered string and a term.

I am not able to figure out how to differentiate between the following situations:

  1. a user pressing enter after coming up with its own value
  2. a user pressing a down (or up) arrow (thereby selecting an autocompletion option) and pressing enter

The event listeners I wrote:

$("#itemInp").on('typeahead:select', function(event, term) {
    console.log("save: term", term);
});

$("#itemInp").on('keyup', function(event) {
    if(event.which == 13) {
        var string = $("#itemInp").val();
        console.log("save: string", string);
    }
});

With the following HTML:

<input id="itemInp"><input>

The first listener catches all selected typeahead terms, allowing for proper saving of the term. Problem is, the second listener is also triggered in case a user presses down and enter, selecting a typeahead term, which is now also saved as a plain string. Is there a way to not trigger the second listener in case a typeahead suggestion is selected?

A fiddle with the code loaded: https://jsfiddle.net/zban3vs6/1/

Edit: I considered a number of hacks, but all come with their own problems:

  1. Add a special character to the string shown in input at the moment it is selected, by adding custom Typeahead display: https://jsfiddle.net/2t9rzhwf/ This causes an additional character to be introduced, which is troublesome if a user presses the down arrow without pressing enter.

  2. Attempt at sequencing the listeners, have the term listener trigger first, set a boolean to true, and filter on this boolean in the second listener. Don't like this way of filtering, since it introduces a delay.

  3. The solution provided by @peter-clause, checking if the selected value is in the list of available items. But that way I can not keep track of whether the user intended to use the autocomplete option to select a term or explicitly is adding a plain string.


Solution

  • I had a similar problem. This is how I solved it.

        var wasSelected = false;
        $("#itemInp").on('typeahead:select', function(event, term) {
            wasSelected = true;
            console.log("save: term", term);
        });
    
        $("#itemInp").on('change', function(event) {
            if(!wasSelected) {
                var string = $("#itemInp").val();
                console.log("save: string", string);
            }
            wasSelected = false;    
        });