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