vendor: 6,525 bytes, lines 1-184
1/*! 2 * typeahead.js 0.11.1 3 * https://github.com/twitter/typeahead.js 4 * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT 5 * 6 * ##### #### #### #### #### #### #### #### #### 7 * NOTE: This file has been edited and is not the same as the original one! 8 * ##### #### #### #### #### #### #### #### #### 9 */ 10 11// Stylemix custom function check 12function stm_custom_func_checker(func) { 13 return typeof func === "function"; 14} 15 16(function(root, factory) { 17 if (typeof define === "function" && define.amd) { 18 define("bloodhound", [ "jquery" ], function(a0) { 19 return root["Bloodhound"] = factory(a0); 20 }); 21 } else if (typeof exports === "object") { 22 module.exports = factory(require("jquery")); 23 } else { 24 root["Bloodhound"] = factory(jQuery); 25 } 26})(this, function($) { 27 var _ = function() { 28 "use strict"; 29 return { 30 isMsie: function() { 31 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 32 }, 33 isBlankString: function(str) { 34 return !str || /^\s*$/.test(str); 35 }, 36 escapeRegExChars: function(str) { 37 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 38 }, 39 isString: function(obj) { 40 return typeof obj === "string"; 41 }, 42 isNumber: function(obj) { 43 return typeof obj === "number"; 44 }, 45 // isArray: $.isArray, 46 // isFunction: $.isFunction, 47 isObject: $.isPlainObject, 48 isUndefined: function(obj) { 49 return typeof obj === "undefined"; 50 }, 51 isElement: function(obj) { 52 return !!(obj && obj.nodeType === 1); 53 }, 54 isJQuery: function(obj) { 55 return obj instanceof $; 56 }, 57 toStr: function toStr(s) { 58 return _.isUndefined(s) || s === null ? "" : s + ""; 59 }, 60 bind: $.proxy, 61 each: function(collection, cb) { 62 $.each(collection, reverseArgs); 63 function reverseArgs(index, value) { 64 return cb(value, index); 65 } 66 }, 67 map: $.map, 68 filter: $.grep, 69 every: function(obj, test) { 70 var result = true; 71 if (!obj) { 72 return result; 73 } 74 $.each(obj, function(key, val) { 75 if (!(result = test.call(null, val, key, obj))) { 76 return false; 77 } 78 }); 79 return !!result; 80 }, 81 some: function(obj, test) { 82 var result = false; 83 if (!obj) { 84 return result; 85 } 86 $.each(obj, function(key, val) { 87 if (result = test.call(null, val, key, obj)) { 88 return false; 89 } 90 }); 91 return !!result; 92 }, 93 mixin: $.extend, 94 identity: function(x) { 95 return x; 96 }, 97 clone: function(obj) { 98 return $.extend(true, {}, obj); 99 }, 100 getIdGenerator: function() { 101 var counter = 0; 102 return function() { 103 return counter++; 104 }; 105 }, 106 templatify: function templatify(obj) { 107 return stm_custom_func_checker(obj) ? obj : template; 108 function template() { 109 return String(obj); 110 } 111 }, 112 defer: function(fn) { 113 setTimeout(fn, 0); 114 }, 115 debounce: function(func, wait, immediate) { 116 var timeout, result; 117 return function() { 118 var context = this, args = arguments, later, callNow; 119 later = function() { 120 timeout = null; 121 if (!immediate) { 122 result = func.apply(context, args); 123 } 124 }; 125 callNow = immediate && !timeout; 126 clearTimeout(timeout); 127 timeout = setTimeout(later, wait); 128 if (callNow) { 129 result = func.apply(context, args); 130 } 131 return result; 132 }; 133 }, 134 throttle: function(func, wait) { 135 var context, args, timeout, result, previous, later; 136 previous = 0; 137 later = function() { 138 previous = new Date(); 139 timeout = null; 140 result = func.apply(context, args); 141 }; 142 return function() { 143 var now = new Date(), remaining = wait - (now - previous); 144 context = this; 145 args = arguments; 146 if (remaining <= 0) { 147 clearTimeout(timeout); 148 timeout = null; 149 previous = now; 150 result = func.apply(context, args); 151 } else if (!timeout) { 152 timeout = setTimeout(later, remaining); 153 } 154 return result; 155 }; 156 }, 157 stringify: function(val) { 158 return _.isString(val) ? val : JSON.stringify(val); 159 }, 160 noop: function() {} 161 }; 162 }(); 163 var VERSION = "0.11.1"; 164 var tokenizers = function() { 165 "use strict"; 166 return { 167 nonword: nonword, 168 whitespace: whitespace, 169 obj: { 170 nonword: getObjTokenizer(nonword), 171 whitespace: getObjTokenizer(whitespace) 172 } 173 }; 174 function whitespace(str) { 175 str = _.toStr(str); 176 return str ? str.split(/\s+/) : []; 177 } 178 function nonword(str) { 179 str = _.toStr(str); 180 return str ? str.split(/\W+/) : []; 181 } 182 function getObjTokenizer(tokenizer) { 183 return function setKey(keys) { 184 keys = Array
vendor: 9,551 bytes, lines 184-444
184.isArray(keys) ? keys : [].slice.call(arguments, 0); 185 return function tokenize(o) { 186 var tokens = []; 187 _.each(keys, function(k) { 188 tokens = tokens.concat(tokenizer(_.toStr(o[k]))); 189 }); 190 return tokens; 191 }; 192 }; 193 } 194 }(); 195 var LruCache = function() { 196 "use strict"; 197 function LruCache(maxSize) { 198 this.maxSize = _.isNumber(maxSize) ? maxSize : 100; 199 this.reset(); 200 if (this.maxSize <= 0) { 201 this.set = this.get = $.noop; 202 } 203 } 204 _.mixin(LruCache.prototype, { 205 set: function set(key, val) { 206 var tailItem = this.list.tail, node; 207 if (this.size >= this.maxSize) { 208 this.list.remove(tailItem); 209 delete this.hash[tailItem.key]; 210 this.size--; 211 } 212 if (node = this.hash[key]) { 213 node.val = val; 214 this.list.moveToFront(node); 215 } else { 216 node = new Node(key, val); 217 this.list.add(node); 218 this.hash[key] = node; 219 this.size++; 220 } 221 }, 222 get: function get(key) { 223 var node = this.hash[key]; 224 if (node) { 225 this.list.moveToFront(node); 226 return node.val; 227 } 228 }, 229 reset: function reset() { 230 this.size = 0; 231 this.hash = {}; 232 this.list = new List(); 233 } 234 }); 235 function List() { 236 this.head = this.tail = null; 237 } 238 _.mixin(List.prototype, { 239 add: function add(node) { 240 if (this.head) { 241 node.next = this.head; 242 this.head.prev = node; 243 } 244 this.head = node; 245 this.tail = this.tail || node; 246 }, 247 remove: function remove(node) { 248 node.prev ? node.prev.next = node.next : this.head = node.next; 249 node.next ? node.next.prev = node.prev : this.tail = node.prev; 250 }, 251 moveToFront: function(node) { 252 this.remove(node); 253 this.add(node); 254 } 255 }); 256 function Node(key, val) { 257 this.key = key; 258 this.val = val; 259 this.prev = this.next = null; 260 } 261 return LruCache; 262 }(); 263 var PersistentStorage = function() { 264 "use strict"; 265 var LOCAL_STORAGE; 266 try { 267 LOCAL_STORAGE = window.localStorage; 268 LOCAL_STORAGE.setItem("~~~", "!"); 269 LOCAL_STORAGE.removeItem("~~~"); 270 } catch (err) { 271 LOCAL_STORAGE = null; 272 } 273 function PersistentStorage(namespace, override) { 274 this.prefix = [ "__", namespace, "__" ].join(""); 275 this.ttlKey = "__ttl__"; 276 this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); 277 this.ls = override || LOCAL_STORAGE; 278 !this.ls && this._noop(); 279 } 280 _.mixin(PersistentStorage.prototype, { 281 _prefix: function(key) { 282 return this.prefix + key; 283 }, 284 _ttlKey: function(key) { 285 return this._prefix(key) + this.ttlKey; 286 }, 287 _noop: function() { 288 this.get = this.set = this.remove = this.clear = this.isExpired = _.noop; 289 }, 290 _safeSet: function(key, val) { 291 try { 292 this.ls.setItem(key, val); 293 } catch (err) { 294 if (err.name === "QuotaExceededError") { 295 this.clear(); 296 this._noop(); 297 } 298 } 299 }, 300 get: function(key) { 301 if (this.isExpired(key)) { 302 this.remove(key); 303 } 304 return decode(this.ls.getItem(this._prefix(key))); 305 }, 306 set: function(key, val, ttl) { 307 if (_.isNumber(ttl)) { 308 this._safeSet(this._ttlKey(key), encode(now() + ttl)); 309 } else { 310 this.ls.removeItem(this._ttlKey(key)); 311 } 312 return this._safeSet(this._prefix(key), encode(val)); 313 }, 314 remove: function(key) { 315 this.ls.removeItem(this._ttlKey(key)); 316 this.ls.removeItem(this._prefix(key)); 317 return this; 318 }, 319 clear: function() { 320 var i, keys = gatherMatchingKeys(this.keyMatcher); 321 for (i = keys.length; i--; ) { 322 this.remove(keys[i]); 323 } 324 return this; 325 }, 326 isExpired: function(key) { 327 var ttl = decode(this.ls.getItem(this._ttlKey(key))); 328 return _.isNumber(ttl) && now() > ttl ? true : false; 329 } 330 }); 331 return PersistentStorage; 332 function now() { 333 return new Date().getTime(); 334 } 335 function encode(val) { 336 return JSON.stringify(_.isUndefined(val) ? null : val); 337 } 338 function decode(val) { 339 return $.parseJSON(val); 340 } 341 function gatherMatchingKeys(keyMatcher) { 342 var i, key, keys = [], len = LOCAL_STORAGE.length; 343 for (i = 0; i < len; i++) { 344 if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) { 345 keys.push(key.replace(keyMatcher, "")); 346 } 347 } 348 return keys; 349 } 350 }(); 351 var Transport = function() { 352 "use strict"; 353 var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); 354 function Transport(o) { 355 o = o || {}; 356 this.cancelled = false; 357 this.lastReq = null; 358 this._send = o.transport; 359 this._get = o.limiter ? o.limiter(this._get) : this._get; 360 this._cache = o.cache === false ? new LruCache(0) : sharedCache; 361 } 362 Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { 363 maxPendingRequests = num; 364 }; 365 Transport.resetCache = function resetCache() { 366 sharedCache.reset(); 367 }; 368 _.mixin(Transport.prototype, { 369 _fingerprint: function fingerprint(o) { 370 o = o || {}; 371 return o.url + o.type + $.param(o.data || {}); 372 }, 373 _get: function(o, cb) { 374 var that = this, fingerprint, jqXhr; 375 fingerprint = this._fingerprint(o); 376 if (this.cancelled || fingerprint !== this.lastReq) { 377 return; 378 } 379 if (jqXhr = pendingRequests[fingerprint]) { 380 jqXhr.done(done).fail(fail); 381 } else if (pendingRequestsCount < maxPendingRequests) { 382 pendingRequestsCount++; 383 pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always); 384 } else { 385 this.onDeckRequestArgs = [].slice.call(arguments, 0); 386 } 387 function done(resp) { 388 cb(null, resp); 389 that._cache.set(fingerprint, resp); 390 } 391 function fail() { 392 cb(true); 393 } 394 function always() { 395 pendingRequestsCount--; 396 delete pendingRequests[fingerprint]; 397 if (that.onDeckRequestArgs) { 398 that._get.apply(that, that.onDeckRequestArgs); 399 that.onDeckRequestArgs = null; 400 } 401 } 402 }, 403 get: function(o, cb) { 404 var resp, fingerprint; 405 cb = cb || $.noop; 406 o = _.isString(o) ? { 407 url: o 408 } : o || {}; 409 fingerprint = this._fingerprint(o); 410 this.cancelled = false; 411 this.lastReq = fingerprint; 412 if (resp = this._cache.get(fingerprint)) { 413 cb(null, resp); 414 } else { 415 this._get(o, cb); 416 } 417 }, 418 cancel: function() { 419 this.cancelled = true; 420 } 421 }); 422 return Transport; 423 }(); 424 var SearchIndex = window.SearchIndex = function() { 425 "use strict"; 426 var CHILDREN = "c", IDS = "i"; 427 function SearchIndex(o) { 428 o = o || {}; 429 if (!o.datumTokenizer || !o.queryTokenizer) { 430 $.error("datumTokenizer and queryTokenizer are both required"); 431 } 432 this.identify = o.identify || _.stringify; 433 this.datumTokenizer = o.datumTokenizer; 434 this.queryTokenizer = o.queryTokenizer; 435 this.reset(); 436 } 437 _.mixin(SearchIndex.prototype, { 438 bootstrap: function bootstrap(o) { 439 this.datums = o.datums; 440 this.trie = o.trie; 441 }, 442 add: function(data) { 443 var that = this; 444 data =
vendor: 8,510 bytes, lines 444-680
444Array.isArray(data) ? data : [ data ]; 445 _.each(data, function(datum) { 446 var id, tokens; 447 that.datums[id = that.identify(datum)] = datum; 448 tokens = normalizeTokens(that.datumTokenizer(datum)); 449 _.each(tokens, function(token) { 450 var node, chars, ch; 451 node = that.trie; 452 chars = token.split(""); 453 while (ch = chars.shift()) { 454 node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode()); 455 node[IDS].push(id); 456 } 457 }); 458 }); 459 }, 460 get: function get(ids) { 461 var that = this; 462 return _.map(ids, function(id) { 463 return that.datums[id]; 464 }); 465 }, 466 search: function search(query) { 467 var that = this, tokens, matches; 468 tokens = normalizeTokens(this.queryTokenizer(query)); 469 _.each(tokens, function(token) { 470 var node, chars, ch, ids; 471 if (matches && matches.length === 0) { 472 return false; 473 } 474 node = that.trie; 475 chars = token.split(""); 476 while (node && (ch = chars.shift())) { 477 node = node[CHILDREN][ch]; 478 } 479 if (node && chars.length === 0) { 480 ids = node[IDS].slice(0); 481 matches = matches ? getIntersection(matches, ids) : ids; 482 } else { 483 matches = []; 484 return false; 485 } 486 }); 487 return matches ? _.map(unique(matches), function(id) { 488 return that.datums[id]; 489 }) : []; 490 }, 491 all: function all() { 492 var values = []; 493 for (var key in this.datums) { 494 values.push(this.datums[key]); 495 } 496 return values; 497 }, 498 reset: function reset() { 499 this.datums = {}; 500 this.trie = newNode(); 501 }, 502 serialize: function serialize() { 503 return { 504 datums: this.datums, 505 trie: this.trie 506 }; 507 } 508 }); 509 return SearchIndex; 510 function normalizeTokens(tokens) { 511 tokens = _.filter(tokens, function(token) { 512 return !!token; 513 }); 514 tokens = _.map(tokens, function(token) { 515 return token.toLowerCase(); 516 }); 517 return tokens; 518 } 519 function newNode() { 520 var node = {}; 521 node[IDS] = []; 522 node[CHILDREN] = {}; 523 return node; 524 } 525 function unique(array) { 526 var seen = {}, uniques = []; 527 for (var i = 0, len = array.length; i < len; i++) { 528 if (!seen[array[i]]) { 529 seen[array[i]] = true; 530 uniques.push(array[i]); 531 } 532 } 533 return uniques; 534 } 535 function getIntersection(arrayA, arrayB) { 536 var ai = 0, bi = 0, intersection = []; 537 arrayA = arrayA.sort(); 538 arrayB = arrayB.sort(); 539 var lenArrayA = arrayA.length, lenArrayB = arrayB.length; 540 while (ai < lenArrayA && bi < lenArrayB) { 541 if (arrayA[ai] < arrayB[bi]) { 542 ai++; 543 } else if (arrayA[ai] > arrayB[bi]) { 544 bi++; 545 } else { 546 intersection.push(arrayA[ai]); 547 ai++; 548 bi++; 549 } 550 } 551 return intersection; 552 } 553 }(); 554 var Prefetch = function() { 555 "use strict"; 556 var keys; 557 keys = { 558 data: "data", 559 protocol: "protocol", 560 thumbprint: "thumbprint" 561 }; 562 function Prefetch(o) { 563 this.url = o.url; 564 this.ttl = o.ttl; 565 this.cache = o.cache; 566 this.prepare = o.prepare; 567 this.transform = o.transform; 568 this.transport = o.transport; 569 this.thumbprint = o.thumbprint; 570 this.storage = new PersistentStorage(o.cacheKey); 571 } 572 _.mixin(Prefetch.prototype, { 573 _settings: function settings() { 574 return { 575 url: this.url, 576 type: "GET", 577 dataType: "json" 578 }; 579 }, 580 store: function store(data) { 581 if (!this.cache) { 582 return; 583 } 584 this.storage.set(keys.data, data, this.ttl); 585 this.storage.set(keys.protocol, location.protocol, this.ttl); 586 this.storage.set(keys.thumbprint, this.thumbprint, this.ttl); 587 }, 588 fromCache: function fromCache() { 589 var stored = {}, isExpired; 590 if (!this.cache) { 591 return null; 592 } 593 stored.data = this.storage.get(keys.data); 594 stored.protocol = this.storage.get(keys.protocol); 595 stored.thumbprint = this.storage.get(keys.thumbprint); 596 isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol; 597 return stored.data && !isExpired ? stored.data : null; 598 }, 599 fromNetwork: function(cb) { 600 var that = this, settings; 601 if (!cb) { 602 return; 603 } 604 settings = this.prepare(this._settings()); 605 this.transport(settings).fail(onError).done(onResponse); 606 function onError() { 607 cb(true); 608 } 609 function onResponse(resp) { 610 cb(null, that.transform(resp)); 611 } 612 }, 613 clear: function clear() { 614 this.storage.clear(); 615 return this; 616 } 617 }); 618 return Prefetch; 619 }(); 620 var Remote = function() { 621 "use strict"; 622 function Remote(o) { 623 this.url = o.url; 624 this.prepare = o.prepare; 625 this.transform = o.transform; 626 this.transport = new Transport({ 627 cache: o.cache, 628 limiter: o.limiter, 629 transport: o.transport 630 }); 631 } 632 _.mixin(Remote.prototype, { 633 _settings: function settings() { 634 return { 635 url: this.url, 636 type: "GET", 637 dataType: "json" 638 }; 639 }, 640 get: function get(query, cb) { 641 var that = this, settings; 642 if (!cb) { 643 return; 644 } 645 query = query || ""; 646 settings = this.prepare(query, this._settings()); 647 return this.transport.get(settings, onResponse); 648 function onResponse(err, resp) { 649 err ? cb([]) : cb(that.transform(resp)); 650 } 651 }, 652 cancelLastRequest: function cancelLastRequest() { 653 this.transport.cancel(); 654 } 655 }); 656 return Remote; 657 }(); 658 var oParser = function() { 659 "use strict"; 660 return function parse(o) { 661 var defaults, sorter; 662 defaults = { 663 initialize: true, 664 identify: _.stringify, 665 datumTokenizer: null, 666 queryTokenizer: null, 667 sufficient: 5, 668 sorter: null, 669 local: [], 670 prefetch: null, 671 remote: null 672 }; 673 o = _.mixin(defaults, o || {}); 674 !o.datumTokenizer && $.error("datumTokenizer is required"); 675 !o.queryTokenizer && $.error("queryTokenizer is required"); 676 sorter = o.sorter; 677 o.sorter = sorter ? function(x) { 678 return x.sort(sorter); 679 } : _.identity; 680 o.local = stm_custom_func_checker
vendor: 7,269 bytes, lines 680-882
680(o.local) ? o.local() : o.local; 681 o.prefetch = parsePrefetch(o.prefetch); 682 o.remote = parseRemote(o.remote); 683 return o; 684 }; 685 function parsePrefetch(o) { 686 var defaults; 687 if (!o) { 688 return null; 689 } 690 defaults = { 691 url: null, 692 ttl: 24 * 60 * 60 * 1e3, 693 cache: true, 694 cacheKey: null, 695 thumbprint: "", 696 prepare: _.identity, 697 transform: _.identity, 698 transport: null 699 }; 700 o = _.isString(o) ? { 701 url: o 702 } : o; 703 o = _.mixin(defaults, o); 704 !o.url && $.error("prefetch requires url to be set"); 705 o.transform = o.filter || o.transform; 706 o.cacheKey = o.cacheKey || o.url; 707 o.thumbprint = VERSION + o.thumbprint; 708 o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; 709 return o; 710 } 711 function parseRemote(o) { 712 var defaults; 713 if (!o) { 714 return; 715 } 716 defaults = { 717 url: null, 718 cache: true, 719 prepare: null, 720 replace: null, 721 wildcard: null, 722 limiter: null, 723 rateLimitBy: "debounce", 724 rateLimitWait: 300, 725 transform: _.identity, 726 transport: null 727 }; 728 o = _.isString(o) ? { 729 url: o 730 } : o; 731 o = _.mixin(defaults, o); 732 !o.url && $.error("remote requires url to be set"); 733 o.transform = o.filter || o.transform; 734 o.prepare = toRemotePrepare(o); 735 o.limiter = toLimiter(o); 736 o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; 737 delete o.replace; 738 delete o.wildcard; 739 delete o.rateLimitBy; 740 delete o.rateLimitWait; 741 return o; 742 } 743 function toRemotePrepare(o) { 744 var prepare, replace, wildcard; 745 prepare = o.prepare; 746 replace = o.replace; 747 wildcard = o.wildcard; 748 if (prepare) { 749 return prepare; 750 } 751 if (replace) { 752 prepare = prepareByReplace; 753 } else if (o.wildcard) { 754 prepare = prepareByWildcard; 755 } else { 756 prepare = idenityPrepare; 757 } 758 return prepare; 759 function prepareByReplace(query, settings) { 760 settings.url = replace(settings.url, query); 761 return settings; 762 } 763 function prepareByWildcard(query, settings) { 764 settings.url = settings.url.replace(wildcard, encodeURIComponent(query)); 765 return settings; 766 } 767 function idenityPrepare(query, settings) { 768 return settings; 769 } 770 } 771 function toLimiter(o) { 772 var limiter, method, wait; 773 limiter = o.limiter; 774 method = o.rateLimitBy; 775 wait = o.rateLimitWait; 776 if (!limiter) { 777 limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait); 778 } 779 return limiter; 780 function debounce(wait) { 781 return function debounce(fn) { 782 return _.debounce(fn, wait); 783 }; 784 } 785 function throttle(wait) { 786 return function throttle(fn) { 787 return _.throttle(fn, wait); 788 }; 789 } 790 } 791 function callbackToDeferred(fn) { 792 return function wrapper(o) { 793 var deferred = $.Deferred(); 794 fn(o, onSuccess, onError); 795 return deferred; 796 function onSuccess(resp) { 797 _.defer(function() { 798 deferred.resolve(resp); 799 }); 800 } 801 function onError(err) { 802 _.defer(function() { 803 deferred.reject(err); 804 }); 805 } 806 }; 807 } 808 }(); 809 var Bloodhound = function() { 810 "use strict"; 811 var old; 812 old = window && window.Bloodhound; 813 function Bloodhound(o) { 814 o = oParser(o); 815 this.sorter = o.sorter; 816 this.identify = o.identify; 817 this.sufficient = o.sufficient; 818 this.local = o.local; 819 this.remote = o.remote ? new Remote(o.remote) : null; 820 this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null; 821 this.index = new SearchIndex({ 822 identify: this.identify, 823 datumTokenizer: o.datumTokenizer, 824 queryTokenizer: o.queryTokenizer 825 }); 826 o.initialize !== false && this.initialize(); 827 } 828 Bloodhound.noConflict = function noConflict() { 829 window && (window.Bloodhound = old); 830 return Bloodhound; 831 }; 832 Bloodhound.tokenizers = tokenizers; 833 _.mixin(Bloodhound.prototype, { 834 __ttAdapter: function ttAdapter() { 835 var that = this; 836 return this.remote ? withAsync : withoutAsync; 837 function withAsync(query, sync, async) { 838 return that.search(query, sync, async); 839 } 840 function withoutAsync(query, sync) { 841 return that.search(query, sync); 842 } 843 }, 844 _loadPrefetch: function loadPrefetch() { 845 var that = this, deferred, serialized; 846 deferred = $.Deferred(); 847 if (!this.prefetch) { 848 deferred.resolve(); 849 } else if (serialized = this.prefetch.fromCache()) { 850 this.index.bootstrap(serialized); 851 deferred.resolve(); 852 } else { 853 this.prefetch.fromNetwork(done); 854 } 855 return deferred.promise(); 856 function done(err, data) { 857 if (err) { 858 return deferred.reject(); 859 } 860 that.add(data); 861 that.prefetch.store(that.index.serialize()); 862 deferred.resolve(); 863 } 864 }, 865 _initialize: function initialize() { 866 var that = this, deferred; 867 this.clear(); 868 (this.initPromise = this._loadPrefetch()).done(addLocalToIndex); 869 return this.initPromise; 870 function addLocalToIndex() { 871 that.add(that.local); 872 } 873 }, 874 initialize: function initialize(force) { 875 return !this.initPromise || force ? this._initialize() : this.initPromise; 876 }, 877 add: function add(data) { 878 this.index.add(data); 879 return this; 880 }, 881 get: function get(ids) { 882 ids =
882Array.isArray(ids) ? ids : [].slice.call(arguments); 883 return this.index.get(ids); 884 }, 885 search: function search(query, sync, async) { 886 var that = this, local; 887 local = this.sorter(this.index.search(query)); 888 sync(this.remote ? local.slice() : local); 889 if (this.remote && local.length < this.sufficient) { 890 this.remote.get(query, processRemote); 891 } else if (this.remote) { 892 this.remote.cancelLastRequest(); 893 } 894 return this; 895 function processRemote(remote) {
vendor: 3,459 bytes, lines 896-995
896 var nonDuplicates = []; 897 _.each(remote, function(r) { 898 !_.some(local, function(l) { 899 return that.identify(r) === that.identify(l); 900 }) && nonDuplicates.push(r); 901 }); 902 async && async(nonDuplicates); 903 } 904 }, 905 all: function all() { 906 return this.index.all(); 907 }, 908 clear: function clear() { 909 this.index.reset(); 910 return this; 911 }, 912 clearPrefetchCache: function clearPrefetchCache() { 913 this.prefetch && this.prefetch.clear(); 914 return this; 915 }, 916 clearRemoteCache: function clearRemoteCache() { 917 Transport.resetCache(); 918 return this; 919 }, 920 ttAdapter: function ttAdapter() { 921 return this.__ttAdapter(); 922 } 923 }); 924 return Bloodhound; 925 }(); 926 return Bloodhound; 927}); 928 929(function(root, factory) { 930 if (typeof define === "function" && define.amd) { 931 define("typeahead.js", [ "jquery" ], function(a0) { 932 return factory(a0); 933 }); 934 } else if (typeof exports === "object") { 935 module.exports = factory(require("jquery")); 936 } else { 937 factory(jQuery); 938 } 939})(this, function($) { 940 var _ = function() { 941 "use strict"; 942 return { 943 isMsie: function() { 944 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 945 }, 946 isBlankString: function(str) { 947 return !str || /^\s*$/.test(str); 948 }, 949 escapeRegExChars: function(str) { 950 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 951 }, 952 isString: function(obj) { 953 return typeof obj === "string"; 954 }, 955 isNumber: function(obj) { 956 return typeof obj === "number"; 957 }, 958 // isArray: $.isArray, 959 // isFunction: $.isFunction, 960 isObject: $.isPlainObject, 961 isUndefined: function(obj) { 962 return typeof obj === "undefined"; 963 }, 964 isElement: function(obj) { 965 return !!(obj && obj.nodeType === 1); 966 }, 967 isJQuery: function(obj) { 968 return obj instanceof $; 969 }, 970 toStr: function toStr(s) { 971 return _.isUndefined(s) || s === null ? "" : s + ""; 972 }, 973 bind: $.proxy, 974 each: function(collection, cb) { 975 $.each(collection, reverseArgs); 976 function reverseArgs(index, value) { 977 return cb(value, index); 978 } 979 }, 980 map: $.map, 981 filter: $.grep, 982 every: function(obj, test) { 983 var result = true; 984 if (!obj) { 985 return result; 986 } 987 $.each(obj, function(key, val) { 988 if (!(result = test.call(null, val, key, obj))) { 989 return false; 990 } 991 }); 992 return !!result; 993 }, 994 some: function(obj, test) { 995 var result = false;
996 if (!obj) { 997 return result; 998 } 999 $.each(obj, function(key, val) { 1000 if (result = test.call(null, val, key, obj)) { 1001 return false; 1002 } 1003 }); 1004 return !!result; 1005 }, 1006 mixin: $.extend, 1007 identity: function(x) { 1008 return x; 1009 }, 1010 clone: function(obj) { 1011 return $.extend(true, {}, obj); 1012 }, 1013 getIdGenerator: function() { 1014 var counter = 0; 1015 return function() { 1016 return counter++; 1017 }; 1018 }, 1019 templatify: function templatify(obj) { 1020 return stm_custom_func_checker
vendor: 10,118 bytes, lines 1020-1317
1020(obj) ? obj : template; 1021 function template() { 1022 return String(obj); 1023 } 1024 }, 1025 defer: function(fn) { 1026 setTimeout(fn, 0); 1027 }, 1028 debounce: function(func, wait, immediate) { 1029 var timeout, result; 1030 return function() { 1031 var context = this, args = arguments, later, callNow; 1032 later = function() { 1033 timeout = null; 1034 if (!immediate) { 1035 result = func.apply(context, args); 1036 } 1037 }; 1038 callNow = immediate && !timeout; 1039 clearTimeout(timeout); 1040 timeout = setTimeout(later, wait); 1041 if (callNow) { 1042 result = func.apply(context, args); 1043 } 1044 return result; 1045 }; 1046 }, 1047 throttle: function(func, wait) { 1048 var context, args, timeout, result, previous, later; 1049 previous = 0; 1050 later = function() { 1051 previous = new Date(); 1052 timeout = null; 1053 result = func.apply(context, args); 1054 }; 1055 return function() { 1056 var now = new Date(), remaining = wait - (now - previous); 1057 context = this; 1058 args = arguments; 1059 if (remaining <= 0) { 1060 clearTimeout(timeout); 1061 timeout = null; 1062 previous = now; 1063 result = func.apply(context, args); 1064 } else if (!timeout) { 1065 timeout = setTimeout(later, remaining); 1066 } 1067 return result; 1068 }; 1069 }, 1070 stringify: function(val) { 1071 return _.isString(val) ? val : JSON.stringify(val); 1072 }, 1073 noop: function() {} 1074 }; 1075 }(); 1076 var WWW = function() { 1077 "use strict"; 1078 var defaultClassNames = { 1079 wrapper: "twitter-typeahead", 1080 input: "tt-input", 1081 hint: "tt-hint", 1082 menu: "tt-menu", 1083 dataset: "tt-dataset", 1084 suggestion: "tt-suggestion", 1085 selectable: "tt-selectable", 1086 empty: "tt-empty", 1087 open: "tt-open", 1088 cursor: "tt-cursor", 1089 highlight: "tt-highlight" 1090 }; 1091 return build; 1092 function build(o) { 1093 var www, classes; 1094 classes = _.mixin({}, defaultClassNames, o); 1095 www = { 1096 css: buildCss(), 1097 classes: classes, 1098 html: buildHtml(classes), 1099 selectors: buildSelectors(classes) 1100 }; 1101 return { 1102 css: www.css, 1103 html: www.html, 1104 classes: www.classes, 1105 selectors: www.selectors, 1106 mixin: function(o) { 1107 _.mixin(o, www); 1108 } 1109 }; 1110 } 1111 function buildHtml(c) { 1112 return { 1113 wrapper: '<span class="' + c.wrapper + '"></span>', 1114 menu: '<div class="' + c.menu + '"></div>' 1115 }; 1116 } 1117 function buildSelectors(classes) { 1118 var selectors = {}; 1119 _.each(classes, function(v, k) { 1120 selectors[k] = "." + v; 1121 }); 1122 return selectors; 1123 } 1124 function buildCss() { 1125 var css = { 1126 wrapper: { 1127 position: "relative", 1128 display: "inline-block" 1129 }, 1130 hint: { 1131 position: "absolute", 1132 top: "0", 1133 left: "0", 1134 borderColor: "transparent", 1135 boxShadow: "none", 1136 opacity: "1" 1137 }, 1138 input: { 1139 position: "relative", 1140 verticalAlign: "top", 1141 backgroundColor: "transparent" 1142 }, 1143 inputWithNoHint: { 1144 position: "relative", 1145 verticalAlign: "top" 1146 }, 1147 menu: { 1148 position: "absolute", 1149 top: "100%", 1150 left: "0", 1151 zIndex: "100", 1152 display: "none" 1153 }, 1154 ltr: { 1155 left: "0", 1156 right: "auto" 1157 }, 1158 rtl: { 1159 left: "auto", 1160 right: " 0" 1161 } 1162 }; 1163 if (_.isMsie()) { 1164 _.mixin(css.input, { 1165 backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" 1166 }); 1167 } 1168 return css; 1169 } 1170 }(); 1171 var EventBus = function() { 1172 "use strict"; 1173 var namespace, deprecationMap; 1174 namespace = "typeahead:"; 1175 deprecationMap = { 1176 render: "rendered", 1177 cursorchange: "cursorchanged", 1178 select: "selected", 1179 autocomplete: "autocompleted" 1180 }; 1181 function EventBus(o) { 1182 if (!o || !o.el) { 1183 $.error("EventBus initialized without el"); 1184 } 1185 this.$el = $(o.el); 1186 } 1187 _.mixin(EventBus.prototype, { 1188 _trigger: function(type, args) { 1189 var $e; 1190 $e = $.Event(namespace + type); 1191 (args = args || []).unshift($e); 1192 this.$el.trigger.apply(this.$el, args); 1193 return $e; 1194 }, 1195 before: function(type) { 1196 var args, $e; 1197 args = [].slice.call(arguments, 1); 1198 $e = this._trigger("before" + type, args); 1199 return $e.isDefaultPrevented(); 1200 }, 1201 trigger: function(type) { 1202 var deprecatedType; 1203 this._trigger(type, [].slice.call(arguments, 1)); 1204 if (deprecatedType = deprecationMap[type]) { 1205 this._trigger(deprecatedType, [].slice.call(arguments, 1)); 1206 } 1207 } 1208 }); 1209 return EventBus; 1210 }(); 1211 var EventEmitter = function() { 1212 "use strict"; 1213 var splitter = /\s+/, nextTick = getNextTick(); 1214 return { 1215 onSync: onSync, 1216 onAsync: onAsync, 1217 off: off, 1218 trigger: trigger 1219 }; 1220 function on(method, types, cb, context) { 1221 var type; 1222 if (!cb) { 1223 return this; 1224 } 1225 types = types.split(splitter); 1226 cb = context ? bindContext(cb, context) : cb; 1227 this._callbacks = this._callbacks || {}; 1228 while (type = types.shift()) { 1229 this._callbacks[type] = this._callbacks[type] || { 1230 sync: [], 1231 async: [] 1232 }; 1233 this._callbacks[type][method].push(cb); 1234 } 1235 return this; 1236 } 1237 function onAsync(types, cb, context) { 1238 return on.call(this, "async", types, cb, context); 1239 } 1240 function onSync(types, cb, context) { 1241 return on.call(this, "sync", types, cb, context); 1242 } 1243 function off(types) { 1244 var type; 1245 if (!this._callbacks) { 1246 return this; 1247 } 1248 types = types.split(splitter); 1249 while (type = types.shift()) { 1250 delete this._callbacks[type]; 1251 } 1252 return this; 1253 } 1254 function trigger(types) { 1255 var type, callbacks, args, syncFlush, asyncFlush; 1256 if (!this._callbacks) { 1257 return this; 1258 } 1259 types = types.split(splitter); 1260 args = [].slice.call(arguments, 1); 1261 while ((type = types.shift()) && (callbacks = this._callbacks[type])) { 1262 syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); 1263 asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); 1264 syncFlush() && nextTick(asyncFlush); 1265 } 1266 return this; 1267 } 1268 function getFlush(callbacks, context, args) { 1269 return flush; 1270 function flush() { 1271 var cancelled; 1272 for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { 1273 cancelled = callbacks[i].apply(context, args) === false; 1274 } 1275 return !cancelled; 1276 } 1277 } 1278 function getNextTick() { 1279 var nextTickFn; 1280 if (window.setImmediate) { 1281 nextTickFn = function nextTickSetImmediate(fn) { 1282 setImmediate(function() { 1283 fn(); 1284 }); 1285 }; 1286 } else { 1287 nextTickFn = function nextTickSetTimeout(fn) { 1288 setTimeout(function() { 1289 fn(); 1290 }, 0); 1291 }; 1292 } 1293 return nextTickFn; 1294 } 1295 function bindContext(fn, context) { 1296 return fn.bind ? fn.bind(context) : function() { 1297 fn.apply(context, [].slice.call(arguments, 0)); 1298 }; 1299 } 1300 }(); 1301 var highlight = function(doc) { 1302 "use strict"; 1303 var defaults = { 1304 node: null, 1305 pattern: null, 1306 tagName: "strong", 1307 className: null, 1308 wordsOnly: false, 1309 caseSensitive: false 1310 }; 1311 return function hightlight(o) { 1312 var regex; 1313 o = _.mixin({}, defaults, o); 1314 if (!o.node || !o.pattern) { 1315 return; 1316 } 1317 o.pattern =
1317Array
vendor: 19,047 bytes, lines 1317-1754
1317.isArray(o.pattern) ? o.pattern : [ o.pattern ]; 1318 regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); 1319 traverse(o.node, hightlightTextNode); 1320 function hightlightTextNode(textNode) { 1321 var match, patternNode, wrapperNode; 1322 if (match = regex.exec(textNode.data)) { 1323 wrapperNode = doc.createElement(o.tagName); 1324 o.className && (wrapperNode.className = o.className); 1325 patternNode = textNode.splitText(match.index); 1326 patternNode.splitText(match[0].length); 1327 wrapperNode.appendChild(patternNode.cloneNode(true)); 1328 textNode.parentNode.replaceChild(wrapperNode, patternNode); 1329 } 1330 return !!match; 1331 } 1332 function traverse(el, hightlightTextNode) { 1333 var childNode, TEXT_NODE_TYPE = 3; 1334 for (var i = 0; i < el.childNodes.length; i++) { 1335 childNode = el.childNodes[i]; 1336 if (childNode.nodeType === TEXT_NODE_TYPE) { 1337 i += hightlightTextNode(childNode) ? 1 : 0; 1338 } else { 1339 traverse(childNode, hightlightTextNode); 1340 } 1341 } 1342 } 1343 }; 1344 function getRegex(patterns, caseSensitive, wordsOnly) { 1345 var escapedPatterns = [], regexStr; 1346 for (var i = 0, len = patterns.length; i < len; i++) { 1347 escapedPatterns.push(_.escapeRegExChars(patterns[i])); 1348 } 1349 regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; 1350 return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); 1351 } 1352 }(window.document); 1353 var Input = function() { 1354 "use strict"; 1355 var specialKeyCodeMap; 1356 specialKeyCodeMap = { 1357 9: "tab", 1358 27: "esc", 1359 37: "left", 1360 39: "right", 1361 13: "enter", 1362 38: "up", 1363 40: "down" 1364 }; 1365 function Input(o, www) { 1366 o = o || {}; 1367 if (!o.input) { 1368 $.error("input is missing"); 1369 } 1370 www.mixin(this); 1371 this.$hint = $(o.hint); 1372 this.$input = $(o.input); 1373 this.query = this.$input.val(); 1374 this.queryWhenFocused = this.hasFocus() ? this.query : null; 1375 this.$overflowHelper = buildOverflowHelper(this.$input); 1376 this._checkLanguageDirection(); 1377 if (this.$hint.length === 0) { 1378 this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; 1379 } 1380 } 1381 Input.normalizeQuery = function(str) { 1382 return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); 1383 }; 1384 _.mixin(Input.prototype, EventEmitter, { 1385 _onBlur: function onBlur() { 1386 this.resetInputValue(); 1387 this.trigger("blurred"); 1388 }, 1389 _onFocus: function onFocus() { 1390 this.queryWhenFocused = this.query; 1391 this.trigger("focused"); 1392 }, 1393 _onKeydown: function onKeydown($e) { 1394 var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; 1395 this._managePreventDefault(keyName, $e); 1396 if (keyName && this._shouldTrigger(keyName, $e)) { 1397 this.trigger(keyName + "Keyed", $e); 1398 } 1399 }, 1400 _onInput: function onInput() { 1401 this._setQuery(this.getInputValue()); 1402 this.clearHintIfInvalid(); 1403 this._checkLanguageDirection(); 1404 }, 1405 _managePreventDefault: function managePreventDefault(keyName, $e) { 1406 var preventDefault; 1407 switch (keyName) { 1408 case "up": 1409 case "down": 1410 preventDefault = !withModifier($e); 1411 break; 1412 1413 default: 1414 preventDefault = false; 1415 } 1416 preventDefault && $e.preventDefault(); 1417 }, 1418 _shouldTrigger: function shouldTrigger(keyName, $e) { 1419 var trigger; 1420 switch (keyName) { 1421 case "tab": 1422 trigger = !withModifier($e); 1423 break; 1424 1425 default: 1426 trigger = true; 1427 } 1428 return trigger; 1429 }, 1430 _checkLanguageDirection: function checkLanguageDirection() { 1431 var dir = (this.$input.css("direction") || "ltr").toLowerCase(); 1432 if (this.dir !== dir) { 1433 this.dir = dir; 1434 this.$hint.attr("dir", dir); 1435 this.trigger("langDirChanged", dir); 1436 } 1437 }, 1438 _setQuery: function setQuery(val, silent) { 1439 var areEquivalent, hasDifferentWhitespace; 1440 areEquivalent = areQueriesEquivalent(val, this.query); 1441 hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; 1442 this.query = val; 1443 if (!silent && !areEquivalent) { 1444 this.trigger("queryChanged", this.query); 1445 } else if (!silent && hasDifferentWhitespace) { 1446 this.trigger("whitespaceChanged", this.query); 1447 } 1448 }, 1449 bind: function() { 1450 var that = this, onBlur, onFocus, onKeydown, onInput; 1451 onBlur = _.bind(this._onBlur, this); 1452 onFocus = _.bind(this._onFocus, this); 1453 onKeydown = _.bind(this._onKeydown, this); 1454 onInput = _.bind(this._onInput, this); 1455 this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); 1456 if (!_.isMsie() || _.isMsie() > 9) { 1457 this.$input.on("input.tt", onInput); 1458 } else { 1459 this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { 1460 if (specialKeyCodeMap[$e.which || $e.keyCode]) { 1461 return; 1462 } 1463 _.defer(_.bind(that._onInput, that, $e)); 1464 }); 1465 } 1466 return this; 1467 }, 1468 focus: function focus() { 1469 this.$input.focus(); 1470 }, 1471 blur: function blur() { 1472 this.$input.blur(); 1473 }, 1474 getLangDir: function getLangDir() { 1475 return this.dir; 1476 }, 1477 getQuery: function getQuery() { 1478 return this.query || ""; 1479 }, 1480 setQuery: function setQuery(val, silent) { 1481 this.setInputValue(val); 1482 this._setQuery(val, silent); 1483 }, 1484 hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { 1485 return this.query !== this.queryWhenFocused; 1486 }, 1487 getInputValue: function getInputValue() { 1488 return this.$input.val(); 1489 }, 1490 setInputValue: function setInputValue(value) { 1491 this.$input.val(value); 1492 this.clearHintIfInvalid(); 1493 this._checkLanguageDirection(); 1494 }, 1495 resetInputValue: function resetInputValue() { 1496 this.setInputValue(this.query); 1497 }, 1498 getHint: function getHint() { 1499 return this.$hint.val(); 1500 }, 1501 setHint: function setHint(value) { 1502 this.$hint.val(value); 1503 }, 1504 clearHint: function clearHint() { 1505 this.setHint(""); 1506 }, 1507 clearHintIfInvalid: function clearHintIfInvalid() { 1508 var val, hint, valIsPrefixOfHint, isValid; 1509 val = this.getInputValue(); 1510 hint = this.getHint(); 1511 valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; 1512 isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); 1513 !isValid && this.clearHint(); 1514 }, 1515 hasFocus: function hasFocus() { 1516 return this.$input.is(":focus"); 1517 }, 1518 hasOverflow: function hasOverflow() { 1519 var constraint = this.$input.width() - 2; 1520 this.$overflowHelper.text(this.getInputValue()); 1521 return this.$overflowHelper.width() >= constraint; 1522 }, 1523 isCursorAtEnd: function() { 1524 var valueLength, selectionStart, range; 1525 valueLength = this.$input.val().length; 1526 selectionStart = this.$input[0].selectionStart; 1527 if (_.isNumber(selectionStart)) { 1528 return selectionStart === valueLength; 1529 } else if (document.selection) { 1530 range = document.selection.createRange(); 1531 range.moveStart("character", -valueLength); 1532 return valueLength === range.text.length; 1533 } 1534 return true; 1535 }, 1536 destroy: function destroy() { 1537 this.$hint.off(".tt"); 1538 this.$input.off(".tt"); 1539 this.$overflowHelper.remove(); 1540 this.$hint = this.$input = this.$overflowHelper = $("<div>"); 1541 } 1542 }); 1543 return Input; 1544 function buildOverflowHelper($input) { 1545 return $('<pre aria-hidden="true"></pre>').css({ 1546 position: "absolute", 1547 visibility: "hidden", 1548 whiteSpace: "pre", 1549 fontFamily: $input.css("font-family"), 1550 fontSize: $input.css("font-size"), 1551 fontStyle: $input.css("font-style"), 1552 fontVariant: $input.css("font-variant"), 1553 fontWeight: $input.css("font-weight"), 1554 wordSpacing: $input.css("word-spacing"), 1555 letterSpacing: $input.css("letter-spacing"), 1556 textIndent: $input.css("text-indent"), 1557 textRendering: $input.css("text-rendering"), 1558 textTransform: $input.css("text-transform") 1559 }).insertAfter($input); 1560 } 1561 function areQueriesEquivalent(a, b) { 1562 return Input.normalizeQuery(a) === Input.normalizeQuery(b); 1563 } 1564 function withModifier($e) { 1565 return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; 1566 } 1567 }(); 1568 var Dataset = function() { 1569 "use strict"; 1570 var keys, nameGenerator; 1571 keys = { 1572 val: "tt-selectable-display", 1573 obj: "tt-selectable-object" 1574 }; 1575 nameGenerator = _.getIdGenerator(); 1576 function Dataset(o, www) { 1577 o = o || {}; 1578 o.templates = o.templates || {}; 1579 o.templates.notFound = o.templates.notFound || o.templates.empty; 1580 if (!o.source) { 1581 $.error("missing source"); 1582 } 1583 if (!o.node) { 1584 $.error("missing node"); 1585 } 1586 if (o.name && !isValidName(o.name)) { 1587 $.error("invalid dataset name: " + o.name); 1588 } 1589 www.mixin(this); 1590 this.highlight = !!o.highlight; 1591 this.name = o.name || nameGenerator(); 1592 this.limit = o.limit || 5; 1593 this.displayFn = getDisplayFn(o.display || o.displayKey); 1594 this.templates = getTemplates(o.templates, this.displayFn); 1595 this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; 1596 this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; 1597 this._resetLastSuggestion(); 1598 this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); 1599 } 1600 Dataset.extractData = function extractData(el) { 1601 var $el = $(el); 1602 if ($el.data(keys.obj)) { 1603 return { 1604 val: $el.data(keys.val) || "", 1605 obj: $el.data(keys.obj) || null 1606 }; 1607 } 1608 return null; 1609 }; 1610 _.mixin(Dataset.prototype, EventEmitter, { 1611 _overwrite: function overwrite(query, suggestions) { 1612 suggestions = suggestions || []; 1613 if (suggestions.length) { 1614 this._renderSuggestions(query, suggestions); 1615 } else if (this.async && this.templates.pending) { 1616 this._renderPending(query); 1617 } else if (!this.async && this.templates.notFound) { 1618 this._renderNotFound(query); 1619 } else { 1620 this._empty(); 1621 } 1622 this.trigger("rendered", this.name, suggestions, false); 1623 }, 1624 _append: function append(query, suggestions) { 1625 suggestions = suggestions || []; 1626 if (suggestions.length && this.$lastSuggestion.length) { 1627 this._appendSuggestions(query, suggestions); 1628 } else if (suggestions.length) { 1629 this._renderSuggestions(query, suggestions); 1630 } else if (!this.$lastSuggestion.length && this.templates.notFound) { 1631 this._renderNotFound(query); 1632 } 1633 this.trigger("rendered", this.name, suggestions, true); 1634 }, 1635 _renderSuggestions: function renderSuggestions(query, suggestions) { 1636 var $fragment; 1637 $fragment = this._getSuggestionsFragment(query, suggestions); 1638 this.$lastSuggestion = $fragment.children().last(); 1639 this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); 1640 }, 1641 _appendSuggestions: function appendSuggestions(query, suggestions) { 1642 var $fragment, $lastSuggestion; 1643 $fragment = this._getSuggestionsFragment(query, suggestions); 1644 $lastSuggestion = $fragment.children().last(); 1645 this.$lastSuggestion.after($fragment); 1646 this.$lastSuggestion = $lastSuggestion; 1647 }, 1648 _renderPending: function renderPending(query) { 1649 var template = this.templates.pending; 1650 this._resetLastSuggestion(); 1651 template && this.$el.html(template({ 1652 query: query, 1653 dataset: this.name 1654 })); 1655 }, 1656 _renderNotFound: function renderNotFound(query) { 1657 var template = this.templates.notFound; 1658 this._resetLastSuggestion(); 1659 template && this.$el.html(template({ 1660 query: query, 1661 dataset: this.name 1662 })); 1663 }, 1664 _empty: function empty() { 1665 this.$el.empty(); 1666 this._resetLastSuggestion(); 1667 }, 1668 _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { 1669 var that = this, fragment; 1670 fragment = document.createDocumentFragment(); 1671 _.each(suggestions, function getSuggestionNode(suggestion) { 1672 var $el, context; 1673 context = that._injectQuery(query, suggestion); 1674 $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); 1675 fragment.appendChild($el[0]); 1676 }); 1677 this.highlight && highlight({ 1678 className: this.classes.highlight, 1679 node: fragment, 1680 pattern: query 1681 }); 1682 return $(fragment); 1683 }, 1684 _getFooter: function getFooter(query, suggestions) { 1685 return this.templates.footer ? this.templates.footer({ 1686 query: query, 1687 suggestions: suggestions, 1688 dataset: this.name 1689 }) : null; 1690 }, 1691 _getHeader: function getHeader(query, suggestions) { 1692 return this.templates.header ? this.templates.header({ 1693 query: query, 1694 suggestions: suggestions, 1695 dataset: this.name 1696 }) : null; 1697 }, 1698 _resetLastSuggestion: function resetLastSuggestion() { 1699 this.$lastSuggestion = $(); 1700 }, 1701 _injectQuery: function injectQuery(query, obj) { 1702 return _.isObject(obj) ? _.mixin({ 1703 _query: query 1704 }, obj) : obj; 1705 }, 1706 update: function update(query) { 1707 var that = this, canceled = false, syncCalled = false, rendered = 0; 1708 this.cancel(); 1709 this.cancel = function cancel() { 1710 canceled = true; 1711 that.cancel = $.noop; 1712 that.async && that.trigger("asyncCanceled", query); 1713 }; 1714 this.source(query, sync, async); 1715 !syncCalled && sync([]); 1716 function sync(suggestions) { 1717 if (syncCalled) { 1718 return; 1719 } 1720 syncCalled = true; 1721 suggestions = (suggestions || []).slice(0, that.limit); 1722 rendered = suggestions.length; 1723 that._overwrite(query, suggestions); 1724 if (rendered < that.limit && that.async) { 1725 that.trigger("asyncRequested", query); 1726 } 1727 } 1728 function async(suggestions) { 1729 suggestions = suggestions || []; 1730 if (!canceled && rendered < that.limit) { 1731 that.cancel = $.noop; 1732 rendered += suggestions.length; 1733 that._append(query, suggestions.slice(0, that.limit - rendered)); 1734 that.async && that.trigger("asyncReceived", query); 1735 } 1736 } 1737 }, 1738 cancel: $.noop, 1739 clear: function clear() { 1740 this._empty(); 1741 this.cancel(); 1742 this.trigger("cleared"); 1743 }, 1744 isEmpty: function isEmpty() { 1745 return this.$el.is(":empty"); 1746 }, 1747 destroy: function destroy() { 1748 this.$el = $("<div>"); 1749 } 1750 }); 1751 return Dataset; 1752 function getDisplayFn(display) { 1753 display = display || _.stringify; 1754 return
1754stm_custom_func_checker
vendor: 22,058 bytes, lines 1754-2242
1754(display) ? display : displayFn; 1755 function displayFn(obj) { 1756 return obj[display]; 1757 } 1758 } 1759 function getTemplates(templates, displayFn) { 1760 return { 1761 notFound: templates.notFound && _.templatify(templates.notFound), 1762 pending: templates.pending && _.templatify(templates.pending), 1763 header: templates.header && _.templatify(templates.header), 1764 footer: templates.footer && _.templatify(templates.footer), 1765 suggestion: templates.suggestion || suggestionTemplate 1766 }; 1767 function suggestionTemplate(context) { 1768 return $("<div>").text(displayFn(context)); 1769 } 1770 } 1771 function isValidName(str) { 1772 return /^[_a-zA-Z0-9-]+$/.test(str); 1773 } 1774 }(); 1775 var Menu = function() { 1776 "use strict"; 1777 function Menu(o, www) { 1778 var that = this; 1779 o = o || {}; 1780 if (!o.node) { 1781 $.error("node is required"); 1782 } 1783 www.mixin(this); 1784 this.$node = $(o.node); 1785 this.query = null; 1786 this.datasets = _.map(o.datasets, initializeDataset); 1787 function initializeDataset(oDataset) { 1788 var node = that.$node.find(oDataset.node).first(); 1789 oDataset.node = node.length ? node : $("<div>").appendTo(that.$node); 1790 return new Dataset(oDataset, www); 1791 } 1792 } 1793 _.mixin(Menu.prototype, EventEmitter, { 1794 _onSelectableClick: function onSelectableClick($e) { 1795 this.trigger("selectableClicked", $($e.currentTarget)); 1796 }, 1797 _onRendered: function onRendered(type, dataset, suggestions, async) { 1798 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 1799 this.trigger("datasetRendered", dataset, suggestions, async); 1800 }, 1801 _onCleared: function onCleared() { 1802 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 1803 this.trigger("datasetCleared"); 1804 }, 1805 _propagate: function propagate() { 1806 this.trigger.apply(this, arguments); 1807 }, 1808 _allDatasetsEmpty: function allDatasetsEmpty() { 1809 return _.every(this.datasets, isDatasetEmpty); 1810 function isDatasetEmpty(dataset) { 1811 return dataset.isEmpty(); 1812 } 1813 }, 1814 _getSelectables: function getSelectables() { 1815 return this.$node.find(this.selectors.selectable); 1816 }, 1817 _removeCursor: function _removeCursor() { 1818 var $selectable = this.getActiveSelectable(); 1819 $selectable && $selectable.removeClass(this.classes.cursor); 1820 }, 1821 _ensureVisible: function ensureVisible($el) { 1822 var elTop, elBottom, nodeScrollTop, nodeHeight; 1823 elTop = $el.position().top; 1824 elBottom = elTop + $el.outerHeight(true); 1825 nodeScrollTop = this.$node.scrollTop(); 1826 nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); 1827 if (elTop < 0) { 1828 this.$node.scrollTop(nodeScrollTop + elTop); 1829 } else if (nodeHeight < elBottom) { 1830 this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); 1831 } 1832 }, 1833 bind: function() { 1834 var that = this, onSelectableClick; 1835 onSelectableClick = _.bind(this._onSelectableClick, this); 1836 this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); 1837 _.each(this.datasets, function(dataset) { 1838 dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); 1839 }); 1840 return this; 1841 }, 1842 isOpen: function isOpen() { 1843 return this.$node.hasClass(this.classes.open); 1844 }, 1845 open: function open() { 1846 this.$node.addClass(this.classes.open); 1847 }, 1848 close: function close() { 1849 this.$node.removeClass(this.classes.open); 1850 this._removeCursor(); 1851 }, 1852 setLanguageDirection: function setLanguageDirection(dir) { 1853 this.$node.attr("dir", dir); 1854 }, 1855 selectableRelativeToCursor: function selectableRelativeToCursor(delta) { 1856 var $selectables, $oldCursor, oldIndex, newIndex; 1857 $oldCursor = this.getActiveSelectable(); 1858 $selectables = this._getSelectables(); 1859 oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; 1860 newIndex = oldIndex + delta; 1861 newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; 1862 newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; 1863 return newIndex === -1 ? null : $selectables.eq(newIndex); 1864 }, 1865 setCursor: function setCursor($selectable) { 1866 this._removeCursor(); 1867 if ($selectable = $selectable && $selectable.first()) { 1868 $selectable.addClass(this.classes.cursor); 1869 this._ensureVisible($selectable); 1870 } 1871 }, 1872 getSelectableData: function getSelectableData($el) { 1873 return $el && $el.length ? Dataset.extractData($el) : null; 1874 }, 1875 getActiveSelectable: function getActiveSelectable() { 1876 var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); 1877 return $selectable.length ? $selectable : null; 1878 }, 1879 getTopSelectable: function getTopSelectable() { 1880 var $selectable = this._getSelectables().first(); 1881 return $selectable.length ? $selectable : null; 1882 }, 1883 update: function update(query) { 1884 var isValidUpdate = query !== this.query; 1885 if (isValidUpdate) { 1886 this.query = query; 1887 _.each(this.datasets, updateDataset); 1888 } 1889 return isValidUpdate; 1890 function updateDataset(dataset) { 1891 dataset.update(query); 1892 } 1893 }, 1894 empty: function empty() { 1895 _.each(this.datasets, clearDataset); 1896 this.query = null; 1897 this.$node.addClass(this.classes.empty); 1898 function clearDataset(dataset) { 1899 dataset.clear(); 1900 } 1901 }, 1902 destroy: function destroy() { 1903 this.$node.off(".tt"); 1904 this.$node = $("<div>"); 1905 _.each(this.datasets, destroyDataset); 1906 function destroyDataset(dataset) { 1907 dataset.destroy(); 1908 } 1909 } 1910 }); 1911 return Menu; 1912 }(); 1913 var DefaultMenu = function() { 1914 "use strict"; 1915 var s = Menu.prototype; 1916 function DefaultMenu() { 1917 Menu.apply(this, [].slice.call(arguments, 0)); 1918 } 1919 _.mixin(DefaultMenu.prototype, Menu.prototype, { 1920 open: function open() { 1921 !this._allDatasetsEmpty() && this._show(); 1922 return s.open.apply(this, [].slice.call(arguments, 0)); 1923 }, 1924 close: function close() { 1925 this._hide(); 1926 return s.close.apply(this, [].slice.call(arguments, 0)); 1927 }, 1928 _onRendered: function onRendered() { 1929 if (this._allDatasetsEmpty()) { 1930 this._hide(); 1931 } else { 1932 this.isOpen() && this._show(); 1933 } 1934 return s._onRendered.apply(this, [].slice.call(arguments, 0)); 1935 }, 1936 _onCleared: function onCleared() { 1937 if (this._allDatasetsEmpty()) { 1938 this._hide(); 1939 } else { 1940 this.isOpen() && this._show(); 1941 } 1942 return s._onCleared.apply(this, [].slice.call(arguments, 0)); 1943 }, 1944 setLanguageDirection: function setLanguageDirection(dir) { 1945 this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); 1946 return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); 1947 }, 1948 _hide: function hide() { 1949 this.$node.hide(); 1950 }, 1951 _show: function show() { 1952 this.$node.css("display", "block"); 1953 } 1954 }); 1955 return DefaultMenu; 1956 }(); 1957 var Typeahead = function() { 1958 "use strict"; 1959 function Typeahead(o, www) { 1960 var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; 1961 o = o || {}; 1962 if (!o.input) { 1963 $.error("missing input"); 1964 } 1965 if (!o.menu) { 1966 $.error("missing menu"); 1967 } 1968 if (!o.eventBus) { 1969 $.error("missing event bus"); 1970 } 1971 www.mixin(this); 1972 this.eventBus = o.eventBus; 1973 this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; 1974 this.input = o.input; 1975 this.menu = o.menu; 1976 this.enabled = true; 1977 this.active = false; 1978 this.input.hasFocus() && this.activate(); 1979 this.dir = this.input.getLangDir(); 1980 this._hacks(); 1981 this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); 1982 onFocused = c(this, "activate", "open", "_onFocused"); 1983 onBlurred = c(this, "deactivate", "_onBlurred"); 1984 onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); 1985 onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); 1986 onEscKeyed = c(this, "isActive", "_onEscKeyed"); 1987 onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); 1988 onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); 1989 onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); 1990 onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); 1991 onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); 1992 onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); 1993 this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); 1994 } 1995 _.mixin(Typeahead.prototype, { 1996 _hacks: function hacks() { 1997 var $input, $menu; 1998 $input = this.input.$input || $("<div>"); 1999 $menu = this.menu.$node || $("<div>"); 2000 $input.on("blur.tt", function($e) { 2001 var active, isActive, hasActive; 2002 active = document.activeElement; 2003 isActive = $menu.is(active); 2004 hasActive = $menu.has(active).length > 0; 2005 if (_.isMsie() && (isActive || hasActive)) { 2006 $e.preventDefault(); 2007 $e.stopImmediatePropagation(); 2008 _.defer(function() { 2009 $input.focus(); 2010 }); 2011 } 2012 }); 2013 $menu.on("mousedown.tt", function($e) { 2014 $e.preventDefault(); 2015 }); 2016 }, 2017 _onSelectableClicked: function onSelectableClicked(type, $el) { 2018 this.select($el); 2019 }, 2020 _onDatasetCleared: function onDatasetCleared() { 2021 this._updateHint(); 2022 }, 2023 _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { 2024 this._updateHint(); 2025 this.eventBus.trigger("render", suggestions, async, dataset); 2026 }, 2027 _onAsyncRequested: function onAsyncRequested(type, dataset, query) { 2028 this.eventBus.trigger("asyncrequest", query, dataset); 2029 }, 2030 _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { 2031 this.eventBus.trigger("asynccancel", query, dataset); 2032 }, 2033 _onAsyncReceived: function onAsyncReceived(type, dataset, query) { 2034 this.eventBus.trigger("asyncreceive", query, dataset); 2035 }, 2036 _onFocused: function onFocused() { 2037 this._minLengthMet() && this.menu.update(this.input.getQuery()); 2038 }, 2039 _onBlurred: function onBlurred() { 2040 if (this.input.hasQueryChangedSinceLastFocus()) { 2041 this.eventBus.trigger("change", this.input.getQuery()); 2042 } 2043 }, 2044 _onEnterKeyed: function onEnterKeyed(type, $e) { 2045 var $selectable; 2046 if ($selectable = this.menu.getActiveSelectable()) { 2047 this.select($selectable) && $e.preventDefault(); 2048 } 2049 }, 2050 _onTabKeyed: function onTabKeyed(type, $e) { 2051 var $selectable; 2052 if ($selectable = this.menu.getActiveSelectable()) { 2053 this.select($selectable) && $e.preventDefault(); 2054 } else if ($selectable = this.menu.getTopSelectable()) { 2055 this.autocomplete($selectable) && $e.preventDefault(); 2056 } 2057 }, 2058 _onEscKeyed: function onEscKeyed() { 2059 this.close(); 2060 }, 2061 _onUpKeyed: function onUpKeyed() { 2062 this.moveCursor(-1); 2063 }, 2064 _onDownKeyed: function onDownKeyed() { 2065 this.moveCursor(+1); 2066 }, 2067 _onLeftKeyed: function onLeftKeyed() { 2068 if (this.dir === "rtl" && this.input.isCursorAtEnd()) { 2069 this.autocomplete(this.menu.getTopSelectable()); 2070 } 2071 }, 2072 _onRightKeyed: function onRightKeyed() { 2073 if (this.dir === "ltr" && this.input.isCursorAtEnd()) { 2074 this.autocomplete(this.menu.getTopSelectable()); 2075 } 2076 }, 2077 _onQueryChanged: function onQueryChanged(e, query) { 2078 this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); 2079 }, 2080 _onWhitespaceChanged: function onWhitespaceChanged() { 2081 this._updateHint(); 2082 }, 2083 _onLangDirChanged: function onLangDirChanged(e, dir) { 2084 if (this.dir !== dir) { 2085 this.dir = dir; 2086 this.menu.setLanguageDirection(dir); 2087 } 2088 }, 2089 _openIfActive: function openIfActive() { 2090 this.isActive() && this.open(); 2091 }, 2092 _minLengthMet: function minLengthMet(query) { 2093 query = _.isString(query) ? query : this.input.getQuery() || ""; 2094 return query.length >= this.minLength; 2095 }, 2096 _updateHint: function updateHint() { 2097 var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; 2098 $selectable = this.menu.getTopSelectable(); 2099 data = this.menu.getSelectableData($selectable); 2100 val = this.input.getInputValue(); 2101 if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { 2102 query = Input.normalizeQuery(val); 2103 escapedQuery = _.escapeRegExChars(query); 2104 frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); 2105 match = frontMatchRegEx.exec(data.val); 2106 match && this.input.setHint(val + match[1]); 2107 } else { 2108 this.input.clearHint(); 2109 } 2110 }, 2111 isEnabled: function isEnabled() { 2112 return this.enabled; 2113 }, 2114 enable: function enable() { 2115 this.enabled = true; 2116 }, 2117 disable: function disable() { 2118 this.enabled = false; 2119 }, 2120 isActive: function isActive() { 2121 return this.active; 2122 }, 2123 activate: function activate() { 2124 if (this.isActive()) { 2125 return true; 2126 } else if (!this.isEnabled() || this.eventBus.before("active")) { 2127 return false; 2128 } else { 2129 this.active = true; 2130 this.eventBus.trigger("active"); 2131 return true; 2132 } 2133 }, 2134 deactivate: function deactivate() { 2135 if (!this.isActive()) { 2136 return true; 2137 } else if (this.eventBus.before("idle")) { 2138 return false; 2139 } else { 2140 this.active = false; 2141 this.close(); 2142 this.eventBus.trigger("idle"); 2143 return true; 2144 } 2145 }, 2146 isOpen: function isOpen() { 2147 return this.menu.isOpen(); 2148 }, 2149 open: function open() { 2150 if (!this.isOpen() && !this.eventBus.before("open")) { 2151 this.menu.open(); 2152 this._updateHint(); 2153 this.eventBus.trigger("open"); 2154 } 2155 return this.isOpen(); 2156 }, 2157 close: function close() { 2158 if (this.isOpen() && !this.eventBus.before("close")) { 2159 this.menu.close(); 2160 this.input.clearHint(); 2161 this.input.resetInputValue(); 2162 this.eventBus.trigger("close"); 2163 } 2164 return !this.isOpen(); 2165 }, 2166 setVal: function setVal(val) { 2167 this.input.setQuery(_.toStr(val)); 2168 }, 2169 getVal: function getVal() { 2170 return this.input.getQuery(); 2171 }, 2172 select: function select($selectable) { 2173 var data = this.menu.getSelectableData($selectable); 2174 if (data && !this.eventBus.before("select", data.obj)) { 2175 this.input.setQuery(data.val, true); 2176 this.eventBus.trigger("select", data.obj); 2177 this.close(); 2178 return true; 2179 } 2180 return false; 2181 }, 2182 autocomplete: function autocomplete($selectable) { 2183 var query, data, isValid; 2184 query = this.input.getQuery(); 2185 data = this.menu.getSelectableData($selectable); 2186 isValid = data && query !== data.val; 2187 if (isValid && !this.eventBus.before("autocomplete", data.obj)) { 2188 this.input.setQuery(data.val); 2189 this.eventBus.trigger("autocomplete", data.obj); 2190 return true; 2191 } 2192 return false; 2193 }, 2194 moveCursor: function moveCursor(delta) { 2195 var query, $candidate, data, payload, cancelMove; 2196 query = this.input.getQuery(); 2197 $candidate = this.menu.selectableRelativeToCursor(delta); 2198 data = this.menu.getSelectableData($candidate); 2199 payload = data ? data.obj : null; 2200 cancelMove = this._minLengthMet() && this.menu.update(query); 2201 if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { 2202 this.menu.setCursor($candidate); 2203 if (data) { 2204 this.input.setInputValue(data.val); 2205 } else { 2206 this.input.resetInputValue(); 2207 this._updateHint(); 2208 } 2209 this.eventBus.trigger("cursorchange", payload); 2210 return true; 2211 } 2212 return false; 2213 }, 2214 destroy: function destroy() { 2215 this.input.destroy(); 2216 this.menu.destroy(); 2217 } 2218 }); 2219 return Typeahead; 2220 function c(ctx) { 2221 var methods = [].slice.call(arguments, 1); 2222 return function() { 2223 var args = [].slice.call(arguments); 2224 _.each(methods, function(method) { 2225 return ctx[method].apply(ctx, args); 2226 }); 2227 }; 2228 } 2229 }(); 2230 (function() { 2231 "use strict"; 2232 var old, keys, methods; 2233 old = $.fn.typeahead; 2234 keys = { 2235 www: "tt-www", 2236 attrs: "tt-attrs", 2237 typeahead: "tt-typeahead" 2238 }; 2239 methods = { 2240 initialize: function initialize(o, datasets) { 2241 var www; 2242 datasets =
2242Array
vendor: 8,576 bytes, lines 2242-2460
2242.isArray(datasets) ? datasets : [].slice.call(arguments, 1); 2243 o = o || {}; 2244 www = WWW(o.classNames); 2245 return this.each(attach); 2246 function attach() { 2247 var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; 2248 _.each(datasets, function(d) { 2249 d.highlight = !!o.highlight; 2250 }); 2251 $input = $(this); 2252 $wrapper = $(www.html.wrapper); 2253 $hint = $elOrNull(o.hint); 2254 $menu = $elOrNull(o.menu); 2255 defaultHint = o.hint !== false && !$hint; 2256 defaultMenu = o.menu !== false && !$menu; 2257 defaultHint && ($hint = buildHintFromInput($input, www)); 2258 defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); 2259 $hint && $hint.val(""); 2260 $input = prepInput($input, www); 2261 if (defaultHint || defaultMenu) { 2262 $wrapper.css(www.css.wrapper); 2263 $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); 2264 $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); 2265 } 2266 MenuConstructor = defaultMenu ? DefaultMenu : Menu; 2267 eventBus = new EventBus({ 2268 el: $input 2269 }); 2270 input = new Input({ 2271 hint: $hint, 2272 input: $input 2273 }, www); 2274 menu = new MenuConstructor({ 2275 node: $menu, 2276 datasets: datasets 2277 }, www); 2278 typeahead = new Typeahead({ 2279 input: input, 2280 menu: menu, 2281 eventBus: eventBus, 2282 minLength: o.minLength 2283 }, www); 2284 $input.data(keys.www, www); 2285 $input.data(keys.typeahead, typeahead); 2286 } 2287 }, 2288 isEnabled: function isEnabled() { 2289 var enabled; 2290 ttEach(this.first(), function(t) { 2291 enabled = t.isEnabled(); 2292 }); 2293 return enabled; 2294 }, 2295 enable: function enable() { 2296 ttEach(this, function(t) { 2297 t.enable(); 2298 }); 2299 return this; 2300 }, 2301 disable: function disable() { 2302 ttEach(this, function(t) { 2303 t.disable(); 2304 }); 2305 return this; 2306 }, 2307 isActive: function isActive() { 2308 var active; 2309 ttEach(this.first(), function(t) { 2310 active = t.isActive(); 2311 }); 2312 return active; 2313 }, 2314 activate: function activate() { 2315 ttEach(this, function(t) { 2316 t.activate(); 2317 }); 2318 return this; 2319 }, 2320 deactivate: function deactivate() { 2321 ttEach(this, function(t) { 2322 t.deactivate(); 2323 }); 2324 return this; 2325 }, 2326 isOpen: function isOpen() { 2327 var open; 2328 ttEach(this.first(), function(t) { 2329 open = t.isOpen(); 2330 }); 2331 return open; 2332 }, 2333 open: function open() { 2334 ttEach(this, function(t) { 2335 t.open(); 2336 }); 2337 return this; 2338 }, 2339 close: function close() { 2340 ttEach(this, function(t) { 2341 t.close(); 2342 }); 2343 return this; 2344 }, 2345 select: function select(el) { 2346 var success = false, $el = $(el); 2347 ttEach(this.first(), function(t) { 2348 success = t.select($el); 2349 }); 2350 return success; 2351 }, 2352 autocomplete: function autocomplete(el) { 2353 var success = false, $el = $(el); 2354 ttEach(this.first(), function(t) { 2355 success = t.autocomplete($el); 2356 }); 2357 return success; 2358 }, 2359 moveCursor: function moveCursoe(delta) { 2360 var success = false; 2361 ttEach(this.first(), function(t) { 2362 success = t.moveCursor(delta); 2363 }); 2364 return success; 2365 }, 2366 val: function val(newVal) { 2367 var query; 2368 if (!arguments.length) { 2369 ttEach(this.first(), function(t) { 2370 query = t.getVal(); 2371 }); 2372 return query; 2373 } else { 2374 ttEach(this, function(t) { 2375 t.setVal(newVal); 2376 }); 2377 return this; 2378 } 2379 }, 2380 destroy: function destroy() { 2381 ttEach(this, function(typeahead, $input) { 2382 revert($input); 2383 typeahead.destroy(); 2384 }); 2385 return this; 2386 } 2387 }; 2388 $.fn.typeahead = function(method) { 2389 if (methods[method]) { 2390 return methods[method].apply(this, [].slice.call(arguments, 1)); 2391 } else { 2392 return methods.initialize.apply(this, arguments); 2393 } 2394 }; 2395 $.fn.typeahead.noConflict = function noConflict() { 2396 $.fn.typeahead = old; 2397 return this; 2398 }; 2399 function ttEach($els, fn) { 2400 $els.each(function() { 2401 var $input = $(this), typeahead; 2402 (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); 2403 }); 2404 } 2405 function buildHintFromInput($input, www) { 2406 return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ 2407 autocomplete: "off", 2408 spellcheck: "false", 2409 tabindex: -1 2410 }); 2411 } 2412 function prepInput($input, www) { 2413 $input.data(keys.attrs, { 2414 dir: $input.attr("dir"), 2415 autocomplete: $input.attr("autocomplete"), 2416 spellcheck: $input.attr("spellcheck"), 2417 style: $input.attr("style") 2418 }); 2419 $input.addClass(www.classes.input).attr({ 2420 autocomplete: "off", 2421 spellcheck: false 2422 }); 2423 try { 2424 !$input.attr("dir") && $input.attr("dir", "auto"); 2425 } catch (e) {} 2426 return $input; 2427 } 2428 function getBackgroundStyles($el) { 2429 return { 2430 backgroundAttachment: $el.css("background-attachment"), 2431 backgroundClip: $el.css("background-clip"), 2432 backgroundColor: $el.css("background-color"), 2433 backgroundImage: $el.css("background-image"), 2434 backgroundOrigin: $el.css("background-origin"), 2435 backgroundPosition: $el.css("background-position"), 2436 backgroundRepeat: $el.css("background-repeat"), 2437 backgroundSize: $el.css("background-size") 2438 }; 2439 } 2440 function revert($input) { 2441 var www, $wrapper; 2442 www = $input.data(keys.www); 2443 $wrapper = $input.parent().filter(www.selectors.wrapper); 2444 _.each($input.data(keys.attrs), function(val, key) { 2445 _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); 2446 }); 2447 $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); 2448 if ($wrapper.length) { 2449 $input.detach().insertAfter($wrapper); 2450 $wrapper.remove(); 2451 } 2452 } 2453 function $elOrNull(obj) { 2454 var isValid, $el; 2455 isValid = _.isJQuery(obj) || _.isElement(obj); 2456 $el = isValid ? $(obj).first() : []; 2457 return $el.length ? $el : null; 2458 } 2459 })(); 2460});
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.