twitter-bootstrap-rails 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of twitter-bootstrap-rails might be problematic. Click here for more details.

Files changed (71) hide show
  1. data/README.md +14 -3
  2. data/app/helpers/bootstrap_flash_helper.rb +12 -0
  3. data/lib/generators/bootstrap/layout/templates/layout.html.erb +1 -0
  4. data/lib/generators/bootstrap/layout/templates/layout.html.haml +1 -0
  5. data/lib/generators/bootstrap/layout/templates/layout.html.slim +1 -0
  6. data/lib/generators/bootstrap/partial/partial_generator.rb +20 -0
  7. data/lib/generators/bootstrap/partial/templates/_login.html.erb +29 -0
  8. data/lib/generators/bootstrap/partial/templates/_navbar.html.erb +13 -0
  9. data/lib/generators/bootstrap/themed/templates/index.html.erb +1 -1
  10. data/lib/generators/bootstrap/themed/templates/index.html.haml +1 -1
  11. data/lib/generators/bootstrap/themed/templates/index.html.slim +1 -1
  12. data/lib/generators/bootstrap/themed/templates/show.html.erb +1 -1
  13. data/lib/generators/bootstrap/themed/templates/show.html.haml +1 -1
  14. data/lib/generators/bootstrap/themed/templates/show.html.slim +1 -1
  15. data/lib/twitter/bootstrap/rails/version.rb +1 -1
  16. data/vendor/assets/javascripts/twitter/bootstrap.js +1 -0
  17. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-affix.js +104 -0
  18. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-alert.js +1 -1
  19. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-button.js +1 -1
  20. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-carousel.js +12 -5
  21. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-collapse.js +4 -3
  22. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-dropdown.js +66 -16
  23. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-modal.js +95 -74
  24. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-popover.js +9 -4
  25. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-scrollspy.js +9 -9
  26. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tab.js +2 -2
  27. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tooltip.js +15 -15
  28. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-transition.js +2 -3
  29. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-typeahead.js +51 -40
  30. data/vendor/toolkit/fontawesome.less +5 -5
  31. data/vendor/toolkit/twitter/bootstrap/accordion.less +3 -2
  32. data/vendor/toolkit/twitter/bootstrap/alerts.less +16 -9
  33. data/vendor/toolkit/twitter/bootstrap/bootstrap.less +1 -1
  34. data/vendor/toolkit/twitter/bootstrap/breadcrumbs.less +10 -10
  35. data/vendor/toolkit/twitter/bootstrap/button-groups.less +76 -23
  36. data/vendor/toolkit/twitter/bootstrap/buttons.less +85 -65
  37. data/vendor/toolkit/twitter/bootstrap/carousel.less +13 -3
  38. data/vendor/toolkit/twitter/bootstrap/close.less +4 -2
  39. data/vendor/toolkit/twitter/bootstrap/code.less +6 -5
  40. data/vendor/toolkit/twitter/bootstrap/component-animations.less +5 -2
  41. data/vendor/toolkit/twitter/bootstrap/dropdowns.less +81 -14
  42. data/vendor/toolkit/twitter/bootstrap/forms.less +100 -48
  43. data/vendor/toolkit/twitter/bootstrap/grid.less +17 -1
  44. data/vendor/toolkit/twitter/bootstrap/hero-unit.less +4 -2
  45. data/vendor/toolkit/twitter/bootstrap/labels-badges.less +19 -2
  46. data/vendor/toolkit/twitter/bootstrap/layouts.less +1 -2
  47. data/vendor/toolkit/twitter/bootstrap/mixins.less +98 -73
  48. data/vendor/toolkit/twitter/bootstrap/modals.less +9 -2
  49. data/vendor/toolkit/twitter/bootstrap/navbar.less +238 -127
  50. data/vendor/toolkit/twitter/bootstrap/navs.less +38 -17
  51. data/vendor/toolkit/twitter/bootstrap/pager.less +5 -4
  52. data/vendor/toolkit/twitter/bootstrap/pagination.less +16 -8
  53. data/vendor/toolkit/twitter/bootstrap/popovers.less +101 -33
  54. data/vendor/toolkit/twitter/bootstrap/progress-bars.less +18 -13
  55. data/vendor/toolkit/twitter/bootstrap/reset.less +6 -3
  56. data/vendor/toolkit/twitter/bootstrap/responsive-1200px-min.less +9 -7
  57. data/vendor/toolkit/twitter/bootstrap/responsive-767px-max.less +86 -68
  58. data/vendor/toolkit/twitter/bootstrap/responsive-768px-979px.less +7 -5
  59. data/vendor/toolkit/twitter/bootstrap/responsive-navbar.less +18 -5
  60. data/vendor/toolkit/twitter/bootstrap/responsive-utilities.less +17 -15
  61. data/vendor/toolkit/twitter/bootstrap/responsive.less +5 -5
  62. data/vendor/toolkit/twitter/bootstrap/scaffolding.less +26 -4
  63. data/vendor/toolkit/twitter/bootstrap/sprites.less +15 -19
  64. data/vendor/toolkit/twitter/bootstrap/tables.less +60 -11
  65. data/vendor/toolkit/twitter/bootstrap/thumbnails.less +9 -4
  66. data/vendor/toolkit/twitter/bootstrap/tooltip.less +47 -12
  67. data/vendor/toolkit/twitter/bootstrap/type.less +57 -92
  68. data/vendor/toolkit/twitter/bootstrap/utilities.less +9 -2
  69. data/vendor/toolkit/twitter/bootstrap/variables.less +100 -29
  70. data/vendor/toolkit/twitter/bootstrap/wells.less +7 -5
  71. metadata +16 -22
@@ -1,5 +1,5 @@
1
1
  /* =========================================================
2
- * bootstrap-modal.js v2.0.4
2
+ * bootstrap-modal.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#modals
4
4
  * =========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -26,10 +26,11 @@
26
26
  /* MODAL CLASS DEFINITION
27
27
  * ====================== */
28
28
 
29
- var Modal = function (content, options) {
29
+ var Modal = function (element, options) {
30
30
  this.options = options
31
- this.$element = $(content)
31
+ this.$element = $(element)
32
32
  .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
33
+ this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
33
34
  }
34
35
 
35
36
  Modal.prototype = {
@@ -52,8 +53,9 @@
52
53
 
53
54
  this.isShown = true
54
55
 
55
- escape.call(this)
56
- backdrop.call(this, function () {
56
+ this.escape()
57
+
58
+ this.backdrop(function () {
57
59
  var transition = $.support.transition && that.$element.hasClass('fade')
58
60
 
59
61
  if (!that.$element.parent().length) {
@@ -67,7 +69,12 @@
67
69
  that.$element[0].offsetWidth // force reflow
68
70
  }
69
71
 
70
- that.$element.addClass('in')
72
+ that.$element
73
+ .addClass('in')
74
+ .attr('aria-hidden', false)
75
+ .focus()
76
+
77
+ that.enforceFocus()
71
78
 
72
79
  transition ?
73
80
  that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
@@ -91,90 +98,98 @@
91
98
 
92
99
  $('body').removeClass('modal-open')
93
100
 
94
- escape.call(this)
101
+ this.escape()
102
+
103
+ $(document).off('focusin.modal')
95
104
 
96
- this.$element.removeClass('in')
105
+ this.$element
106
+ .removeClass('in')
107
+ .attr('aria-hidden', true)
97
108
 
98
109
  $.support.transition && this.$element.hasClass('fade') ?
99
- hideWithTransition.call(this) :
100
- hideModal.call(this)
110
+ this.hideWithTransition() :
111
+ this.hideModal()
101
112
  }
102
113
 
103
- }
104
-
105
-
106
- /* MODAL PRIVATE METHODS
107
- * ===================== */
108
-
109
- function hideWithTransition() {
110
- var that = this
111
- , timeout = setTimeout(function () {
112
- that.$element.off($.support.transition.end)
113
- hideModal.call(that)
114
- }, 500)
114
+ , enforceFocus: function () {
115
+ var that = this
116
+ $(document).on('focusin.modal', function (e) {
117
+ if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
118
+ that.$element.focus()
119
+ }
120
+ })
121
+ }
115
122
 
116
- this.$element.one($.support.transition.end, function () {
117
- clearTimeout(timeout)
118
- hideModal.call(that)
119
- })
120
- }
123
+ , escape: function () {
124
+ var that = this
125
+ if (this.isShown && this.options.keyboard) {
126
+ this.$element.on('keyup.dismiss.modal', function ( e ) {
127
+ e.which == 27 && that.hide()
128
+ })
129
+ } else if (!this.isShown) {
130
+ this.$element.off('keyup.dismiss.modal')
131
+ }
132
+ }
121
133
 
122
- function hideModal(that) {
123
- this.$element
124
- .hide()
125
- .trigger('hidden')
134
+ , hideWithTransition: function () {
135
+ var that = this
136
+ , timeout = setTimeout(function () {
137
+ that.$element.off($.support.transition.end)
138
+ that.hideModal()
139
+ }, 500)
140
+
141
+ this.$element.one($.support.transition.end, function () {
142
+ clearTimeout(timeout)
143
+ that.hideModal()
144
+ })
145
+ }
126
146
 
127
- backdrop.call(this)
128
- }
147
+ , hideModal: function (that) {
148
+ this.$element
149
+ .hide()
150
+ .trigger('hidden')
129
151
 
130
- function backdrop(callback) {
131
- var that = this
132
- , animate = this.$element.hasClass('fade') ? 'fade' : ''
152
+ this.backdrop()
153
+ }
133
154
 
134
- if (this.isShown && this.options.backdrop) {
135
- var doAnimate = $.support.transition && animate
155
+ , removeBackdrop: function () {
156
+ this.$backdrop.remove()
157
+ this.$backdrop = null
158
+ }
136
159
 
137
- this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
138
- .appendTo(document.body)
160
+ , backdrop: function (callback) {
161
+ var that = this
162
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
139
163
 
140
- if (this.options.backdrop != 'static') {
141
- this.$backdrop.click($.proxy(this.hide, this))
142
- }
164
+ if (this.isShown && this.options.backdrop) {
165
+ var doAnimate = $.support.transition && animate
143
166
 
144
- if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
167
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
168
+ .appendTo(document.body)
145
169
 
146
- this.$backdrop.addClass('in')
170
+ if (this.options.backdrop != 'static') {
171
+ this.$backdrop.click($.proxy(this.hide, this))
172
+ }
147
173
 
148
- doAnimate ?
149
- this.$backdrop.one($.support.transition.end, callback) :
150
- callback()
174
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
151
175
 
152
- } else if (!this.isShown && this.$backdrop) {
153
- this.$backdrop.removeClass('in')
176
+ this.$backdrop.addClass('in')
154
177
 
155
- $.support.transition && this.$element.hasClass('fade')?
156
- this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
157
- removeBackdrop.call(this)
178
+ doAnimate ?
179
+ this.$backdrop.one($.support.transition.end, callback) :
180
+ callback()
158
181
 
159
- } else if (callback) {
160
- callback()
161
- }
162
- }
182
+ } else if (!this.isShown && this.$backdrop) {
183
+ this.$backdrop.removeClass('in')
163
184
 
164
- function removeBackdrop() {
165
- this.$backdrop.remove()
166
- this.$backdrop = null
167
- }
185
+ $.support.transition && this.$element.hasClass('fade')?
186
+ this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
187
+ this.removeBackdrop()
168
188
 
169
- function escape() {
170
- var that = this
171
- if (this.isShown && this.options.keyboard) {
172
- $(document).on('keyup.dismiss.modal', function ( e ) {
173
- e.which == 27 && that.hide()
174
- })
175
- } else if (!this.isShown) {
176
- $(document).off('keyup.dismiss.modal')
177
- }
189
+ } else if (callback) {
190
+ callback()
191
+ }
192
+ }
178
193
  }
179
194
 
180
195
 
@@ -206,12 +221,18 @@
206
221
 
207
222
  $(function () {
208
223
  $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
209
- var $this = $(this), href
210
- , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
211
- , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
224
+ var $this = $(this)
225
+ , href = $this.attr('href')
226
+ , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
227
+ , option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
212
228
 
213
229
  e.preventDefault()
214
- $target.modal(option)
230
+
231
+ $target
232
+ .modal(option)
233
+ .one('hide', function () {
234
+ $this.focus()
235
+ })
215
236
  })
216
237
  })
217
238
 
@@ -1,5 +1,5 @@
1
1
  /* ===========================================================
2
- * bootstrap-popover.js v2.0.4
2
+ * bootstrap-popover.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#popovers
4
4
  * ===========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -26,7 +26,7 @@
26
26
  /* POPOVER PUBLIC CLASS DEFINITION
27
27
  * =============================== */
28
28
 
29
- var Popover = function ( element, options ) {
29
+ var Popover = function (element, options) {
30
30
  this.init('popover', element, options)
31
31
  }
32
32
 
@@ -43,8 +43,8 @@
43
43
  , title = this.getTitle()
44
44
  , content = this.getContent()
45
45
 
46
- $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)
47
- $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content)
46
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
47
+ $tip.find('.popover-content > *')[this.options.html ? 'html' : 'text'](content)
48
48
 
49
49
  $tip.removeClass('fade top bottom left right in')
50
50
  }
@@ -71,6 +71,10 @@
71
71
  return this.$tip
72
72
  }
73
73
 
74
+ , destroy: function () {
75
+ this.hide().$element.off('.' + this.type).removeData(this.type)
76
+ }
77
+
74
78
  })
75
79
 
76
80
 
@@ -91,6 +95,7 @@
91
95
 
92
96
  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
93
97
  placement: 'right'
98
+ , trigger: 'click'
94
99
  , content: ''
95
100
  , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
96
101
  })
@@ -1,5 +1,5 @@
1
1
  /* =============================================================
2
- * bootstrap-scrollspy.js v2.0.4
2
+ * bootstrap-scrollspy.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#scrollspy
4
4
  * =============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -23,15 +23,15 @@
23
23
  "use strict"; // jshint ;_;
24
24
 
25
25
 
26
- /* SCROLLSPY CLASS DEFINITION
27
- * ========================== */
26
+ /* SCROLLSPY CLASS DEFINITION
27
+ * ========================== */
28
28
 
29
- function ScrollSpy( element, options) {
29
+ function ScrollSpy(element, options) {
30
30
  var process = $.proxy(this.process, this)
31
31
  , $element = $(element).is('body') ? $(window) : $(element)
32
32
  , href
33
33
  this.options = $.extend({}, $.fn.scrollspy.defaults, options)
34
- this.$scrollElement = $element.on('scroll.scroll.data-api', process)
34
+ this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
35
35
  this.selector = (this.options.target
36
36
  || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
37
37
  || '') + ' .nav li > a'
@@ -58,7 +58,7 @@
58
58
  , href = $el.data('target') || $el.attr('href')
59
59
  , $href = /^#\w/.test(href) && $(href)
60
60
  return ( $href
61
- && href.length
61
+ && $href.length
62
62
  && [[ $href.position().top, href ]] ) || null
63
63
  })
64
64
  .sort(function (a, b) { return a[0] - b[0] })
@@ -108,7 +108,7 @@
108
108
  .parent('li')
109
109
  .addClass('active')
110
110
 
111
- if (active.parent('.dropdown-menu')) {
111
+ if (active.parent('.dropdown-menu').length) {
112
112
  active = active.closest('li.dropdown').addClass('active')
113
113
  }
114
114
 
@@ -121,7 +121,7 @@
121
121
  /* SCROLLSPY PLUGIN DEFINITION
122
122
  * =========================== */
123
123
 
124
- $.fn.scrollspy = function ( option ) {
124
+ $.fn.scrollspy = function (option) {
125
125
  return this.each(function () {
126
126
  var $this = $(this)
127
127
  , data = $this.data('scrollspy')
@@ -141,7 +141,7 @@
141
141
  /* SCROLLSPY DATA-API
142
142
  * ================== */
143
143
 
144
- $(function () {
144
+ $(window).on('load', function () {
145
145
  $('[data-spy="scroll"]').each(function () {
146
146
  var $spy = $(this)
147
147
  $spy.scrollspy($spy.data())
@@ -1,5 +1,5 @@
1
1
  /* ========================================================
2
- * bootstrap-tab.js v2.0.4
2
+ * bootstrap-tab.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#tabs
4
4
  * ========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -26,7 +26,7 @@
26
26
  /* TAB CLASS DEFINITION
27
27
  * ==================== */
28
28
 
29
- var Tab = function ( element ) {
29
+ var Tab = function (element) {
30
30
  this.element = $(element)
31
31
  }
32
32
 
@@ -1,5 +1,5 @@
1
1
  /* ===========================================================
2
- * bootstrap-tooltip.js v2.0.4
2
+ * bootstrap-tooltip.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#tooltips
4
4
  * Inspired by the original jQuery.tipsy by Jason Frame
5
5
  * ===========================================================
@@ -44,11 +44,13 @@
44
44
  this.options = this.getOptions(options)
45
45
  this.enabled = true
46
46
 
47
- if (this.options.trigger != 'manual') {
48
- eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
47
+ if (this.options.trigger == 'click') {
48
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
49
+ } else if (this.options.trigger != 'manual') {
50
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
49
51
  eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
50
- this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
51
- this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
52
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
53
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
52
54
  }
53
55
 
54
56
  this.options.selector ?
@@ -148,20 +150,11 @@
148
150
  }
149
151
  }
150
152
 
151
- , isHTML: function(text) {
152
- // html string detection logic adapted from jQuery
153
- return typeof text != 'string'
154
- || ( text.charAt(0) === "<"
155
- && text.charAt( text.length - 1 ) === ">"
156
- && text.length >= 3
157
- ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text)
158
- }
159
-
160
153
  , setContent: function () {
161
154
  var $tip = this.tip()
162
155
  , title = this.getTitle()
163
156
 
164
- $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)
157
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
165
158
  $tip.removeClass('fade in top bottom left right')
166
159
  }
167
160
 
@@ -185,6 +178,8 @@
185
178
  $.support.transition && this.$tip.hasClass('fade') ?
186
179
  removeWithAnimation() :
187
180
  $tip.remove()
181
+
182
+ return this
188
183
  }
189
184
 
190
185
  , fixTitle: function () {
@@ -244,6 +239,10 @@
244
239
  this[this.tip().hasClass('in') ? 'hide' : 'show']()
245
240
  }
246
241
 
242
+ , destroy: function () {
243
+ this.hide().$element.off('.' + this.type).removeData(this.type)
244
+ }
245
+
247
246
  }
248
247
 
249
248
 
@@ -270,6 +269,7 @@
270
269
  , trigger: 'hover'
271
270
  , title: ''
272
271
  , delay: 0
272
+ , html: true
273
273
  }
274
274
 
275
275
  }(window.jQuery);
@@ -1,5 +1,5 @@
1
1
  /* ===================================================
2
- * bootstrap-transition.js v2.0.4
2
+ * bootstrap-transition.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#transitions
4
4
  * ===================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -36,8 +36,7 @@
36
36
  , transEndEventNames = {
37
37
  'WebkitTransition' : 'webkitTransitionEnd'
38
38
  , 'MozTransition' : 'transitionend'
39
- , 'OTransition' : 'oTransitionEnd'
40
- , 'msTransition' : 'MSTransitionEnd'
39
+ , 'OTransition' : 'oTransitionEnd otransitionend'
41
40
  , 'transition' : 'transitionend'
42
41
  }
43
42
  , name
@@ -1,5 +1,5 @@
1
1
  /* =============================================================
2
- * bootstrap-typeahead.js v2.0.4
2
+ * bootstrap-typeahead.js v2.1.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#typeahead
4
4
  * =============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -77,17 +77,23 @@
77
77
  }
78
78
 
79
79
  , lookup: function (event) {
80
- var that = this
81
- , items
82
- , q
80
+ var items
83
81
 
84
82
  this.query = this.$element.val()
85
83
 
86
- if (!this.query) {
84
+ if (!this.query || this.query.length < this.options.minLength) {
87
85
  return this.shown ? this.hide() : this
88
86
  }
89
87
 
90
- items = $.grep(this.source, function (item) {
88
+ items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
89
+
90
+ return items ? this.process(items) : this
91
+ }
92
+
93
+ , process: function (items) {
94
+ var that = this
95
+
96
+ items = $.grep(items, function (item) {
91
97
  return that.matcher(item)
92
98
  })
93
99
 
@@ -169,7 +175,7 @@
169
175
  .on('keyup', $.proxy(this.keyup, this))
170
176
 
171
177
  if ($.browser.webkit || $.browser.msie) {
172
- this.$element.on('keydown', $.proxy(this.keypress, this))
178
+ this.$element.on('keydown', $.proxy(this.keydown, this))
173
179
  }
174
180
 
175
181
  this.$menu
@@ -177,6 +183,40 @@
177
183
  .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
178
184
  }
179
185
 
186
+ , move: function (e) {
187
+ if (!this.shown) return
188
+
189
+ switch(e.keyCode) {
190
+ case 9: // tab
191
+ case 13: // enter
192
+ case 27: // escape
193
+ e.preventDefault()
194
+ break
195
+
196
+ case 38: // up arrow
197
+ e.preventDefault()
198
+ this.prev()
199
+ break
200
+
201
+ case 40: // down arrow
202
+ e.preventDefault()
203
+ this.next()
204
+ break
205
+ }
206
+
207
+ e.stopPropagation()
208
+ }
209
+
210
+ , keydown: function (e) {
211
+ this.suppressKeyPressRepeat = !~$.inArray(e.keyCode, [40,38,9,13,27])
212
+ this.move(e)
213
+ }
214
+
215
+ , keypress: function (e) {
216
+ if (this.suppressKeyPressRepeat) return
217
+ this.move(e)
218
+ }
219
+
180
220
  , keyup: function (e) {
181
221
  switch(e.keyCode) {
182
222
  case 40: // down arrow
@@ -202,39 +242,9 @@
202
242
  e.preventDefault()
203
243
  }
204
244
 
205
- , keypress: function (e) {
206
- if (!this.shown) return
207
-
208
- switch(e.keyCode) {
209
- case 9: // tab
210
- case 13: // enter
211
- case 27: // escape
212
- e.preventDefault()
213
- break
214
-
215
- case 38: // up arrow
216
- if (e.type != 'keydown') break
217
- e.preventDefault()
218
- this.prev()
219
- break
220
-
221
- case 40: // down arrow
222
- if (e.type != 'keydown') break
223
- e.preventDefault()
224
- this.next()
225
- break
226
- }
227
-
228
- e.stopPropagation()
229
- }
230
-
231
245
  , blur: function (e) {
232
246
  var that = this
233
- setTimeout(function () {
234
- if (!that.$menu.is(':hover')) {
235
- that.hide();
236
- }
237
- }, 150)
247
+ setTimeout(function () { that.hide() }, 150)
238
248
  }
239
249
 
240
250
  , click: function (e) {
@@ -269,12 +279,13 @@
269
279
  , items: 8
270
280
  , menu: '<ul class="typeahead dropdown-menu"></ul>'
271
281
  , item: '<li><a href="#"></a></li>'
282
+ , minLength: 1
272
283
  }
273
284
 
274
285
  $.fn.typeahead.Constructor = Typeahead
275
286
 
276
287
 
277
- /* TYPEAHEAD DATA-API
288
+ /* TYPEAHEAD DATA-API
278
289
  * ================== */
279
290
 
280
291
  $(function () {
@@ -286,4 +297,4 @@
286
297
  })
287
298
  })
288
299
 
289
- }(window.jQuery);
300
+ }(window.jQuery);