blob: 09c2fba21e12bd70c5437b8f2c736f4b245a5029 [file] [log] [blame]
/* =============================================================
* bootstrap-combobox.js v1.0.0
* =============================================================
* Copyright 2012 Daniel Farrell
*
* 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 Combobox = function (element, options) {
this.options = $.extend({}, $.fn.combobox.defaults, options)
this.$container = this.setup(element)
this.$element = this.$container.find('input')
this.$button = this.$container.find('.dropdown-toggle')
this.$target = this.$container.find('select')
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.placeholder = this.options.placeholder || this.$target.attr('data-placeholder')
this.$element.attr('placeholder', this.placeholder)
this.shown = false
this.selected = false
this.refresh()
this.listen()
}
/* NOTE: COMBOBOX EXTENDS BOOTSTRAP-TYPEAHEAD.js
========================================== */
Combobox.prototype = $.extend({}, $.fn.typeahead.Constructor.prototype, {
constructor:Combobox, setup:function (element) {
var select = $(element)
, combobox = $(this.options.template)
select.before(combobox)
select.detach()
combobox.append(select)
return combobox
},
parse:function () {
var map = {}
, source = []
, selected = false
this.$target.find('option').each(function () {
var option = $(this)
map[option.text()] = option.val()
source.push(option.text())
if (option.attr('selected')) selected = option.html()
})
this.map = map
if (selected) {
this.$element.val(selected)
this.$container.addClass('combobox-selected')
this.selected = true
}
return source
},
toggle:function () {
if (this.$container.hasClass('combobox-selected')) {
this.clearTarget()
this.$element.val('').focus()
} else {
if (this.shown) {
this.hide()
} else {
this.lookup()
}
}
},
clearTarget:function () {
this.$target.val('')
this.$container.removeClass('combobox-selected')
this.selected = false
this.$target.trigger('change')
},
refresh:function () {
this.source = this.parse()
this.options.items = this.source.length
}
// modified typeahead function adding container and target handling
, select:function () {
var val = this.$menu.find('.active').attr('data-value')
this.$element.val(val)
this.$container.addClass('combobox-selected')
this.$target.val(this.map[val])
this.$target.trigger('change')
this.selected = true
return this.hide()
}
// modified typeahead function removing the blank handling
, lookup:function (event) {
var that = this
, items
, q
this.query = this.$element.val()
items = $.grep(this.source, function (item) {
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()
}
// modified typeahead function adding button handling
, 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))
}
// hide menu hack
this.$button.on('mouseenter', $.proxy(this.addClassOnMouseEnter, this.$button))
.on('mouseleave', $.proxy(this.addClassOnMouseLeave, this.$button));
$(window).on('click', $.proxy(this.hideList, this));
// hide menu hack end
this.$menu
.on('click', $.proxy(this.click, this))
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
this.$button
.on('click', $.proxy(this.toggle, this))
}
// modified typeahead function to clear on type and prevent on moving around
, keyup:function (e) {
switch (e.keyCode) {
case 40: // down arrow
case 39: // right arrow
case 38: // up arrow
case 37: // left arrow
case 36: // home
case 35: // end
case 16: // shift
break
case 9: // tab
case 13: // enter
if (!this.shown) return
this.select()
break
case 27: // escape
if (!this.shown) return
this.hide()
break
default:
this.clearTarget()
this.lookup()
}
e.stopPropagation()
e.preventDefault()
},
addClassOnMouseEnter:function (e) {
console.warn("Enter");
this.addClass('hover');
},
addClassOnMouseLeave:function (e) {
console.warn("Leave");
this.removeClass('hover');
},
// modified typeahead function to only hide menu if it is visible
blur:function (e) {
var that = this
e.stopPropagation()
e.preventDefault()
var val = this.$element.val()
if (!this.selected && val != "") {
this.$element.val("")
this.$target.val("").trigger('change')
}
if (this.shown) {
setTimeout(function () {
that.hide()
}, 150)
}
},
/**
* hide list
* @param e
*/
hideList:function (e) {
if (!this.$button.is(".hover")) {
var that = this;
if (this.shown) {
setTimeout(function () {
that.hide()
}, 150)
}
}
}
})
/* COMBOBOX PLUGIN DEFINITION
* =========================== */
$.fn.combobox = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('combobox')
, options = typeof option == 'object' && option
if (!data) $this.data('combobox', (data = new Combobox(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.combobox.defaults = {
template:'<div class="combobox-container"><input type="text" autocomplete="off" /><span class="add-on btn dropdown-toggle" data-dropdown="dropdown"><span class="caret"/><span class="combobox-clear"><i class="icon-remove"/></span></span></div>',
menu:'<ul class="typeahead typeahead-long dropdown-menu"></ul>',
item:'<li><a href="#"></a></li>', placeholder:null
}
$.fn.combobox.Constructor = Combobox
}(window.jQuery);