1
/* =============================================================
2
* bootstrap-typeahead.js v2.0.2
3
* http://twitter.github.com/bootstrap/javascript.html#typeahead
4
* =============================================================
5
* Copyright 2012 Twitter, Inc.
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
11
* http://www.apache.org/licenses/LICENSE-2.0
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
18
* ============================================================ */
24
var Typeahead = function ( element, options ) {
25
this.$element = $(element)
26
this.options = $.extend({}, $.fn.typeahead.defaults, options)
27
this.matcher = this.options.matcher || this.matcher
28
this.sorter = this.options.sorter || this.sorter
29
this.highlighter = this.options.highlighter || this.highlighter
30
this.$menu = $(this.options.menu).appendTo('body')
31
this.source = this.options.source
36
Typeahead.prototype = {
38
constructor: Typeahead
40
, select: function () {
41
var val = this.$menu.find('.active').attr('data-value')
42
this.$element.val(val)
43
this.$element.change();
48
var pos = $.extend({}, this.$element.offset(), {
49
height: this.$element[0].offsetHeight
53
top: pos.top + pos.height
68
, lookup: function (event) {
73
this.query = this.$element.val()
76
return this.shown ? this.hide() : this
79
items = $.grep(this.source, function (item) {
80
if (that.matcher(item)) return item
83
items = this.sorter(items)
86
return this.shown ? this.hide() : this
89
return this.render(items.slice(0, this.options.items)).show()
92
, matcher: function (item) {
93
return ~item.toLowerCase().indexOf(this.query.toLowerCase())
96
, sorter: function (items) {
99
, caseInsensitive = []
102
while (item = items.shift()) {
103
if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
104
else if (~item.indexOf(this.query)) caseSensitive.push(item)
105
else caseInsensitive.push(item)
108
return beginswith.concat(caseSensitive, caseInsensitive)
111
, highlighter: function (item) {
112
return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) {
113
return '<strong>' + match + '</strong>'
117
, render: function (items) {
120
items = $(items).map(function (i, item) {
121
i = $(that.options.item).attr('data-value', item)
122
i.find('a').html(that.highlighter(item))
126
items.first().addClass('active')
127
this.$menu.html(items)
131
, next: function (event) {
132
var active = this.$menu.find('.active').removeClass('active')
133
, next = active.next()
136
next = $(this.$menu.find('li')[0])
139
next.addClass('active')
142
, prev: function (event) {
143
var active = this.$menu.find('.active').removeClass('active')
144
, prev = active.prev()
147
prev = this.$menu.find('li').last()
150
prev.addClass('active')
153
, listen: function () {
155
.on('blur', $.proxy(this.blur, this))
156
.on('keypress', $.proxy(this.keypress, this))
157
.on('keyup', $.proxy(this.keyup, this))
159
if ($.browser.webkit || $.browser.msie) {
160
this.$element.on('keydown', $.proxy(this.keypress, this))
164
.on('click', $.proxy(this.click, this))
165
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
168
, keyup: function (e) {
170
case 40: // down arrow
176
if (!this.shown) return
181
if (!this.shown) return
193
, keypress: function (e) {
194
if (!this.shown) return
208
case 40: // down arrow
217
, blur: function (e) {
219
setTimeout(function () { that.hide() }, 150)
222
, click: function (e) {
228
, mouseenter: function (e) {
229
this.$menu.find('.active').removeClass('active')
230
$(e.currentTarget).addClass('active')
236
/* TYPEAHEAD PLUGIN DEFINITION
237
* =========================== */
239
$.fn.typeahead = function ( option ) {
240
return this.each(function () {
242
, data = $this.data('typeahead')
243
, options = typeof option == 'object' && option
244
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
245
if (typeof option == 'string') data[option]()
249
$.fn.typeahead.defaults = {
252
, menu: '<ul class="typeahead dropdown-menu"></ul>'
253
, item: '<li><a href="#"></a></li>'
256
$.fn.typeahead.Constructor = Typeahead
259
/* TYPEAHEAD DATA-API
260
* ================== */
263
$('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
265
if ($this.data('typeahead')) return
267
$this.typeahead($this.data())
b'\\ No newline at end of file'