diff --git a/ordr2/static/js/bootstrap-typeahead.js b/ordr2/static/js/bootstrap-typeahead.js index 1426185..9cc84d8 100755 --- a/ordr2/static/js/bootstrap-typeahead.js +++ b/ordr2/static/js/bootstrap-typeahead.js @@ -1,8 +1,8 @@ /* ============================================================= - * bootstrap-typeahead.js v2.0.0 - * http://twitter.github.com/bootstrap/javascript.html#typeahead + * bootstrap-typeahead.js v2.3.2 + * http://getbootstrap.com/2.3.2/javascript.html#typeahead * ============================================================= - * Copyright 2012 Twitter, Inc. + * Copyright 2013 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,18 +17,24 @@ * limitations under the License. * ============================================================ */ -!function( $ ){ - "use strict" +!function($){ - var Typeahead = function ( element, options ) { + "use strict"; // jshint ;_; + + + /* TYPEAHEAD PUBLIC CLASS DEFINITION + * ================================= */ + + var Typeahead = function (element, options) { this.$element = $(element) this.options = $.extend({}, $.fn.typeahead.defaults, options) 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.updater = this.options.updater || this.updater this.source = this.options.source + this.$menu = $(this.options.menu) this.shown = false this.listen() } @@ -39,21 +45,29 @@ , select: function () { var val = this.$menu.find('.active').attr('data-value') - this.$element.val(val) + this.$element + .val(this.updater(val)) + .change() return this.hide() } + , updater: function (item) { + return item + } + , show: function () { - var pos = $.extend({}, this.$element.offset(), { + var pos = $.extend({}, this.$element.position(), { height: this.$element[0].offsetHeight }) - this.$menu.css({ - top: pos.top + pos.height - , left: pos.left - }) + this.$menu + .insertAfter(this.$element) + .css({ + top: pos.top + pos.height + , left: pos.left + }) + .show() - this.$menu.show() this.shown = true return this } @@ -65,18 +79,24 @@ } , lookup: function (event) { - var that = this - , items - , q + var items this.query = this.$element.val() - if (!this.query) { + if (!this.query || this.query.length < this.options.minLength) { return this.shown ? this.hide() : this } - items = $.grep(this.source, function (item) { - if (that.matcher(item)) return item + items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source + + return items ? this.process(items) : this + } + + , process: function (items) { + var that = this + + items = $.grep(items, function (item) { + return that.matcher(item) }) items = this.sorter(items) @@ -108,7 +128,8 @@ } , highlighter: function (item) { - return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) { + var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') + return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { return '' + match + '' }) } @@ -151,26 +172,71 @@ , listen: function () { this.$element + .on('focus', $.proxy(this.focus, this)) .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)) + if (this.eventSupported('keydown')) { + this.$element.on('keydown', $.proxy(this.keydown, this)) } this.$menu .on('click', $.proxy(this.click, this)) .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) + .on('mouseleave', 'li', $.proxy(this.mouseleave, this)) } - , keyup: function (e) { + , eventSupported: function(eventName) { + var isSupported = eventName in this.$element + if (!isSupported) { + this.$element.setAttribute(eventName, 'return;') + isSupported = typeof this.$element[eventName] === 'function' + } + return isSupported + } + + , move: function (e) { + if (!this.shown) return + + switch(e.keyCode) { + case 9: // tab + case 13: // enter + case 27: // escape + e.preventDefault() + break + + case 38: // up arrow + e.preventDefault() + this.prev() + break + + case 40: // down arrow + e.preventDefault() + this.next() + break + } + e.stopPropagation() - e.preventDefault() + } + + , keydown: function (e) { + this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]) + this.move(e) + } + , keypress: function (e) { + if (this.suppressKeyPressRepeat) return + this.move(e) + } + + , keyup: function (e) { switch(e.keyCode) { case 40: // down arrow case 38: // up arrow + case 16: // shift + case 17: // ctrl + case 18: // alt break case 9: // tab @@ -180,6 +246,7 @@ break case 27: // escape + if (!this.shown) return this.hide() break @@ -187,56 +254,46 @@ this.lookup() } - } - - , keypress: function (e) { e.stopPropagation() - if (!this.shown) return - - switch(e.keyCode) { - case 9: // tab - case 13: // enter - case 27: // escape - e.preventDefault() - break - - case 38: // up arrow - e.preventDefault() - this.prev() - break + e.preventDefault() + } - case 40: // down arrow - e.preventDefault() - this.next() - break - } + , focus: function (e) { + this.focused = true } , blur: function (e) { - var that = this - e.stopPropagation() - e.preventDefault() - setTimeout(function () { that.hide() }, 150) + this.focused = false + if (!this.mousedover && this.shown) this.hide() } , click: function (e) { e.stopPropagation() e.preventDefault() this.select() + this.$element.focus() } , mouseenter: function (e) { + this.mousedover = true this.$menu.find('.active').removeClass('active') $(e.currentTarget).addClass('active') } + , mouseleave: function (e) { + this.mousedover = false + if (!this.focused && this.shown) this.hide() + } + } /* TYPEAHEAD PLUGIN DEFINITION * =========================== */ - $.fn.typeahead = function ( option ) { + var old = $.fn.typeahead + + $.fn.typeahead = function (option) { return this.each(function () { var $this = $(this) , data = $this.data('typeahead') @@ -251,21 +308,28 @@ , items: 8 , menu: '' , item: '
  • ' + , minLength: 1 } $.fn.typeahead.Constructor = Typeahead + /* TYPEAHEAD NO CONFLICT + * =================== */ + + $.fn.typeahead.noConflict = function () { + $.fn.typeahead = old + return this + } + + /* 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()) - }) + $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { + var $this = $(this) + if ($this.data('typeahead')) return + $this.typeahead($this.data()) }) -}( window.jQuery ) +}(window.jQuery);