twitter-typeahead-rails 0.10.2 → 0.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,127 +1,134 @@
1
1
  /*!
2
- * typeahead.js 0.10.2
2
+ * typeahead.js 0.10.5
3
3
  * https://github.com/twitter/typeahead.js
4
4
  * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
5
5
  */
6
6
 
7
7
  (function($) {
8
- var _ = {
9
- isMsie: function() {
10
- return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
11
- },
12
- isBlankString: function(str) {
13
- return !str || /^\s*$/.test(str);
14
- },
15
- escapeRegExChars: function(str) {
16
- return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
17
- },
18
- isString: function(obj) {
19
- return typeof obj === "string";
20
- },
21
- isNumber: function(obj) {
22
- return typeof obj === "number";
23
- },
24
- isArray: $.isArray,
25
- isFunction: $.isFunction,
26
- isObject: $.isPlainObject,
27
- isUndefined: function(obj) {
28
- return typeof obj === "undefined";
29
- },
30
- bind: $.proxy,
31
- each: function(collection, cb) {
32
- $.each(collection, reverseArgs);
33
- function reverseArgs(index, value) {
34
- return cb(value, index);
35
- }
36
- },
37
- map: $.map,
38
- filter: $.grep,
39
- every: function(obj, test) {
40
- var result = true;
41
- if (!obj) {
42
- return result;
43
- }
44
- $.each(obj, function(key, val) {
45
- if (!(result = test.call(null, val, key, obj))) {
46
- return false;
8
+ var _ = function() {
9
+ "use strict";
10
+ return {
11
+ isMsie: function() {
12
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
13
+ },
14
+ isBlankString: function(str) {
15
+ return !str || /^\s*$/.test(str);
16
+ },
17
+ escapeRegExChars: function(str) {
18
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
19
+ },
20
+ isString: function(obj) {
21
+ return typeof obj === "string";
22
+ },
23
+ isNumber: function(obj) {
24
+ return typeof obj === "number";
25
+ },
26
+ isArray: $.isArray,
27
+ isFunction: $.isFunction,
28
+ isObject: $.isPlainObject,
29
+ isUndefined: function(obj) {
30
+ return typeof obj === "undefined";
31
+ },
32
+ toStr: function toStr(s) {
33
+ return _.isUndefined(s) || s === null ? "" : s + "";
34
+ },
35
+ bind: $.proxy,
36
+ each: function(collection, cb) {
37
+ $.each(collection, reverseArgs);
38
+ function reverseArgs(index, value) {
39
+ return cb(value, index);
47
40
  }
48
- });
49
- return !!result;
50
- },
51
- some: function(obj, test) {
52
- var result = false;
53
- if (!obj) {
54
- return result;
55
- }
56
- $.each(obj, function(key, val) {
57
- if (result = test.call(null, val, key, obj)) {
58
- return false;
41
+ },
42
+ map: $.map,
43
+ filter: $.grep,
44
+ every: function(obj, test) {
45
+ var result = true;
46
+ if (!obj) {
47
+ return result;
59
48
  }
60
- });
61
- return !!result;
62
- },
63
- mixin: $.extend,
64
- getUniqueId: function() {
65
- var counter = 0;
66
- return function() {
67
- return counter++;
68
- };
69
- }(),
70
- templatify: function templatify(obj) {
71
- return $.isFunction(obj) ? obj : template;
72
- function template() {
73
- return String(obj);
74
- }
75
- },
76
- defer: function(fn) {
77
- setTimeout(fn, 0);
78
- },
79
- debounce: function(func, wait, immediate) {
80
- var timeout, result;
81
- return function() {
82
- var context = this, args = arguments, later, callNow;
83
- later = function() {
84
- timeout = null;
85
- if (!immediate) {
86
- result = func.apply(context, args);
49
+ $.each(obj, function(key, val) {
50
+ if (!(result = test.call(null, val, key, obj))) {
51
+ return false;
87
52
  }
88
- };
89
- callNow = immediate && !timeout;
90
- clearTimeout(timeout);
91
- timeout = setTimeout(later, wait);
92
- if (callNow) {
93
- result = func.apply(context, args);
53
+ });
54
+ return !!result;
55
+ },
56
+ some: function(obj, test) {
57
+ var result = false;
58
+ if (!obj) {
59
+ return result;
94
60
  }
95
- return result;
96
- };
97
- },
98
- throttle: function(func, wait) {
99
- var context, args, timeout, result, previous, later;
100
- previous = 0;
101
- later = function() {
102
- previous = new Date();
103
- timeout = null;
104
- result = func.apply(context, args);
105
- };
106
- return function() {
107
- var now = new Date(), remaining = wait - (now - previous);
108
- context = this;
109
- args = arguments;
110
- if (remaining <= 0) {
61
+ $.each(obj, function(key, val) {
62
+ if (result = test.call(null, val, key, obj)) {
63
+ return false;
64
+ }
65
+ });
66
+ return !!result;
67
+ },
68
+ mixin: $.extend,
69
+ getUniqueId: function() {
70
+ var counter = 0;
71
+ return function() {
72
+ return counter++;
73
+ };
74
+ }(),
75
+ templatify: function templatify(obj) {
76
+ return $.isFunction(obj) ? obj : template;
77
+ function template() {
78
+ return String(obj);
79
+ }
80
+ },
81
+ defer: function(fn) {
82
+ setTimeout(fn, 0);
83
+ },
84
+ debounce: function(func, wait, immediate) {
85
+ var timeout, result;
86
+ return function() {
87
+ var context = this, args = arguments, later, callNow;
88
+ later = function() {
89
+ timeout = null;
90
+ if (!immediate) {
91
+ result = func.apply(context, args);
92
+ }
93
+ };
94
+ callNow = immediate && !timeout;
111
95
  clearTimeout(timeout);
96
+ timeout = setTimeout(later, wait);
97
+ if (callNow) {
98
+ result = func.apply(context, args);
99
+ }
100
+ return result;
101
+ };
102
+ },
103
+ throttle: function(func, wait) {
104
+ var context, args, timeout, result, previous, later;
105
+ previous = 0;
106
+ later = function() {
107
+ previous = new Date();
112
108
  timeout = null;
113
- previous = now;
114
109
  result = func.apply(context, args);
115
- } else if (!timeout) {
116
- timeout = setTimeout(later, remaining);
117
- }
118
- return result;
119
- };
120
- },
121
- noop: function() {}
122
- };
123
- var VERSION = "0.10.2";
124
- var tokenizers = function(root) {
110
+ };
111
+ return function() {
112
+ var now = new Date(), remaining = wait - (now - previous);
113
+ context = this;
114
+ args = arguments;
115
+ if (remaining <= 0) {
116
+ clearTimeout(timeout);
117
+ timeout = null;
118
+ previous = now;
119
+ result = func.apply(context, args);
120
+ } else if (!timeout) {
121
+ timeout = setTimeout(later, remaining);
122
+ }
123
+ return result;
124
+ };
125
+ },
126
+ noop: function() {}
127
+ };
128
+ }();
129
+ var VERSION = "0.10.5";
130
+ var tokenizers = function() {
131
+ "use strict";
125
132
  return {
126
133
  nonword: nonword,
127
134
  whitespace: whitespace,
@@ -130,26 +137,35 @@
130
137
  whitespace: getObjTokenizer(whitespace)
131
138
  }
132
139
  };
133
- function whitespace(s) {
134
- return s.split(/\s+/);
140
+ function whitespace(str) {
141
+ str = _.toStr(str);
142
+ return str ? str.split(/\s+/) : [];
135
143
  }
136
- function nonword(s) {
137
- return s.split(/\W+/);
144
+ function nonword(str) {
145
+ str = _.toStr(str);
146
+ return str ? str.split(/\W+/) : [];
138
147
  }
139
148
  function getObjTokenizer(tokenizer) {
140
- return function setKey(key) {
149
+ return function setKey() {
150
+ var args = [].slice.call(arguments, 0);
141
151
  return function tokenize(o) {
142
- return tokenizer(o[key]);
152
+ var tokens = [];
153
+ _.each(args, function(k) {
154
+ tokens = tokens.concat(tokenizer(_.toStr(o[k])));
155
+ });
156
+ return tokens;
143
157
  };
144
158
  };
145
159
  }
146
160
  }();
147
161
  var LruCache = function() {
162
+ "use strict";
148
163
  function LruCache(maxSize) {
149
- this.maxSize = maxSize || 100;
150
- this.size = 0;
151
- this.hash = {};
152
- this.list = new List();
164
+ this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
165
+ this.reset();
166
+ if (this.maxSize <= 0) {
167
+ this.set = this.get = $.noop;
168
+ }
153
169
  }
154
170
  _.mixin(LruCache.prototype, {
155
171
  set: function set(key, val) {
@@ -174,6 +190,11 @@
174
190
  this.list.moveToFront(node);
175
191
  return node.val;
176
192
  }
193
+ },
194
+ reset: function reset() {
195
+ this.size = 0;
196
+ this.hash = {};
197
+ this.list = new List();
177
198
  }
178
199
  });
179
200
  function List() {
@@ -205,6 +226,7 @@
205
226
  return LruCache;
206
227
  }();
207
228
  var PersistentStorage = function() {
229
+ "use strict";
208
230
  var ls, methods;
209
231
  try {
210
232
  ls = window.localStorage;
@@ -216,7 +238,7 @@
216
238
  function PersistentStorage(namespace) {
217
239
  this.prefix = [ "__", namespace, "__" ].join("");
218
240
  this.ttlKey = "__ttl__";
219
- this.keyMatcher = new RegExp("^" + this.prefix);
241
+ this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
220
242
  }
221
243
  if (ls && window.JSON) {
222
244
  methods = {
@@ -284,21 +306,28 @@
284
306
  }
285
307
  }();
286
308
  var Transport = function() {
287
- var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);
309
+ "use strict";
310
+ var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
288
311
  function Transport(o) {
289
312
  o = o || {};
313
+ this.cancelled = false;
314
+ this.lastUrl = null;
290
315
  this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
291
316
  this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;
317
+ this._cache = o.cache === false ? new LruCache(0) : sharedCache;
292
318
  }
293
319
  Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
294
320
  maxPendingRequests = num;
295
321
  };
296
- Transport.resetCache = function clearCache() {
297
- requestCache = new LruCache(10);
322
+ Transport.resetCache = function resetCache() {
323
+ sharedCache.reset();
298
324
  };
299
325
  _.mixin(Transport.prototype, {
300
326
  _get: function(url, o, cb) {
301
327
  var that = this, jqXhr;
328
+ if (this.cancelled || url !== this.lastUrl) {
329
+ return;
330
+ }
302
331
  if (jqXhr = pendingRequests[url]) {
303
332
  jqXhr.done(done).fail(fail);
304
333
  } else if (pendingRequestsCount < maxPendingRequests) {
@@ -309,7 +338,7 @@
309
338
  }
310
339
  function done(resp) {
311
340
  cb && cb(null, resp);
312
- requestCache.set(url, resp);
341
+ that._cache.set(url, resp);
313
342
  }
314
343
  function fail() {
315
344
  cb && cb(true);
@@ -329,7 +358,9 @@
329
358
  cb = o;
330
359
  o = {};
331
360
  }
332
- if (resp = requestCache.get(url)) {
361
+ this.cancelled = false;
362
+ this.lastUrl = url;
363
+ if (resp = this._cache.get(url)) {
333
364
  _.defer(function() {
334
365
  cb && cb(null, resp);
335
366
  });
@@ -337,6 +368,9 @@
337
368
  this._get(url, o, cb);
338
369
  }
339
370
  return !!resp;
371
+ },
372
+ cancel: function() {
373
+ this.cancelled = true;
340
374
  }
341
375
  });
342
376
  return Transport;
@@ -359,6 +393,7 @@
359
393
  }
360
394
  }();
361
395
  var SearchIndex = function() {
396
+ "use strict";
362
397
  function SearchIndex(o) {
363
398
  o = o || {};
364
399
  if (!o.datumTokenizer || !o.queryTokenizer) {
@@ -445,7 +480,7 @@
445
480
  }
446
481
  function unique(array) {
447
482
  var seen = {}, uniques = [];
448
- for (var i = 0; i < array.length; i++) {
483
+ for (var i = 0, len = array.length; i < len; i++) {
449
484
  if (!seen[array[i]]) {
450
485
  seen[array[i]] = true;
451
486
  uniques.push(array[i]);
@@ -457,7 +492,8 @@
457
492
  var ai = 0, bi = 0, intersection = [];
458
493
  arrayA = arrayA.sort(compare);
459
494
  arrayB = arrayB.sort(compare);
460
- while (ai < arrayA.length && bi < arrayB.length) {
495
+ var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
496
+ while (ai < lenArrayA && bi < lenArrayB) {
461
497
  if (arrayA[ai] < arrayB[bi]) {
462
498
  ai++;
463
499
  } else if (arrayA[ai] > arrayB[bi]) {
@@ -475,6 +511,7 @@
475
511
  }
476
512
  }();
477
513
  var oParser = function() {
514
+ "use strict";
478
515
  return {
479
516
  local: getLocal,
480
517
  prefetch: getPrefetch,
@@ -508,6 +545,7 @@
508
545
  var remote, defaults;
509
546
  defaults = {
510
547
  url: null,
548
+ cache: true,
511
549
  wildcard: "%QUERY",
512
550
  replace: null,
513
551
  rateLimitBy: "debounce",
@@ -542,6 +580,7 @@
542
580
  }
543
581
  }();
544
582
  (function(root) {
583
+ "use strict";
545
584
  var old, keys;
546
585
  old = root.Bloodhound;
547
586
  keys = {
@@ -590,6 +629,9 @@
590
629
  },
591
630
  _getFromRemote: function getFromRemote(query, cb) {
592
631
  var that = this, url, uriEncodedQuery;
632
+ if (!this.transport) {
633
+ return;
634
+ }
593
635
  query = query || "";
594
636
  uriEncodedQuery = encodeURIComponent(query);
595
637
  url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
@@ -598,6 +640,9 @@
598
640
  err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
599
641
  }
600
642
  },
643
+ _cancelLastRemoteRequest: function cancelLastRemoteRequest() {
644
+ this.transport && this.transport.cancel();
645
+ },
601
646
  _saveToStorage: function saveToStorage(data, thumbprint, ttl) {
602
647
  if (this.storage) {
603
648
  this.storage.set(keys.data, data, ttl);
@@ -635,9 +680,7 @@
635
680
  var that = this, matches = [], cacheHit = false;
636
681
  matches = this.index.get(query);
637
682
  matches = this.sorter(matches).slice(0, this.limit);
638
- if (matches.length < this.limit && this.transport) {
639
- cacheHit = this._getFromRemote(query, returnRemoteMatches);
640
- }
683
+ matches.length < this.limit ? cacheHit = this._getFromRemote(query, returnRemoteMatches) : this._cancelLastRemoteRequest();
641
684
  if (!cacheHit) {
642
685
  (matches.length > 0 || !this.transport) && cb && cb(matches);
643
686
  }
@@ -681,71 +724,79 @@
681
724
  return false;
682
725
  }
683
726
  })(this);
684
- var html = {
685
- wrapper: '<span class="twitter-typeahead"></span>',
686
- dropdown: '<span class="tt-dropdown-menu"></span>',
687
- dataset: '<div class="tt-dataset-%CLASS%"></div>',
688
- suggestions: '<span class="tt-suggestions"></span>',
689
- suggestion: '<div class="tt-suggestion"></div>'
690
- };
691
- var css = {
692
- wrapper: {
693
- position: "relative",
694
- display: "inline-block"
695
- },
696
- hint: {
697
- position: "absolute",
698
- top: "0",
699
- left: "0",
700
- borderColor: "transparent",
701
- boxShadow: "none"
702
- },
703
- input: {
704
- position: "relative",
705
- verticalAlign: "top",
706
- backgroundColor: "transparent"
707
- },
708
- inputWithNoHint: {
709
- position: "relative",
710
- verticalAlign: "top"
711
- },
712
- dropdown: {
713
- position: "absolute",
714
- top: "100%",
715
- left: "0",
716
- zIndex: "100",
717
- display: "none"
718
- },
719
- suggestions: {
720
- display: "block"
721
- },
722
- suggestion: {
723
- whiteSpace: "nowrap",
724
- cursor: "pointer"
725
- },
726
- suggestionChild: {
727
- whiteSpace: "normal"
728
- },
729
- ltr: {
730
- left: "0",
731
- right: "auto"
732
- },
733
- rtl: {
734
- left: "auto",
735
- right: " 0"
727
+ var html = function() {
728
+ return {
729
+ wrapper: '<span class="twitter-typeahead"></span>',
730
+ dropdown: '<span class="tt-dropdown-menu"></span>',
731
+ dataset: '<div class="tt-dataset-%CLASS%"></div>',
732
+ suggestions: '<span class="tt-suggestions"></span>',
733
+ suggestion: '<div class="tt-suggestion"></div>'
734
+ };
735
+ }();
736
+ var css = function() {
737
+ "use strict";
738
+ var css = {
739
+ wrapper: {
740
+ position: "relative",
741
+ display: "inline-block"
742
+ },
743
+ hint: {
744
+ position: "absolute",
745
+ top: "0",
746
+ left: "0",
747
+ borderColor: "transparent",
748
+ boxShadow: "none",
749
+ opacity: "1"
750
+ },
751
+ input: {
752
+ position: "relative",
753
+ verticalAlign: "top",
754
+ backgroundColor: "transparent"
755
+ },
756
+ inputWithNoHint: {
757
+ position: "relative",
758
+ verticalAlign: "top"
759
+ },
760
+ dropdown: {
761
+ position: "absolute",
762
+ top: "100%",
763
+ left: "0",
764
+ zIndex: "100",
765
+ display: "none"
766
+ },
767
+ suggestions: {
768
+ display: "block"
769
+ },
770
+ suggestion: {
771
+ whiteSpace: "nowrap",
772
+ cursor: "pointer"
773
+ },
774
+ suggestionChild: {
775
+ whiteSpace: "normal"
776
+ },
777
+ ltr: {
778
+ left: "0",
779
+ right: "auto"
780
+ },
781
+ rtl: {
782
+ left: "auto",
783
+ right: " 0"
784
+ }
785
+ };
786
+ if (_.isMsie()) {
787
+ _.mixin(css.input, {
788
+ backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
789
+ });
736
790
  }
737
- };
738
- if (_.isMsie()) {
739
- _.mixin(css.input, {
740
- backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
741
- });
742
- }
743
- if (_.isMsie() && _.isMsie() <= 7) {
744
- _.mixin(css.input, {
745
- marginTop: "-1px"
746
- });
747
- }
791
+ if (_.isMsie() && _.isMsie() <= 7) {
792
+ _.mixin(css.input, {
793
+ marginTop: "-1px"
794
+ });
795
+ }
796
+ return css;
797
+ }();
748
798
  var EventBus = function() {
799
+ "use strict";
749
800
  var namespace = "typeahead:";
750
801
  function EventBus(o) {
751
802
  if (!o || !o.el) {
@@ -762,6 +813,7 @@
762
813
  return EventBus;
763
814
  }();
764
815
  var EventEmitter = function() {
816
+ "use strict";
765
817
  var splitter = /\s+/, nextTick = getNextTick();
766
818
  return {
767
819
  onSync: onSync,
@@ -821,7 +873,7 @@
821
873
  return flush;
822
874
  function flush() {
823
875
  var cancelled;
824
- for (var i = 0; !cancelled && i < callbacks.length; i += 1) {
876
+ for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
825
877
  cancelled = callbacks[i].apply(context, args) === false;
826
878
  }
827
879
  return !cancelled;
@@ -851,6 +903,7 @@
851
903
  }
852
904
  }();
853
905
  var highlight = function(doc) {
906
+ "use strict";
854
907
  var defaults = {
855
908
  node: null,
856
909
  pattern: null,
@@ -869,7 +922,7 @@
869
922
  regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
870
923
  traverse(o.node, hightlightTextNode);
871
924
  function hightlightTextNode(textNode) {
872
- var match, patternNode;
925
+ var match, patternNode, wrapperNode;
873
926
  if (match = regex.exec(textNode.data)) {
874
927
  wrapperNode = doc.createElement(o.tagName);
875
928
  o.className && (wrapperNode.className = o.className);
@@ -894,7 +947,7 @@
894
947
  };
895
948
  function getRegex(patterns, caseSensitive, wordsOnly) {
896
949
  var escapedPatterns = [], regexStr;
897
- for (var i = 0; i < patterns.length; i++) {
950
+ for (var i = 0, len = patterns.length; i < len; i++) {
898
951
  escapedPatterns.push(_.escapeRegExChars(patterns[i]));
899
952
  }
900
953
  regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
@@ -902,6 +955,7 @@
902
955
  }
903
956
  }(window.document);
904
957
  var Input = function() {
958
+ "use strict";
905
959
  var specialKeyCodeMap;
906
960
  specialKeyCodeMap = {
907
961
  9: "tab",
@@ -997,8 +1051,9 @@
997
1051
  inputValue = this.getInputValue();
998
1052
  areEquivalent = areQueriesEquivalent(inputValue, this.query);
999
1053
  hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;
1054
+ this.query = inputValue;
1000
1055
  if (!areEquivalent) {
1001
- this.trigger("queryChanged", this.query = inputValue);
1056
+ this.trigger("queryChanged", this.query);
1002
1057
  } else if (hasDifferentWhitespace) {
1003
1058
  this.trigger("whitespaceChanged", this.query);
1004
1059
  }
@@ -1095,6 +1150,7 @@
1095
1150
  }
1096
1151
  }();
1097
1152
  var Dataset = function() {
1153
+ "use strict";
1098
1154
  var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";
1099
1155
  function Dataset(o) {
1100
1156
  o = o || {};
@@ -1148,6 +1204,7 @@
1148
1204
  nodes = _.map(suggestions, getSuggestionNode);
1149
1205
  $suggestions.append.apply($suggestions, nodes);
1150
1206
  that.highlight && highlight({
1207
+ className: "tt-highlight",
1151
1208
  node: $suggestions[0],
1152
1209
  pattern: query
1153
1210
  });
@@ -1227,6 +1284,7 @@
1227
1284
  }
1228
1285
  }();
1229
1286
  var Dropdown = function() {
1287
+ "use strict";
1230
1288
  function Dropdown(o) {
1231
1289
  var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
1232
1290
  o = o || {};
@@ -1386,6 +1444,7 @@
1386
1444
  }
1387
1445
  }();
1388
1446
  var Typeahead = function() {
1447
+ "use strict";
1389
1448
  var attrsKey = "ttAttrs";
1390
1449
  function Typeahead(o) {
1391
1450
  var $menu, $input, $hint;
@@ -1396,7 +1455,7 @@
1396
1455
  this.isActivated = false;
1397
1456
  this.autoselect = !!o.autoselect;
1398
1457
  this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
1399
- this.$node = buildDomStructure(o.input, o.withHint);
1458
+ this.$node = buildDom(o.input, o.withHint);
1400
1459
  $menu = this.$node.find(".tt-dropdown-menu");
1401
1460
  $input = this.$node.find(".tt-input");
1402
1461
  $hint = this.$node.find(".tt-hint");
@@ -1564,6 +1623,7 @@
1564
1623
  this.dropdown.close();
1565
1624
  },
1566
1625
  setVal: function setVal(val) {
1626
+ val = _.toStr(val);
1567
1627
  if (this.isActivated) {
1568
1628
  this.input.setInputValue(val);
1569
1629
  } else {
@@ -1583,15 +1643,16 @@
1583
1643
  }
1584
1644
  });
1585
1645
  return Typeahead;
1586
- function buildDomStructure(input, withHint) {
1646
+ function buildDom(input, withHint) {
1587
1647
  var $input, $wrapper, $dropdown, $hint;
1588
1648
  $input = $(input);
1589
1649
  $wrapper = $(html.wrapper).css(css.wrapper);
1590
1650
  $dropdown = $(html.dropdown).css(css.dropdown);
1591
1651
  $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));
1592
- $hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder").prop("disabled", true).attr({
1652
+ $hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder required").prop("readonly", true).attr({
1593
1653
  autocomplete: "off",
1594
- spellcheck: "false"
1654
+ spellcheck: "false",
1655
+ tabindex: -1
1595
1656
  });
1596
1657
  $input.data(attrsKey, {
1597
1658
  dir: $input.attr("dir"),
@@ -1630,6 +1691,7 @@
1630
1691
  }
1631
1692
  }();
1632
1693
  (function() {
1694
+ "use strict";
1633
1695
  var old, typeaheadKey, methods;
1634
1696
  old = $.fn.typeahead;
1635
1697
  typeaheadKey = "ttTypeahead";
@@ -1702,8 +1764,12 @@
1702
1764
  }
1703
1765
  };
1704
1766
  $.fn.typeahead = function(method) {
1705
- if (methods[method]) {
1706
- return methods[method].apply(this, [].slice.call(arguments, 1));
1767
+ var tts;
1768
+ if (methods[method] && method !== "initialize") {
1769
+ tts = this.filter(function() {
1770
+ return !!$(this).data(typeaheadKey);
1771
+ });
1772
+ return methods[method].apply(tts, [].slice.call(arguments, 1));
1707
1773
  } else {
1708
1774
  return methods.initialize.apply(this, arguments);
1709
1775
  }