PageSourceSearch

https://sellersprite.ai/assets-v2/vendor/bootstrap-tagsinput/js/typeahead.js

js sellersprite.ai collected 2026-09-24 13:04:49 UTC 96,186 bytes, 2,451 lines download raw bytes

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

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.