0
0
mirror of https://github.com/twbs/bootstrap.git synced 2024-11-29 11:24:18 +01:00
Bootstrap/js/bootstrap-typeahead.js

242 lines
5.7 KiB
JavaScript
Raw Normal View History

2012-01-07 03:30:32 +01:00
/* =============================================================
* bootstrap-typeahead.js v2.0.0
* http://twitter.github.com/bootstrap/javascript.html#collapsible
* =============================================================
2012-01-15 08:28:48 +01:00
* Copyright 2012 Twitter, Inc.
2012-01-07 03:30:32 +01:00
*
* 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
2012-01-08 09:49:38 +01:00
, matcher: function (item, query) {
2012-01-22 06:46:47 +01:00
// ;_; http://jsperf.com/asdfdfasdfa
return ~item.toLowerCase().indexOf(query.toLowerCase())
2012-01-07 03:30:32 +01:00
}
2012-01-08 09:49:38 +01:00
, select: function () {
var val = this.$menu.find('.active').attr('data-value')
this.$element.val(val)
return this.hide()
2012-01-07 03:30:32 +01:00
}
, show: function () {
2012-01-08 09:49:38 +01:00
var pos = $.extend({}, this.$element.offset(), {
height: this.$element[0].offsetHeight
})
this.$menu.css({
top: pos.top + pos.height
, left: pos.left
})
2012-01-07 03:30:32 +01:00
this.$menu.show()
2012-01-08 09:49:38 +01:00
this.shown = true
2012-01-07 03:30:32 +01:00
return this
}
, hide: function () {
this.$menu.hide()
2012-01-08 09:49:38 +01:00
this.shown = false
2012-01-07 03:30:32 +01:00
return this
}
, lookup: function (event) {
var query = this.$element.val()
, that = this
2012-01-08 09:49:38 +01:00
, items
if (!query) {
return this.shown ? this.hide() : this
}
2012-01-07 03:30:32 +01:00
2012-01-08 09:49:38 +01:00
items = this.data.filter(function (item) {
if (that.matcher(item, query)) return item
2012-01-07 03:30:32 +01:00
})
if (!items.length) {
return this.shown ? this.hide() : this
}
2012-01-08 09:49:38 +01:00
return this.render(items.slice(0, this.options.items)).show()
2012-01-07 03:30:32 +01:00
}
2012-01-08 09:49:38 +01:00
, render: function (items) {
2012-01-07 03:30:32 +01:00
var that = this
items = $(items).map(function (i, item) {
2012-01-08 09:49:38 +01:00
i = $(that.options.item).attr('data-value', item)
i.find('a').text(item)
return i[0]
2012-01-07 03:30:32 +01:00
})
items.first().addClass('active')
2012-01-08 09:49:38 +01:00
this.$menu.html(items)
2012-01-07 03:30:32 +01:00
return this
}
, next: function (event) {
var active = this.$menu.find('.active').removeClass('active')
2012-01-08 09:49:38 +01:00
, next = active.next()
if (!next.length) {
next = $(this.$menu.find('li')[0])
}
2012-01-07 03:30:32 +01:00
next.addClass('active')
}
, prev: function (event) {
var active = this.$menu.find('.active').removeClass('active')
2012-01-08 09:49:38 +01:00
, prev = active.prev()
2012-01-07 03:30:32 +01:00
2012-01-08 09:49:38 +01:00
if (!prev.length) {
prev = this.$menu.find('li').last()
}
prev.addClass('active')
2012-01-07 03:30:32 +01:00
}
2012-01-08 09:49:38 +01:00
, keyup: function (e) {
e.stopPropagation()
e.preventDefault()
switch(e.keyCode) {
case 40: // down arrow
case 38: // up arrow
break
2012-01-07 03:30:32 +01:00
case 9: // tab
case 13: // enter
this.select()
break
case 27: // escape
this.hide()
break
default:
this.lookup()
}
2012-01-08 09:49:38 +01:00
2012-01-07 03:30:32 +01:00
}
2012-01-08 09:49:38 +01:00
, keypress: function (e) {
e.stopPropagation()
switch(e.keyCode) {
2012-01-07 03:30:32 +01:00
case 9: // tab
case 13: // enter
case 27: // escape
2012-01-08 09:49:38 +01:00
e.preventDefault()
2012-01-07 03:30:32 +01:00
break
case 38: // up arrow
if (!this.shown) return
2012-01-08 09:49:38 +01:00
e.preventDefault()
2012-01-07 03:30:32 +01:00
this.prev()
break
case 40: // down arrow
if (!this.shown) return
2012-01-08 09:49:38 +01:00
e.preventDefault()
2012-01-07 03:30:32 +01:00
this.next()
break
}
2012-01-08 09:49:38 +01:00
}
, 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')
}
2012-01-07 03:30:32 +01:00
, listen: function () {
this.$element
2012-01-08 09:49:38 +01:00
.on('blur', $.proxy(this.blur, this))
2012-01-07 03:30:32 +01:00
.on('keypress', $.proxy(this.keypress, this))
2012-01-08 09:49:38 +01:00
.on('keyup', $.proxy(this.keyup, this))
2012-01-07 03:30:32 +01:00
if ($.browser.webkit || $.browser.msie) {
2012-01-08 09:49:38 +01:00
this.$element.on('keydown', $.proxy(this.keypress, this))
2012-01-07 03:30:32 +01:00
}
this.$menu
2012-01-08 09:49:38 +01:00
.on('click', $.proxy(this.click, this))
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
2012-01-07 03:30:32 +01:00
}
}
2012-01-08 09:49:38 +01:00
2012-01-07 03:30:32 +01:00
/* TYPEAHEAD PLUGIN DEFINITION
2012-01-08 09:49:38 +01:00
* =========================== */
2012-01-07 03:30:32 +01:00
$.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 = {
2012-01-08 09:49:38 +01:00
items: 8
, menu: '<ul class="typeahead dropdown-menu"></ul>'
, item: '<li><a href="#"></a></li>'
2012-01-07 03:30:32 +01:00
}
$.fn.typeahead.Constructor = Typeahead
2012-01-08 09:49:38 +01:00
/* 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())
})
})
2012-01-07 03:30:32 +01:00
}( window.jQuery )