vendor: 8,557 bytes, lines 1-330
1/* ============================================================= 2 * bootstrap-mml_typeahead.js v2.3.2 3 * http://twbs.github.com/bootstrap/javascript.html#mml_typeahead 4 * ============================================================= 5 * Copyright 2013 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 MML_Typeahead = function (element, options) { 30 this.$element = $(element) 31 this.options = $.extend({}, $.fn.mml_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.source = this.options.source 37 this.$menu = $(this.options.menu) 38 this.shown = false 39 this.listen() 40 } 41 42 MML_Typeahead.prototype = { 43 44 constructor: MML_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.position(), { 60 height: this.$element[0].offsetHeight 61 }) 62 63 this.$menu 64 .insertAfter(this.$element) 65 .css({ 66 top: pos.top + pos.height 67 }) 68 .show() 69 70 this.shown = true 71 return this 72 } 73 74 , hide: function () { 75 this.$menu.hide() 76 this.shown = false 77 return this 78 } 79 80 , lookup: function (event) { 81 var items 82 83 this.query = this.$element.val() 84 85 if (!this.query || this.query.length < this.options.minLength) { 86 return this.shown ? this.hide() : this 87 } 88 89 items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source 90 91 return items ? this.process(items) : this 92 } 93 94 , process: function (items) { 95 var that = this 96 97 items = $.grep(items, function (item) { 98 return that.matcher(item) 99 }) 100 101 items = this.sorter(items) 102 103 if (!items.length) { 104 return this.shown ? this.hide() : this 105 } 106 107 return this.render(items.slice(0, this.options.items)).show() 108 } 109 110 , matcher: function (item) { 111 return ~item.toLowerCase().indexOf(this.query.toLowerCase()) 112 } 113 114 , sorter: function (items) { 115 var beginswith = [] 116 , caseSensitive = [] 117 , caseInsensitive = [] 118 , item 119 120 while (item = items.shift()) { 121 if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item) 122 else if (~item.indexOf(this.query)) caseSensitive.push(item) 123 else caseInsensitive.push(item) 124 } 125 126 return beginswith.concat(caseSensitive, caseInsensitive) 127 } 128 129 , highlighter: function (item) { 130 var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') 131 return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { 132 return '<strong>' + match + '</strong>' 133 }) 134 } 135 136 , render: function (items) { 137 var that = this 138 139 items = $(items).map(function (i, item) { 140 i = $(that.options.item).attr('data-value', item) 141 i.find('a').html(that.highlighter(item)) 142 return i[0] 143 }) 144 145 items.first().addClass('active') 146 this.$menu.html(items) 147 return this 148 } 149 150 , next: function (event) { 151 var active = this.$menu.find('.active').removeClass('active') 152 , next = active.next() 153 154 if (!next.length) { 155 next = $(this.$menu.find('li')[0]) 156 } 157 158 next.addClass('active') 159 } 160 161 , prev: function (event) { 162 var active = this.$menu.find('.active').removeClass('active') 163 , prev = active.prev() 164 165 if (!prev.length) { 166 prev = this.$menu.find('li').last() 167 } 168 169 prev.addClass('active') 170 } 171 172 , listen: function () { 173 this.$element 174 .on('focus', $.proxy(this.focus, this)) 175 .on('blur', $.proxy(this.blur, this)) 176 .on('keypress', $.proxy(this.keypress, this)) 177 .on('keyup', $.proxy(this.keyup, this)) 178 179 if (this.eventSupported('keydown')) { 180 this.$element.on('keydown', $.proxy(this.keydown, this)) 181 } 182 183 this.$menu 184 .on('click', $.proxy(this.click, this)) 185 .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) 186 .on('mouseleave', 'li', $.proxy(this.mouseleave, this)); 187 } 188 189 , eventSupported: function(eventName) { 190 var isSupported = eventName in this.$element 191 if (!isSupported) { 192 this.$element.setAttribute(eventName, 'return;') 193 isSupported = typeof this.$element[eventName] === 'function' 194 } 195 return isSupported 196 } 197 198 , move: function (e) { 199 if (!this.shown) return 200 201 switch(e.keyCode) { 202 case 9: // tab 203 case 13: // enter 204 case 27: // escape 205 e.preventDefault() 206 break 207 208 case 38: // up arrow 209 e.preventDefault() 210 this.prev() 211 break 212 213 case 40: // down arrow 214 e.preventDefault() 215 this.next() 216 break 217 } 218 219 e.stopPropagation() 220 } 221 222 , keydown: function (e) { 223 this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]) 224 this.move(e) 225 } 226 227 , keypress: function (e) { 228 if (this.suppressKeyPressRepeat) return 229 this.move(e) 230 } 231 232 , keyup: function (e) { 233 switch(e.keyCode) { 234 case 40: // down arrow 235 case 38: // up arrow 236 case 16: // shift 237 case 17: // ctrl 238 case 18: // alt 239 break 240 241 case 9: // tab 242 case 13: // enter 243 if (!this.shown) return 244 this.select() 245 break 246 247 case 27: // escape 248 if (!this.shown) return 249 this.hide() 250 break 251 252 default: 253 this.lookup() 254 } 255 256 e.stopPropagation() 257 e.preventDefault() 258 } 259 260 , focus: function (e) { 261 this.focused = true 262 } 263 264 , blur: function (e) { 265 this.focused = false 266 if (!this.mousedover && this.shown) this.hide() 267 } 268 269 , click: function (e) { 270 e.stopPropagation() 271 e.preventDefault() 272 this.select() 273 this.$element.focus() 274 setTimeout( function () { 275 $('#step2').submit(); 276 }, 500); 277 } 278 279 , mouseenter: function (e) { 280 this.mousedover = true 281 this.$menu.find('.active').removeClass('active') 282 $(e.currentTarget).addClass('active') 283 } 284 285 , mouseleave: function (e) { 286 this.mousedover = false 287 if (!this.focused && this.shown) this.hide() 288 } 289 290 } 291 292 293 /* TYPEAHEAD PLUGIN DEFINITION 294 * =========================== */ 295 296 var old = $.fn.mml_typeahead 297 298 $.fn.mml_typeahead = function (option) { 299 return this.each(function () { 300 var $this = $(this) 301 , data = $this.data('mml_typeahead') 302 , options = typeof option == 'object' && option 303 if (!data) $this.data('mml_typeahead', (data = new MML_Typeahead(this, options))) 304 if (typeof option == 'string') data[option]() 305 }) 306 } 307 308 $.fn.mml_typeahead.defaults = { 309 source: [] 310 , items: 8 311 , menu: '<ul class="mml_typeahead dropdown-menu"></ul>' 312 , item: '<li><a href="#"></a></li>' 313 , minLength: 1 314 } 315 316 $.fn.mml_typeahead.Constructor = MML_Typeahead 317 318 319 /* TYPEAHEAD NO CONFLICT 320 * =================== */ 321 322 $.fn.mml_typeahead.noConflict = function () { 323 $.fn.mml_typeahead = old 324 return this 325 } 326 327 328 /* TYPEAHEAD DATA-API 329 * ================== */ 330
331 $(document).on('focus.mml_typeahead.data-api', '[data-provide="mml_typeahead"]', function (e) { 332 var $this = $(this) 333 if ($this.data('mml_typeahead')) return 334 $this.mml_typeahead($this.data()) 335 }) 336 337}(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.