Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Bootstrap's Typeahead plugin extended (allowing for AJAX functionality) among other things

This is a fork of Bootstrap Typeahead that adds minimal but powerful extensions.

For example, process typeahead list asynchronously and return objects

  # This example does an AJAX lookup and is in CoffeeScript
  $('.typeahead').typeahead(
    # source can be a function
    source: (typeahead, query) ->
      # this function receives the typeahead object and the query string
      $.ajax(
        url: "/lookup/?q="+query
        # i'm binding the function here using CoffeeScript syntactic sugar,
        # you can use for example Underscore's bind function instead.
        success: (data) =>
          # data must be a list of either strings or objects
          # data = [{'name': 'Joe', }, {'name': 'Henry'}, ...]
          typeahead.process(data)
      )
    # if we return objects to typeahead.process we must specify the property
    # that typeahead uses to look up the display value
    property: "name"
  )

For example, process typeahead list synchronously and fire a callback on selection

  // This example is in Javascript, collects html in some li's and returns it
  $('.typeahead').typeahead({
    source: function (typeahead, query) {
      var return_list = []
      $("li").each(function(i,v){
        return_list.push($(v).html())
      })
      // here I'm just returning a list of strings
      return return_list
    },
    // typeahead calls this function when a object is selected, and
    // passes an object or string depending on what you processed, in this case a string
    onselect: function (obj) {
      alert('Selected '+obj)
    }

  })

and a very simple example, showing you can pass list of objects as source, and get that object via onselect

  $('.typeahead').typeahead({
    // note that "value" is the default setting for the property option
    source: [{value: 'Charlie'}, {value: 'Gudbergur'}, ...],
    onselect: function(obj) { console.log(obj) }
  })

Note that onselect works without source as a function and vice versa. Events may be a cleaner solution to passing callbacks and using bind all over the place, but I tried to strike a balance between modifying the core source too much and adding functionality, so until further improvements on the original Typeahead source I think these additions are very helpful.

Update 02/23/2012: Fixed a bug

Gudbergur Erlendsson, reach me here or gudbergur at gmail

/* =============================================================
* bootstrap-typeahead.js v2.0.0
* http://twitter.github.com/bootstrap/javascript.html#typeahead
* =============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function( $ ){
"use strict"
var Typeahead = function ( element, options ) {
this.$element = $(element)
this.options = $.extend({}, $.fn.typeahead.defaults, options)
this.matcher = this.options.matcher || this.matcher
this.sorter = this.options.sorter || this.sorter
this.highlighter = this.options.highlighter || this.highlighter
this.$menu = $(this.options.menu).appendTo('body')
this.source = this.options.source
this.onselect = this.options.onselect
this.strings = true
this.shown = false
this.listen()
}
Typeahead.prototype = {
constructor: Typeahead
, select: function () {
var val = JSON.parse(this.$menu.find('.active').attr('data-value'))
, text
if (!this.strings) text = val[this.options.property]
else text = val
this.$element.val(text)
if (typeof this.onselect == "function")
this.onselect(val)
return this.hide()
}
, show: function () {
var pos = $.extend({}, this.$element.offset(), {
height: this.$element[0].offsetHeight
})
this.$menu.css({
top: pos.top + pos.height
, left: pos.left
})
this.$menu.show()
this.shown = true
return this
}
, hide: function () {
this.$menu.hide()
this.shown = false
return this
}
, lookup: function (event) {
var that = this
, items
, q
, value
this.query = this.$element.val()
if (typeof this.source == "function") {
value = this.source(this, this.query)
if (value) this.process(value)
} else {
this.process(this.source)
}
}
, process: function (results) {
var that = this
, items
, q
if (results.length && typeof results[0] != "string")
this.strings = false
this.query = this.$element.val()
if (!this.query) {
return this.shown ? this.hide() : this
}
items = $.grep(results, function (item) {
if (!that.strings)
item = item[that.options.property]
if (that.matcher(item)) return item
})
items = this.sorter(items)
if (!items.length) {
return this.shown ? this.hide() : this
}
return this.render(items.slice(0, this.options.items)).show()
}
, matcher: function (item) {
return ~item.toLowerCase().indexOf(this.query.toLowerCase())
}
, sorter: function (items) {
var beginswith = []
, caseSensitive = []
, caseInsensitive = []
, item
, sortby
while (item = items.shift()) {
if (this.strings) sortby = item
else sortby = item[this.options.property]
if (!sortby.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
else if (~sortby.indexOf(this.query)) caseSensitive.push(item)
else caseInsensitive.push(item)
}
return beginswith.concat(caseSensitive, caseInsensitive)
}
, highlighter: function (item) {
return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>'
})
}
, render: function (items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', JSON.stringify(item))
if (!that.strings)
item = item[that.options.property]
i.find('a').html(that.highlighter(item))
return i[0]
})
items.first().addClass('active')
this.$menu.html(items)
return this
}
, next: function (event) {
var active = this.$menu.find('.active').removeClass('active')
, next = active.next()
if (!next.length) {
next = $(this.$menu.find('li')[0])
}
next.addClass('active')
}
, prev: function (event) {
var active = this.$menu.find('.active').removeClass('active')
, prev = active.prev()
if (!prev.length) {
prev = this.$menu.find('li').last()
}
prev.addClass('active')
}
, listen: function () {
this.$element
.on('blur', $.proxy(this.blur, this))
.on('keypress', $.proxy(this.keypress, this))
.on('keyup', $.proxy(this.keyup, this))
if ($.browser.webkit || $.browser.msie) {
this.$element.on('keydown', $.proxy(this.keypress, this))
}
this.$menu
.on('click', $.proxy(this.click, this))
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
}
, keyup: function (e) {
e.stopPropagation()
e.preventDefault()
switch(e.keyCode) {
case 40: // down arrow
case 38: // up arrow
break
case 9: // tab
case 13: // enter
if (!this.shown) return
this.select()
break
case 27: // escape
this.hide()
break
default:
this.lookup()
}
}
, keypress: function (e) {
e.stopPropagation()
if (!this.shown) return
switch(e.keyCode) {
case 9: // tab
case 13: // enter
case 27: // escape
e.preventDefault()
break
case 38: // up arrow
e.preventDefault()
this.prev()
break
case 40: // down arrow
e.preventDefault()
this.next()
break
}
}
, blur: function (e) {
var that = this
e.stopPropagation()
e.preventDefault()
setTimeout(function () { that.hide() }, 150)
}
, click: function (e) {
e.stopPropagation()
e.preventDefault()
this.select()
}
, mouseenter: function (e) {
this.$menu.find('.active').removeClass('active')
$(e.currentTarget).addClass('active')
}
}
/* TYPEAHEAD PLUGIN DEFINITION
* =========================== */
$.fn.typeahead = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('typeahead')
, options = typeof option == 'object' && option
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.typeahead.defaults = {
source: []
, items: 8
, menu: '<ul class="typeahead dropdown-menu"></ul>'
, item: '<li><a href="#"></a></li>'
, onselect: null
, property: 'value'
}
$.fn.typeahead.Constructor = Typeahead
/* TYPEAHEAD DATA-API
* ================== */
$(function () {
$('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
var $this = $(this)
if ($this.data('typeahead')) return
e.preventDefault()
$this.typeahead($this.data())
})
})
}( window.jQuery );
/* =============================================================
* bootstrap-typeahead.js v2.0.0
* http://twitter.github.com/bootstrap/javascript.html#typeahead
* =============================================================
* Copyright 2012 Twitter, Inc.
@@ -29,6 +29,8 @@
this.highlighter = this.options.highlighter || this.highlighter
this.$menu = $(this.options.menu).appendTo('body')
this.source = this.options.source
+ this.onselect = this.options.onselect
+ this.strings = true
this.shown = false
this.listen()
}
@@ -38,8 +40,17 @@
constructor: Typeahead
, select: function () {
- var val = this.$menu.find('.active').attr('data-value')
- this.$element.val(val)
+ var val = JSON.parse(this.$menu.find('.active').attr('data-value'))
+ , text
+
+ if (!this.strings) text = val[this.options.property]
+ else text = val
+
+ this.$element.val(text)
+
+ if (typeof this.onselect == "function")
+ this.onselect(val)
+
return this.hide()
}
@@ -68,6 +79,25 @@
var that = this
, items
, q
+ , value
+
+ this.query = this.$element.val()
+
+ if (typeof this.source == "function")
+ value = this.source(this, this.query)
+ if (value)
+ this.process(value)
+ else
+ this.process(this.source)
+ }
+
+ , process: function (results) {
+ var that = this
+ , items
+ , q
+
+ if (results.length && typeof results[0] != "string")
+ this.strings = false
this.query = this.$element.val()
@@ -75,7 +105,9 @@
return this.shown ? this.hide() : this
}
- items = $.grep(this.source, function (item) {
+ items = $.grep(results, function (item) {
+ if (!that.strings)
+ item = item[that.options.property]
if (that.matcher(item)) return item
})
@@ -97,10 +129,14 @@
, caseSensitive = []
, caseInsensitive = []
, item
+ , sortby
while (item = items.shift()) {
- if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
- else if (~item.indexOf(this.query)) caseSensitive.push(item)
+ if (this.strings) sortby = item
+ else sortby = item[this.options.property]
+
+ if (!sortby.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+ else if (~sortby.indexOf(this.query)) caseSensitive.push(item)
else caseInsensitive.push(item)
}
@@ -117,7 +153,9 @@
var that = this
items = $(items).map(function (i, item) {
- i = $(that.options.item).attr('data-value', item)
+ i = $(that.options.item).attr('data-value', JSON.stringify(item))
+ if (!that.strings)
+ item = item[that.options.property]
i.find('a').html(that.highlighter(item))
return i[0]
})
@@ -251,6 +289,8 @@
, items: 8
, menu: '<ul class="typeahead dropdown-menu"></ul>'
, item: '<li><a href="#"></a></li>'
+ , onselect: null
+ , property: 'value'
}
$.fn.typeahead.Constructor = Typeahead
@pezholio

Is there any way I can stop the first item from being automatically selected? At the moment the onselect event is fired when a user tabs out of the typeahead element. (posted this to a fork of the original by mistake originally)

@pezholio

I've actually answered my own question now. See my Gist here

@Nerian

Hi. Thanks for doing this, it is really useful.

I used an array of objects as a source and it worked like a charm. For 40 objects is great, but when there are 3000 it is a little slow so I wanted to make it asynchronous using ajax. But I am having some problem there, there is something I am doing wrong but I don't what it is. Please take a look:

https://gist.github.com/1978187

Thanks!

@jonathanmaron

I think it would make sense for this functionality to be included in the official Typeahead Plugin. I guess many people require this functionality.

@jrust

Thanks for this. Added a few other additions (comma-separated support, disabling auto-select of the first element, and auto-setting the width): https://gist.github.com/2030277

@sivamotamarri

Hi. Thanks for doing this patch , it is really useful.
I used an array of objects as a source by doing ajax request to the server and getting element. but once i selected the item and refreshed the page , then users session got expired and user going to login page .I don't know why it is happening .
please take look into this :

$('[data-provide="typeahead"]').typeahead({
source: function (typeahead, query) {
return $.post($('#data-url').val(), { q: query }, function (data) {
return typeahead.process(data);
});
}
});

@nerdlobe

There's a bug if the returned json list is empty.
to fix, I added:

  if (!results)return;

to the line 1572

@sivamotamarri

Thank you nerdlobe for the fix. its working now

@OndrejSlamecka

Are you going to make a pull request to https://github.com/twitter/bootstrap? Your improvements are really useful and should be in the original source.

@richardshepherd

Agreed. This got me out of a tight spot - well worth a pull request :)

@koichirose

I agree with all of you, but can't get it to work properly:

Here's what I came up with:

var brands_el = $("#brands");
    brands_el.typeahead({
        source: function(typeahead, query) {
            if(this.ajax_call)
                this.ajax_call.abort();
            this.ajax_call = $.ajax({
                data: {
                    keyword: query,
                    store_id: $("#store_id").val()
                },
                url: brands_el.data('autocomplete_source'),
                success: function(data) {
                    typeahead.process(data);
                }
            });
        },
        property: 'brand',
        onselect: function (obj) {
            console.log(obj);
        }
    });

Returned JSON when input is 'm':

[{"brand_id":"2","value":"Maison Martin Margiela"},{"brand_id":"21","value":"Frankie Morello"},{"brand_id":"25","value":"Ben Sherman"}]

Same code here: http://pastie.org/3799234

The problem is that if I write 'm' in my input, the dropdown shows:
M
M
M
M
m

Which would be 3 upper Ms from 'Maison Martin Margiela', 1 upper 'M' from 'Frankie Morello', 1 lower m from 'Ben Sherman'.

The final goal is having the 'brand' property in the dropdown, and the 'brand_id' property in a hidden input when I select a result.

I can't understand what is going on...

Could you help me?

Thank you

@richardshepherd

On line 7, add in

dataType : 'json',

So it becomes

        this.ajax_call = $.ajax({
            dataType : 'json',
            data: {
                keyword: query,
                store_id: $("#store_id").val()
            },
            url: brands_el.data('autocomplete_source'),
            success: function(data) {
                typeahead.process(data);
            }
        });

Hope that helps!

@koichirose

Thank you, I'll try :)

@lucastex

Hi gudbergur, The script works great for me.

Me and a friend just added a new feature, to wait while user is typing and to fire the ajax search only when he stops to type, to make things better to the server. We've just added two new vars, one for the timer and other to keep the time that it would wait (in the Typeahead declaration):

this.timer_lookup = false
this.timer_timeout = this.options.timeout || 400

and before calling the lookup method, (in the 'default' statement in the keyUp function:

var that = this;
clearTimeout(this.timer_lookup);
this.timer_lookup = setTimeout(function(){that.lookup()}, this.timer_timeout);

It works like a charm :)

This adds a default timeout of 400 mls, but user can define in the typeahead declaration, with the 'timeout' parameter :)

@Nerian

@lucastex that would be very useful, nice!

@gudbergur: What do you think about creating a repo for his project? That way it would be easier to handle contributions.

@richardshepherd

@lucastex great addition!

@gudbergur
Owner

@lucastex very nice!
@Nerian I think I'll do that soon, there seems to be a lot of interest in this functionality

@lucastex

Cool! Hope it can be added in your fork :)

@trippo

@koichirose can you send me your script to update also the id field ? thanks

@koichirose

@trippo sorry I did not do it yet, I used a normal select for my brands for now :/
In the 'onselect' function anyway, you should be able to console.log(obj) and check what you need to update the id field.

@trippo

@koichirose it's true.. it's very simple using in onselect function the obj.id field thanks a lot

@jpdelatorre

Hey guys, need some help.

On my ajax call, I'm returning JSON format like this

[{'id':'1', 'label': 'apple'}, {'id':'2', 'label':'banana'}, {'id':'3', 'label':'orange'}]

And on my front-end, I have 2 input fields, one is visible with the typeahead event and the other one is a hidden field.

I'd like to show the label on the field with typeahead and at the same time save the id of the selected option to the hidden field. Any ideas how this can be done?

@trippo

@jpdelatorre: it's simple you can use a hidden field and use this code:
....,
property: 'label',
onselect: function (obj) {
$('#field_id').val(obj.id);
}

@jpdelatorre

@trippo thank you. I didn't know about the 'property' property.

@trippo

@jpdelatorre i use this code can you copy:

$('#city-search').typeahead({
source: function(typeahead, query){
$.ajax({
url: "/ajax/geoautocomplete/"+$('#language_id').val()+"/"+$('#region_id').val(),
type: "POST",
data: "query="+query ,
dataType: "JSON",
async: false,
success: function(data){
typeahead.process(data);
}
})
},
property: 'name',
items:11,
onselect: function (obj) {
if(obj.region_id){
$('#region_id').val(obj.region_id);
}
else{
if(obj.province_id){
val=$('#province_id').val();
$('#province_id').val(val+obj.province_id+"~");
}
$('#town_id').val(obj.town_id);
}
}
});

@dansingerman

@gudbergur , @lucastex - thanks guys, this has really helped me. Would be nice to have a proper repo.
Maybe when Twitter officially add this to bootstrap they'll use this. (If they don't I'd be interested to see how their version differs)

@gudbergur
Owner

Note that this functionality has now been committed to the 2.1.0-wip branch of Bootstrap, will keep this gist around for older versions though!

@coli

It doesn't look like the 2.1.0-wip one supports objects/id...

@gudbergur
Owner

@coli Yup, the pull request that was added to 2.1.0-wip only adds the function-as-a-source part of my fork and not the rest, so until that happens you have to keep using the fork if you want to populate the typeahead with objects.

@thorst

So I liked your gist, but it doesn't quite do everything i need. Here is my branch:

https://gist.github.com/2960885

Enhancements:

  • minLength parameter- ala jquery ui autocomplete. Requires textbox to have a set length before calling source.

  • By default no options are selected. If you tab while no option is selected it will leave your textbox value as is.

  • Up/Down - when it reaches the start or finish the next press will deselect all options, then next press will start scroll over options again. This is needed to allow tab off of input.

  • Left/Right no longer refresh datasource. There will probably be other keys we want to ignore.

Full Repo @ https://github.com/thorst/Bootstrap-Typeahead-Fork

@mmoscosa

I am a bit stuck as I keep on getting:

Uncaught TypeError: Cannot call method 'toLowerCase' of undefined

see http://stackoverflow.com/questions/11235644/twitter-bootstrap-typeahead-method-tolowercase-of-undefined for full question.

basically I am following @trippo code and I keep getting the error mentioned above.

any thoughts?!

I have tried minified jQUery non minified jquery, linking google jQuery and nothing...

@trippo

@mmoscosa i have create a little example for you :)
download from this link http://cl.ly/3w1B0w2m2P0O2p1B250p
to try write v , va , val , vald in text box.
I hope this work for you

@mmoscosa

@trippo Thank you very much!

I tried and it works when the array is as you put it on the example you kindly shared with me.

However, the array I get as a result is as you can see below, so I try to do:

    typeahead.process(results.data.manufacturers);

and I get the same error as mentioned above,

Uncaught TypeError: Cannot call method 'toLowerCase' of undefined
{"data":{"manufacturers":[{"Manufacturer":{"id":"1","manufacturer":"Bowtech","bow":true,"string":false,"release":false,"scope":false,"sight":false,"long_rod_stabilizer":false,"side_rod_stabilizer":false,"riser":false,"limbs":false,"tabs":false,"buttons":false,"clicker":false,"arrow":null,"nock":null,"point":null,"vane":null,"created":"2012-06-03 13:30:23","modified":"2012-06-03 13:30:26"},"Arrow":[],"Bow":[{"id":"1","name":"Mio","user_id":"4fca0cbb-1750-4bc4-af12-60f3bd6152ee","active":true,"type_id":"1","axle_to_axle":null,"peep_to_sight":null,"peep_to_arrow":null,"peep_to_knocking_point":null,"draw_length":"17.00","draw_weight":"50.00","brace_height":null,"created":"2012-06-03 13:26:02","modified":"2012-06-03 13:26:06","BowsManufacturer":{"id":"1","bow_id":"1","manufacturer_id":"1","created":"2012-06-03 13:46:32","modified":"2012-06-03 13:46:34"}}]},{"Manufacturer":{"id":"3","manufacturer":"Hoyt","bow":true,"string":null,"release":null,"scope":null,"sight":null,"long_rod_stabilizer":null,"side_rod_stabilizer":null,"riser":true,"limbs":true,"tabs":null,"buttons":null,"clicker":null,"arrow":null,"nock":null,"point":null,"vane":null,"created":"2012-06-06 23:10:11","modified":"2012-06-06 23:10:13"},"Arrow":[],"Bow":[]}]},"meta":{"status":"ok","feedback":[{"message":"Unable to establish class","level":"warning"}],"request":{"http_host":"archertrainer.mmoscosa.homelinux.net","http_user_agent":"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit\/536.11 (KHTML, like Gecko) Chrome\/20.0.1132.47 Safari\/536.11","server_addr":"127.0.0.1","remote_addr":"127.0.0.1","server_protocol":"HTTP\/1.1","request_method":"GET","request_uri":"\/bows\/get_manufacturers.json","request_time":1341179217},"credentials":{"class":null,"apikey":null,"username":null},"time_epoch":"1341179222","time_local":"Sun, 01 Jul 2012 22:47:02 +0100","version":"0.3"}}
@rjayako

Hello everyone, I'm having a little issue getting this to work.

The server responses with the correct json request however typeahead only displays the first letter of my returned result. For example if I type k it will display:
k
k
K
k
K

Could you help me figure out why?

Here is my js

$('.user').typeahead({
    source : function(typeahead, query) {
        return $.post('getUser', {
            query : query
        }, function(data) {
            return typeahead.process(data);
        });
    }
});

and my html

http://pastie.org/private/gr1byesbjgmrzxvrgp4a

Thank you.

@koichirose

@rayshinn, it's the same problem I had, just read @richardsheperd's answer above...
I did not try it though, in the end I didn't use the typeahead plugin at all.

@rjayako

@koichirose I have already tried @richardshepherd solution with no luck. Perhaps I am implementing it wrong? Could you provide me with an example?

Thanks

@ReubenBond

Fantastic work! I used this to write a Knockout.js binding (http://blogs.msdn.com/b/rebond/archive/2012/07/18/knockout-js-binding-for-bootstrap-typeahead-plugin.aspx) Feedback on that is welcome, I'm probably doing it wrong.

@pwwebdev

Great plugin.

Is it possible to set the href location? Now it's just # and I want to use it for quick navigation (when you select the result you are redirected to that specific page).

@tibbon

Totally dumb question, but if I'm using the Twitter-Bootstrap gem, where do I put this to override it?

@xlozinguez

Not sure if anyone has encountered this problem but I've followed @trippo example and everything works fine... except that my options didn't show up so I used Chrome's js debugger and noticed that the process method was invoked twice: one time via the success callback and the second time via the lookup function wich seems to be the default to the keyup event...

The problem with this is that the first one has the response items, the other has an empty array...

Noone ever had this issue?

@xlozinguez

Only way to prevent that is to comment out the line as such:

, lookup: function (event) {
      var that = this
        , items
        , q
        , value

      this.query = this.$element.val()

      if (typeof this.source == "function") {
        value = this.source(this, this.query)
        //if (value) this.process(value) <-- this will trigger process twice...
      } else {
        this.process(this.source)
      }
    }
@slacktracer

I'm being really lazy here, but... Any plans for a new version? ( I mean, forking the new typeahead, 2.1)

@shellac

That's a bug due to lax syntax, I think. The 'else' is associated with the inner 'if (value)'. Try adding a semicolon after 'this.process(value)'?

@benjsno

I had some trouble on Chrome. When clicking on menu, the input wasn't fill.
I have modified line 257 :

setTimeout(function () { that.hide() }, 150)

in

setTimeout(function () { that.hide() }, 300)

thanks
(Chrome V 22.0.1229.94, Mac OS X 10.8.2)

@jonschlinkert

This is great, @gudberger have you considered making this an actual repo, so issues can be logged and uses can fork and do pull requests? Seems like it would get some traction

@Morpho

I'd love to see this in Bootstrap 2.1!

@noreiller

To those who get the error message "Uncaught TypeError: Cannot call method 'toLowerCase'", I resolved this by sending to the process callback a simple array with the values instead of the full JSON.
So instead of

[{'name': 'Joe', }, {'name': 'Henry'}, ...]

You have to send

['Joe', 'Henry', ...]
@ikkentim

I get an error on line 147 when using the character '['. :
Invalid regular expression: missing terminating ] for character class

(due to the regular expression) ;(

@northern

Not sure if this helps anyone but for v2.2.2 the asynchronous data retrieval seems to be built-in without the need of a forked ajax version:

http://www.lukeschreur.com/posts/bootstrap-asynchronous-auto-complete-input-fields

@dhenze

I've updated your code to use it with Boostrap v2.2.2. https://gist.github.com/4502186

Didn't check for any improvements, does work fine for me. Very much appreciated, this is a great enhancement. Very much appreciated.

@alexdma

Loved this one, though I only got it to work on Firefox.

but under IE9, Opera and Chrome, it does not seem to capture scroll key presses for scrolling across dropdown items.

Also, in no browser was it accepting selection by mouse click, unlike the plain non-Ajax typeahead.

I might have done something wrong though. The only other script running on the page is jquery-latest.

Does anyone have a clue? I can provide whatever code sample I used for this plugin.

@alexdma

Ok I'm beginning to figure out - it's the use of the deprecated $.browser for detecting keydown event support...

@mrgcohen

https://gist.github.com/mrgcohen/5062352

Here's an additional example where it does not search for all entries when a user types fast. I needed something for a project but don't have time to fork. Hope someone finds this useful. Also it will cache searches so you won't be making a ton of calls (easy to disable if you choose).

So if you search for

Supercalifragilisticexpialidocious

and you are a fast typer and type superca really fast instead of making ajax calls for..

s
su
sup
super
superca

It will just do

superca

https://gist.github.com/mrgcohen/5062352

cheers :smiley:

@dnprock

I just attempted to integrate this again and notice the gist is broken with jquery 1.9. $.browser.webkit call was removed.

Quick solution is to use jquery migrate:

http://stackoverflow.com/questions/9638247/is-jquery-browser-deprecated

It's useful to update the gist.

@donriga

Great fork!!! I try to autocomplete two days to do, but only solved the problem of installing a fork

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.