vendor: 6,825 bytes, lines 1-276
1/* ============================================================= 2 * bootstrap-typeahead.js v2.0.4 3 * http://twitter.github.com/bootstrap/javascript.html#typeahead 4 * ============================================================= 5 * Copyright 2012 Twitter, Inc. 6 * 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 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 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 * ============================================================ */ 19 20 21!function($){ 22 23 "use strict"; // jshint ;_; 24 25 26 /* TYPEAHEAD PUBLIC CLASS DEFINITION 27 * ================================= */ 28 29 var Typeahead = function (element, options) { 30 this.$element = $(element) 31 this.options = $.extend({}, $.fn.typeahead.defaults, options) 32 this.matcher = this.options.matcher || this.matcher 33 this.sorter = this.options.sorter || this.sorter 34 this.highlighter = this.options.highlighter || this.highlighter 35 this.updater = this.options.updater || this.updater 36 this.$menu = $(this.options.menu).appendTo('body') 37 this.source = this.options.source 38 this.shown = false 39 this.listen() 40 } 41 42 Typeahead.prototype = { 43 44 constructor: Typeahead 45 46 , select: function () { 47 var val = this.$menu.find('.active').attr('data-value') 48 this.$element 49 .val(this.updater(val)) 50 .change() 51 return this.hide() 52 } 53 54 , updater: function (item) { 55 return item 56 } 57 58 , show: function () { 59 var pos = $.extend({}, this.$element.offset(), { 60 height: this.$element[0].offsetHeight 61 }) 62 63 this.$menu.css({ 64 top: pos.top + pos.height 65 , left: pos.left 66 }) 67 68 this.$menu.show() 69 this.shown = true 70 return this 71 } 72 73 , hide: function () { 74 this.$menu.hide() 75 this.shown = false 76 return this 77 } 78 79 , lookup: function (event) { 80 var that = this 81 , items 82 , q 83 84 this.query = this.$element.val() 85 86 if (!this.query) { 87 return this.shown ? this.hide() : this 88 } 89 90 items = $.grep(this.source, function (item) { 91 return that.matcher(item) 92 }) 93 94 items = this.sorter(items) 95 96 if (!items.length) { 97 return this.shown ? this.hide() : this 98 } 99 100 return this.render(items.slice(0, this.options.items)).show() 101 } 102 103 , matcher: function (item) { 104 return ~item.toLowerCase().indexOf(this.query.toLowerCase()) 105 } 106 107 , sorter: function (items) { 108 var beginswith = [] 109 , caseSensitive = [] 110 , caseInsensitive = [] 111 , item 112 113 while (item = items.shift()) { 114 if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item) 115 else if (~item.indexOf(this.query)) caseSensitive.push(item) 116 else caseInsensitive.push(item) 117 } 118 119 return beginswith.concat(caseSensitive, caseInsensitive) 120 } 121 122 , highlighter: function (item) { 123 var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') 124 return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { 125 return '<strong>' + match + '</strong>' 126 }) 127 } 128 129 , render: function (items) { 130 var that = this 131 132 items = $(items).map(function (i, item) { 133 i = $(that.options.item).attr('data-value', item) 134 i.find('a').html(that.highlighter(item)) 135 return i[0] 136 }) 137 138 items.first().addClass('active') 139 this.$menu.html(items) 140 return this 141 } 142 143 , next: function (event) { 144 var active = this.$menu.find('.active').removeClass('active') 145 , next = active.next() 146 147 if (!next.length) { 148 next = $(this.$menu.find('li')[0]) 149 } 150 151 next.addClass('active') 152 } 153 154 , prev: function (event) { 155 var active = this.$menu.find('.active').removeClass('active') 156 , prev = active.prev() 157 158 if (!prev.length) { 159 prev = this.$menu.find('li').last() 160 } 161 162 prev.addClass('active') 163 } 164 165 , listen: function () { 166 this.$element 167 .on('blur', $.proxy(this.blur, this)) 168 .on('keypress', $.proxy(this.keypress, this)) 169 .on('keyup', $.proxy(this.keyup, this)) 170 171 if ($.browser.webkit || $.browser.msie) { 172 this.$element.on('keydown', $.proxy(this.keypress, this)) 173 } 174 175 this.$menu 176 .on('click', $.proxy(this.click, this)) 177 .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) 178 } 179 180 , keyup: function (e) { 181 switch(e.keyCode) { 182 case 40: // down arrow 183 case 38: // up arrow 184 break 185 186 case 9: // tab 187 case 13: // enter 188 if (!this.shown) return 189 this.select() 190 break 191 192 case 27: // escape 193 if (!this.shown) return 194 this.hide() 195 break 196 197 default: 198 this.lookup() 199 } 200 201 e.stopPropagation() 202 e.preventDefault() 203 } 204 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 , blur: function (e) { 232 var that = this 233 setTimeout(function () { that.hide() }, 150) 234 } 235 236 , click: function (e) { 237 e.stopPropagation() 238 e.preventDefault() 239 this.select() 240 } 241 242 , mouseenter: function (e) { 243 this.$menu.find('.active').removeClass('active') 244 $(e.currentTarget).addClass('active') 245 } 246 247 } 248 249 250 /* TYPEAHEAD PLUGIN DEFINITION 251 * =========================== */ 252 253 $.fn.typeahead = function (option) { 254 return this.each(function () { 255 var $this = $(this) 256 , data = $this.data('typeahead') 257 , options = typeof option == 'object' && option 258 if (!data) $this.data('typeahead', (data = new Typeahead(this, options))) 259 if (typeof option == 'string') data[option]() 260 }) 261 } 262 263 $.fn.typeahead.defaults = { 264 source: [] 265 , items: 8 266 , menu: '<ul class="typeahead dropdown-menu"></ul>' 267 , item: '<li><a href="#"></a></li>' 268 } 269 270 $.fn.typeahead.Constructor = Typeahead 271 272 273 /* TYPEAHEAD DATA-API 274 * ================== */ 275 276 $(function () {
277 $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { 278 var $this = $(this) 279 if ($this.data('typeahead')) return 280 e.preventDefault() 281 $this.typeahead($this.data()) 282 }) 283 }) 284 285}(window.jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.