twitter-typeahead-rails 0.10.5 → 0.11.1.pre.corejavascript
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.
- checksums.yaml +5 -13
- data/README.md +3 -4
- data/lib/twitter-typeahead-rails/version.rb +1 -1
- data/vendor/assets/javascripts/twitter/typeahead.js +0 -2
- data/vendor/assets/javascripts/twitter/typeahead.min.js +0 -2
- data/vendor/assets/javascripts/twitter/typeahead/bloodhound.js +480 -279
- data/vendor/assets/javascripts/twitter/typeahead/bloodhound.min.js +7 -0
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.bundle.js +1538 -858
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.bundle.min.js +4 -3
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.jquery.js +895 -540
- data/vendor/assets/javascripts/twitter/typeahead/typeahead.jquery.min.js +7 -0
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MmQ3ZDUzNTQ3ODU3NWU4Njg1ZDY4ZmMzZDE1NDI0YjEwMjg3NjYwNA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ef1c9d7c03cb7ceb3422f9da077080ca20504e66
|
4
|
+
data.tar.gz: 4574d3cb280a3fd7fa8ddb7ac24c9b7ba0b3db2c
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YTgzNTA5YjI1OWMyNThhZTZmZTQ4ODZlNTEzOTUxY2I4ODhlZGFmMGViNGQ1
|
11
|
-
NTU0MDJiYjhkYWI0ODQ4YTg4MzNhNDg4ZWJjNWJhYTliMDU1YTY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NGFhNTRhNjViNGYxZGI1ZjBiOWE2YWU0NjIxNWE4ZDAyNmViZjcxZTg4NWEy
|
14
|
-
NWEyMWI3ZTM2MDZhYzY5YThjOTBjMjczYmYzODUzYTQ4OTFhYzczNGUyZmJk
|
15
|
-
MzgwYWJmMTExMjU1MjRkY2U4ZTA2M2M5MjQ4NTczMmJlNWE4ZGQ=
|
6
|
+
metadata.gz: ba47f2ede69b1d391e9d247d216f6ddf8563a6dad88968eef7e0b58b03dfb1c015033661153d18d3d7d497ce171e9f9525040b44ff0c098ec1d53d57a64fb9d7
|
7
|
+
data.tar.gz: 0d97243cd0557b7a1d39ca6e60e36cb26eb0b1c5bc11c07055423eeb67cc6eb663f6769e64374a7f82d259c80a6799d4d80619c1bcc4f9fb63567487242ac2b0
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Twitter typeahead.js jquery plugin
|
2
2
|
|
3
|
-
This asset gem packages the [twitter typeahead.js](https://github.com/
|
3
|
+
This asset gem packages the [mantained twitter typeahead.js](https://github.com/corejavascript/typeahead.js) jquery plugin for the Rails asset pipeline.
|
4
4
|
|
5
5
|
To learn more about typeahead.js read the post [Twitter's engineering blog](http://engineering.twitter.com/2013/02/twitter-typeaheadjs-you-autocomplete-me.html).
|
6
6
|
|
@@ -42,7 +42,7 @@ Add one of the following to your application.js manifest:
|
|
42
42
|
|
43
43
|
```js
|
44
44
|
|
45
|
-
// Twitter typeahead
|
45
|
+
// Twitter typeahead example.
|
46
46
|
|
47
47
|
// instantiate the bloodhound suggestion engine
|
48
48
|
var numbers = new Bloodhound({
|
@@ -72,7 +72,7 @@ $('.example-numbers .typeahead').typeahead(null, {
|
|
72
72
|
});
|
73
73
|
```
|
74
74
|
|
75
|
-
Currently this version tracks version v0.
|
75
|
+
Currently this version tracks version v0.11.1.
|
76
76
|
|
77
77
|
## Contributing
|
78
78
|
|
@@ -81,4 +81,3 @@ Currently this version tracks version v0.10.5.
|
|
81
81
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
82
82
|
4. Push to the branch (`git push origin my-new-feature`)
|
83
83
|
5. Create new Pull Request
|
84
|
-
|
@@ -1,10 +1,20 @@
|
|
1
1
|
/*!
|
2
|
-
* typeahead.js 0.
|
2
|
+
* typeahead.js 0.11.1
|
3
3
|
* https://github.com/twitter/typeahead.js
|
4
|
-
* Copyright 2013-
|
4
|
+
* Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
|
5
5
|
*/
|
6
6
|
|
7
|
-
(function(
|
7
|
+
(function(root, factory) {
|
8
|
+
if (typeof define === "function" && define.amd) {
|
9
|
+
define([ "jquery" ], function(a0) {
|
10
|
+
return root["Bloodhound"] = factory(a0);
|
11
|
+
});
|
12
|
+
} else if (typeof exports === "object") {
|
13
|
+
module.exports = factory(require("jquery"));
|
14
|
+
} else {
|
15
|
+
root["Bloodhound"] = factory(jQuery);
|
16
|
+
}
|
17
|
+
})(this, function($) {
|
8
18
|
var _ = function() {
|
9
19
|
"use strict";
|
10
20
|
return {
|
@@ -29,6 +39,12 @@
|
|
29
39
|
isUndefined: function(obj) {
|
30
40
|
return typeof obj === "undefined";
|
31
41
|
},
|
42
|
+
isElement: function(obj) {
|
43
|
+
return !!(obj && obj.nodeType === 1);
|
44
|
+
},
|
45
|
+
isJQuery: function(obj) {
|
46
|
+
return obj instanceof $;
|
47
|
+
},
|
32
48
|
toStr: function toStr(s) {
|
33
49
|
return _.isUndefined(s) || s === null ? "" : s + "";
|
34
50
|
},
|
@@ -66,12 +82,18 @@
|
|
66
82
|
return !!result;
|
67
83
|
},
|
68
84
|
mixin: $.extend,
|
69
|
-
|
85
|
+
identity: function(x) {
|
86
|
+
return x;
|
87
|
+
},
|
88
|
+
clone: function(obj) {
|
89
|
+
return $.extend(true, {}, obj);
|
90
|
+
},
|
91
|
+
getIdGenerator: function() {
|
70
92
|
var counter = 0;
|
71
93
|
return function() {
|
72
94
|
return counter++;
|
73
95
|
};
|
74
|
-
}
|
96
|
+
},
|
75
97
|
templatify: function templatify(obj) {
|
76
98
|
return $.isFunction(obj) ? obj : template;
|
77
99
|
function template() {
|
@@ -123,10 +145,13 @@
|
|
123
145
|
return result;
|
124
146
|
};
|
125
147
|
},
|
148
|
+
stringify: function(val) {
|
149
|
+
return _.isString(val) ? val : JSON.stringify(val);
|
150
|
+
},
|
126
151
|
noop: function() {}
|
127
152
|
};
|
128
153
|
}();
|
129
|
-
var VERSION = "0.
|
154
|
+
var VERSION = "0.11.1";
|
130
155
|
var tokenizers = function() {
|
131
156
|
"use strict";
|
132
157
|
return {
|
@@ -146,11 +171,11 @@
|
|
146
171
|
return str ? str.split(/\W+/) : [];
|
147
172
|
}
|
148
173
|
function getObjTokenizer(tokenizer) {
|
149
|
-
return function setKey() {
|
150
|
-
|
174
|
+
return function setKey(keys) {
|
175
|
+
keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
|
151
176
|
return function tokenize(o) {
|
152
177
|
var tokens = [];
|
153
|
-
_.each(
|
178
|
+
_.each(keys, function(k) {
|
154
179
|
tokens = tokens.concat(tokenizer(_.toStr(o[k])));
|
155
180
|
});
|
156
181
|
return tokens;
|
@@ -173,6 +198,7 @@
|
|
173
198
|
if (this.size >= this.maxSize) {
|
174
199
|
this.list.remove(tailItem);
|
175
200
|
delete this.hash[tailItem.key];
|
201
|
+
this.size--;
|
176
202
|
}
|
177
203
|
if (node = this.hash[key]) {
|
178
204
|
node.val = val;
|
@@ -227,73 +253,72 @@
|
|
227
253
|
}();
|
228
254
|
var PersistentStorage = function() {
|
229
255
|
"use strict";
|
230
|
-
var
|
256
|
+
var LOCAL_STORAGE;
|
231
257
|
try {
|
232
|
-
|
233
|
-
|
234
|
-
|
258
|
+
LOCAL_STORAGE = window.localStorage;
|
259
|
+
LOCAL_STORAGE.setItem("~~~", "!");
|
260
|
+
LOCAL_STORAGE.removeItem("~~~");
|
235
261
|
} catch (err) {
|
236
|
-
|
262
|
+
LOCAL_STORAGE = null;
|
237
263
|
}
|
238
|
-
function PersistentStorage(namespace) {
|
264
|
+
function PersistentStorage(namespace, override) {
|
239
265
|
this.prefix = [ "__", namespace, "__" ].join("");
|
240
266
|
this.ttlKey = "__ttl__";
|
241
267
|
this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
|
268
|
+
this.ls = override || LOCAL_STORAGE;
|
269
|
+
!this.ls && this._noop();
|
242
270
|
}
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
get
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
}
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
} else {
|
261
|
-
ls.removeItem(this._ttlKey(key));
|
262
|
-
}
|
263
|
-
return ls.setItem(this._prefix(key), encode(val));
|
264
|
-
},
|
265
|
-
remove: function(key) {
|
266
|
-
ls.removeItem(this._ttlKey(key));
|
267
|
-
ls.removeItem(this._prefix(key));
|
268
|
-
return this;
|
269
|
-
},
|
270
|
-
clear: function() {
|
271
|
-
var i, key, keys = [], len = ls.length;
|
272
|
-
for (i = 0; i < len; i++) {
|
273
|
-
if ((key = ls.key(i)).match(this.keyMatcher)) {
|
274
|
-
keys.push(key.replace(this.keyMatcher, ""));
|
275
|
-
}
|
276
|
-
}
|
277
|
-
for (i = keys.length; i--; ) {
|
278
|
-
this.remove(keys[i]);
|
271
|
+
_.mixin(PersistentStorage.prototype, {
|
272
|
+
_prefix: function(key) {
|
273
|
+
return this.prefix + key;
|
274
|
+
},
|
275
|
+
_ttlKey: function(key) {
|
276
|
+
return this._prefix(key) + this.ttlKey;
|
277
|
+
},
|
278
|
+
_noop: function() {
|
279
|
+
this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
|
280
|
+
},
|
281
|
+
_safeSet: function(key, val) {
|
282
|
+
try {
|
283
|
+
this.ls.setItem(key, val);
|
284
|
+
} catch (err) {
|
285
|
+
if (err.name === "QuotaExceededError") {
|
286
|
+
this.clear();
|
287
|
+
this._noop();
|
279
288
|
}
|
280
|
-
return this;
|
281
|
-
},
|
282
|
-
isExpired: function(key) {
|
283
|
-
var ttl = decode(ls.getItem(this._ttlKey(key)));
|
284
|
-
return _.isNumber(ttl) && now() > ttl ? true : false;
|
285
289
|
}
|
286
|
-
}
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
290
|
+
},
|
291
|
+
get: function(key) {
|
292
|
+
if (this.isExpired(key)) {
|
293
|
+
this.remove(key);
|
294
|
+
}
|
295
|
+
return decode(this.ls.getItem(this._prefix(key)));
|
296
|
+
},
|
297
|
+
set: function(key, val, ttl) {
|
298
|
+
if (_.isNumber(ttl)) {
|
299
|
+
this._safeSet(this._ttlKey(key), encode(now() + ttl));
|
300
|
+
} else {
|
301
|
+
this.ls.removeItem(this._ttlKey(key));
|
302
|
+
}
|
303
|
+
return this._safeSet(this._prefix(key), encode(val));
|
304
|
+
},
|
305
|
+
remove: function(key) {
|
306
|
+
this.ls.removeItem(this._ttlKey(key));
|
307
|
+
this.ls.removeItem(this._prefix(key));
|
308
|
+
return this;
|
309
|
+
},
|
310
|
+
clear: function() {
|
311
|
+
var i, keys = gatherMatchingKeys(this.keyMatcher);
|
312
|
+
for (i = keys.length; i--; ) {
|
313
|
+
this.remove(keys[i]);
|
314
|
+
}
|
315
|
+
return this;
|
316
|
+
},
|
317
|
+
isExpired: function(key) {
|
318
|
+
var ttl = decode(this.ls.getItem(this._ttlKey(key)));
|
319
|
+
return _.isNumber(ttl) && now() > ttl ? true : false;
|
320
|
+
}
|
321
|
+
});
|
297
322
|
return PersistentStorage;
|
298
323
|
function now() {
|
299
324
|
return new Date().getTime();
|
@@ -302,7 +327,16 @@
|
|
302
327
|
return JSON.stringify(_.isUndefined(val) ? null : val);
|
303
328
|
}
|
304
329
|
function decode(val) {
|
305
|
-
return
|
330
|
+
return $.parseJSON(val);
|
331
|
+
}
|
332
|
+
function gatherMatchingKeys(keyMatcher) {
|
333
|
+
var i, key, keys = [], len = LOCAL_STORAGE.length;
|
334
|
+
for (i = 0; i < len; i++) {
|
335
|
+
if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
|
336
|
+
keys.push(key.replace(keyMatcher, ""));
|
337
|
+
}
|
338
|
+
}
|
339
|
+
return keys;
|
306
340
|
}
|
307
341
|
}();
|
308
342
|
var Transport = function() {
|
@@ -311,9 +345,9 @@
|
|
311
345
|
function Transport(o) {
|
312
346
|
o = o || {};
|
313
347
|
this.cancelled = false;
|
314
|
-
this.
|
315
|
-
this._send = o.transport
|
316
|
-
this._get = o.
|
348
|
+
this.lastReq = null;
|
349
|
+
this._send = o.transport;
|
350
|
+
this._get = o.limiter ? o.limiter(this._get) : this._get;
|
317
351
|
this._cache = o.cache === false ? new LruCache(0) : sharedCache;
|
318
352
|
}
|
319
353
|
Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
|
@@ -323,84 +357,73 @@
|
|
323
357
|
sharedCache.reset();
|
324
358
|
};
|
325
359
|
_.mixin(Transport.prototype, {
|
326
|
-
|
327
|
-
|
328
|
-
|
360
|
+
_fingerprint: function fingerprint(o) {
|
361
|
+
o = o || {};
|
362
|
+
return o.url + o.type + $.param(o.data || {});
|
363
|
+
},
|
364
|
+
_get: function(o, cb) {
|
365
|
+
var that = this, fingerprint, jqXhr;
|
366
|
+
fingerprint = this._fingerprint(o);
|
367
|
+
if (this.cancelled || fingerprint !== this.lastReq) {
|
329
368
|
return;
|
330
369
|
}
|
331
|
-
if (jqXhr = pendingRequests[
|
370
|
+
if (jqXhr = pendingRequests[fingerprint]) {
|
332
371
|
jqXhr.done(done).fail(fail);
|
333
372
|
} else if (pendingRequestsCount < maxPendingRequests) {
|
334
373
|
pendingRequestsCount++;
|
335
|
-
pendingRequests[
|
374
|
+
pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
|
336
375
|
} else {
|
337
376
|
this.onDeckRequestArgs = [].slice.call(arguments, 0);
|
338
377
|
}
|
339
378
|
function done(resp) {
|
340
|
-
cb
|
341
|
-
that._cache.set(
|
379
|
+
cb(null, resp);
|
380
|
+
that._cache.set(fingerprint, resp);
|
342
381
|
}
|
343
382
|
function fail() {
|
344
|
-
cb
|
383
|
+
cb(true);
|
345
384
|
}
|
346
385
|
function always() {
|
347
386
|
pendingRequestsCount--;
|
348
|
-
delete pendingRequests[
|
387
|
+
delete pendingRequests[fingerprint];
|
349
388
|
if (that.onDeckRequestArgs) {
|
350
389
|
that._get.apply(that, that.onDeckRequestArgs);
|
351
390
|
that.onDeckRequestArgs = null;
|
352
391
|
}
|
353
392
|
}
|
354
393
|
},
|
355
|
-
get: function(
|
356
|
-
var resp;
|
357
|
-
|
358
|
-
|
359
|
-
o
|
360
|
-
}
|
394
|
+
get: function(o, cb) {
|
395
|
+
var resp, fingerprint;
|
396
|
+
cb = cb || $.noop;
|
397
|
+
o = _.isString(o) ? {
|
398
|
+
url: o
|
399
|
+
} : o || {};
|
400
|
+
fingerprint = this._fingerprint(o);
|
361
401
|
this.cancelled = false;
|
362
|
-
this.
|
363
|
-
if (resp = this._cache.get(
|
364
|
-
|
365
|
-
cb && cb(null, resp);
|
366
|
-
});
|
402
|
+
this.lastReq = fingerprint;
|
403
|
+
if (resp = this._cache.get(fingerprint)) {
|
404
|
+
cb(null, resp);
|
367
405
|
} else {
|
368
|
-
this._get(
|
406
|
+
this._get(o, cb);
|
369
407
|
}
|
370
|
-
return !!resp;
|
371
408
|
},
|
372
409
|
cancel: function() {
|
373
410
|
this.cancelled = true;
|
374
411
|
}
|
375
412
|
});
|
376
413
|
return Transport;
|
377
|
-
function callbackToDeferred(fn) {
|
378
|
-
return function customSendWrapper(url, o) {
|
379
|
-
var deferred = $.Deferred();
|
380
|
-
fn(url, o, onSuccess, onError);
|
381
|
-
return deferred;
|
382
|
-
function onSuccess(resp) {
|
383
|
-
_.defer(function() {
|
384
|
-
deferred.resolve(resp);
|
385
|
-
});
|
386
|
-
}
|
387
|
-
function onError(err) {
|
388
|
-
_.defer(function() {
|
389
|
-
deferred.reject(err);
|
390
|
-
});
|
391
|
-
}
|
392
|
-
};
|
393
|
-
}
|
394
414
|
}();
|
395
|
-
var SearchIndex = function() {
|
415
|
+
var SearchIndex = window.SearchIndex = function() {
|
396
416
|
"use strict";
|
417
|
+
var CHILDREN = "c", IDS = "i";
|
397
418
|
function SearchIndex(o) {
|
398
419
|
o = o || {};
|
399
420
|
if (!o.datumTokenizer || !o.queryTokenizer) {
|
400
421
|
$.error("datumTokenizer and queryTokenizer are both required");
|
401
422
|
}
|
423
|
+
this.identify = o.identify || _.stringify;
|
402
424
|
this.datumTokenizer = o.datumTokenizer;
|
403
425
|
this.queryTokenizer = o.queryTokenizer;
|
426
|
+
this.matchAnyQueryToken = o.matchAnyQueryToken;
|
404
427
|
this.reset();
|
405
428
|
}
|
406
429
|
_.mixin(SearchIndex.prototype, {
|
@@ -413,46 +436,61 @@
|
|
413
436
|
data = _.isArray(data) ? data : [ data ];
|
414
437
|
_.each(data, function(datum) {
|
415
438
|
var id, tokens;
|
416
|
-
id = that.
|
439
|
+
that.datums[id = that.identify(datum)] = datum;
|
417
440
|
tokens = normalizeTokens(that.datumTokenizer(datum));
|
418
441
|
_.each(tokens, function(token) {
|
419
442
|
var node, chars, ch;
|
420
443
|
node = that.trie;
|
421
444
|
chars = token.split("");
|
422
445
|
while (ch = chars.shift()) {
|
423
|
-
node = node
|
424
|
-
node.
|
446
|
+
node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
|
447
|
+
node[IDS].push(id);
|
425
448
|
}
|
426
449
|
});
|
427
450
|
});
|
428
451
|
},
|
429
|
-
get: function get(
|
452
|
+
get: function get(ids) {
|
453
|
+
var that = this;
|
454
|
+
return _.map(ids, function(id) {
|
455
|
+
return that.datums[id];
|
456
|
+
});
|
457
|
+
},
|
458
|
+
search: function search(query) {
|
430
459
|
var that = this, tokens, matches;
|
431
460
|
tokens = normalizeTokens(this.queryTokenizer(query));
|
432
461
|
_.each(tokens, function(token) {
|
433
462
|
var node, chars, ch, ids;
|
434
|
-
if (matches && matches.length === 0) {
|
463
|
+
if (matches && matches.length === 0 && !that.matchAnyQueryToken) {
|
435
464
|
return false;
|
436
465
|
}
|
437
466
|
node = that.trie;
|
438
467
|
chars = token.split("");
|
439
468
|
while (node && (ch = chars.shift())) {
|
440
|
-
node = node
|
469
|
+
node = node[CHILDREN][ch];
|
441
470
|
}
|
442
471
|
if (node && chars.length === 0) {
|
443
|
-
ids = node.
|
472
|
+
ids = node[IDS].slice(0);
|
444
473
|
matches = matches ? getIntersection(matches, ids) : ids;
|
445
474
|
} else {
|
446
|
-
|
447
|
-
|
475
|
+
if (!that.matchAnyQueryToken) {
|
476
|
+
matches = [];
|
477
|
+
return false;
|
478
|
+
}
|
448
479
|
}
|
449
480
|
});
|
450
481
|
return matches ? _.map(unique(matches), function(id) {
|
451
482
|
return that.datums[id];
|
452
483
|
}) : [];
|
453
484
|
},
|
485
|
+
all: function all() {
|
486
|
+
var values = [];
|
487
|
+
for (var key in this.datums) {
|
488
|
+
values.push(this.datums[key]);
|
489
|
+
}
|
490
|
+
return values;
|
491
|
+
},
|
454
492
|
reset: function reset() {
|
455
|
-
this.datums =
|
493
|
+
this.datums = {};
|
456
494
|
this.trie = newNode();
|
457
495
|
},
|
458
496
|
serialize: function serialize() {
|
@@ -473,10 +511,10 @@
|
|
473
511
|
return tokens;
|
474
512
|
}
|
475
513
|
function newNode() {
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
514
|
+
var node = {};
|
515
|
+
node[IDS] = [];
|
516
|
+
node[CHILDREN] = {};
|
517
|
+
return node;
|
480
518
|
}
|
481
519
|
function unique(array) {
|
482
520
|
var seen = {}, uniques = [];
|
@@ -490,8 +528,8 @@
|
|
490
528
|
}
|
491
529
|
function getIntersection(arrayA, arrayB) {
|
492
530
|
var ai = 0, bi = 0, intersection = [];
|
493
|
-
arrayA = arrayA.sort(
|
494
|
-
arrayB = arrayB.sort(
|
531
|
+
arrayA = arrayA.sort();
|
532
|
+
arrayB = arrayB.sort();
|
495
533
|
var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
|
496
534
|
while (ai < lenArrayA && bi < lenArrayB) {
|
497
535
|
if (arrayA[ai] < arrayB[bi]) {
|
@@ -505,169 +543,330 @@
|
|
505
543
|
}
|
506
544
|
}
|
507
545
|
return intersection;
|
508
|
-
|
509
|
-
|
546
|
+
}
|
547
|
+
}();
|
548
|
+
var Prefetch = function() {
|
549
|
+
"use strict";
|
550
|
+
var keys;
|
551
|
+
keys = {
|
552
|
+
data: "data",
|
553
|
+
protocol: "protocol",
|
554
|
+
thumbprint: "thumbprint"
|
555
|
+
};
|
556
|
+
function Prefetch(o) {
|
557
|
+
this.url = o.url;
|
558
|
+
this.ttl = o.ttl;
|
559
|
+
this.cache = o.cache;
|
560
|
+
this.prepare = o.prepare;
|
561
|
+
this.transform = o.transform;
|
562
|
+
this.transport = o.transport;
|
563
|
+
this.thumbprint = o.thumbprint;
|
564
|
+
this.storage = new PersistentStorage(o.cacheKey);
|
565
|
+
}
|
566
|
+
_.mixin(Prefetch.prototype, {
|
567
|
+
_settings: function settings() {
|
568
|
+
return {
|
569
|
+
url: this.url,
|
570
|
+
type: "GET",
|
571
|
+
dataType: "json"
|
572
|
+
};
|
573
|
+
},
|
574
|
+
store: function store(data) {
|
575
|
+
if (!this.cache) {
|
576
|
+
return;
|
577
|
+
}
|
578
|
+
this.storage.set(keys.data, data, this.ttl);
|
579
|
+
this.storage.set(keys.protocol, location.protocol, this.ttl);
|
580
|
+
this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
|
581
|
+
},
|
582
|
+
fromCache: function fromCache() {
|
583
|
+
var stored = {}, isExpired;
|
584
|
+
if (!this.cache) {
|
585
|
+
return null;
|
586
|
+
}
|
587
|
+
stored.data = this.storage.get(keys.data);
|
588
|
+
stored.protocol = this.storage.get(keys.protocol);
|
589
|
+
stored.thumbprint = this.storage.get(keys.thumbprint);
|
590
|
+
isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
|
591
|
+
return stored.data && !isExpired ? stored.data : null;
|
592
|
+
},
|
593
|
+
fromNetwork: function(cb) {
|
594
|
+
var that = this, settings;
|
595
|
+
if (!cb) {
|
596
|
+
return;
|
597
|
+
}
|
598
|
+
settings = this.prepare(this._settings());
|
599
|
+
this.transport(settings).fail(onError).done(onResponse);
|
600
|
+
function onError() {
|
601
|
+
cb(true);
|
602
|
+
}
|
603
|
+
function onResponse(resp) {
|
604
|
+
cb(null, that.transform(resp));
|
605
|
+
}
|
606
|
+
},
|
607
|
+
clear: function clear() {
|
608
|
+
this.storage.clear();
|
609
|
+
return this;
|
510
610
|
}
|
611
|
+
});
|
612
|
+
return Prefetch;
|
613
|
+
}();
|
614
|
+
var Remote = function() {
|
615
|
+
"use strict";
|
616
|
+
function Remote(o) {
|
617
|
+
this.url = o.url;
|
618
|
+
this.prepare = o.prepare;
|
619
|
+
this.transform = o.transform;
|
620
|
+
this.indexResponse = o.indexResponse;
|
621
|
+
this.transport = new Transport({
|
622
|
+
cache: o.cache,
|
623
|
+
limiter: o.limiter,
|
624
|
+
transport: o.transport
|
625
|
+
});
|
511
626
|
}
|
627
|
+
_.mixin(Remote.prototype, {
|
628
|
+
_settings: function settings() {
|
629
|
+
return {
|
630
|
+
url: this.url,
|
631
|
+
type: "GET",
|
632
|
+
dataType: "json"
|
633
|
+
};
|
634
|
+
},
|
635
|
+
get: function get(query, cb) {
|
636
|
+
var that = this, settings;
|
637
|
+
if (!cb) {
|
638
|
+
return;
|
639
|
+
}
|
640
|
+
query = query || "";
|
641
|
+
settings = this.prepare(query, this._settings());
|
642
|
+
return this.transport.get(settings, onResponse);
|
643
|
+
function onResponse(err, resp) {
|
644
|
+
err ? cb([]) : cb(that.transform(resp));
|
645
|
+
}
|
646
|
+
},
|
647
|
+
cancelLastRequest: function cancelLastRequest() {
|
648
|
+
this.transport.cancel();
|
649
|
+
}
|
650
|
+
});
|
651
|
+
return Remote;
|
512
652
|
}();
|
513
653
|
var oParser = function() {
|
514
654
|
"use strict";
|
515
|
-
return {
|
516
|
-
|
517
|
-
|
518
|
-
|
655
|
+
return function parse(o) {
|
656
|
+
var defaults, sorter;
|
657
|
+
defaults = {
|
658
|
+
initialize: true,
|
659
|
+
identify: _.stringify,
|
660
|
+
datumTokenizer: null,
|
661
|
+
queryTokenizer: null,
|
662
|
+
matchAnyQueryToken: false,
|
663
|
+
sufficient: 5,
|
664
|
+
indexRemote: false,
|
665
|
+
sorter: null,
|
666
|
+
local: [],
|
667
|
+
prefetch: null,
|
668
|
+
remote: null
|
669
|
+
};
|
670
|
+
o = _.mixin(defaults, o || {});
|
671
|
+
!o.datumTokenizer && $.error("datumTokenizer is required");
|
672
|
+
!o.queryTokenizer && $.error("queryTokenizer is required");
|
673
|
+
sorter = o.sorter;
|
674
|
+
o.sorter = sorter ? function(x) {
|
675
|
+
return x.sort(sorter);
|
676
|
+
} : _.identity;
|
677
|
+
o.local = _.isFunction(o.local) ? o.local() : o.local;
|
678
|
+
o.prefetch = parsePrefetch(o.prefetch);
|
679
|
+
o.remote = parseRemote(o.remote);
|
680
|
+
return o;
|
519
681
|
};
|
520
|
-
function
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
682
|
+
function parsePrefetch(o) {
|
683
|
+
var defaults;
|
684
|
+
if (!o) {
|
685
|
+
return null;
|
686
|
+
}
|
525
687
|
defaults = {
|
526
688
|
url: null,
|
527
|
-
thumbprint: "",
|
528
689
|
ttl: 24 * 60 * 60 * 1e3,
|
529
|
-
|
530
|
-
|
690
|
+
cache: true,
|
691
|
+
cacheKey: null,
|
692
|
+
thumbprint: "",
|
693
|
+
prepare: _.identity,
|
694
|
+
transform: _.identity,
|
695
|
+
transport: null
|
531
696
|
};
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
return prefetch;
|
697
|
+
o = _.isString(o) ? {
|
698
|
+
url: o
|
699
|
+
} : o;
|
700
|
+
o = _.mixin(defaults, o);
|
701
|
+
!o.url && $.error("prefetch requires url to be set");
|
702
|
+
o.transform = o.filter || o.transform;
|
703
|
+
o.cacheKey = o.cacheKey || o.url;
|
704
|
+
o.thumbprint = VERSION + o.thumbprint;
|
705
|
+
o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
|
706
|
+
return o;
|
543
707
|
}
|
544
|
-
function
|
545
|
-
var
|
708
|
+
function parseRemote(o) {
|
709
|
+
var defaults;
|
710
|
+
if (!o) {
|
711
|
+
return;
|
712
|
+
}
|
546
713
|
defaults = {
|
547
714
|
url: null,
|
548
715
|
cache: true,
|
549
|
-
|
716
|
+
prepare: null,
|
550
717
|
replace: null,
|
718
|
+
wildcard: null,
|
719
|
+
limiter: null,
|
551
720
|
rateLimitBy: "debounce",
|
552
721
|
rateLimitWait: 300,
|
553
|
-
|
554
|
-
|
555
|
-
ajax: {}
|
722
|
+
transform: _.identity,
|
723
|
+
transport: null
|
556
724
|
};
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
725
|
+
o = _.isString(o) ? {
|
726
|
+
url: o
|
727
|
+
} : o;
|
728
|
+
o = _.mixin(defaults, o);
|
729
|
+
!o.url && $.error("remote requires url to be set");
|
730
|
+
o.transform = o.filter || o.transform;
|
731
|
+
o.prepare = toRemotePrepare(o);
|
732
|
+
o.limiter = toLimiter(o);
|
733
|
+
o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
|
734
|
+
delete o.replace;
|
735
|
+
delete o.wildcard;
|
736
|
+
delete o.rateLimitBy;
|
737
|
+
delete o.rateLimitWait;
|
738
|
+
return o;
|
739
|
+
}
|
740
|
+
function toRemotePrepare(o) {
|
741
|
+
var prepare, replace, wildcard;
|
742
|
+
prepare = o.prepare;
|
743
|
+
replace = o.replace;
|
744
|
+
wildcard = o.wildcard;
|
745
|
+
if (prepare) {
|
746
|
+
return prepare;
|
747
|
+
}
|
748
|
+
if (replace) {
|
749
|
+
prepare = prepareByReplace;
|
750
|
+
} else if (o.wildcard) {
|
751
|
+
prepare = prepareByWildcard;
|
752
|
+
} else {
|
753
|
+
prepare = idenityPrepare;
|
754
|
+
}
|
755
|
+
return prepare;
|
756
|
+
function prepareByReplace(query, settings) {
|
757
|
+
settings.url = replace(settings.url, query);
|
758
|
+
return settings;
|
759
|
+
}
|
760
|
+
function prepareByWildcard(query, settings) {
|
761
|
+
settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
|
762
|
+
return settings;
|
568
763
|
}
|
569
|
-
|
570
|
-
|
571
|
-
|
764
|
+
function idenityPrepare(query, settings) {
|
765
|
+
return settings;
|
766
|
+
}
|
767
|
+
}
|
768
|
+
function toLimiter(o) {
|
769
|
+
var limiter, method, wait;
|
770
|
+
limiter = o.limiter;
|
771
|
+
method = o.rateLimitBy;
|
772
|
+
wait = o.rateLimitWait;
|
773
|
+
if (!limiter) {
|
774
|
+
limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
|
775
|
+
}
|
776
|
+
return limiter;
|
777
|
+
function debounce(wait) {
|
778
|
+
return function debounce(fn) {
|
572
779
|
return _.debounce(fn, wait);
|
573
780
|
};
|
574
781
|
}
|
575
|
-
function
|
576
|
-
return function(fn) {
|
782
|
+
function throttle(wait) {
|
783
|
+
return function throttle(fn) {
|
577
784
|
return _.throttle(fn, wait);
|
578
785
|
};
|
579
786
|
}
|
580
787
|
}
|
788
|
+
function callbackToDeferred(fn) {
|
789
|
+
return function wrapper(o) {
|
790
|
+
var deferred = $.Deferred();
|
791
|
+
fn(o, onSuccess, onError);
|
792
|
+
return deferred;
|
793
|
+
function onSuccess(resp) {
|
794
|
+
_.defer(function() {
|
795
|
+
deferred.resolve(resp);
|
796
|
+
});
|
797
|
+
}
|
798
|
+
function onError(err) {
|
799
|
+
_.defer(function() {
|
800
|
+
deferred.reject(err);
|
801
|
+
});
|
802
|
+
}
|
803
|
+
};
|
804
|
+
}
|
581
805
|
}();
|
582
|
-
|
806
|
+
var Bloodhound = function() {
|
583
807
|
"use strict";
|
584
|
-
var old
|
585
|
-
old =
|
586
|
-
keys = {
|
587
|
-
data: "data",
|
588
|
-
protocol: "protocol",
|
589
|
-
thumbprint: "thumbprint"
|
590
|
-
};
|
591
|
-
root.Bloodhound = Bloodhound;
|
808
|
+
var old;
|
809
|
+
old = window && window.Bloodhound;
|
592
810
|
function Bloodhound(o) {
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
this.
|
597
|
-
this.
|
598
|
-
this.
|
599
|
-
this.
|
600
|
-
this.prefetch =
|
601
|
-
this.remote = oParser.remote(o);
|
602
|
-
this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;
|
811
|
+
o = oParser(o);
|
812
|
+
this.sorter = o.sorter;
|
813
|
+
this.identify = o.identify;
|
814
|
+
this.sufficient = o.sufficient;
|
815
|
+
this.indexRemote = o.indexRemote;
|
816
|
+
this.local = o.local;
|
817
|
+
this.remote = o.remote ? new Remote(o.remote) : null;
|
818
|
+
this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
|
603
819
|
this.index = new SearchIndex({
|
820
|
+
identify: this.identify,
|
604
821
|
datumTokenizer: o.datumTokenizer,
|
605
822
|
queryTokenizer: o.queryTokenizer
|
606
823
|
});
|
607
|
-
|
824
|
+
o.initialize !== false && this.initialize();
|
608
825
|
}
|
609
826
|
Bloodhound.noConflict = function noConflict() {
|
610
|
-
|
827
|
+
window && (window.Bloodhound = old);
|
611
828
|
return Bloodhound;
|
612
829
|
};
|
613
830
|
Bloodhound.tokenizers = tokenizers;
|
614
831
|
_.mixin(Bloodhound.prototype, {
|
615
|
-
|
616
|
-
var that = this
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
} else {
|
621
|
-
deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);
|
622
|
-
}
|
623
|
-
return deferred;
|
624
|
-
function handlePrefetchResponse(resp) {
|
625
|
-
that.clear();
|
626
|
-
that.add(o.filter ? o.filter(resp) : resp);
|
627
|
-
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);
|
628
|
-
}
|
629
|
-
},
|
630
|
-
_getFromRemote: function getFromRemote(query, cb) {
|
631
|
-
var that = this, url, uriEncodedQuery;
|
632
|
-
if (!this.transport) {
|
633
|
-
return;
|
832
|
+
__ttAdapter: function ttAdapter() {
|
833
|
+
var that = this;
|
834
|
+
return this.remote ? withAsync : withoutAsync;
|
835
|
+
function withAsync(query, sync, async) {
|
836
|
+
return that.search(query, sync, async);
|
634
837
|
}
|
635
|
-
|
636
|
-
|
637
|
-
url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
|
638
|
-
return this.transport.get(url, this.remote.ajax, handleRemoteResponse);
|
639
|
-
function handleRemoteResponse(err, resp) {
|
640
|
-
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
|
838
|
+
function withoutAsync(query, sync) {
|
839
|
+
return that.search(query, sync);
|
641
840
|
}
|
642
841
|
},
|
643
|
-
|
644
|
-
this
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
this.
|
650
|
-
|
842
|
+
_loadPrefetch: function loadPrefetch() {
|
843
|
+
var that = this, deferred, serialized;
|
844
|
+
deferred = $.Deferred();
|
845
|
+
if (!this.prefetch) {
|
846
|
+
deferred.resolve();
|
847
|
+
} else if (serialized = this.prefetch.fromCache()) {
|
848
|
+
this.index.bootstrap(serialized);
|
849
|
+
deferred.resolve();
|
850
|
+
} else {
|
851
|
+
this.prefetch.fromNetwork(done);
|
651
852
|
}
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
853
|
+
return deferred.promise();
|
854
|
+
function done(err, data) {
|
855
|
+
if (err) {
|
856
|
+
return deferred.reject();
|
857
|
+
}
|
858
|
+
that.add(data);
|
859
|
+
that.prefetch.store(that.index.serialize());
|
860
|
+
deferred.resolve();
|
659
861
|
}
|
660
|
-
isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;
|
661
|
-
return stored.data && !isExpired ? stored.data : null;
|
662
862
|
},
|
663
863
|
_initialize: function initialize() {
|
664
|
-
var that = this,
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
return this.initPromise = deferred.promise();
|
864
|
+
var that = this, deferred;
|
865
|
+
this.clear();
|
866
|
+
(this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
|
867
|
+
return this.initPromise;
|
669
868
|
function addLocalToIndex() {
|
670
|
-
that.add(
|
869
|
+
that.add(that.local);
|
671
870
|
}
|
672
871
|
},
|
673
872
|
initialize: function initialize(force) {
|
@@ -675,53 +874,55 @@
|
|
675
874
|
},
|
676
875
|
add: function add(data) {
|
677
876
|
this.index.add(data);
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
877
|
+
return this;
|
878
|
+
},
|
879
|
+
get: function get(ids) {
|
880
|
+
ids = _.isArray(ids) ? ids : [].slice.call(arguments);
|
881
|
+
return this.index.get(ids);
|
882
|
+
},
|
883
|
+
search: function search(query, sync, async) {
|
884
|
+
var that = this, local;
|
885
|
+
sync = sync || _.noop;
|
886
|
+
async = async || _.noop;
|
887
|
+
local = this.sorter(this.index.search(query));
|
888
|
+
sync(this.remote ? local.slice() : local);
|
889
|
+
if (this.remote && local.length < this.sufficient) {
|
890
|
+
this.remote.get(query, processRemote);
|
891
|
+
} else if (this.remote) {
|
892
|
+
this.remote.cancelLastRequest();
|
893
|
+
}
|
894
|
+
return this;
|
895
|
+
function processRemote(remote) {
|
896
|
+
var nonDuplicates = [];
|
897
|
+
_.each(remote, function(r) {
|
898
|
+
!_.some(local, function(l) {
|
899
|
+
return that.identify(r) === that.identify(l);
|
900
|
+
}) && nonDuplicates.push(r);
|
696
901
|
});
|
697
|
-
|
902
|
+
that.indexRemote && that.add(nonDuplicates);
|
903
|
+
async(nonDuplicates);
|
698
904
|
}
|
699
905
|
},
|
906
|
+
all: function all() {
|
907
|
+
return this.index.all();
|
908
|
+
},
|
700
909
|
clear: function clear() {
|
701
910
|
this.index.reset();
|
911
|
+
return this;
|
702
912
|
},
|
703
913
|
clearPrefetchCache: function clearPrefetchCache() {
|
704
|
-
this.
|
914
|
+
this.prefetch && this.prefetch.clear();
|
915
|
+
return this;
|
705
916
|
},
|
706
917
|
clearRemoteCache: function clearRemoteCache() {
|
707
|
-
|
918
|
+
Transport.resetCache();
|
919
|
+
return this;
|
708
920
|
},
|
709
921
|
ttAdapter: function ttAdapter() {
|
710
|
-
return
|
922
|
+
return this.__ttAdapter();
|
711
923
|
}
|
712
924
|
});
|
713
925
|
return Bloodhound;
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
return array.sort(sortFn);
|
718
|
-
}
|
719
|
-
function noSort(array) {
|
720
|
-
return array;
|
721
|
-
}
|
722
|
-
}
|
723
|
-
function ignoreDuplicates() {
|
724
|
-
return false;
|
725
|
-
}
|
726
|
-
})(this);
|
727
|
-
})(window.jQuery);
|
926
|
+
}();
|
927
|
+
return Bloodhound;
|
928
|
+
});
|