Twitter Typeahead.js: show all options when click/focus
Asked Answered
H

9

30

I'm using Typeahead.js in an autocomplete text input, and it's great. But I need to activate the dropdown menu with all the available options when the input gets focus. Every possible solution I've seen involves initializing the input with some value, but I need to show all the options.

How could I achieve this?

Hautrhin answered 5/11, 2013 at 19:37 Comment(1)
Related question: stackoverflow.com/questions/23429918.Jalisajalisco
H
14

You need to use the option minLength: 0

Note:

There's a pull request which solved this issue

Hautrhin answered 7/11, 2013 at 11:24 Comment(2)
As of today (10/31/14), the library still does not perform the requested behavior when passed minLength: 0 (although it will if you type something and then backspace so that there is no longer any input). Scottie's solution above works, however.Hornpipe
The minLength: 0 option seems to partially work. If you click in an input field you can see all available results by pressing the down arrow on your keyboard. Would be nice though if did this on focus.Seurat
D
28

Any answer that says "minLength: 0 is all you need", is NOT TRUE.

"Out Of The Box" Typeahead v0.11.1 'does need' minLength set to 0, but ALSO if you are using the out of the box Bloodhound Engine, then you need to be sure to set

identify: function(obj) { return obj.team; },

on your Bloodhound Object..

You also need a "middle man" function to handle your "empty query", which is where you will tell Bloodhound to cooperate..

function nflTeamsWithDefaults(q, sync) {
  if (q === '') {
    sync(nflTeams.all()); // This is the only change needed to get 'ALL' items as the defaults
  } else {
    nflTeams.search(q, sync);
  }
}

You can see the FULL EXAMPLE here..

var nflTeams = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('team'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  identify: function(obj) { return obj.team; },
  prefetch: '../data/nfl.json'
});

function nflTeamsWithDefaults(q, sync) {
  if (q === '') {
    sync(nflTeams.all()); // This is the only change needed to get 'ALL' items as the defaults
  }

  else {
    nflTeams.search(q, sync);
  }
}

$('#default-suggestions .typeahead').typeahead({
  minLength: 0,
  highlight: true
},
{
  name: 'nfl-teams',
  display: 'team',
  source: nflTeamsWithDefaults
});

MORE SPECIFICALLY YOU CAN SEE THE OFFICIAL TWITTER TYPEAHEAD DEFAULT SUGGESTION ON FOCUS EXAMPLE AT THE FOLLOWING ADDRESS, WITH THE SIMPLE CHANGE FROM .get() TO .all() (SEE ABOVE OR BELOW)

http://twitter.github.io/typeahead.js/examples/#default-suggestions

... hope this helps someone, as it took me some time to find this information (found it by following all the bug reports & experimenting to find .all() method) ...

Depth answered 27/9, 2015 at 21:0 Comment(3)
This is just perfect. Works very well with version 0.11.1Continental
Somehow this isn't working when you have "remote" option for Bloodhound. nflTeams search runs, remote query is executed, data fetched but it doesn't appear as typehints. Any clue how to solve that?Dorotea
And I've found a solution by myself. Bloodhound search had 3 params: q, sync and async, so you just need to add async for middleman function and also search inside it.Dorotea
H
14

You need to use the option minLength: 0

Note:

There's a pull request which solved this issue

Hautrhin answered 7/11, 2013 at 11:24 Comment(2)
As of today (10/31/14), the library still does not perform the requested behavior when passed minLength: 0 (although it will if you type something and then backspace so that there is no longer any input). Scottie's solution above works, however.Hornpipe
The minLength: 0 option seems to partially work. If you click in an input field you can see all available results by pressing the down arrow on your keyboard. Would be nice though if did this on focus.Seurat
B
11

I made a quick modification to 10.2 that made "the basics" example found here display on focus.

i changed the mixin _onFocus (line 1459) FROM:

_onFocused: function onFocused() {
    this.isActivated = true;
    this.dropdown.open();
},

TO:

_onFocused: function onFocused() {
    this.isActivated = true;
    var val = this.input.getInputValue(); 
    var query = Input.normalizeQuery(val);
    this.dropdown.update(query);
    this.dropdown.open();
},

It's hardly official but it got the job done.

Binoculars answered 9/7, 2014 at 23:31 Comment(1)
Nice, it's working, but you missed var in front of val and query.Biestings
R
3

Using 0.10.4

To return all results for blank query add the following at line 450 of bloodhound.js

     if (query == "") { return that.datums; }

To trigger the match on focus trigger the key down event on your input when focused

     $(input_element).on("click", function () {
        ev = $.Event("keydown")
        ev.keyCode = ev.which = 40
        $(this).trigger(ev)
        return true
    });
Rustin answered 17/9, 2014 at 13:52 Comment(1)
This is valid solution. To make it work on input click you need to combine this with https://mcmap.net/q/468859/-twitter-typeahead-js-show-all-options-when-click-focus (above). Side note : line 450 means get method from SearchIndex class. Shame that there is need for source hacking to get such basic functionality, they are working on it like a turtles..Walkin
I
3

There is a way to do this now without having to modify the typeahead source file. You have to do two things - set minlength to 0 and also add an event handler for the focus event: In the below example which I copied from the first example on the Twitter page (https://twitter.github.io/typeahead.js/examples/) - make sure the location to typeahead.js and jquery-ui.js is correct.

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="typeahead.js"></script>
<script src="jquery-ui.js"></script>
   <script>
   $(function(){
var substringMatcher = function(strs) {
  return function findMatches(q, cb) {
    var matches, substrRegex;

    // an array that will be populated with substring matches
    matches = [];

    // regex used to determine if a string contains the substring `q`
    substrRegex = new RegExp(q, 'i');

    // iterate through the pool of strings and for any string that
    // contains the substring `q`, add it to the `matches` array
    $.each(strs, function(i, str) {
      if (substrRegex.test(str)) {
        // the typeahead jQuery plugin expects suggestions to a
        // JavaScript object, refer to typeahead docs for more info
        matches.push({ value: str });
      }
    });

    cb(matches);
  };
};

var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California',
  'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii',
  'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana',
  'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
  'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
  'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota',
  'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island',
  'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
  'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
];

$('.typeahead').typeahead({
  hint: true,
  highlight: true,
  minLength: 0
},
{
  name: 'states',
  displayKey: 'value',
  source: substringMatcher(states)
});
 $('.typeahead').on( 'focus', function() {
          if($(this).val() === '') // you can also check for minLength
              $(this).data().ttTypeahead.input.trigger('queryChanged', '');
      });
});
   </script>
    </head>
<body>
  <input class="typeahead" type="text" placeholder="States of USA">
</div>

</body>
</html>

Verified this works with 0.10.5. Note: Found this does not work with the Bloodhound search engine since the queryTokenizer for Bloodhound expects a character.

Immovable answered 17/2, 2015 at 0:13 Comment(0)
H
2

There's an easier way to do this now without modifying the source. It might be that the source has changed since this was originally answered, but I thought it worth putting here just in case.

After creating the typeahead:

var $element = $('#myTextElement');
$element.typeahead({ source: ['Billy', 'Brenda', 'Brian', 'Bobby'] });

Simply set the minLength to 0:

$element.data('typeahead').options.minLength = 0;

The minLength options is forced to 1 when the typeahead is created, but you can set it after creation and it works perfectly.

Haplo answered 22/8, 2014 at 9:40 Comment(2)
This did not work for me on 0.10.5. I get the following error: TypeError: $element.data(...) is undefinedLithium
@SteveL, Yes - it look likes they've changed things quite a lot in 0.10.5. I tried modifying the minLength property using the new version, but it doesn't seem to work. Here is a fiddle where you can see my feeble attempts: jsfiddle.net/zL9uxm45Haplo
T
1

In typeahead v.0.11.1, the patch referenced in other answers has been applied. You can achieve this with the option:

minLength: 0

Works on keyboard or mouse focus. No code changes or new events needed.

Talkingto answered 22/5, 2015 at 1:57 Comment(0)
Z
1

The easiest way that I achieved this behavior is to set minLinegth to zero and to set the prefetch property. Instead to set local JSON source just put the search url without the query parameter:

let baseUrl = 'some-url.com',
    url = baseUrl + '?search=%QUERY';

...

$el.typeahead({
    minLength: 0,
    highlight: true,
    prefetch: baseUrl
}, {
    ...
});
Zhukov answered 20/5, 2021 at 15:15 Comment(0)
T
0

Another option is to use the non-public APIs of Typeahead. The full Typeahead object is available through jQuery's data method.

var _typeaheadElem = $('#myInput').find('.typeahead');
var _typeahead = _typeaheadElem.data('ttTypeahead');

_typeaheadElem.focus(function() {
    /* WARNING: This is hackery abusing non-public Typeahead APIs */
    if (_typeaheadElem.val() === "") {
        var input = _typeahead.input; //Reference to the TA Input class
        //Set the component's current query to something !== input.
        input.query = "Recent People";
        input._onInput("");
    }
});

See more code that works in v0.10.2 http://pastebin.com/adWHFupF

This is linked to PR 719 https://github.com/twitter/typeahead.js/pull/719

Tobytobye answered 8/5, 2014 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.