diff --git a/docs/javascript.html b/docs/javascript.html
index 0aebf8609a622a9e2bd92075676694d3e2d06c10..28d91cb4ec2deda2e0e6778fb423a99bdcd10165 100644
--- a/docs/javascript.html
+++ b/docs/javascript.html
@@ -876,7 +876,7 @@ $('#my-alert').bind('closed', function () {
       <div class="row">
         <div class="span3 columns">
           <p>The collapse plugin offers simple, flexible collapsible element support for making accordions and other collapsible ui components.</p>
-          <a href="../js/bootstrap-collapsible.js" target="_blank" class="btn primary">Download</a>
+          <a href="../js/bootstrap-collapse.js" target="_blank" class="btn primary">Download</a>
         </div>
         <div class="span9 columns">
           <h3>Using bootstrap-collapse.js</h3>
diff --git a/js/bootstrap-typeahead.js b/js/bootstrap-typeahead.js
new file mode 100644
index 0000000000000000000000000000000000000000..52ced3fef8d25c6d84c4b700ce285981b388d151
--- /dev/null
+++ b/js/bootstrap-typeahead.js
@@ -0,0 +1,190 @@
+/* =============================================================
+ * bootstrap-typeahead.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#collapsible
+ * =============================================================
+ * Copyright 2011 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.$menu = $(this.options.menu).appendTo('body')
+    this.data = this.options.data
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , matcher: function(item, query) {
+      return ~item.indexOf(query)
+    }
+
+  , select: function(event) {
+      this.$element.val($(event.target).attr('data-value'))
+      this.hide()
+    }
+
+  , show: function () {
+      this.shown = true
+      this.$menu.show()
+      return this
+    }
+
+  , hide: function () {
+      this.shown = false
+      this.$menu.hide()
+      return this
+    }
+
+  , lookup: function (event) {
+      var query = this.$element.val()
+        , that = this
+
+      var items = this.data.filter(function (item) {
+        if (that.matcher(item, query)) {
+          return item
+        }
+      })
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items).show()
+    }
+
+  , render: function(items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        return $(that.options.item)
+          .text(item)
+          .attr('data-value', item)[0]
+      })
+
+      items.first().addClass('active')
+
+      this.$menu.append(items)
+
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next() || $(this.$menu.find('li')[0])
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.prev() || this.$menu.find('li').last()
+
+      next.addClass('active')
+    }
+
+  , keyup: function () {
+      event
+        .stopPropagation()
+        .preventDefault()
+
+      switch(event.keyCode) {
+        case 9: // tab
+        case 13: // enter
+          this.select()
+          break
+
+        case 27: // escape
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+  }
+
+  , keypress: function (event) {
+      event.stopPropagation()
+      switch(event.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          event.preventDefault()
+          break
+
+        case 38: // up arrow
+          this.prev()
+          event.preventDefault()
+          break
+
+        case 40: // down arrow
+          this.next()
+          event.preventDefault()
+          break
+      }
+  }
+
+  , listen: function () {
+      this.$element
+        .on('focus', this.show)
+        .on('blur', $.proxy(this.hide, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup', this.keyup)
+        .on('change', $.proxy(this.lookup, this))
+
+      if ($.browser.webkit || $.browser.msie) {
+        this.$element.on('keydown', this.keypress)
+      }
+
+      this.$menu
+        .on('click', '* > *', $.proxy(this.select, this))
+        .on('mouseenter', function () {
+          /* remove selected class, add to mouseover */
+        })
+    }
+  }
+
+  /* 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 = {
+    data: null
+  , items: 8
+  , empty: false
+  , noresults: false
+  , menu: '<ul class="dropdown-menu"></ul>'
+  , item: '<li></li>'
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+}( window.jQuery )
\ No newline at end of file
diff --git a/js/tests/index.html b/js/tests/index.html
index e8ed2c5feb7b88f15c6a2ee3c31141e82e202004..27c2b34125c62701e54a738cdd0cccce5106e089 100644
--- a/js/tests/index.html
+++ b/js/tests/index.html
@@ -22,6 +22,7 @@
   <script src="../../js/bootstrap-tab.js"></script>
   <script src="../../js/bootstrap-twipsy.js"></script>
   <script src="../../js/bootstrap-popover.js"></script>
+  <script src="../../js/bootstrap-typeahead.js"></script>
 
   <!-- unit tests -->
   <script src="unit/bootstrap-transition.js"></script>
@@ -34,6 +35,7 @@
   <script src="unit/bootstrap-tab.js"></script>
   <script src="unit/bootstrap-twipsy.js"></script>
   <script src="unit/bootstrap-popover.js"></script>
+  <script src="unit/bootstrap-typeahead.js"></script>
 
 <body>
   <div>
diff --git a/js/tests/unit/bootstrap-typeahead.js b/js/tests/unit/bootstrap-typeahead.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc46a7990935ad5bbcc9f2cd37d26f8e7a990e3d
--- /dev/null
+++ b/js/tests/unit/bootstrap-typeahead.js
@@ -0,0 +1,122 @@
+$(function () {
+
+    module("bootstrap-typeahead")
+
+      test("should be defined on jquery object", function () {
+        ok($(document.body).typeahead, 'alert method is defined')
+      })
+
+      test("should return element", function () {
+        ok($(document.body).typeahead()[0] == document.body, 'document.body returned')
+      })
+
+      test("should listen to an input", function () {
+        var $input = $('<input />')
+        $input.typeahead()
+        ok($input.data('events').focus, 'has a focus event')
+        ok($input.data('events').blur, 'has a blur event')
+        ok($input.data('events').keypress, 'has a keypress event')
+        ok($input.data('events').keyup, 'has a keyup event')
+        ok($input.data('events').change, 'has a change event')
+        if ($.browser.webkit || $.browser.msie) {
+          ok($input.data('events').keydown, 'has a keydown event')
+        } else {
+          ok($input.data('events').keydown, 'does not have a keydown event')
+        }
+      })
+
+      test("should create a menu", function () {
+        var $input = $('<input />')
+        ok($input.typeahead().data('typeahead').$menu, 'has a menu')
+      })
+
+      test("should listen to the menu", function () {
+        var $input = $('<input />')
+          , $menu = $input.typeahead().data('typeahead').$menu
+
+        ok($menu.data('events').mouseover, 'has a mouseover(pseudo: mouseenter)')
+        ok($menu.data('events').click, 'has a click')
+      })
+
+      test("should show menu when query entered", function () {
+        var $input = $('<input />').typeahead({
+              data: ['aa', 'ab', 'ac']
+            })
+          , typeahead = $input.data('typeahead')
+
+        $input.val('a').change()
+
+        ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
+        equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
+        equals(typeahead.$menu.find('.active').length, 1, 'one item is active')
+
+        typeahead.$menu.remove()
+      })
+
+      test("should hide menu when query entered", function () {
+        var $input = $('<input />').typeahead({
+              data: ['aa', 'ab', 'ac']
+            })
+          , typeahead = $input.data('typeahead')
+
+        $input.val('a').change()
+
+        ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
+        equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
+        equals(typeahead.$menu.find('.active').length, 1, 'one item is active')
+
+        $input.blur()
+
+        ok(!typeahead.$menu.is(":visible"), "typeahead is no longer visible")
+
+        typeahead.$menu.remove()
+      })
+
+      test("should set next item when down arrow is pressed", function () {
+        var $input = $('<input />').typeahead({
+              data: ['aa', 'ab', 'ac']
+            })
+          , typeahead = $input.data('typeahead')
+
+        $input.val('a').change()
+
+        ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
+        equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
+        equals(typeahead.$menu.find('.active').length, 1, 'one item is active')
+        ok(typeahead.$menu.find('li').first().hasClass('active'), "first item is active")
+
+        $input.trigger({
+          type: 'keypress'
+        , keyCode: 40
+        })
+
+        ok(typeahead.$menu.find('li').first().next().hasClass('active'), "second item is active")
+
+
+        $input.trigger({
+          type: 'keypress'
+        , keyCode: 38
+        })
+
+        ok(typeahead.$menu.find('li').first().hasClass('active'), "first item is active")
+
+        typeahead.$menu.remove()
+      })
+
+
+      test("should set input value to selected item", function () {
+        var $input = $('<input />').typeahead({
+              data: ['aa', 'ab', 'ac']
+            })
+          , typeahead = $input.data('typeahead')
+
+        $input.val('a').change()
+
+        $(typeahead.$menu.find('li')[2]).trigger('click')
+
+        equals($input.val(), 'ac', 'input value was correctly set')
+        ok(!typeahead.$menu.is(':visible'), 'the menu was hidden')
+
+        typeahead.$menu.remove()
+      })
+})
\ No newline at end of file