summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js')
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js1551
1 files changed, 1551 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js b/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js
new file mode 100644
index 0000000000..f3efd80cb3
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js
@@ -0,0 +1,1551 @@
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("typeahead.js", [ "jquery" ], function(a0) {
10 return factory(a0);
11 });
12 } else if (typeof exports === "object") {
13 module.exports = factory(require("jquery"));
14 } else {
15 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 WWW = function() {
155 "use strict";
156 var defaultClassNames = {
157 wrapper: "twitter-typeahead",
158 input: "tt-input",
159 hint: "tt-hint",
160 menu: "tt-menu",
161 dataset: "tt-dataset",
162 suggestion: "tt-suggestion",
163 selectable: "tt-selectable",
164 empty: "tt-empty",
165 open: "tt-open",
166 cursor: "tt-cursor",
167 highlight: "tt-highlight"
168 };
169 return build;
170 function build(o) {
171 var www, classes;
172 classes = _.mixin({}, defaultClassNames, o);
173 www = {
174 css: buildCss(),
175 classes: classes,
176 html: buildHtml(classes),
177 selectors: buildSelectors(classes)
178 };
179 return {
180 css: www.css,
181 html: www.html,
182 classes: www.classes,
183 selectors: www.selectors,
184 mixin: function(o) {
185 _.mixin(o, www);
186 }
187 };
188 }
189 function buildHtml(c) {
190 return {
191 wrapper: '<span class="' + c.wrapper + '"></span>',
192 menu: '<div class="' + c.menu + '"></div>'
193 };
194 }
195 function buildSelectors(classes) {
196 var selectors = {};
197 _.each(classes, function(v, k) {
198 selectors[k] = "." + v;
199 });
200 return selectors;
201 }
202 function buildCss() {
203 var css = {
204 wrapper: {
205 position: "relative",
206 display: "inline-block"
207 },
208 hint: {
209 position: "absolute",
210 top: "0",
211 left: "0",
212 borderColor: "transparent",
213 boxShadow: "none",
214 opacity: "1"
215 },
216 input: {
217 position: "relative",
218 verticalAlign: "top",
219 backgroundColor: "transparent"
220 },
221 inputWithNoHint: {
222 position: "relative",
223 verticalAlign: "top"
224 },
225 menu: {
226 position: "absolute",
227 top: "100%",
228 left: "0",
229 zIndex: "100",
230 display: "none"
231 },
232 ltr: {
233 left: "0",
234 right: "auto"
235 },
236 rtl: {
237 left: "auto",
238 right: " 0"
239 }
240 };
241 if (_.isMsie()) {
242 _.mixin(css.input, {
243 backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
244 });
245 }
246 return css;
247 }
248 }();
249 var EventBus = function() {
250 "use strict";
251 var namespace, deprecationMap;
252 namespace = "typeahead:";
253 deprecationMap = {
254 render: "rendered",
255 cursorchange: "cursorchanged",
256 select: "selected",
257 autocomplete: "autocompleted"
258 };
259 function EventBus(o) {
260 if (!o || !o.el) {
261 $.error("EventBus initialized without el");
262 }
263 this.$el = $(o.el);
264 }
265 _.mixin(EventBus.prototype, {
266 _trigger: function(type, args) {
267 var $e;
268 $e = $.Event(namespace + type);
269 (args = args || []).unshift($e);
270 this.$el.trigger.apply(this.$el, args);
271 return $e;
272 },
273 before: function(type) {
274 var args, $e;
275 args = [].slice.call(arguments, 1);
276 $e = this._trigger("before" + type, args);
277 return $e.isDefaultPrevented();
278 },
279 trigger: function(type) {
280 var deprecatedType;
281 this._trigger(type, [].slice.call(arguments, 1));
282 if (deprecatedType = deprecationMap[type]) {
283 this._trigger(deprecatedType, [].slice.call(arguments, 1));
284 }
285 }
286 });
287 return EventBus;
288 }();
289 var EventEmitter = function() {
290 "use strict";
291 var splitter = /\s+/, nextTick = getNextTick();
292 return {
293 onSync: onSync,
294 onAsync: onAsync,
295 off: off,
296 trigger: trigger
297 };
298 function on(method, types, cb, context) {
299 var type;
300 if (!cb) {
301 return this;
302 }
303 types = types.split(splitter);
304 cb = context ? bindContext(cb, context) : cb;
305 this._callbacks = this._callbacks || {};
306 while (type = types.shift()) {
307 this._callbacks[type] = this._callbacks[type] || {
308 sync: [],
309 async: []
310 };
311 this._callbacks[type][method].push(cb);
312 }
313 return this;
314 }
315 function onAsync(types, cb, context) {
316 return on.call(this, "async", types, cb, context);
317 }
318 function onSync(types, cb, context) {
319 return on.call(this, "sync", types, cb, context);
320 }
321 function off(types) {
322 var type;
323 if (!this._callbacks) {
324 return this;
325 }
326 types = types.split(splitter);
327 while (type = types.shift()) {
328 delete this._callbacks[type];
329 }
330 return this;
331 }
332 function trigger(types) {
333 var type, callbacks, args, syncFlush, asyncFlush;
334 if (!this._callbacks) {
335 return this;
336 }
337 types = types.split(splitter);
338 args = [].slice.call(arguments, 1);
339 while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
340 syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
341 asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
342 syncFlush() && nextTick(asyncFlush);
343 }
344 return this;
345 }
346 function getFlush(callbacks, context, args) {
347 return flush;
348 function flush() {
349 var cancelled;
350 for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
351 cancelled = callbacks[i].apply(context, args) === false;
352 }
353 return !cancelled;
354 }
355 }
356 function getNextTick() {
357 var nextTickFn;
358 if (window.setImmediate) {
359 nextTickFn = function nextTickSetImmediate(fn) {
360 setImmediate(function() {
361 fn();
362 });
363 };
364 } else {
365 nextTickFn = function nextTickSetTimeout(fn) {
366 setTimeout(function() {
367 fn();
368 }, 0);
369 };
370 }
371 return nextTickFn;
372 }
373 function bindContext(fn, context) {
374 return fn.bind ? fn.bind(context) : function() {
375 fn.apply(context, [].slice.call(arguments, 0));
376 };
377 }
378 }();
379 var highlight = function(doc) {
380 "use strict";
381 var defaults = {
382 node: null,
383 pattern: null,
384 tagName: "strong",
385 className: null,
386 wordsOnly: false,
387 caseSensitive: false
388 };
389 return function hightlight(o) {
390 var regex;
391 o = _.mixin({}, defaults, o);
392 if (!o.node || !o.pattern) {
393 return;
394 }
395 o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
396 regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
397 traverse(o.node, hightlightTextNode);
398 function hightlightTextNode(textNode) {
399 var match, patternNode, wrapperNode;
400 if (match = regex.exec(textNode.data)) {
401 wrapperNode = doc.createElement(o.tagName);
402 o.className && (wrapperNode.className = o.className);
403 patternNode = textNode.splitText(match.index);
404 patternNode.splitText(match[0].length);
405 wrapperNode.appendChild(patternNode.cloneNode(true));
406 textNode.parentNode.replaceChild(wrapperNode, patternNode);
407 }
408 return !!match;
409 }
410 function traverse(el, hightlightTextNode) {
411 var childNode, TEXT_NODE_TYPE = 3;
412 for (var i = 0; i < el.childNodes.length; i++) {
413 childNode = el.childNodes[i];
414 if (childNode.nodeType === TEXT_NODE_TYPE) {
415 i += hightlightTextNode(childNode) ? 1 : 0;
416 } else {
417 traverse(childNode, hightlightTextNode);
418 }
419 }
420 }
421 };
422 function getRegex(patterns, caseSensitive, wordsOnly) {
423 var escapedPatterns = [], regexStr;
424 for (var i = 0, len = patterns.length; i < len; i++) {
425 escapedPatterns.push(_.escapeRegExChars(patterns[i]));
426 }
427 regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
428 return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
429 }
430 }(window.document);
431 var Input = function() {
432 "use strict";
433 var specialKeyCodeMap;
434 specialKeyCodeMap = {
435 9: "tab",
436 27: "esc",
437 37: "left",
438 39: "right",
439 13: "enter",
440 38: "up",
441 40: "down"
442 };
443 function Input(o, www) {
444 o = o || {};
445 if (!o.input) {
446 $.error("input is missing");
447 }
448 www.mixin(this);
449 this.$hint = $(o.hint);
450 this.$input = $(o.input);
451 this.query = this.$input.val();
452 this.queryWhenFocused = this.hasFocus() ? this.query : null;
453 this.$overflowHelper = buildOverflowHelper(this.$input);
454 this._checkLanguageDirection();
455 if (this.$hint.length === 0) {
456 this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
457 }
458 }
459 Input.normalizeQuery = function(str) {
460 return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
461 };
462 _.mixin(Input.prototype, EventEmitter, {
463 _onBlur: function onBlur() {
464 this.resetInputValue();
465 this.trigger("blurred");
466 },
467 _onFocus: function onFocus() {
468 this.queryWhenFocused = this.query;
469 this.trigger("focused");
470 },
471 _onKeydown: function onKeydown($e) {
472 var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
473 this._managePreventDefault(keyName, $e);
474 if (keyName && this._shouldTrigger(keyName, $e)) {
475 this.trigger(keyName + "Keyed", $e);
476 }
477 },
478 _onInput: function onInput() {
479 this._setQuery(this.getInputValue());
480 this.clearHintIfInvalid();
481 this._checkLanguageDirection();
482 },
483 _managePreventDefault: function managePreventDefault(keyName, $e) {
484 var preventDefault;
485 switch (keyName) {
486 case "up":
487 case "down":
488 preventDefault = !withModifier($e);
489 break;
490
491 default:
492 preventDefault = false;
493 }
494 preventDefault && $e.preventDefault();
495 },
496 _shouldTrigger: function shouldTrigger(keyName, $e) {
497 var trigger;
498 switch (keyName) {
499 case "tab":
500 trigger = !withModifier($e);
501 break;
502
503 default:
504 trigger = true;
505 }
506 return trigger;
507 },
508 _checkLanguageDirection: function checkLanguageDirection() {
509 var dir = (this.$input.css("direction") || "ltr").toLowerCase();
510 if (this.dir !== dir) {
511 this.dir = dir;
512 this.$hint.attr("dir", dir);
513 this.trigger("langDirChanged", dir);
514 }
515 },
516 _setQuery: function setQuery(val, silent) {
517 var areEquivalent, hasDifferentWhitespace;
518 areEquivalent = areQueriesEquivalent(val, this.query);
519 hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
520 this.query = val;
521 if (!silent && !areEquivalent) {
522 this.trigger("queryChanged", this.query);
523 } else if (!silent && hasDifferentWhitespace) {
524 this.trigger("whitespaceChanged", this.query);
525 }
526 },
527 bind: function() {
528 var that = this, onBlur, onFocus, onKeydown, onInput;
529 onBlur = _.bind(this._onBlur, this);
530 onFocus = _.bind(this._onFocus, this);
531 onKeydown = _.bind(this._onKeydown, this);
532 onInput = _.bind(this._onInput, this);
533 this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
534 if (!_.isMsie() || _.isMsie() > 9) {
535 this.$input.on("input.tt", onInput);
536 } else {
537 this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
538 if (specialKeyCodeMap[$e.which || $e.keyCode]) {
539 return;
540 }
541 _.defer(_.bind(that._onInput, that, $e));
542 });
543 }
544 return this;
545 },
546 focus: function focus() {
547 this.$input.focus();
548 },
549 blur: function blur() {
550 this.$input.blur();
551 },
552 getLangDir: function getLangDir() {
553 return this.dir;
554 },
555 getQuery: function getQuery() {
556 return this.query || "";
557 },
558 setQuery: function setQuery(val, silent) {
559 this.setInputValue(val);
560 this._setQuery(val, silent);
561 },
562 hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
563 return this.query !== this.queryWhenFocused;
564 },
565 getInputValue: function getInputValue() {
566 return this.$input.val();
567 },
568 setInputValue: function setInputValue(value) {
569 this.$input.val(value);
570 this.clearHintIfInvalid();
571 this._checkLanguageDirection();
572 },
573 resetInputValue: function resetInputValue() {
574 this.setInputValue(this.query);
575 },
576 getHint: function getHint() {
577 return this.$hint.val();
578 },
579 setHint: function setHint(value) {
580 this.$hint.val(value);
581 },
582 clearHint: function clearHint() {
583 this.setHint("");
584 },
585 clearHintIfInvalid: function clearHintIfInvalid() {
586 var val, hint, valIsPrefixOfHint, isValid;
587 val = this.getInputValue();
588 hint = this.getHint();
589 valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
590 isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
591 !isValid && this.clearHint();
592 },
593 hasFocus: function hasFocus() {
594 return this.$input.is(":focus");
595 },
596 hasOverflow: function hasOverflow() {
597 var constraint = this.$input.width() - 2;
598 this.$overflowHelper.text(this.getInputValue());
599 return this.$overflowHelper.width() >= constraint;
600 },
601 isCursorAtEnd: function() {
602 var valueLength, selectionStart, range;
603 valueLength = this.$input.val().length;
604 selectionStart = this.$input[0].selectionStart;
605 if (_.isNumber(selectionStart)) {
606 return selectionStart === valueLength;
607 } else if (document.selection) {
608 range = document.selection.createRange();
609 range.moveStart("character", -valueLength);
610 return valueLength === range.text.length;
611 }
612 return true;
613 },
614 destroy: function destroy() {
615 this.$hint.off(".tt");
616 this.$input.off(".tt");
617 this.$overflowHelper.remove();
618 this.$hint = this.$input = this.$overflowHelper = $("<div>");
619 }
620 });
621 return Input;
622 function buildOverflowHelper($input) {
623 return $('<pre aria-hidden="true"></pre>').css({
624 position: "absolute",
625 visibility: "hidden",
626 whiteSpace: "pre",
627 fontFamily: $input.css("font-family"),
628 fontSize: $input.css("font-size"),
629 fontStyle: $input.css("font-style"),
630 fontVariant: $input.css("font-variant"),
631 fontWeight: $input.css("font-weight"),
632 wordSpacing: $input.css("word-spacing"),
633 letterSpacing: $input.css("letter-spacing"),
634 textIndent: $input.css("text-indent"),
635 textRendering: $input.css("text-rendering"),
636 textTransform: $input.css("text-transform")
637 }).insertAfter($input);
638 }
639 function areQueriesEquivalent(a, b) {
640 return Input.normalizeQuery(a) === Input.normalizeQuery(b);
641 }
642 function withModifier($e) {
643 return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
644 }
645 }();
646 var Dataset = function() {
647 "use strict";
648 var keys, nameGenerator;
649 keys = {
650 val: "tt-selectable-display",
651 obj: "tt-selectable-object"
652 };
653 nameGenerator = _.getIdGenerator();
654 function Dataset(o, www) {
655 o = o || {};
656 o.templates = o.templates || {};
657 o.templates.notFound = o.templates.notFound || o.templates.empty;
658 if (!o.source) {
659 $.error("missing source");
660 }
661 if (!o.node) {
662 $.error("missing node");
663 }
664 if (o.name && !isValidName(o.name)) {
665 $.error("invalid dataset name: " + o.name);
666 }
667 www.mixin(this);
668 this.highlight = !!o.highlight;
669 this.name = o.name || nameGenerator();
670 this.limit = o.limit || 5;
671 this.displayFn = getDisplayFn(o.display || o.displayKey);
672 this.templates = getTemplates(o.templates, this.displayFn);
673 this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
674 this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
675 this._resetLastSuggestion();
676 this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
677 }
678 Dataset.extractData = function extractData(el) {
679 var $el = $(el);
680 if ($el.data(keys.obj)) {
681 return {
682 val: $el.data(keys.val) || "",
683 obj: $el.data(keys.obj) || null
684 };
685 }
686 return null;
687 };
688 _.mixin(Dataset.prototype, EventEmitter, {
689 _overwrite: function overwrite(query, suggestions) {
690 suggestions = suggestions || [];
691 if (suggestions.length) {
692 this._renderSuggestions(query, suggestions);
693 } else if (this.async && this.templates.pending) {
694 this._renderPending(query);
695 } else if (!this.async && this.templates.notFound) {
696 this._renderNotFound(query);
697 } else {
698 this._empty();
699 }
700 this.trigger("rendered", this.name, suggestions, false);
701 },
702 _append: function append(query, suggestions) {
703 suggestions = suggestions || [];
704 if (suggestions.length && this.$lastSuggestion.length) {
705 this._appendSuggestions(query, suggestions);
706 } else if (suggestions.length) {
707 this._renderSuggestions(query, suggestions);
708 } else if (!this.$lastSuggestion.length && this.templates.notFound) {
709 this._renderNotFound(query);
710 }
711 this.trigger("rendered", this.name, suggestions, true);
712 },
713 _renderSuggestions: function renderSuggestions(query, suggestions) {
714 var $fragment;
715 $fragment = this._getSuggestionsFragment(query, suggestions);
716 this.$lastSuggestion = $fragment.children().last();
717 this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
718 },
719 _appendSuggestions: function appendSuggestions(query, suggestions) {
720 var $fragment, $lastSuggestion;
721 $fragment = this._getSuggestionsFragment(query, suggestions);
722 $lastSuggestion = $fragment.children().last();
723 this.$lastSuggestion.after($fragment);
724 this.$lastSuggestion = $lastSuggestion;
725 },
726 _renderPending: function renderPending(query) {
727 var template = this.templates.pending;
728 this._resetLastSuggestion();
729 template && this.$el.html(template({
730 query: query,
731 dataset: this.name
732 }));
733 },
734 _renderNotFound: function renderNotFound(query) {
735 var template = this.templates.notFound;
736 this._resetLastSuggestion();
737 template && this.$el.html(template({
738 query: query,
739 dataset: this.name
740 }));
741 },
742 _empty: function empty() {
743 this.$el.empty();
744 this._resetLastSuggestion();
745 },
746 _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
747 var that = this, fragment;
748 fragment = document.createDocumentFragment();
749 _.each(suggestions, function getSuggestionNode(suggestion) {
750 var $el, context;
751 context = that._injectQuery(query, suggestion);
752 $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
753 fragment.appendChild($el[0]);
754 });
755 this.highlight && highlight({
756 className: this.classes.highlight,
757 node: fragment,
758 pattern: query
759 });
760 return $(fragment);
761 },
762 _getFooter: function getFooter(query, suggestions) {
763 return this.templates.footer ? this.templates.footer({
764 query: query,
765 suggestions: suggestions,
766 dataset: this.name
767 }) : null;
768 },
769 _getHeader: function getHeader(query, suggestions) {
770 return this.templates.header ? this.templates.header({
771 query: query,
772 suggestions: suggestions,
773 dataset: this.name
774 }) : null;
775 },
776 _resetLastSuggestion: function resetLastSuggestion() {
777 this.$lastSuggestion = $();
778 },
779 _injectQuery: function injectQuery(query, obj) {
780 return _.isObject(obj) ? _.mixin({
781 _query: query
782 }, obj) : obj;
783 },
784 update: function update(query) {
785 var that = this, canceled = false, syncCalled = false, rendered = 0;
786 this.cancel();
787 this.cancel = function cancel() {
788 canceled = true;
789 that.cancel = $.noop;
790 that.async && that.trigger("asyncCanceled", query);
791 };
792 this.source(query, sync, async);
793 !syncCalled && sync([]);
794 function sync(suggestions) {
795 if (syncCalled) {
796 return;
797 }
798 syncCalled = true;
799 suggestions = (suggestions || []).slice(0, that.limit);
800 rendered = suggestions.length;
801 that._overwrite(query, suggestions);
802 if (rendered < that.limit && that.async) {
803 that.trigger("asyncRequested", query);
804 }
805 }
806 function async(suggestions) {
807 suggestions = suggestions || [];
808 if (!canceled && rendered < that.limit) {
809 that.cancel = $.noop;
810 rendered += suggestions.length;
811
812 // HACK: because we don't have a synchronous way of
813 // retrieving results, we use the async function every
814 // time we update the drop-down; however, the typeahead
815 // does some internal book-keeping which means that we
816 // only get the additional items in the drop-down when
817 // the next set of results is fetched, instead of all
818 // of them (it appears to implicitly track which
819 // results have already been shown in the drop-down); by
820 // forcing an overwrite, we see all of the new results
821 // every time we fetch a set of suggestions
822 //that._append(query, suggestions.slice(0, that.limit - rendered));
823 that._overwrite(query, suggestions);
824
825 that.async && that.trigger("asyncReceived", query);
826 }
827 }
828 },
829 cancel: $.noop,
830 clear: function clear() {
831 this._empty();
832 this.cancel();
833 this.trigger("cleared");
834 },
835 isEmpty: function isEmpty() {
836 return this.$el.is(":empty");
837 },
838 destroy: function destroy() {
839 this.$el = $("<div>");
840 }
841 });
842 return Dataset;
843 function getDisplayFn(display) {
844 display = display || _.stringify;
845 return _.isFunction(display) ? display : displayFn;
846 function displayFn(obj) {
847 return obj[display];
848 }
849 }
850 function getTemplates(templates, displayFn) {
851 return {
852 notFound: templates.notFound && _.templatify(templates.notFound),
853 pending: templates.pending && _.templatify(templates.pending),
854 header: templates.header && _.templatify(templates.header),
855 footer: templates.footer && _.templatify(templates.footer),
856 suggestion: templates.suggestion || suggestionTemplate
857 };
858 function suggestionTemplate(context) {
859 return $("<div>").text(displayFn(context));
860 }
861 }
862 function isValidName(str) {
863 return /^[_a-zA-Z0-9-]+$/.test(str);
864 }
865 }();
866 var Menu = function() {
867 "use strict";
868 function Menu(o, www) {
869 var that = this;
870 o = o || {};
871 if (!o.node) {
872 $.error("node is required");
873 }
874 www.mixin(this);
875 this.$node = $(o.node);
876 this.query = null;
877 this.datasets = _.map(o.datasets, initializeDataset);
878 function initializeDataset(oDataset) {
879 var node = that.$node.find(oDataset.node).first();
880 oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
881 return new Dataset(oDataset, www);
882 }
883 }
884 _.mixin(Menu.prototype, EventEmitter, {
885 _onSelectableClick: function onSelectableClick($e) {
886 this.trigger("selectableClicked", $($e.currentTarget));
887 },
888 _onRendered: function onRendered(type, dataset, suggestions, async) {
889 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
890 this.trigger("datasetRendered", dataset, suggestions, async);
891 },
892 _onCleared: function onCleared() {
893 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
894 this.trigger("datasetCleared");
895 },
896 _propagate: function propagate() {
897 this.trigger.apply(this, arguments);
898 },
899 _allDatasetsEmpty: function allDatasetsEmpty() {
900 return _.every(this.datasets, isDatasetEmpty);
901 function isDatasetEmpty(dataset) {
902 return dataset.isEmpty();
903 }
904 },
905 _getSelectables: function getSelectables() {
906 return this.$node.find(this.selectors.selectable);
907 },
908 _removeCursor: function _removeCursor() {
909 var $selectable = this.getActiveSelectable();
910 $selectable && $selectable.removeClass(this.classes.cursor);
911 },
912 _ensureVisible: function ensureVisible($el) {
913 var elTop, elBottom, nodeScrollTop, nodeHeight;
914 elTop = $el.position().top;
915 elBottom = elTop + $el.outerHeight(true);
916 nodeScrollTop = this.$node.scrollTop();
917 nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
918 if (elTop < 0) {
919 this.$node.scrollTop(nodeScrollTop + elTop);
920 } else if (nodeHeight < elBottom) {
921 this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
922 }
923 },
924 bind: function() {
925 var that = this, onSelectableClick;
926 onSelectableClick = _.bind(this._onSelectableClick, this);
927 this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
928 _.each(this.datasets, function(dataset) {
929 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);
930 });
931 return this;
932 },
933 isOpen: function isOpen() {
934 return this.$node.hasClass(this.classes.open);
935 },
936 open: function open() {
937 this.$node.addClass(this.classes.open);
938 },
939 close: function close() {
940 this.$node.removeClass(this.classes.open);
941 this._removeCursor();
942 },
943 setLanguageDirection: function setLanguageDirection(dir) {
944 this.$node.attr("dir", dir);
945 },
946 selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
947 var $selectables, $oldCursor, oldIndex, newIndex;
948 $oldCursor = this.getActiveSelectable();
949 $selectables = this._getSelectables();
950 oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
951 newIndex = oldIndex + delta;
952 newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
953 newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
954 return newIndex === -1 ? null : $selectables.eq(newIndex);
955 },
956 setCursor: function setCursor($selectable) {
957 this._removeCursor();
958 if ($selectable = $selectable && $selectable.first()) {
959 $selectable.addClass(this.classes.cursor);
960 this._ensureVisible($selectable);
961 }
962 },
963 getSelectableData: function getSelectableData($el) {
964 return $el && $el.length ? Dataset.extractData($el) : null;
965 },
966 getActiveSelectable: function getActiveSelectable() {
967 var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
968 return $selectable.length ? $selectable : null;
969 },
970 getTopSelectable: function getTopSelectable() {
971 var $selectable = this._getSelectables().first();
972 return $selectable.length ? $selectable : null;
973 },
974 update: function update(query) {
975 var isValidUpdate = query !== this.query;
976 if (isValidUpdate) {
977 this.query = query;
978 _.each(this.datasets, updateDataset);
979 }
980 return isValidUpdate;
981 function updateDataset(dataset) {
982 dataset.update(query);
983 }
984 },
985 empty: function empty() {
986 _.each(this.datasets, clearDataset);
987 this.query = null;
988 this.$node.addClass(this.classes.empty);
989 function clearDataset(dataset) {
990 dataset.clear();
991 }
992 },
993 destroy: function destroy() {
994 this.$node.off(".tt");
995 this.$node = $("<div>");
996 _.each(this.datasets, destroyDataset);
997 function destroyDataset(dataset) {
998 dataset.destroy();
999 }
1000 }
1001 });
1002 return Menu;
1003 }();
1004 var DefaultMenu = function() {
1005 "use strict";
1006 var s = Menu.prototype;
1007 function DefaultMenu() {
1008 Menu.apply(this, [].slice.call(arguments, 0));
1009 }
1010 _.mixin(DefaultMenu.prototype, Menu.prototype, {
1011 open: function open() {
1012 !this._allDatasetsEmpty() && this._show();
1013 return s.open.apply(this, [].slice.call(arguments, 0));
1014 },
1015 close: function close() {
1016 this._hide();
1017 return s.close.apply(this, [].slice.call(arguments, 0));
1018 },
1019 _onRendered: function onRendered() {
1020 if (this._allDatasetsEmpty()) {
1021 this._hide();
1022 } else {
1023 this.isOpen() && this._show();
1024 }
1025 return s._onRendered.apply(this, [].slice.call(arguments, 0));
1026 },
1027 _onCleared: function onCleared() {
1028 if (this._allDatasetsEmpty()) {
1029 this._hide();
1030 } else {
1031 this.isOpen() && this._show();
1032 }
1033 return s._onCleared.apply(this, [].slice.call(arguments, 0));
1034 },
1035 setLanguageDirection: function setLanguageDirection(dir) {
1036 this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
1037 return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
1038 },
1039 _hide: function hide() {
1040 this.$node.hide();
1041 },
1042 _show: function show() {
1043 this.$node.css("display", "block");
1044 }
1045 });
1046 return DefaultMenu;
1047 }();
1048 var Typeahead = function() {
1049 "use strict";
1050 function Typeahead(o, www) {
1051 var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
1052 o = o || {};
1053 if (!o.input) {
1054 $.error("missing input");
1055 }
1056 if (!o.menu) {
1057 $.error("missing menu");
1058 }
1059 if (!o.eventBus) {
1060 $.error("missing event bus");
1061 }
1062 www.mixin(this);
1063 this.eventBus = o.eventBus;
1064 this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
1065 this.input = o.input;
1066 this.menu = o.menu;
1067 this.enabled = true;
1068 this.active = false;
1069 this.input.hasFocus() && this.activate();
1070 this.dir = this.input.getLangDir();
1071 this._hacks();
1072 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);
1073 onFocused = c(this, "activate", "open", "_onFocused");
1074 onBlurred = c(this, "deactivate", "_onBlurred");
1075 onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
1076 onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
1077 onEscKeyed = c(this, "isActive", "_onEscKeyed");
1078 onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
1079 onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
1080 onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
1081 onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
1082 onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
1083 onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
1084 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);
1085 }
1086 _.mixin(Typeahead.prototype, {
1087 _hacks: function hacks() {
1088 var $input, $menu;
1089 $input = this.input.$input || $("<div>");
1090 $menu = this.menu.$node || $("<div>");
1091 $input.on("blur.tt", function($e) {
1092 var active, isActive, hasActive;
1093 active = document.activeElement;
1094 isActive = $menu.is(active);
1095 hasActive = $menu.has(active).length > 0;
1096 if (_.isMsie() && (isActive || hasActive)) {
1097 $e.preventDefault();
1098 $e.stopImmediatePropagation();
1099 _.defer(function() {
1100 $input.focus();
1101 });
1102 }
1103 });
1104 $menu.on("mousedown.tt", function($e) {
1105 $e.preventDefault();
1106 });
1107 },
1108 _onSelectableClicked: function onSelectableClicked(type, $el) {
1109 this.select($el);
1110 },
1111 _onDatasetCleared: function onDatasetCleared() {
1112 this._updateHint();
1113 },
1114 _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
1115 this._updateHint();
1116 this.eventBus.trigger("render", suggestions, async, dataset);
1117 },
1118 _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
1119 this.eventBus.trigger("asyncrequest", query, dataset);
1120 },
1121 _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
1122 this.eventBus.trigger("asynccancel", query, dataset);
1123 },
1124 _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
1125 this.eventBus.trigger("asyncreceive", query, dataset);
1126 },
1127 _onFocused: function onFocused() {
1128 this._minLengthMet() && this.menu.update(this.input.getQuery());
1129 },
1130 _onBlurred: function onBlurred() {
1131 if (this.input.hasQueryChangedSinceLastFocus()) {
1132 this.eventBus.trigger("change", this.input.getQuery());
1133 }
1134 },
1135 _onEnterKeyed: function onEnterKeyed(type, $e) {
1136 var $selectable;
1137 if ($selectable = this.menu.getActiveSelectable()) {
1138 this.select($selectable) && $e.preventDefault();
1139 }
1140 },
1141 _onTabKeyed: function onTabKeyed(type, $e) {
1142 var $selectable;
1143 if ($selectable = this.menu.getActiveSelectable()) {
1144 this.select($selectable) && $e.preventDefault();
1145 } else if ($selectable = this.menu.getTopSelectable()) {
1146 this.autocomplete($selectable) && $e.preventDefault();
1147 }
1148 },
1149 _onEscKeyed: function onEscKeyed() {
1150 this.close();
1151 },
1152 _onUpKeyed: function onUpKeyed() {
1153 this.moveCursor(-1);
1154 },
1155 _onDownKeyed: function onDownKeyed() {
1156 this.moveCursor(+1);
1157 },
1158 _onLeftKeyed: function onLeftKeyed() {
1159 if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
1160 this.autocomplete(this.menu.getTopSelectable());
1161 }
1162 },
1163 _onRightKeyed: function onRightKeyed() {
1164 if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
1165 this.autocomplete(this.menu.getTopSelectable());
1166 }
1167 },
1168 _onQueryChanged: function onQueryChanged(e, query) {
1169 this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
1170 },
1171 _onWhitespaceChanged: function onWhitespaceChanged() {
1172 this._updateHint();
1173 },
1174 _onLangDirChanged: function onLangDirChanged(e, dir) {
1175 if (this.dir !== dir) {
1176 this.dir = dir;
1177 this.menu.setLanguageDirection(dir);
1178 }
1179 },
1180 _openIfActive: function openIfActive() {
1181 this.isActive() && this.open();
1182 },
1183 _minLengthMet: function minLengthMet(query) {
1184 query = _.isString(query) ? query : this.input.getQuery() || "";
1185 return query.length >= this.minLength;
1186 },
1187 _updateHint: function updateHint() {
1188 var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
1189 $selectable = this.menu.getTopSelectable();
1190 data = this.menu.getSelectableData($selectable);
1191 val = this.input.getInputValue();
1192 if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
1193 query = Input.normalizeQuery(val);
1194 escapedQuery = _.escapeRegExChars(query);
1195 frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
1196 match = frontMatchRegEx.exec(data.val);
1197 match && this.input.setHint(val + match[1]);
1198 } else {
1199 this.input.clearHint();
1200 }
1201 },
1202 isEnabled: function isEnabled() {
1203 return this.enabled;
1204 },
1205 enable: function enable() {
1206 this.enabled = true;
1207 },
1208 disable: function disable() {
1209 this.enabled = false;
1210 },
1211 isActive: function isActive() {
1212 return this.active;
1213 },
1214 activate: function activate() {
1215 if (this.isActive()) {
1216 return true;
1217 } else if (!this.isEnabled() || this.eventBus.before("active")) {
1218 return false;
1219 } else {
1220 this.active = true;
1221 this.eventBus.trigger("active");
1222 return true;
1223 }
1224 },
1225 deactivate: function deactivate() {
1226 if (!this.isActive()) {
1227 return true;
1228 } else if (this.eventBus.before("idle")) {
1229 return false;
1230 } else {
1231 this.active = false;
1232 this.close();
1233 this.eventBus.trigger("idle");
1234 return true;
1235 }
1236 },
1237 isOpen: function isOpen() {
1238 return this.menu.isOpen();
1239 },
1240 open: function open() {
1241 if (!this.isOpen() && !this.eventBus.before("open")) {
1242 this.menu.open();
1243 this._updateHint();
1244 this.eventBus.trigger("open");
1245 }
1246 return this.isOpen();
1247 },
1248 close: function close() {
1249 if (this.isOpen() && !this.eventBus.before("close")) {
1250 this.menu.close();
1251 this.input.clearHint();
1252 this.input.resetInputValue();
1253 this.eventBus.trigger("close");
1254 }
1255 return !this.isOpen();
1256 },
1257 setVal: function setVal(val) {
1258 this.input.setQuery(_.toStr(val));
1259 },
1260 getVal: function getVal() {
1261 return this.input.getQuery();
1262 },
1263 select: function select($selectable) {
1264 var data = this.menu.getSelectableData($selectable);
1265 if (data && !this.eventBus.before("select", data.obj)) {
1266 this.input.setQuery(data.val, true);
1267 this.eventBus.trigger("select", data.obj);
1268 this.close();
1269 return true;
1270 }
1271 return false;
1272 },
1273 autocomplete: function autocomplete($selectable) {
1274 var query, data, isValid;
1275 query = this.input.getQuery();
1276 data = this.menu.getSelectableData($selectable);
1277 isValid = data && query !== data.val;
1278 if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
1279 this.input.setQuery(data.val);
1280 this.eventBus.trigger("autocomplete", data.obj);
1281 return true;
1282 }
1283 return false;
1284 },
1285 moveCursor: function moveCursor(delta) {
1286 var query, $candidate, data, payload, cancelMove;
1287 query = this.input.getQuery();
1288 $candidate = this.menu.selectableRelativeToCursor(delta);
1289 data = this.menu.getSelectableData($candidate);
1290 payload = data ? data.obj : null;
1291 cancelMove = this._minLengthMet() && this.menu.update(query);
1292 if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
1293 this.menu.setCursor($candidate);
1294 if (data) {
1295 this.input.setInputValue(data.val);
1296 } else {
1297 this.input.resetInputValue();
1298 this._updateHint();
1299 }
1300 this.eventBus.trigger("cursorchange", payload);
1301 return true;
1302 }
1303 return false;
1304 },
1305 destroy: function destroy() {
1306 this.input.destroy();
1307 this.menu.destroy();
1308 }
1309 });
1310 return Typeahead;
1311 function c(ctx) {
1312 var methods = [].slice.call(arguments, 1);
1313 return function() {
1314 var args = [].slice.call(arguments);
1315 _.each(methods, function(method) {
1316 return ctx[method].apply(ctx, args);
1317 });
1318 };
1319 }
1320 }();
1321 (function() {
1322 "use strict";
1323 var old, keys, methods;
1324 old = $.fn.typeahead;
1325 keys = {
1326 www: "tt-www",
1327 attrs: "tt-attrs",
1328 typeahead: "tt-typeahead"
1329 };
1330 methods = {
1331 initialize: function initialize(o, datasets) {
1332 var www;
1333 datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
1334 o = o || {};
1335 www = WWW(o.classNames);
1336 return this.each(attach);
1337 function attach() {
1338 var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
1339 _.each(datasets, function(d) {
1340 d.highlight = !!o.highlight;
1341 });
1342 $input = $(this);
1343 $wrapper = $(www.html.wrapper);
1344 $hint = $elOrNull(o.hint);
1345 $menu = $elOrNull(o.menu);
1346 defaultHint = o.hint !== false && !$hint;
1347 defaultMenu = o.menu !== false && !$menu;
1348 defaultHint && ($hint = buildHintFromInput($input, www));
1349 defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
1350 $hint && $hint.val("");
1351 $input = prepInput($input, www);
1352 if (defaultHint || defaultMenu) {
1353 $wrapper.css(www.css.wrapper);
1354 $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
1355 $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
1356 }
1357 MenuConstructor = defaultMenu ? DefaultMenu : Menu;
1358 eventBus = new EventBus({
1359 el: $input
1360 });
1361 input = new Input({
1362 hint: $hint,
1363 input: $input
1364 }, www);
1365 menu = new MenuConstructor({
1366 node: $menu,
1367 datasets: datasets
1368 }, www);
1369 typeahead = new Typeahead({
1370 input: input,
1371 menu: menu,
1372 eventBus: eventBus,
1373 minLength: o.minLength
1374 }, www);
1375 $input.data(keys.www, www);
1376 $input.data(keys.typeahead, typeahead);
1377 }
1378 },
1379 isEnabled: function isEnabled() {
1380 var enabled;
1381 ttEach(this.first(), function(t) {
1382 enabled = t.isEnabled();
1383 });
1384 return enabled;
1385 },
1386 enable: function enable() {
1387 ttEach(this, function(t) {
1388 t.enable();
1389 });
1390 return this;
1391 },
1392 disable: function disable() {
1393 ttEach(this, function(t) {
1394 t.disable();
1395 });
1396 return this;
1397 },
1398 isActive: function isActive() {
1399 var active;
1400 ttEach(this.first(), function(t) {
1401 active = t.isActive();
1402 });
1403 return active;
1404 },
1405 activate: function activate() {
1406 ttEach(this, function(t) {
1407 t.activate();
1408 });
1409 return this;
1410 },
1411 deactivate: function deactivate() {
1412 ttEach(this, function(t) {
1413 t.deactivate();
1414 });
1415 return this;
1416 },
1417 isOpen: function isOpen() {
1418 var open;
1419 ttEach(this.first(), function(t) {
1420 open = t.isOpen();
1421 });
1422 return open;
1423 },
1424 open: function open() {
1425 ttEach(this, function(t) {
1426 t.open();
1427 });
1428 return this;
1429 },
1430 close: function close() {
1431 ttEach(this, function(t) {
1432 t.close();
1433 });
1434 return this;
1435 },
1436 select: function select(el) {
1437 var success = false, $el = $(el);
1438 ttEach(this.first(), function(t) {
1439 success = t.select($el);
1440 });
1441 return success;
1442 },
1443 autocomplete: function autocomplete(el) {
1444 var success = false, $el = $(el);
1445 ttEach(this.first(), function(t) {
1446 success = t.autocomplete($el);
1447 });
1448 return success;
1449 },
1450 moveCursor: function moveCursoe(delta) {
1451 var success = false;
1452 ttEach(this.first(), function(t) {
1453 success = t.moveCursor(delta);
1454 });
1455 return success;
1456 },
1457 val: function val(newVal) {
1458 var query;
1459 if (!arguments.length) {
1460 ttEach(this.first(), function(t) {
1461 query = t.getVal();
1462 });
1463 return query;
1464 } else {
1465 ttEach(this, function(t) {
1466 t.setVal(newVal);
1467 });
1468 return this;
1469 }
1470 },
1471 destroy: function destroy() {
1472 ttEach(this, function(typeahead, $input) {
1473 revert($input);
1474 typeahead.destroy();
1475 });
1476 return this;
1477 }
1478 };
1479 $.fn.typeahead = function(method) {
1480 if (methods[method]) {
1481 return methods[method].apply(this, [].slice.call(arguments, 1));
1482 } else {
1483 return methods.initialize.apply(this, arguments);
1484 }
1485 };
1486 $.fn.typeahead.noConflict = function noConflict() {
1487 $.fn.typeahead = old;
1488 return this;
1489 };
1490 function ttEach($els, fn) {
1491 $els.each(function() {
1492 var $input = $(this), typeahead;
1493 (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
1494 });
1495 }
1496 function buildHintFromInput($input, www) {
1497 return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
1498 autocomplete: "off",
1499 spellcheck: "false",
1500 tabindex: -1
1501 });
1502 }
1503 function prepInput($input, www) {
1504 $input.data(keys.attrs, {
1505 dir: $input.attr("dir"),
1506 autocomplete: $input.attr("autocomplete"),
1507 spellcheck: $input.attr("spellcheck"),
1508 style: $input.attr("style")
1509 });
1510 $input.addClass(www.classes.input).attr({
1511 autocomplete: "off",
1512 spellcheck: false
1513 });
1514 try {
1515 !$input.attr("dir") && $input.attr("dir", "auto");
1516 } catch (e) {}
1517 return $input;
1518 }
1519 function getBackgroundStyles($el) {
1520 return {
1521 backgroundAttachment: $el.css("background-attachment"),
1522 backgroundClip: $el.css("background-clip"),
1523 backgroundColor: $el.css("background-color"),
1524 backgroundImage: $el.css("background-image"),
1525 backgroundOrigin: $el.css("background-origin"),
1526 backgroundPosition: $el.css("background-position"),
1527 backgroundRepeat: $el.css("background-repeat"),
1528 backgroundSize: $el.css("background-size")
1529 };
1530 }
1531 function revert($input) {
1532 var www, $wrapper;
1533 www = $input.data(keys.www);
1534 $wrapper = $input.parent().filter(www.selectors.wrapper);
1535 _.each($input.data(keys.attrs), function(val, key) {
1536 _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
1537 });
1538 $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
1539 if ($wrapper.length) {
1540 $input.detach().insertAfter($wrapper);
1541 $wrapper.remove();
1542 }
1543 }
1544 function $elOrNull(obj) {
1545 var isValid, $el;
1546 isValid = _.isJQuery(obj) || _.isElement(obj);
1547 $el = isValid ? $(obj).first() : [];
1548 return $el.length ? $el : null;
1549 }
1550 })();
1551}); \ No newline at end of file