PageSourceSearch

https://www.xanax.com/-/media/Base-Themes/Core-Libraries/scripts/typeahead.js

js xanax.com collected 2026-09-24 22:54:25 UTC 104,933 bytes, 2,621 lines download raw bytes

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

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.