tim.rohrer tim.rohrer - 1 year ago 62
jQuery Question

Using typeahead, how have user's typed input that matches be seen as a match?

I am contributing to a Wordpress plugin project that uses Twitter Typeahead (and Bloodhound) and JQuery.

The plugin incorporates information about organizational groups. When users type in the name of a group they wish to add to the database, Typeahead/Bloodhound provide suggestions (popup) based on existing groups. If the user selects an existing group with the mouse or arrow keys from the suggestions in the popup, or presses tab when the desired autocompleted group name is shown but only partially completed by the user, the match is selected and the remaining elements/fields for that group are populated from the database. This is desired behavior which works.

If the user types in a new group name (for which Typeahead/Bloodhound doesn't find a match), the group name and additional information entered by the user are used to create a new group in the database. This part also works.

The problem occurs when the user types the name of a existing group, but instead of selecting the group from the autocompleted/popup suggestions, the user continues to type the whole group name, and then presses tab or clicks the mouse on the next field. When the user does this, data related to the group is not auto populated.

From the js file:

$('input#group').typeahead(null, {
displayKey: 'value',
source: array_of_groups
}).on('typeahead:autocompleted typeahead:selected', function($e, group){
$('input[name=website]').val(group.website);
$('input[name=email]').val(group.email);
$('input[name=phone]').val(group.phone);
});


I've read the typeahead documentation, but I'm not seeing (or understanding?) any options or custom events that would let me change the behavior of how the library handles a tab when all the letters of the autocomplete suggestion have already been typed in by the user. Nor do I see a way to have Typeahead/Bloodhound do a final check to see if the input string matches any of the existing values in the source.

I found a similar question (Select value during onblur event when using typeahead) which I think basically involves looping through the data source again looking for a match. I may be able to implement something like this, but I'm looking for a solution more tightly integrated with Typeahead/Bloodhound.

Another suggestion I found would inject a keystroke (i.e., tab) on blur, but as I pointed out above, tabbing after the entire name is typed out doesn't seem to trigger the function. Nor am I sure that would then trigger the Typeahead custom event.

Here is code jsfiddle that mimics the relevant portion of the project. I learned in this extraction that if the user types the name of the group without matching the exact case, tab will in fact grab the right suggestion as a match. The problem remains though if the user types the exact name of the group and hits tab (or clicks to mouse to the next field) typeahead matching is not triggered.

I'm going to look closer at see if there is a way to use a combination of templates and functions, but suggestions welcome.

Answer Source

After researching the Twitter Typeahead documentation, I found the custom event called typeahead:change:

typeahead:change – Normalized version of the native change event. Fired when input loses focus and the value has changed since it originally received focus.

Using this, I created two events, one for the lost focus situation, and another if the suggestion is selected.

var myTypeahead = $('input#group').typeahead({
  minLength: 0,
  hint: true
}, {
  displayKey: 'gname',
  source: groups.ttAdapter()
});

myTypeahead.on('typeahead:change', function($e, group) {
  $.each(groupData, function() {
    if (this["gname"].toUpperCase() === group.toUpperCase()) {
        console.log("Match!");
      $('input[name=website]').val(this.gwebsite);
      $('input[name=notes]').val(this.gname);
    }
  });
});

myTypeahead.on('typeahead:autocompleted typeahead:selected', function($e, group) {
  //  myTypeahead.off('typeahead:change');
  $('input[name=website]').val(group.gwebsite);
  $('input[name=notes]').val(group.gname);
});

Here is the revised jsfiddle.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download