twitter-typeahead-rails 0.10.1 → 0.10.2
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.
- data/README.md +2 -2
- data/lib/twitter-typeahead-rails/version.rb +1 -1
- data/vendor/assets/javascripts/twitter/typeahead/bloodhound.js +77 -44
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.bundle.js +170 -112
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.bundle.min.js +3 -3
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.jquery.js +95 -70
- metadata +2 -2
data/README.md
CHANGED
@@ -46,7 +46,7 @@ Add one of the following to your application.js manifest:
|
|
46
46
|
|
47
47
|
// instantiate the bloodhound suggestion engine
|
48
48
|
var numbers = new Bloodhound({
|
49
|
-
datumTokenizer:
|
49
|
+
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('num'),
|
50
50
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
51
51
|
local: [
|
52
52
|
{ num: 'one' },
|
@@ -72,7 +72,7 @@ $('.example-numbers .typeahead').typeahead(null, {
|
|
72
72
|
});
|
73
73
|
```
|
74
74
|
|
75
|
-
Currently this version tracks version v0.10.
|
75
|
+
Currently this version tracks version v0.10.2.
|
76
76
|
|
77
77
|
## Contributing
|
78
78
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
|
-
* typeahead.js 0.10.
|
2
|
+
* typeahead.js 0.10.2
|
3
3
|
* https://github.com/twitter/typeahead.js
|
4
|
-
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
|
4
|
+
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
|
5
5
|
*/
|
6
6
|
|
7
7
|
(function($) {
|
@@ -120,8 +120,31 @@
|
|
120
120
|
},
|
121
121
|
noop: function() {}
|
122
122
|
};
|
123
|
-
var VERSION = "0.10.
|
124
|
-
var
|
123
|
+
var VERSION = "0.10.2";
|
124
|
+
var tokenizers = function(root) {
|
125
|
+
return {
|
126
|
+
nonword: nonword,
|
127
|
+
whitespace: whitespace,
|
128
|
+
obj: {
|
129
|
+
nonword: getObjTokenizer(nonword),
|
130
|
+
whitespace: getObjTokenizer(whitespace)
|
131
|
+
}
|
132
|
+
};
|
133
|
+
function whitespace(s) {
|
134
|
+
return s.split(/\s+/);
|
135
|
+
}
|
136
|
+
function nonword(s) {
|
137
|
+
return s.split(/\W+/);
|
138
|
+
}
|
139
|
+
function getObjTokenizer(tokenizer) {
|
140
|
+
return function setKey(key) {
|
141
|
+
return function tokenize(o) {
|
142
|
+
return tokenizer(o[key]);
|
143
|
+
};
|
144
|
+
};
|
145
|
+
}
|
146
|
+
}();
|
147
|
+
var LruCache = function() {
|
125
148
|
function LruCache(maxSize) {
|
126
149
|
this.maxSize = maxSize || 100;
|
127
150
|
this.size = 0;
|
@@ -180,7 +203,7 @@
|
|
180
203
|
this.prev = this.next = null;
|
181
204
|
}
|
182
205
|
return LruCache;
|
183
|
-
}(
|
206
|
+
}();
|
184
207
|
var PersistentStorage = function() {
|
185
208
|
var ls, methods;
|
186
209
|
try {
|
@@ -277,17 +300,20 @@
|
|
277
300
|
_get: function(url, o, cb) {
|
278
301
|
var that = this, jqXhr;
|
279
302
|
if (jqXhr = pendingRequests[url]) {
|
280
|
-
jqXhr.done(done);
|
303
|
+
jqXhr.done(done).fail(fail);
|
281
304
|
} else if (pendingRequestsCount < maxPendingRequests) {
|
282
305
|
pendingRequestsCount++;
|
283
|
-
pendingRequests[url] = this._send(url, o).done(done).always(always);
|
306
|
+
pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);
|
284
307
|
} else {
|
285
308
|
this.onDeckRequestArgs = [].slice.call(arguments, 0);
|
286
309
|
}
|
287
310
|
function done(resp) {
|
288
|
-
cb && cb(resp);
|
311
|
+
cb && cb(null, resp);
|
289
312
|
requestCache.set(url, resp);
|
290
313
|
}
|
314
|
+
function fail() {
|
315
|
+
cb && cb(true);
|
316
|
+
}
|
291
317
|
function always() {
|
292
318
|
pendingRequestsCount--;
|
293
319
|
delete pendingRequests[url];
|
@@ -298,14 +324,14 @@
|
|
298
324
|
}
|
299
325
|
},
|
300
326
|
get: function(url, o, cb) {
|
301
|
-
var
|
327
|
+
var resp;
|
302
328
|
if (_.isFunction(o)) {
|
303
329
|
cb = o;
|
304
330
|
o = {};
|
305
331
|
}
|
306
332
|
if (resp = requestCache.get(url)) {
|
307
333
|
_.defer(function() {
|
308
|
-
cb && cb(resp);
|
334
|
+
cb && cb(null, resp);
|
309
335
|
});
|
310
336
|
} else {
|
311
337
|
this._get(url, o, cb);
|
@@ -340,8 +366,7 @@
|
|
340
366
|
}
|
341
367
|
this.datumTokenizer = o.datumTokenizer;
|
342
368
|
this.queryTokenizer = o.queryTokenizer;
|
343
|
-
this.
|
344
|
-
this.trie = newNode();
|
369
|
+
this.reset();
|
345
370
|
}
|
346
371
|
_.mixin(SearchIndex.prototype, {
|
347
372
|
bootstrap: function bootstrap(o) {
|
@@ -356,7 +381,7 @@
|
|
356
381
|
id = that.datums.push(datum) - 1;
|
357
382
|
tokens = normalizeTokens(that.datumTokenizer(datum));
|
358
383
|
_.each(tokens, function(token) {
|
359
|
-
var node, chars, ch
|
384
|
+
var node, chars, ch;
|
360
385
|
node = that.trie;
|
361
386
|
chars = token.split("");
|
362
387
|
while (ch = chars.shift()) {
|
@@ -391,6 +416,10 @@
|
|
391
416
|
return that.datums[id];
|
392
417
|
}) : [];
|
393
418
|
},
|
419
|
+
reset: function reset() {
|
420
|
+
this.datums = [];
|
421
|
+
this.trie = newNode();
|
422
|
+
},
|
394
423
|
serialize: function serialize() {
|
395
424
|
return {
|
396
425
|
datums: this.datums,
|
@@ -452,11 +481,7 @@
|
|
452
481
|
remote: getRemote
|
453
482
|
};
|
454
483
|
function getLocal(o) {
|
455
|
-
|
456
|
-
if (_.isFunction(local)) {
|
457
|
-
local = local.call(null);
|
458
|
-
}
|
459
|
-
return local;
|
484
|
+
return o.local || null;
|
460
485
|
}
|
461
486
|
function getPrefetch(o) {
|
462
487
|
var prefetch, defaults;
|
@@ -516,13 +541,15 @@
|
|
516
541
|
}
|
517
542
|
}
|
518
543
|
}();
|
519
|
-
|
520
|
-
var keys;
|
544
|
+
(function(root) {
|
545
|
+
var old, keys;
|
546
|
+
old = root.Bloodhound;
|
521
547
|
keys = {
|
522
548
|
data: "data",
|
523
549
|
protocol: "protocol",
|
524
550
|
thumbprint: "thumbprint"
|
525
551
|
};
|
552
|
+
root.Bloodhound = Bloodhound;
|
526
553
|
function Bloodhound(o) {
|
527
554
|
if (!o || !o.local && !o.prefetch && !o.remote) {
|
528
555
|
$.error("one of local, prefetch, or remote is required");
|
@@ -540,14 +567,11 @@
|
|
540
567
|
});
|
541
568
|
this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;
|
542
569
|
}
|
543
|
-
Bloodhound.
|
544
|
-
|
545
|
-
|
546
|
-
},
|
547
|
-
nonword: function nonwordTokenizer(s) {
|
548
|
-
return s.split(/\W+/);
|
549
|
-
}
|
570
|
+
Bloodhound.noConflict = function noConflict() {
|
571
|
+
root.Bloodhound = old;
|
572
|
+
return Bloodhound;
|
550
573
|
};
|
574
|
+
Bloodhound.tokenizers = tokenizers;
|
551
575
|
_.mixin(Bloodhound.prototype, {
|
552
576
|
_loadPrefetch: function loadPrefetch(o) {
|
553
577
|
var that = this, serialized, deferred;
|
@@ -559,9 +583,8 @@
|
|
559
583
|
}
|
560
584
|
return deferred;
|
561
585
|
function handlePrefetchResponse(resp) {
|
562
|
-
|
563
|
-
|
564
|
-
that.add(filtered);
|
586
|
+
that.clear();
|
587
|
+
that.add(o.filter ? o.filter(resp) : resp);
|
565
588
|
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);
|
566
589
|
}
|
567
590
|
},
|
@@ -571,9 +594,8 @@
|
|
571
594
|
uriEncodedQuery = encodeURIComponent(query);
|
572
595
|
url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
|
573
596
|
return this.transport.get(url, this.remote.ajax, handleRemoteResponse);
|
574
|
-
function handleRemoteResponse(resp) {
|
575
|
-
|
576
|
-
cb(filtered);
|
597
|
+
function handleRemoteResponse(err, resp) {
|
598
|
+
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
|
577
599
|
}
|
578
600
|
},
|
579
601
|
_saveToStorage: function saveToStorage(data, thumbprint, ttl) {
|
@@ -593,30 +615,32 @@
|
|
593
615
|
isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;
|
594
616
|
return stored.data && !isExpired ? stored.data : null;
|
595
617
|
},
|
596
|
-
|
597
|
-
var that = this, deferred;
|
618
|
+
_initialize: function initialize() {
|
619
|
+
var that = this, local = this.local, deferred;
|
598
620
|
deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();
|
599
|
-
|
621
|
+
local && deferred.done(addLocalToIndex);
|
600
622
|
this.transport = this.remote ? new Transport(this.remote) : null;
|
601
|
-
this.
|
602
|
-
return deferred.promise();
|
603
|
-
};
|
604
|
-
return deferred.promise();
|
623
|
+
return this.initPromise = deferred.promise();
|
605
624
|
function addLocalToIndex() {
|
606
|
-
that.add(
|
625
|
+
that.add(_.isFunction(local) ? local() : local);
|
607
626
|
}
|
608
627
|
},
|
628
|
+
initialize: function initialize(force) {
|
629
|
+
return !this.initPromise || force ? this._initialize() : this.initPromise;
|
630
|
+
},
|
609
631
|
add: function add(data) {
|
610
632
|
this.index.add(data);
|
611
633
|
},
|
612
634
|
get: function get(query, cb) {
|
613
|
-
var that = this, matches, cacheHit = false;
|
635
|
+
var that = this, matches = [], cacheHit = false;
|
614
636
|
matches = this.index.get(query);
|
615
637
|
matches = this.sorter(matches).slice(0, this.limit);
|
616
638
|
if (matches.length < this.limit && this.transport) {
|
617
639
|
cacheHit = this._getFromRemote(query, returnRemoteMatches);
|
618
640
|
}
|
619
|
-
!cacheHit
|
641
|
+
if (!cacheHit) {
|
642
|
+
(matches.length > 0 || !this.transport) && cb && cb(matches);
|
643
|
+
}
|
620
644
|
function returnRemoteMatches(remoteMatches) {
|
621
645
|
var matchesWithBackfill = matches.slice(0);
|
622
646
|
_.each(remoteMatches, function(remoteMatch) {
|
@@ -630,6 +654,15 @@
|
|
630
654
|
cb && cb(that.sorter(matchesWithBackfill));
|
631
655
|
}
|
632
656
|
},
|
657
|
+
clear: function clear() {
|
658
|
+
this.index.reset();
|
659
|
+
},
|
660
|
+
clearPrefetchCache: function clearPrefetchCache() {
|
661
|
+
this.storage && this.storage.clear();
|
662
|
+
},
|
663
|
+
clearRemoteCache: function clearRemoteCache() {
|
664
|
+
this.transport && Transport.resetCache();
|
665
|
+
},
|
633
666
|
ttAdapter: function ttAdapter() {
|
634
667
|
return _.bind(this.get, this);
|
635
668
|
}
|
@@ -647,5 +680,5 @@
|
|
647
680
|
function ignoreDuplicates() {
|
648
681
|
return false;
|
649
682
|
}
|
650
|
-
}();
|
683
|
+
})(this);
|
651
684
|
})(window.jQuery);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
|
-
* typeahead.js 0.10.
|
2
|
+
* typeahead.js 0.10.2
|
3
3
|
* https://github.com/twitter/typeahead.js
|
4
|
-
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
|
4
|
+
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
|
5
5
|
*/
|
6
6
|
|
7
7
|
(function($) {
|
@@ -120,8 +120,31 @@
|
|
120
120
|
},
|
121
121
|
noop: function() {}
|
122
122
|
};
|
123
|
-
var VERSION = "0.10.
|
124
|
-
var
|
123
|
+
var VERSION = "0.10.2";
|
124
|
+
var tokenizers = function(root) {
|
125
|
+
return {
|
126
|
+
nonword: nonword,
|
127
|
+
whitespace: whitespace,
|
128
|
+
obj: {
|
129
|
+
nonword: getObjTokenizer(nonword),
|
130
|
+
whitespace: getObjTokenizer(whitespace)
|
131
|
+
}
|
132
|
+
};
|
133
|
+
function whitespace(s) {
|
134
|
+
return s.split(/\s+/);
|
135
|
+
}
|
136
|
+
function nonword(s) {
|
137
|
+
return s.split(/\W+/);
|
138
|
+
}
|
139
|
+
function getObjTokenizer(tokenizer) {
|
140
|
+
return function setKey(key) {
|
141
|
+
return function tokenize(o) {
|
142
|
+
return tokenizer(o[key]);
|
143
|
+
};
|
144
|
+
};
|
145
|
+
}
|
146
|
+
}();
|
147
|
+
var LruCache = function() {
|
125
148
|
function LruCache(maxSize) {
|
126
149
|
this.maxSize = maxSize || 100;
|
127
150
|
this.size = 0;
|
@@ -180,7 +203,7 @@
|
|
180
203
|
this.prev = this.next = null;
|
181
204
|
}
|
182
205
|
return LruCache;
|
183
|
-
}(
|
206
|
+
}();
|
184
207
|
var PersistentStorage = function() {
|
185
208
|
var ls, methods;
|
186
209
|
try {
|
@@ -277,17 +300,20 @@
|
|
277
300
|
_get: function(url, o, cb) {
|
278
301
|
var that = this, jqXhr;
|
279
302
|
if (jqXhr = pendingRequests[url]) {
|
280
|
-
jqXhr.done(done);
|
303
|
+
jqXhr.done(done).fail(fail);
|
281
304
|
} else if (pendingRequestsCount < maxPendingRequests) {
|
282
305
|
pendingRequestsCount++;
|
283
|
-
pendingRequests[url] = this._send(url, o).done(done).always(always);
|
306
|
+
pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);
|
284
307
|
} else {
|
285
308
|
this.onDeckRequestArgs = [].slice.call(arguments, 0);
|
286
309
|
}
|
287
310
|
function done(resp) {
|
288
|
-
cb && cb(resp);
|
311
|
+
cb && cb(null, resp);
|
289
312
|
requestCache.set(url, resp);
|
290
313
|
}
|
314
|
+
function fail() {
|
315
|
+
cb && cb(true);
|
316
|
+
}
|
291
317
|
function always() {
|
292
318
|
pendingRequestsCount--;
|
293
319
|
delete pendingRequests[url];
|
@@ -298,14 +324,14 @@
|
|
298
324
|
}
|
299
325
|
},
|
300
326
|
get: function(url, o, cb) {
|
301
|
-
var
|
327
|
+
var resp;
|
302
328
|
if (_.isFunction(o)) {
|
303
329
|
cb = o;
|
304
330
|
o = {};
|
305
331
|
}
|
306
332
|
if (resp = requestCache.get(url)) {
|
307
333
|
_.defer(function() {
|
308
|
-
cb && cb(resp);
|
334
|
+
cb && cb(null, resp);
|
309
335
|
});
|
310
336
|
} else {
|
311
337
|
this._get(url, o, cb);
|
@@ -340,8 +366,7 @@
|
|
340
366
|
}
|
341
367
|
this.datumTokenizer = o.datumTokenizer;
|
342
368
|
this.queryTokenizer = o.queryTokenizer;
|
343
|
-
this.
|
344
|
-
this.trie = newNode();
|
369
|
+
this.reset();
|
345
370
|
}
|
346
371
|
_.mixin(SearchIndex.prototype, {
|
347
372
|
bootstrap: function bootstrap(o) {
|
@@ -356,7 +381,7 @@
|
|
356
381
|
id = that.datums.push(datum) - 1;
|
357
382
|
tokens = normalizeTokens(that.datumTokenizer(datum));
|
358
383
|
_.each(tokens, function(token) {
|
359
|
-
var node, chars, ch
|
384
|
+
var node, chars, ch;
|
360
385
|
node = that.trie;
|
361
386
|
chars = token.split("");
|
362
387
|
while (ch = chars.shift()) {
|
@@ -391,6 +416,10 @@
|
|
391
416
|
return that.datums[id];
|
392
417
|
}) : [];
|
393
418
|
},
|
419
|
+
reset: function reset() {
|
420
|
+
this.datums = [];
|
421
|
+
this.trie = newNode();
|
422
|
+
},
|
394
423
|
serialize: function serialize() {
|
395
424
|
return {
|
396
425
|
datums: this.datums,
|
@@ -452,11 +481,7 @@
|
|
452
481
|
remote: getRemote
|
453
482
|
};
|
454
483
|
function getLocal(o) {
|
455
|
-
|
456
|
-
if (_.isFunction(local)) {
|
457
|
-
local = local.call(null);
|
458
|
-
}
|
459
|
-
return local;
|
484
|
+
return o.local || null;
|
460
485
|
}
|
461
486
|
function getPrefetch(o) {
|
462
487
|
var prefetch, defaults;
|
@@ -516,13 +541,15 @@
|
|
516
541
|
}
|
517
542
|
}
|
518
543
|
}();
|
519
|
-
|
520
|
-
var keys;
|
544
|
+
(function(root) {
|
545
|
+
var old, keys;
|
546
|
+
old = root.Bloodhound;
|
521
547
|
keys = {
|
522
548
|
data: "data",
|
523
549
|
protocol: "protocol",
|
524
550
|
thumbprint: "thumbprint"
|
525
551
|
};
|
552
|
+
root.Bloodhound = Bloodhound;
|
526
553
|
function Bloodhound(o) {
|
527
554
|
if (!o || !o.local && !o.prefetch && !o.remote) {
|
528
555
|
$.error("one of local, prefetch, or remote is required");
|
@@ -540,14 +567,11 @@
|
|
540
567
|
});
|
541
568
|
this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;
|
542
569
|
}
|
543
|
-
Bloodhound.
|
544
|
-
|
545
|
-
|
546
|
-
},
|
547
|
-
nonword: function nonwordTokenizer(s) {
|
548
|
-
return s.split(/\W+/);
|
549
|
-
}
|
570
|
+
Bloodhound.noConflict = function noConflict() {
|
571
|
+
root.Bloodhound = old;
|
572
|
+
return Bloodhound;
|
550
573
|
};
|
574
|
+
Bloodhound.tokenizers = tokenizers;
|
551
575
|
_.mixin(Bloodhound.prototype, {
|
552
576
|
_loadPrefetch: function loadPrefetch(o) {
|
553
577
|
var that = this, serialized, deferred;
|
@@ -559,9 +583,8 @@
|
|
559
583
|
}
|
560
584
|
return deferred;
|
561
585
|
function handlePrefetchResponse(resp) {
|
562
|
-
|
563
|
-
|
564
|
-
that.add(filtered);
|
586
|
+
that.clear();
|
587
|
+
that.add(o.filter ? o.filter(resp) : resp);
|
565
588
|
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);
|
566
589
|
}
|
567
590
|
},
|
@@ -571,9 +594,8 @@
|
|
571
594
|
uriEncodedQuery = encodeURIComponent(query);
|
572
595
|
url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
|
573
596
|
return this.transport.get(url, this.remote.ajax, handleRemoteResponse);
|
574
|
-
function handleRemoteResponse(resp) {
|
575
|
-
|
576
|
-
cb(filtered);
|
597
|
+
function handleRemoteResponse(err, resp) {
|
598
|
+
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
|
577
599
|
}
|
578
600
|
},
|
579
601
|
_saveToStorage: function saveToStorage(data, thumbprint, ttl) {
|
@@ -593,30 +615,32 @@
|
|
593
615
|
isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;
|
594
616
|
return stored.data && !isExpired ? stored.data : null;
|
595
617
|
},
|
596
|
-
|
597
|
-
var that = this, deferred;
|
618
|
+
_initialize: function initialize() {
|
619
|
+
var that = this, local = this.local, deferred;
|
598
620
|
deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();
|
599
|
-
|
621
|
+
local && deferred.done(addLocalToIndex);
|
600
622
|
this.transport = this.remote ? new Transport(this.remote) : null;
|
601
|
-
this.
|
602
|
-
return deferred.promise();
|
603
|
-
};
|
604
|
-
return deferred.promise();
|
623
|
+
return this.initPromise = deferred.promise();
|
605
624
|
function addLocalToIndex() {
|
606
|
-
that.add(
|
625
|
+
that.add(_.isFunction(local) ? local() : local);
|
607
626
|
}
|
608
627
|
},
|
628
|
+
initialize: function initialize(force) {
|
629
|
+
return !this.initPromise || force ? this._initialize() : this.initPromise;
|
630
|
+
},
|
609
631
|
add: function add(data) {
|
610
632
|
this.index.add(data);
|
611
633
|
},
|
612
634
|
get: function get(query, cb) {
|
613
|
-
var that = this, matches, cacheHit = false;
|
635
|
+
var that = this, matches = [], cacheHit = false;
|
614
636
|
matches = this.index.get(query);
|
615
637
|
matches = this.sorter(matches).slice(0, this.limit);
|
616
638
|
if (matches.length < this.limit && this.transport) {
|
617
639
|
cacheHit = this._getFromRemote(query, returnRemoteMatches);
|
618
640
|
}
|
619
|
-
!cacheHit
|
641
|
+
if (!cacheHit) {
|
642
|
+
(matches.length > 0 || !this.transport) && cb && cb(matches);
|
643
|
+
}
|
620
644
|
function returnRemoteMatches(remoteMatches) {
|
621
645
|
var matchesWithBackfill = matches.slice(0);
|
622
646
|
_.each(remoteMatches, function(remoteMatch) {
|
@@ -630,6 +654,15 @@
|
|
630
654
|
cb && cb(that.sorter(matchesWithBackfill));
|
631
655
|
}
|
632
656
|
},
|
657
|
+
clear: function clear() {
|
658
|
+
this.index.reset();
|
659
|
+
},
|
660
|
+
clearPrefetchCache: function clearPrefetchCache() {
|
661
|
+
this.storage && this.storage.clear();
|
662
|
+
},
|
663
|
+
clearRemoteCache: function clearRemoteCache() {
|
664
|
+
this.transport && Transport.resetCache();
|
665
|
+
},
|
633
666
|
ttAdapter: function ttAdapter() {
|
634
667
|
return _.bind(this.get, this);
|
635
668
|
}
|
@@ -647,13 +680,13 @@
|
|
647
680
|
function ignoreDuplicates() {
|
648
681
|
return false;
|
649
682
|
}
|
650
|
-
}();
|
683
|
+
})(this);
|
651
684
|
var html = {
|
652
685
|
wrapper: '<span class="twitter-typeahead"></span>',
|
653
686
|
dropdown: '<span class="tt-dropdown-menu"></span>',
|
654
687
|
dataset: '<div class="tt-dataset-%CLASS%"></div>',
|
655
688
|
suggestions: '<span class="tt-suggestions"></span>',
|
656
|
-
suggestion: '<div class="tt-suggestion"
|
689
|
+
suggestion: '<div class="tt-suggestion"></div>'
|
657
690
|
};
|
658
691
|
var css = {
|
659
692
|
wrapper: {
|
@@ -771,7 +804,7 @@
|
|
771
804
|
return this;
|
772
805
|
}
|
773
806
|
function trigger(types) {
|
774
|
-
var
|
807
|
+
var type, callbacks, args, syncFlush, asyncFlush;
|
775
808
|
if (!this._callbacks) {
|
776
809
|
return this;
|
777
810
|
}
|
@@ -795,7 +828,7 @@
|
|
795
828
|
}
|
796
829
|
}
|
797
830
|
function getNextTick() {
|
798
|
-
var nextTickFn
|
831
|
+
var nextTickFn;
|
799
832
|
if (window.setImmediate) {
|
800
833
|
nextTickFn = function nextTickSetImmediate(fn) {
|
801
834
|
setImmediate(function() {
|
@@ -892,7 +925,7 @@
|
|
892
925
|
this.$hint = $(o.hint);
|
893
926
|
this.$input = $(o.input).on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
|
894
927
|
if (this.$hint.length === 0) {
|
895
|
-
this.
|
928
|
+
this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
|
896
929
|
}
|
897
930
|
if (!_.isMsie()) {
|
898
931
|
this.$input.on("input.tt", onInput);
|
@@ -911,11 +944,11 @@
|
|
911
944
|
return (str || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
|
912
945
|
};
|
913
946
|
_.mixin(Input.prototype, EventEmitter, {
|
914
|
-
_onBlur: function onBlur(
|
947
|
+
_onBlur: function onBlur() {
|
915
948
|
this.resetInputValue();
|
916
949
|
this.trigger("blurred");
|
917
950
|
},
|
918
|
-
_onFocus: function onFocus(
|
951
|
+
_onFocus: function onFocus() {
|
919
952
|
this.trigger("focused");
|
920
953
|
},
|
921
954
|
_onKeydown: function onKeydown($e) {
|
@@ -925,14 +958,14 @@
|
|
925
958
|
this.trigger(keyName + "Keyed", $e);
|
926
959
|
}
|
927
960
|
},
|
928
|
-
_onInput: function onInput(
|
961
|
+
_onInput: function onInput() {
|
929
962
|
this._checkInputValue();
|
930
963
|
},
|
931
964
|
_managePreventDefault: function managePreventDefault(keyName, $e) {
|
932
965
|
var preventDefault, hintValue, inputValue;
|
933
966
|
switch (keyName) {
|
934
967
|
case "tab":
|
935
|
-
hintValue = this.
|
968
|
+
hintValue = this.getHint();
|
936
969
|
inputValue = this.getInputValue();
|
937
970
|
preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);
|
938
971
|
break;
|
@@ -987,19 +1020,27 @@
|
|
987
1020
|
},
|
988
1021
|
setInputValue: function setInputValue(value, silent) {
|
989
1022
|
this.$input.val(value);
|
990
|
-
|
1023
|
+
silent ? this.clearHint() : this._checkInputValue();
|
991
1024
|
},
|
992
|
-
|
1025
|
+
resetInputValue: function resetInputValue() {
|
1026
|
+
this.setInputValue(this.query, true);
|
1027
|
+
},
|
1028
|
+
getHint: function getHint() {
|
993
1029
|
return this.$hint.val();
|
994
1030
|
},
|
995
|
-
|
1031
|
+
setHint: function setHint(value) {
|
996
1032
|
this.$hint.val(value);
|
997
1033
|
},
|
998
|
-
resetInputValue: function resetInputValue() {
|
999
|
-
this.$input.val(this.query);
|
1000
|
-
},
|
1001
1034
|
clearHint: function clearHint() {
|
1002
|
-
this
|
1035
|
+
this.setHint("");
|
1036
|
+
},
|
1037
|
+
clearHintIfInvalid: function clearHintIfInvalid() {
|
1038
|
+
var val, hint, valIsPrefixOfHint, isValid;
|
1039
|
+
val = this.getInputValue();
|
1040
|
+
hint = this.getHint();
|
1041
|
+
valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
|
1042
|
+
isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
|
1043
|
+
!isValid && this.clearHint();
|
1003
1044
|
},
|
1004
1045
|
getLanguageDirection: function getLanguageDirection() {
|
1005
1046
|
return (this.$input.css("direction") || "ltr").toLowerCase();
|
@@ -1033,7 +1074,7 @@
|
|
1033
1074
|
return $('<pre aria-hidden="true"></pre>').css({
|
1034
1075
|
position: "absolute",
|
1035
1076
|
visibility: "hidden",
|
1036
|
-
whiteSpace: "
|
1077
|
+
whiteSpace: "pre",
|
1037
1078
|
fontFamily: $input.css("font-family"),
|
1038
1079
|
fontSize: $input.css("font-size"),
|
1039
1080
|
fontStyle: $input.css("font-style"),
|
@@ -1112,10 +1153,8 @@
|
|
1112
1153
|
});
|
1113
1154
|
return $suggestions;
|
1114
1155
|
function getSuggestionNode(suggestion) {
|
1115
|
-
var $el
|
1116
|
-
|
1117
|
-
outerHtml = html.suggestion.replace("%BODY%", innerHtml);
|
1118
|
-
$el = $(outerHtml).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
|
1156
|
+
var $el;
|
1157
|
+
$el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
|
1119
1158
|
$el.children().each(function() {
|
1120
1159
|
$(this).css(css.suggestionChild);
|
1121
1160
|
});
|
@@ -1141,13 +1180,21 @@
|
|
1141
1180
|
update: function update(query) {
|
1142
1181
|
var that = this;
|
1143
1182
|
this.query = query;
|
1144
|
-
this.
|
1145
|
-
|
1146
|
-
|
1183
|
+
this.canceled = false;
|
1184
|
+
this.source(query, render);
|
1185
|
+
function render(suggestions) {
|
1186
|
+
if (!that.canceled && query === that.query) {
|
1187
|
+
that._render(query, suggestions);
|
1188
|
+
}
|
1147
1189
|
}
|
1148
1190
|
},
|
1191
|
+
cancel: function cancel() {
|
1192
|
+
this.canceled = true;
|
1193
|
+
},
|
1149
1194
|
clear: function clear() {
|
1150
|
-
this.
|
1195
|
+
this.cancel();
|
1196
|
+
this.$el.empty();
|
1197
|
+
this.trigger("rendered");
|
1151
1198
|
},
|
1152
1199
|
isEmpty: function isEmpty() {
|
1153
1200
|
return this.$el.is(":empty");
|
@@ -1206,7 +1253,7 @@
|
|
1206
1253
|
this._removeCursor();
|
1207
1254
|
this._setCursor($($e.currentTarget), true);
|
1208
1255
|
},
|
1209
|
-
_onSuggestionMouseLeave: function onSuggestionMouseLeave(
|
1256
|
+
_onSuggestionMouseLeave: function onSuggestionMouseLeave() {
|
1210
1257
|
this._removeCursor();
|
1211
1258
|
},
|
1212
1259
|
_onRendered: function onRendered() {
|
@@ -1341,17 +1388,34 @@
|
|
1341
1388
|
var Typeahead = function() {
|
1342
1389
|
var attrsKey = "ttAttrs";
|
1343
1390
|
function Typeahead(o) {
|
1344
|
-
var $menu, $input, $hint
|
1391
|
+
var $menu, $input, $hint;
|
1345
1392
|
o = o || {};
|
1346
1393
|
if (!o.input) {
|
1347
1394
|
$.error("missing input");
|
1348
1395
|
}
|
1396
|
+
this.isActivated = false;
|
1349
1397
|
this.autoselect = !!o.autoselect;
|
1350
1398
|
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
|
1351
1399
|
this.$node = buildDomStructure(o.input, o.withHint);
|
1352
1400
|
$menu = this.$node.find(".tt-dropdown-menu");
|
1353
1401
|
$input = this.$node.find(".tt-input");
|
1354
1402
|
$hint = this.$node.find(".tt-hint");
|
1403
|
+
$input.on("blur.tt", function($e) {
|
1404
|
+
var active, isActive, hasActive;
|
1405
|
+
active = document.activeElement;
|
1406
|
+
isActive = $menu.is(active);
|
1407
|
+
hasActive = $menu.has(active).length > 0;
|
1408
|
+
if (_.isMsie() && (isActive || hasActive)) {
|
1409
|
+
$e.preventDefault();
|
1410
|
+
$e.stopImmediatePropagation();
|
1411
|
+
_.defer(function() {
|
1412
|
+
$input.focus();
|
1413
|
+
});
|
1414
|
+
}
|
1415
|
+
});
|
1416
|
+
$menu.on("mousedown.tt", function($e) {
|
1417
|
+
$e.preventDefault();
|
1418
|
+
});
|
1355
1419
|
this.eventBus = o.eventBus || new EventBus({
|
1356
1420
|
el: $input
|
1357
1421
|
});
|
@@ -1363,15 +1427,7 @@
|
|
1363
1427
|
input: $input,
|
1364
1428
|
hint: $hint
|
1365
1429
|
}).onSync("focused", this._onFocused, this).onSync("blurred", this._onBlurred, this).onSync("enterKeyed", this._onEnterKeyed, this).onSync("tabKeyed", this._onTabKeyed, this).onSync("escKeyed", this._onEscKeyed, this).onSync("upKeyed", this._onUpKeyed, this).onSync("downKeyed", this._onDownKeyed, this).onSync("leftKeyed", this._onLeftKeyed, this).onSync("rightKeyed", this._onRightKeyed, this).onSync("queryChanged", this._onQueryChanged, this).onSync("whitespaceChanged", this._onWhitespaceChanged, this);
|
1366
|
-
|
1367
|
-
if (_.isMsie() && _.isMsie() < 9) {
|
1368
|
-
$input[0].onbeforedeactivate = function() {
|
1369
|
-
window.event.returnValue = false;
|
1370
|
-
$input[0].onbeforedeactivate = null;
|
1371
|
-
};
|
1372
|
-
}
|
1373
|
-
$e.preventDefault();
|
1374
|
-
});
|
1430
|
+
this._setLanguageDirection();
|
1375
1431
|
}
|
1376
1432
|
_.mixin(Typeahead.prototype, {
|
1377
1433
|
_onSuggestionClicked: function onSuggestionClicked(type, $el) {
|
@@ -1382,7 +1438,6 @@
|
|
1382
1438
|
},
|
1383
1439
|
_onCursorMoved: function onCursorMoved() {
|
1384
1440
|
var datum = this.dropdown.getDatumForCursor();
|
1385
|
-
this.input.clearHint();
|
1386
1441
|
this.input.setInputValue(datum.value, true);
|
1387
1442
|
this.eventBus.trigger("cursorchanged", datum.raw, datum.datasetName);
|
1388
1443
|
},
|
@@ -1402,10 +1457,12 @@
|
|
1402
1457
|
this.eventBus.trigger("closed");
|
1403
1458
|
},
|
1404
1459
|
_onFocused: function onFocused() {
|
1405
|
-
this.
|
1460
|
+
this.isActivated = true;
|
1406
1461
|
this.dropdown.open();
|
1407
1462
|
},
|
1408
1463
|
_onBlurred: function onBlurred() {
|
1464
|
+
this.isActivated = false;
|
1465
|
+
this.dropdown.empty();
|
1409
1466
|
this.dropdown.close();
|
1410
1467
|
},
|
1411
1468
|
_onEnterKeyed: function onEnterKeyed(type, $e) {
|
@@ -1426,7 +1483,7 @@
|
|
1426
1483
|
this._select(datum);
|
1427
1484
|
$e.preventDefault();
|
1428
1485
|
} else {
|
1429
|
-
this._autocomplete();
|
1486
|
+
this._autocomplete(true);
|
1430
1487
|
}
|
1431
1488
|
},
|
1432
1489
|
_onEscKeyed: function onEscKeyed() {
|
@@ -1435,19 +1492,13 @@
|
|
1435
1492
|
},
|
1436
1493
|
_onUpKeyed: function onUpKeyed() {
|
1437
1494
|
var query = this.input.getQuery();
|
1438
|
-
|
1439
|
-
this.dropdown.update(query);
|
1440
|
-
}
|
1495
|
+
this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();
|
1441
1496
|
this.dropdown.open();
|
1442
|
-
this.dropdown.moveCursorUp();
|
1443
1497
|
},
|
1444
1498
|
_onDownKeyed: function onDownKeyed() {
|
1445
1499
|
var query = this.input.getQuery();
|
1446
|
-
|
1447
|
-
this.dropdown.update(query);
|
1448
|
-
}
|
1500
|
+
this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();
|
1449
1501
|
this.dropdown.open();
|
1450
|
-
this.dropdown.moveCursorDown();
|
1451
1502
|
},
|
1452
1503
|
_onLeftKeyed: function onLeftKeyed() {
|
1453
1504
|
this.dir === "rtl" && this._autocomplete();
|
@@ -1456,9 +1507,8 @@
|
|
1456
1507
|
this.dir === "ltr" && this._autocomplete();
|
1457
1508
|
},
|
1458
1509
|
_onQueryChanged: function onQueryChanged(e, query) {
|
1459
|
-
this.input.
|
1460
|
-
this.dropdown.empty();
|
1461
|
-
query.length >= this.minLength && this.dropdown.update(query);
|
1510
|
+
this.input.clearHintIfInvalid();
|
1511
|
+
query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();
|
1462
1512
|
this.dropdown.open();
|
1463
1513
|
this._setLanguageDirection();
|
1464
1514
|
},
|
@@ -1475,29 +1525,31 @@
|
|
1475
1525
|
}
|
1476
1526
|
},
|
1477
1527
|
_updateHint: function updateHint() {
|
1478
|
-
var datum,
|
1528
|
+
var datum, val, query, escapedQuery, frontMatchRegEx, match;
|
1479
1529
|
datum = this.dropdown.getDatumForTopSuggestion();
|
1480
1530
|
if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {
|
1481
|
-
|
1482
|
-
query = Input.normalizeQuery(
|
1531
|
+
val = this.input.getInputValue();
|
1532
|
+
query = Input.normalizeQuery(val);
|
1483
1533
|
escapedQuery = _.escapeRegExChars(query);
|
1484
|
-
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(
|
1534
|
+
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
|
1485
1535
|
match = frontMatchRegEx.exec(datum.value);
|
1486
|
-
this.input.
|
1536
|
+
match ? this.input.setHint(val + match[1]) : this.input.clearHint();
|
1537
|
+
} else {
|
1538
|
+
this.input.clearHint();
|
1487
1539
|
}
|
1488
1540
|
},
|
1489
|
-
_autocomplete: function autocomplete() {
|
1490
|
-
var hint, query, datum;
|
1491
|
-
hint = this.input.
|
1541
|
+
_autocomplete: function autocomplete(laxCursor) {
|
1542
|
+
var hint, query, isCursorAtEnd, datum;
|
1543
|
+
hint = this.input.getHint();
|
1492
1544
|
query = this.input.getQuery();
|
1493
|
-
|
1545
|
+
isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();
|
1546
|
+
if (hint && query !== hint && isCursorAtEnd) {
|
1494
1547
|
datum = this.dropdown.getDatumForTopSuggestion();
|
1495
1548
|
datum && this.input.setInputValue(datum.value);
|
1496
1549
|
this.eventBus.trigger("autocompleted", datum.raw, datum.datasetName);
|
1497
1550
|
}
|
1498
1551
|
},
|
1499
1552
|
_select: function select(datum) {
|
1500
|
-
this.input.clearHint();
|
1501
1553
|
this.input.setQuery(datum.value);
|
1502
1554
|
this.input.setInputValue(datum.value, true);
|
1503
1555
|
this._setLanguageDirection();
|
@@ -1511,11 +1563,17 @@
|
|
1511
1563
|
close: function close() {
|
1512
1564
|
this.dropdown.close();
|
1513
1565
|
},
|
1514
|
-
|
1515
|
-
|
1566
|
+
setVal: function setVal(val) {
|
1567
|
+
if (this.isActivated) {
|
1568
|
+
this.input.setInputValue(val);
|
1569
|
+
} else {
|
1570
|
+
this.input.setQuery(val);
|
1571
|
+
this.input.setInputValue(val, true);
|
1572
|
+
}
|
1573
|
+
this._setLanguageDirection();
|
1516
1574
|
},
|
1517
|
-
|
1518
|
-
this.input.
|
1575
|
+
getVal: function getVal() {
|
1576
|
+
return this.input.getQuery();
|
1519
1577
|
},
|
1520
1578
|
destroy: function destroy() {
|
1521
1579
|
this.input.destroy();
|
@@ -1617,17 +1675,17 @@
|
|
1617
1675
|
}
|
1618
1676
|
},
|
1619
1677
|
val: function val(newVal) {
|
1620
|
-
return !arguments.length ?
|
1621
|
-
function
|
1678
|
+
return !arguments.length ? getVal(this.first()) : this.each(setVal);
|
1679
|
+
function setVal() {
|
1622
1680
|
var $input = $(this), typeahead;
|
1623
1681
|
if (typeahead = $input.data(typeaheadKey)) {
|
1624
|
-
typeahead.
|
1682
|
+
typeahead.setVal(newVal);
|
1625
1683
|
}
|
1626
1684
|
}
|
1627
|
-
function
|
1685
|
+
function getVal($input) {
|
1628
1686
|
var typeahead, query;
|
1629
1687
|
if (typeahead = $input.data(typeaheadKey)) {
|
1630
|
-
query = typeahead.
|
1688
|
+
query = typeahead.getVal();
|
1631
1689
|
}
|
1632
1690
|
return query;
|
1633
1691
|
}
|