algoliasearch-rails 1.7.2 → 1.8.0
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 +4 -4
- data/ChangeLog +7 -1
- data/README.md +12 -8
- data/VERSION +1 -1
- data/algoliasearch-rails.gemspec +9 -7
- data/lib/algoliasearch/tasks/algoliasearch.rake +1 -15
- data/vendor/assets/javascripts/algolia/algoliasearch.js +12 -56
- data/vendor/assets/javascripts/algolia/algoliasearch.min.js +2 -2
- data/vendor/assets/javascripts/algolia/bloodhound.js +651 -0
- data/vendor/assets/javascripts/algolia/typeahead.bundle.js +1658 -0
- data/vendor/assets/javascripts/algolia/typeahead.bundle.min.js +7 -0
- data/vendor/assets/javascripts/algolia/typeahead.jquery.js +1130 -0
- metadata +8 -6
- data/vendor/assets/javascripts/algolia/typeahead.js +0 -1183
- data/vendor/assets/javascripts/algolia/typeahead.min.js +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e6a128b2bfe1e2ecf10c3e27ec35860245fd518
|
4
|
+
data.tar.gz: a90c923b44b691e3731b35727d3fbd511fb0c2c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d47ac7a0de3b463a2edaa9b1870be20eada52bcff7f49cf31012e75f0ac6f85b10bf0d4a43deb07114955fe57227eae96b35591b2d813bf6d7c4395004da48b
|
7
|
+
data.tar.gz: 04d6de5aab6d594f5537c5f455f383600c0963af19039f592a2f1ccfe72803d3f393f91206c64a5e1bb7b4bffeb4640ebcdd6589be3938e9f8acc339d3a5fef5
|
data/ChangeLog
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
|
3
|
+
2014-02-12 1.8.0
|
4
|
+
|
5
|
+
* Upgrade to official Twitter Typeahead.js 0.10.1 (/!\ API has changed)
|
6
|
+
* Fixed reindexing rake task (#12)
|
7
|
+
|
3
8
|
2014-02-04 1.7.2
|
4
9
|
|
5
10
|
* Add a ```raw_search``` method, retrieving the JSON raw answer
|
11
|
+
* Support STI subclasses (#11)
|
6
12
|
* Updated dependencies
|
7
13
|
|
8
14
|
2014-01-31 1.7.1
|
9
15
|
|
10
16
|
* Ensure methods are not conflicting with already defined ones (use algolia_METHOD_NAME)
|
11
|
-
* Add ```:if``` and ```:unless``` options to control objects indexing
|
17
|
+
* Add ```:if``` and ```:unless``` options to control objects indexing (#10)
|
12
18
|
|
13
19
|
2014-01-07 1.7.0
|
14
20
|
|
data/README.md
CHANGED
@@ -399,11 +399,11 @@ p Contact.search("jon doe", hitsPerPage: 5, page: 2)
|
|
399
399
|
Typeahead UI
|
400
400
|
-------------
|
401
401
|
|
402
|
-
Require ```algolia/algoliasearch.min``` (see [algoliasearch-client-js](https://github.com/algolia/algoliasearch-client-js)) and ```algolia/typeahead.js```
|
402
|
+
Require ```algolia/algoliasearch.min``` (see [algoliasearch-client-js](https://github.com/algolia/algoliasearch-client-js)) and ```algolia/typeahead.jquery.js``` somewhere in your JavaScript manifest, for example in ```application.js``` if you are using Rails 3.1+:
|
403
403
|
|
404
404
|
```javascript
|
405
405
|
//= require algolia/algoliasearch.min
|
406
|
-
//= require algolia/typeahead.
|
406
|
+
//= require algolia/typeahead.jquery
|
407
407
|
```
|
408
408
|
|
409
409
|
We recommend the usage of [hogan](http://twitter.github.io/hogan.js/), a JavaScript templating engine from Twitter.
|
@@ -416,15 +416,19 @@ Turns any ```input[type="text"]``` element into a typeahead, for example:
|
|
416
416
|
|
417
417
|
```javascript
|
418
418
|
<input name="email" placeholder="test@example.org" id="user_email" />
|
419
|
+
|
419
420
|
<script type="text/javascript">
|
420
421
|
$(document).ready(function() {
|
421
422
|
var client = new AlgoliaSearch('YourApplicationID', 'SearchOnlyApplicationKey');
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
423
|
+
var template = Hogan.compile('{{{_highlightResult.email.value}}} ({{{_highlightResult.first_name.value}}} {{{_highlightResult.last_name.value}}})');
|
424
|
+
$('input#user_email').typeahead(null, {
|
425
|
+
source: client.initIndex('<%= Contact.index_name %>').ttAdapter(),
|
426
|
+
displayKey: 'email',
|
427
|
+
templates: {
|
428
|
+
suggestion: function(hit) {
|
429
|
+
return template.render(hit);
|
430
|
+
}
|
431
|
+
}
|
428
432
|
});
|
429
433
|
});
|
430
434
|
</script>
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.8.0
|
data/algoliasearch-rails.gemspec
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "algoliasearch-rails"
|
9
|
-
s.version = "1.
|
9
|
+
s.version = "1.8.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["Algolia"]
|
13
|
-
s.date = "2014-
|
13
|
+
s.date = "2014-02-12"
|
14
14
|
s.description = "AlgoliaSearch integration to your favorite ORM"
|
15
15
|
s.email = "contact@algolia.com"
|
16
16
|
s.extra_rdoc_files = [
|
@@ -42,8 +42,10 @@ Gem::Specification.new do |s|
|
|
42
42
|
"spec/utilities_spec.rb",
|
43
43
|
"vendor/assets/javascripts/algolia/algoliasearch.js",
|
44
44
|
"vendor/assets/javascripts/algolia/algoliasearch.min.js",
|
45
|
-
"vendor/assets/javascripts/algolia/typeahead.js",
|
46
|
-
"vendor/assets/javascripts/algolia/typeahead.
|
45
|
+
"vendor/assets/javascripts/algolia/typeahead.jquery.js",
|
46
|
+
"vendor/assets/javascripts/algolia/typeahead.bundle.js",
|
47
|
+
"vendor/assets/javascripts/algolia/typeahead.bundle.min.js",
|
48
|
+
"vendor/assets/javascripts/algolia/bloodhound.js"
|
47
49
|
]
|
48
50
|
s.homepage = "http://github.com/algolia/algoliasearch-rails"
|
49
51
|
s.licenses = ["MIT"]
|
@@ -56,7 +58,7 @@ Gem::Specification.new do |s|
|
|
56
58
|
|
57
59
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
58
60
|
s.add_runtime_dependency(%q<json>, [">= 1.5.1"])
|
59
|
-
s.add_runtime_dependency(%q<algoliasearch>, [">= 1.
|
61
|
+
s.add_runtime_dependency(%q<algoliasearch>, [">= 1.2.0"])
|
60
62
|
s.add_development_dependency(%q<will_paginate>, [">= 2.3.15"])
|
61
63
|
s.add_development_dependency(%q<kaminari>, [">= 0"])
|
62
64
|
s.add_development_dependency "travis"
|
@@ -64,11 +66,11 @@ Gem::Specification.new do |s|
|
|
64
66
|
s.add_development_dependency "rdoc"
|
65
67
|
else
|
66
68
|
s.add_dependency(%q<json>, [">= 1.5.1"])
|
67
|
-
s.add_dependency(%q<algoliasearch>, [">= 1.
|
69
|
+
s.add_dependency(%q<algoliasearch>, [">= 1.2.0"])
|
68
70
|
end
|
69
71
|
else
|
70
72
|
s.add_dependency(%q<json>, [">= 1.5.1"])
|
71
|
-
s.add_dependency(%q<algoliasearch>, [">= 1.
|
73
|
+
s.add_dependency(%q<algoliasearch>, [">= 1.2.0"])
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
@@ -3,27 +3,13 @@ namespace :algoliasearch do
|
|
3
3
|
desc "Reindex all models"
|
4
4
|
task :reindex => :environment do
|
5
5
|
puts "reindexing all models"
|
6
|
-
load_models
|
7
6
|
AlgoliaSearch::Utilities.reindex_all_models
|
8
7
|
end
|
9
8
|
|
10
9
|
desc "Clear all indexes"
|
11
10
|
task :clear_indexes => :environment do
|
12
11
|
puts "clearing all indexes"
|
13
|
-
load_models
|
14
12
|
AlgoliaSearch::Utilities.clear_all_indexes
|
15
13
|
end
|
16
|
-
|
17
|
-
def load_models
|
18
|
-
app_root = Rails.root
|
19
|
-
dirs = ["#{app_root}/app/models/"] + Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
|
20
|
-
|
21
|
-
dirs.each do |base|
|
22
|
-
Dir["#{base}**/*.rb"].each do |file|
|
23
|
-
model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
|
24
|
-
next if model_name.nil?
|
25
|
-
model_name.camelize.constantize
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
14
|
+
|
29
15
|
end
|
@@ -21,7 +21,7 @@
|
|
21
21
|
* THE SOFTWARE.
|
22
22
|
*/
|
23
23
|
|
24
|
-
var ALGOLIA_VERSION = '2.
|
24
|
+
var ALGOLIA_VERSION = '2.4.0';
|
25
25
|
|
26
26
|
/*
|
27
27
|
* Copyright (c) 2013 Algolia
|
@@ -820,64 +820,20 @@ AlgoliaSearch.prototype.Index.prototype = {
|
|
820
820
|
},
|
821
821
|
|
822
822
|
/*
|
823
|
-
* Get
|
824
|
-
* @param
|
825
|
-
* @param propertyName(optional) if set, contains the name of property that will be used for
|
823
|
+
* Get a Typeahead.js adapter
|
824
|
+
* @param searchParams contains an object with query parameters (see search for details)
|
826
825
|
*/
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
},
|
834
|
-
/*
|
835
|
-
* Update parameter of transport layer for Typeahead.js
|
836
|
-
* @param args contains an object with query parameters (see search for details)
|
837
|
-
* @param propertyName(optional) if set, contains the name of property that will be used for
|
838
|
-
*/
|
839
|
-
setTypeaheadParams: function(args, valueOption) {
|
840
|
-
this.typeAHeadArgs = args;
|
841
|
-
if (typeof valueOption !== 'undefined') {
|
842
|
-
this.typeAheadValueOption = valueOption;
|
843
|
-
}
|
844
|
-
},
|
845
|
-
// Method used by Typeahead.js.
|
846
|
-
get: function(query, processRemoteData, that, cb, suggestions) {
|
847
|
-
self = this;
|
848
|
-
this.search(query, function(success, content) {
|
849
|
-
if (success) {
|
850
|
-
for (var i = 0; i < content.hits.length; ++i) {
|
851
|
-
// Add an attribute value with the first string
|
852
|
-
var obj = content.hits[i],
|
853
|
-
found = false;
|
854
|
-
|
855
|
-
if (typeof obj.value === 'undefined') {
|
856
|
-
if (self.typeAheadValueOption != null) {
|
857
|
-
if (typeof self.typeAheadValueOption === 'function') {
|
858
|
-
obj.value = self.typeAheadValueOption(obj);
|
859
|
-
found = true;
|
860
|
-
} else if (typeof obj[self.typeAheadValueOption] !== 'undefined') {
|
861
|
-
obj.value = obj[self.typeAheadValueOption];
|
862
|
-
found = true;
|
863
|
-
}
|
864
|
-
}
|
865
|
-
if (! found) {
|
866
|
-
for (var propertyName in obj) {
|
867
|
-
if (!found && obj.hasOwnProperty(propertyName) && typeof obj[propertyName] === 'string') {
|
868
|
-
obj.value = obj[propertyName];
|
869
|
-
found = true;
|
870
|
-
}
|
871
|
-
}
|
872
|
-
}
|
873
|
-
}
|
874
|
-
suggestions.push(that._transformDatum(obj));
|
826
|
+
ttAdapter: function(params) {
|
827
|
+
var self = this;
|
828
|
+
return function(query, cb) {
|
829
|
+
self.search(query, function(success, content) {
|
830
|
+
if (success) {
|
831
|
+
cb(content.hits);
|
875
832
|
}
|
876
|
-
|
877
|
-
|
878
|
-
}, self.typeAheadArgs);
|
879
|
-
return true;
|
833
|
+
}, params);
|
834
|
+
};
|
880
835
|
},
|
836
|
+
|
881
837
|
/*
|
882
838
|
* Wait the publication of a task on the server.
|
883
839
|
* All server task are asynchronous and you can check with this method that the task is published.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
|
-
* algoliasearch 2.
|
2
|
+
* algoliasearch 2.4.0
|
3
3
|
* https://github.com/algolia/algoliasearch-client-js
|
4
4
|
* Copyright 2014 Algolia SAS; Licensed MIT
|
5
5
|
*/
|
6
6
|
|
7
|
-
function AlgoliaExplainResults(a,b,c){function d(a,b){if("object"==typeof a&&"matchedWords"in a&&"value"in a){for(var c=!1,e=0;e<a.matchedWords.length;++e){var f=a.matchedWords[e];f in b||(b[f]=1,c=!0)}return c?[a.value]:[]}if(a instanceof Array){for(var g=[],h=0;h<a.length;++h){var i=d(a[h],b);g=g.concat(i)}return g}if("object"==typeof a){var g=[];for(prop in a)a.hasOwnProperty(prop)&&(g=g.concat(d(a[prop],b)));return g}return[]}function e(a,b,c){if(-1===c.indexOf("."))return c in a._highlightResult?d(a._highlightResult[c],b):[];for(var e=c.split("."),f=a._highlightResult,g=0;g<e.length;++g){if(!(e[g]in f))return[];f=f[e[g]]}return d(f,b)}var f={},g={},h=e(a,g,b);if(f.title=h.length>0?h[0]:"",f.subtitles=[],"undefined"!=typeof c)for(var i=0;i<c.length;++i)for(var j=e(a,g,c[i]),k=0;k<j.length;++k)f.subtitles.push({attr:c[i],value:j[k]});return f}var ALGOLIA_VERSION="2.3.8",AlgoliaSearch=function(a,b,c,d,e){this.applicationID=a,this.apiKey=b,this._isUndefined(e)&&(e=[a+"-1.algolia.io",a+"-2.algolia.io",a+"-3.algolia.io"]),this.hosts=[];for(var f=0;f<e.length;++f)Math.random()>.5&&this.hosts.reverse(),this._isUndefined(c)||null==c?this.hosts.push(("https:"==document.location.protocol?"https":"http")+"://"+e[f]):"https"===c||"HTTPS"===c?this.hosts.push("https://"+e[f]):this.hosts.push("http://"+e[f]);Math.random()>.5&&this.hosts.reverse(),(this._isUndefined(d)||d)&&this._jsonRequest({method:"GET",url:"/1/isalive"}),this.extraHeaders=[]};AlgoliaSearch.prototype={deleteIndex:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){var d={operation:"move",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},copyIndex:function(a,b,c){var d={operation:"copy",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},getLogs:function(a,b,c){this._isUndefined(b)&&(b=0),this._isUndefined(c)&&(c=10),this._jsonRequest({method:"GET",url:"/1/logs?offset="+b+"&length="+c,callback:a})},listIndexes:function(a){this._jsonRequest({method:"GET",url:"/1/indexes/",callback:a})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){this._jsonRequest({method:"GET",url:"/1/keys",callback:a})},getUserKeyACL:function(a,b){this._jsonRequest({method:"GET",url:"/1/keys/"+a,callback:b})},deleteUserKey:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/keys/"+a,callback:b})},addUserKey:function(a,b){var c={};c.acl=a,this._jsonRequest({method:"POST",url:"/1/keys",body:c,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this._jsonRequest({method:"POST",url:"/1/indexes/"+f.indexName+"/keys",body:g,callback:e})},startQueriesBatch:function(){this.batch=[]},addQueryInBatch:function(a,b,c){var d="query="+encodeURIComponent(b);this._isUndefined(c)||null==c||(d=this._getSearchParams(c,d)),this.batch.push({indexName:a,params:d})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a,b){for(var c=this,d={requests:[],apiKey:this.apiKey,appID:this.applicationID},e=0;e<c.batch.length;++e)d.requests.push(c.batch[e]);if(window.clearTimeout(c.onDelayTrigger),!this._isUndefined(b)&&null!=b&&b>0){var f=window.setTimeout(function(){c._sendQueriesBatch(d,a)},b);c.onDelayTrigger=f}else this._sendQueriesBatch(d,a)},Index:function(a,b){this.indexName=b,this.as=a,this.typeAheadArgs=null,this.typeAheadValueOption=null},setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:b})},_jsonRequest:function(a){var b=this,c=a.callback,d=null,e=a.url;if(this._isUndefined(a.body)||(e=a.url+"_body_"+JSON.stringify(a.body)),!this._isUndefined(a.cache)&&(d=a.cache,!this._isUndefined(d[e])))return this._isUndefined(c)||c(!0,d[e]),void 0;var f=function(g){var h=0;return b._isUndefined(g)||(h=g),b.hosts.length<=h?(b._isUndefined(c)||c(!1,{message:"Cannot contact server"}),void 0):(a.callback=function(g,i,j,k){i||b._isUndefined(k)||console.log("Error: "+k.message),i&&!b._isUndefined(a.cache)&&(d[e]=k),!i&&g&&h+1<b.hosts.length?f(h+1):b._isUndefined(c)||c(i,k)},a.hostname=b.hosts[h],b._jsonRequestByHost(a),void 0)};f()},_jsonRequestByHost:function(a){var b=null,c=this;this._isUndefined(a.body)||(b=JSON.stringify(a.body));var d=a.hostname+a.url,e=null;if(e=new XMLHttpRequest,"withCredentials"in e){e.open(a.method,d,!0),e.setRequestHeader("X-Algolia-API-Key",this.apiKey),e.setRequestHeader("X-Algolia-Application-Id",this.applicationID);for(var f=0;f<this.extraHeaders.length;++f)e.setRequestHeader(this.extraHeaders[f].key,this.extraHeaders[f].value);null!=b&&e.setRequestHeader("Content-type","application/json")}else"undefined"!=typeof XDomainRequest?(e=new XDomainRequest,e.open(a.method,d)):console.log("your browser is too old to support CORS requests");e.send(b),e.onload=function(b){if(c._isUndefined(b)||null==b.target)a.callback(!1,!0,b,JSON.parse(e.responseText));else{var d=0===b.target.status||503===b.target.status,f=200===b.target.status||201===b.target.status;a.callback(d,f,b.target,null!=b.target.response?JSON.parse(b.target.response):null)}},e.onerror=function(){a.callback(!0,!1,null,{message:"Could not connect to Host"})}},_getSearchParams:function(a,b){if(this._isUndefined(a)||null==a)return b;for(var c in a)null!=c&&a.hasOwnProperty(c)&&(b+=0===b.length?"?":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):a[c]));return b},_isUndefined:function(a){return void 0===a},applicationID:null,apiKey:null,hosts:[],cache:{},extraHeaders:[]},AlgoliaSearch.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){var d=this;this.as._isUndefined(c)?this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(d.indexName),body:a,callback:b}):this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(c),body:a,callback:b})},addObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"addObject",body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},getObject:function(a,b,c){var d=this,e="";if(!this.as._isUndefined(c)){e="?attributes=";for(var f=0;f<c.length;++f)0!==f&&(e+=","),e+=c[f]}this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(a)+e,callback:b})},partialUpdateObject:function(a,b){var c=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"partialUpdateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},saveObject:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"updateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},deleteObject:function(a,b){if(null==a||0===a.length)return b(!1,{message:"empty objectID"}),void 0;var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c,d){var e=this,f="query="+encodeURIComponent(a);if(this.as._isUndefined(c)||null==c||(f=this.as._getSearchParams(c,f)),window.clearTimeout(e.onDelayTrigger),!this.as._isUndefined(d)&&null!=d&&d>0){var g=window.setTimeout(function(){e._search(f,b)},d);e.onDelayTrigger=g}else this._search(f,b)},browse:function(a,b,c){var d=this,e="?page="+a;_.isUndefined(c)||(e+="&hitsPerPage="+c),this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/browse"+e,callback:b})},getTypeaheadTransport:function(a,b){return this.typeAheadArgs=a,"undefined"!=typeof b&&(this.typeAheadValueOption=b),this},setTypeaheadParams:function(a,b){this.typeAHeadArgs=a,"undefined"!=typeof b&&(this.typeAheadValueOption=b)},get:function(a,b,c,d,e){return self=this,this.search(a,function(a,b){if(a){for(var f=0;f<b.hits.length;++f){var g=b.hits[f],h=!1;if("undefined"==typeof g.value&&(null!=self.typeAheadValueOption&&("function"==typeof self.typeAheadValueOption?(g.value=self.typeAheadValueOption(g),h=!0):"undefined"!=typeof g[self.typeAheadValueOption]&&(g.value=g[self.typeAheadValueOption],h=!0)),!h))for(var i in g)!h&&g.hasOwnProperty(i)&&"string"==typeof g[i]&&(g.value=g[i],h=!0);e.push(c._transformDatum(g))}d&&d(e)}},self.typeAheadArgs),!0},waitTask:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/task/"+a,callback:function(d,e){if(d&&"published"===e.status)b(!0,e);else{if(d&&e.pendingTask)return c.waitTask(a,b);b(!1,e)}}})},clearIndex:function(a){var b=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/clear",callback:a})},getSettings:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/settings",callback:a})},setSettings:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c=this,d={};d.acl=a,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys",body:d,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(f.indexName)+"/keys",body:g,callback:e})},_search:function(a,b){this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:{params:a,apiKey:this.as.apiKey,appID:this.as.applicationID},callback:b})},as:null,indexName:null,cache:{},typeAheadArgs:null,typeAheadValueOption:null,emptyConstructor:function(){}},function(a){var b;window.AlgoliaSearchHelper=function(c,d,e){var f={facets:[],disjunctiveFacets:[],hitsPerPage:20};this.init(c,d,a.extend({},f,e)),b=this},AlgoliaSearchHelper.prototype={init:function(a,b,c){this.client=a,this.index=b,this.options=c,this.page=0,this.refinements={},this.disjunctiveRefinements={}},search:function(a,b){this.q=a,this.searchCallback=b,this.page=0,this.refinements={},this.disjunctiveRefinements={},this._search()},toggleRefine:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":"+b;return this.refinements[d]=!this.refinements[d],this.page=0,this._search(),!0}this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};for(var e=0;e<this.options.disjunctiveFacets.length;++e)if(this.options.disjunctiveFacets[e]==a)return this.disjunctiveRefinements[a][b]=!this.disjunctiveRefinements[a][b],this.page=0,this._search(),!0;return!1},isRefined:function(a,b){var c=a+":"+b;return this.refinements[c]?!0:this.disjunctiveRefinements[a]&&this.disjunctiveRefinements[a][b]?!0:!1},nextPage:function(){this._gotoPage(this.page+1)},previousPage:function(){this.page>0&&this._gotoPage(this.page-1)},_gotoPage:function(a){this.page=a,this._search()},_search:function(){this.client.startQueriesBatch(),this.client.addQueryInBatch(this.index,this.q,this._getHitsSearchParams());for(var a=0;a<this.options.disjunctiveFacets.length;++a)this.client.addQueryInBatch(this.index,this.q,this._getDisjunctiveFacetSearchParams(this.options.disjunctiveFacets[a]));this.client.sendQueriesBatch(function(a,c){if(!a)return b.searchCallback(!1,c),void 0;var d=c.results[0];d.disjunctiveFacets={};for(var e=1;e<c.results.length;++e)for(var f in c.results[e].facets)if(d.disjunctiveFacets[f]=c.results[e].facets[f],b.disjunctiveRefinements[f])for(var g in b.disjunctiveRefinements[f])!d.disjunctiveFacets[f][g]&&b.disjunctiveRefinements[f][g]&&(d.disjunctiveFacets[f][g]=0);b.searchCallback(!0,d)})},_getHitsSearchParams:function(){return{hitsPerPage:this.options.hitsPerPage,page:this.page,facets:this.options.facets,facetFilters:this._getFacetFilters()}},_getDisjunctiveFacetSearchParams:function(a){return{hitsPerPage:1,page:0,facets:a,facetFilters:this._getFacetFilters(a)}},_getFacetFilters:function(a){var b=[];for(var c in this.refinements)this.refinements[c]&&b.push(c);for(var d in this.disjunctiveRefinements)if(d!=a){var e=[];for(var f in this.disjunctiveRefinements[d])this.disjunctiveRefinements[d][f]&&e.push(d+":"+f);e.length>0&&b.push(e)}return b}}}(jQuery);
|
7
|
+
function AlgoliaExplainResults(a,b,c){function d(a,b){if("object"==typeof a&&"matchedWords"in a&&"value"in a){for(var c=!1,e=0;e<a.matchedWords.length;++e){var f=a.matchedWords[e];f in b||(b[f]=1,c=!0)}return c?[a.value]:[]}if(a instanceof Array){for(var g=[],h=0;h<a.length;++h){var i=d(a[h],b);g=g.concat(i)}return g}if("object"==typeof a){var g=[];for(prop in a)a.hasOwnProperty(prop)&&(g=g.concat(d(a[prop],b)));return g}return[]}function e(a,b,c){if(-1===c.indexOf("."))return c in a._highlightResult?d(a._highlightResult[c],b):[];for(var e=c.split("."),f=a._highlightResult,g=0;g<e.length;++g){if(!(e[g]in f))return[];f=f[e[g]]}return d(f,b)}var f={},g={},h=e(a,g,b);if(f.title=h.length>0?h[0]:"",f.subtitles=[],"undefined"!=typeof c)for(var i=0;i<c.length;++i)for(var j=e(a,g,c[i]),k=0;k<j.length;++k)f.subtitles.push({attr:c[i],value:j[k]});return f}var ALGOLIA_VERSION="2.4.0",AlgoliaSearch=function(a,b,c,d,e){this.applicationID=a,this.apiKey=b,this._isUndefined(e)&&(e=[a+"-1.algolia.io",a+"-2.algolia.io",a+"-3.algolia.io"]),this.hosts=[];for(var f=0;f<e.length;++f)Math.random()>.5&&this.hosts.reverse(),this._isUndefined(c)||null==c?this.hosts.push(("https:"==document.location.protocol?"https":"http")+"://"+e[f]):"https"===c||"HTTPS"===c?this.hosts.push("https://"+e[f]):this.hosts.push("http://"+e[f]);Math.random()>.5&&this.hosts.reverse(),(this._isUndefined(d)||d)&&this._jsonRequest({method:"GET",url:"/1/isalive"}),this.extraHeaders=[]};AlgoliaSearch.prototype={deleteIndex:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){var d={operation:"move",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},copyIndex:function(a,b,c){var d={operation:"copy",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},getLogs:function(a,b,c){this._isUndefined(b)&&(b=0),this._isUndefined(c)&&(c=10),this._jsonRequest({method:"GET",url:"/1/logs?offset="+b+"&length="+c,callback:a})},listIndexes:function(a){this._jsonRequest({method:"GET",url:"/1/indexes/",callback:a})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){this._jsonRequest({method:"GET",url:"/1/keys",callback:a})},getUserKeyACL:function(a,b){this._jsonRequest({method:"GET",url:"/1/keys/"+a,callback:b})},deleteUserKey:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/keys/"+a,callback:b})},addUserKey:function(a,b){var c={};c.acl=a,this._jsonRequest({method:"POST",url:"/1/keys",body:c,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this._jsonRequest({method:"POST",url:"/1/indexes/"+f.indexName+"/keys",body:g,callback:e})},startQueriesBatch:function(){this.batch=[]},addQueryInBatch:function(a,b,c){var d="query="+encodeURIComponent(b);this._isUndefined(c)||null==c||(d=this._getSearchParams(c,d)),this.batch.push({indexName:a,params:d})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a,b){for(var c=this,d={requests:[],apiKey:this.apiKey,appID:this.applicationID},e=0;e<c.batch.length;++e)d.requests.push(c.batch[e]);if(window.clearTimeout(c.onDelayTrigger),!this._isUndefined(b)&&null!=b&&b>0){var f=window.setTimeout(function(){c._sendQueriesBatch(d,a)},b);c.onDelayTrigger=f}else this._sendQueriesBatch(d,a)},Index:function(a,b){this.indexName=b,this.as=a,this.typeAheadArgs=null,this.typeAheadValueOption=null},setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:b})},_jsonRequest:function(a){var b=this,c=a.callback,d=null,e=a.url;if(this._isUndefined(a.body)||(e=a.url+"_body_"+JSON.stringify(a.body)),!this._isUndefined(a.cache)&&(d=a.cache,!this._isUndefined(d[e])))return this._isUndefined(c)||c(!0,d[e]),void 0;var f=function(g){var h=0;return b._isUndefined(g)||(h=g),b.hosts.length<=h?(b._isUndefined(c)||c(!1,{message:"Cannot contact server"}),void 0):(a.callback=function(g,i,j,k){i||b._isUndefined(k)||console.log("Error: "+k.message),i&&!b._isUndefined(a.cache)&&(d[e]=k),!i&&g&&h+1<b.hosts.length?f(h+1):b._isUndefined(c)||c(i,k)},a.hostname=b.hosts[h],b._jsonRequestByHost(a),void 0)};f()},_jsonRequestByHost:function(a){var b=null,c=this;this._isUndefined(a.body)||(b=JSON.stringify(a.body));var d=a.hostname+a.url,e=null;if(e=new XMLHttpRequest,"withCredentials"in e){e.open(a.method,d,!0),e.setRequestHeader("X-Algolia-API-Key",this.apiKey),e.setRequestHeader("X-Algolia-Application-Id",this.applicationID);for(var f=0;f<this.extraHeaders.length;++f)e.setRequestHeader(this.extraHeaders[f].key,this.extraHeaders[f].value);null!=b&&e.setRequestHeader("Content-type","application/json")}else"undefined"!=typeof XDomainRequest?(e=new XDomainRequest,e.open(a.method,d)):console.log("your browser is too old to support CORS requests");e.send(b),e.onload=function(b){if(c._isUndefined(b)||null==b.target)a.callback(!1,!0,b,JSON.parse(e.responseText));else{var d=0===b.target.status||503===b.target.status,f=200===b.target.status||201===b.target.status;a.callback(d,f,b.target,null!=b.target.response?JSON.parse(b.target.response):null)}},e.onerror=function(){a.callback(!0,!1,null,{message:"Could not connect to Host"})}},_getSearchParams:function(a,b){if(this._isUndefined(a)||null==a)return b;for(var c in a)null!=c&&a.hasOwnProperty(c)&&(b+=0===b.length?"?":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):a[c]));return b},_isUndefined:function(a){return void 0===a},applicationID:null,apiKey:null,hosts:[],cache:{},extraHeaders:[]},AlgoliaSearch.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){var d=this;this.as._isUndefined(c)?this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(d.indexName),body:a,callback:b}):this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(c),body:a,callback:b})},addObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"addObject",body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},getObject:function(a,b,c){var d=this,e="";if(!this.as._isUndefined(c)){e="?attributes=";for(var f=0;f<c.length;++f)0!==f&&(e+=","),e+=c[f]}this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(a)+e,callback:b})},partialUpdateObject:function(a,b){var c=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"partialUpdateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},saveObject:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"updateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},deleteObject:function(a,b){if(null==a||0===a.length)return b(!1,{message:"empty objectID"}),void 0;var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c,d){var e=this,f="query="+encodeURIComponent(a);if(this.as._isUndefined(c)||null==c||(f=this.as._getSearchParams(c,f)),window.clearTimeout(e.onDelayTrigger),!this.as._isUndefined(d)&&null!=d&&d>0){var g=window.setTimeout(function(){e._search(f,b)},d);e.onDelayTrigger=g}else this._search(f,b)},browse:function(a,b,c){var d=this,e="?page="+a;_.isUndefined(c)||(e+="&hitsPerPage="+c),this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/browse"+e,callback:b})},ttAdapter:function(a){var b=this;return function(c,d){b.search(c,function(a,b){a&&d(b.hits)},a)}},waitTask:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/task/"+a,callback:function(d,e){if(d&&"published"===e.status)b(!0,e);else{if(d&&e.pendingTask)return c.waitTask(a,b);b(!1,e)}}})},clearIndex:function(a){var b=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/clear",callback:a})},getSettings:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/settings",callback:a})},setSettings:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c=this,d={};d.acl=a,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys",body:d,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(f.indexName)+"/keys",body:g,callback:e})},_search:function(a,b){this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:{params:a,apiKey:this.as.apiKey,appID:this.as.applicationID},callback:b})},as:null,indexName:null,cache:{},typeAheadArgs:null,typeAheadValueOption:null,emptyConstructor:function(){}},function(a){var b;window.AlgoliaSearchHelper=function(c,d,e){var f={facets:[],disjunctiveFacets:[],hitsPerPage:20};this.init(c,d,a.extend({},f,e)),b=this},AlgoliaSearchHelper.prototype={init:function(a,b,c){this.client=a,this.index=b,this.options=c,this.page=0,this.refinements={},this.disjunctiveRefinements={}},search:function(a,b){this.q=a,this.searchCallback=b,this.page=0,this.refinements={},this.disjunctiveRefinements={},this._search()},toggleRefine:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":"+b;return this.refinements[d]=!this.refinements[d],this.page=0,this._search(),!0}this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};for(var e=0;e<this.options.disjunctiveFacets.length;++e)if(this.options.disjunctiveFacets[e]==a)return this.disjunctiveRefinements[a][b]=!this.disjunctiveRefinements[a][b],this.page=0,this._search(),!0;return!1},isRefined:function(a,b){var c=a+":"+b;return this.refinements[c]?!0:this.disjunctiveRefinements[a]&&this.disjunctiveRefinements[a][b]?!0:!1},nextPage:function(){this._gotoPage(this.page+1)},previousPage:function(){this.page>0&&this._gotoPage(this.page-1)},_gotoPage:function(a){this.page=a,this._search()},_search:function(){this.client.startQueriesBatch(),this.client.addQueryInBatch(this.index,this.q,this._getHitsSearchParams());for(var a=0;a<this.options.disjunctiveFacets.length;++a)this.client.addQueryInBatch(this.index,this.q,this._getDisjunctiveFacetSearchParams(this.options.disjunctiveFacets[a]));this.client.sendQueriesBatch(function(a,c){if(!a)return b.searchCallback(!1,c),void 0;var d=c.results[0];d.disjunctiveFacets={};for(var e=1;e<c.results.length;++e)for(var f in c.results[e].facets)if(d.disjunctiveFacets[f]=c.results[e].facets[f],b.disjunctiveRefinements[f])for(var g in b.disjunctiveRefinements[f])!d.disjunctiveFacets[f][g]&&b.disjunctiveRefinements[f][g]&&(d.disjunctiveFacets[f][g]=0);b.searchCallback(!0,d)})},_getHitsSearchParams:function(){return{hitsPerPage:this.options.hitsPerPage,page:this.page,facets:this.options.facets,facetFilters:this._getFacetFilters()}},_getDisjunctiveFacetSearchParams:function(a){return{hitsPerPage:1,page:0,facets:a,facetFilters:this._getFacetFilters(a)}},_getFacetFilters:function(a){var b=[];for(var c in this.refinements)this.refinements[c]&&b.push(c);for(var d in this.disjunctiveRefinements)if(d!=a){var e=[];for(var f in this.disjunctiveRefinements[d])this.disjunctiveRefinements[d][f]&&e.push(d+":"+f);e.length>0&&b.push(e)}return b}}}(jQuery);
|
@@ -0,0 +1,651 @@
|
|
1
|
+
/*!
|
2
|
+
* typeahead.js 0.10.1
|
3
|
+
* https://github.com/twitter/typeahead.js
|
4
|
+
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
|
5
|
+
*/
|
6
|
+
|
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;
|
47
|
+
}
|
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;
|
59
|
+
}
|
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);
|
87
|
+
}
|
88
|
+
};
|
89
|
+
callNow = immediate && !timeout;
|
90
|
+
clearTimeout(timeout);
|
91
|
+
timeout = setTimeout(later, wait);
|
92
|
+
if (callNow) {
|
93
|
+
result = func.apply(context, args);
|
94
|
+
}
|
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) {
|
111
|
+
clearTimeout(timeout);
|
112
|
+
timeout = null;
|
113
|
+
previous = now;
|
114
|
+
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.1";
|
124
|
+
var LruCache = function(root, undefined) {
|
125
|
+
function LruCache(maxSize) {
|
126
|
+
this.maxSize = maxSize || 100;
|
127
|
+
this.size = 0;
|
128
|
+
this.hash = {};
|
129
|
+
this.list = new List();
|
130
|
+
}
|
131
|
+
_.mixin(LruCache.prototype, {
|
132
|
+
set: function set(key, val) {
|
133
|
+
var tailItem = this.list.tail, node;
|
134
|
+
if (this.size >= this.maxSize) {
|
135
|
+
this.list.remove(tailItem);
|
136
|
+
delete this.hash[tailItem.key];
|
137
|
+
}
|
138
|
+
if (node = this.hash[key]) {
|
139
|
+
node.val = val;
|
140
|
+
this.list.moveToFront(node);
|
141
|
+
} else {
|
142
|
+
node = new Node(key, val);
|
143
|
+
this.list.add(node);
|
144
|
+
this.hash[key] = node;
|
145
|
+
this.size++;
|
146
|
+
}
|
147
|
+
},
|
148
|
+
get: function get(key) {
|
149
|
+
var node = this.hash[key];
|
150
|
+
if (node) {
|
151
|
+
this.list.moveToFront(node);
|
152
|
+
return node.val;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
});
|
156
|
+
function List() {
|
157
|
+
this.head = this.tail = null;
|
158
|
+
}
|
159
|
+
_.mixin(List.prototype, {
|
160
|
+
add: function add(node) {
|
161
|
+
if (this.head) {
|
162
|
+
node.next = this.head;
|
163
|
+
this.head.prev = node;
|
164
|
+
}
|
165
|
+
this.head = node;
|
166
|
+
this.tail = this.tail || node;
|
167
|
+
},
|
168
|
+
remove: function remove(node) {
|
169
|
+
node.prev ? node.prev.next = node.next : this.head = node.next;
|
170
|
+
node.next ? node.next.prev = node.prev : this.tail = node.prev;
|
171
|
+
},
|
172
|
+
moveToFront: function(node) {
|
173
|
+
this.remove(node);
|
174
|
+
this.add(node);
|
175
|
+
}
|
176
|
+
});
|
177
|
+
function Node(key, val) {
|
178
|
+
this.key = key;
|
179
|
+
this.val = val;
|
180
|
+
this.prev = this.next = null;
|
181
|
+
}
|
182
|
+
return LruCache;
|
183
|
+
}(this);
|
184
|
+
var PersistentStorage = function() {
|
185
|
+
var ls, methods;
|
186
|
+
try {
|
187
|
+
ls = window.localStorage;
|
188
|
+
ls.setItem("~~~", "!");
|
189
|
+
ls.removeItem("~~~");
|
190
|
+
} catch (err) {
|
191
|
+
ls = null;
|
192
|
+
}
|
193
|
+
function PersistentStorage(namespace) {
|
194
|
+
this.prefix = [ "__", namespace, "__" ].join("");
|
195
|
+
this.ttlKey = "__ttl__";
|
196
|
+
this.keyMatcher = new RegExp("^" + this.prefix);
|
197
|
+
}
|
198
|
+
if (ls && window.JSON) {
|
199
|
+
methods = {
|
200
|
+
_prefix: function(key) {
|
201
|
+
return this.prefix + key;
|
202
|
+
},
|
203
|
+
_ttlKey: function(key) {
|
204
|
+
return this._prefix(key) + this.ttlKey;
|
205
|
+
},
|
206
|
+
get: function(key) {
|
207
|
+
if (this.isExpired(key)) {
|
208
|
+
this.remove(key);
|
209
|
+
}
|
210
|
+
return decode(ls.getItem(this._prefix(key)));
|
211
|
+
},
|
212
|
+
set: function(key, val, ttl) {
|
213
|
+
if (_.isNumber(ttl)) {
|
214
|
+
ls.setItem(this._ttlKey(key), encode(now() + ttl));
|
215
|
+
} else {
|
216
|
+
ls.removeItem(this._ttlKey(key));
|
217
|
+
}
|
218
|
+
return ls.setItem(this._prefix(key), encode(val));
|
219
|
+
},
|
220
|
+
remove: function(key) {
|
221
|
+
ls.removeItem(this._ttlKey(key));
|
222
|
+
ls.removeItem(this._prefix(key));
|
223
|
+
return this;
|
224
|
+
},
|
225
|
+
clear: function() {
|
226
|
+
var i, key, keys = [], len = ls.length;
|
227
|
+
for (i = 0; i < len; i++) {
|
228
|
+
if ((key = ls.key(i)).match(this.keyMatcher)) {
|
229
|
+
keys.push(key.replace(this.keyMatcher, ""));
|
230
|
+
}
|
231
|
+
}
|
232
|
+
for (i = keys.length; i--; ) {
|
233
|
+
this.remove(keys[i]);
|
234
|
+
}
|
235
|
+
return this;
|
236
|
+
},
|
237
|
+
isExpired: function(key) {
|
238
|
+
var ttl = decode(ls.getItem(this._ttlKey(key)));
|
239
|
+
return _.isNumber(ttl) && now() > ttl ? true : false;
|
240
|
+
}
|
241
|
+
};
|
242
|
+
} else {
|
243
|
+
methods = {
|
244
|
+
get: _.noop,
|
245
|
+
set: _.noop,
|
246
|
+
remove: _.noop,
|
247
|
+
clear: _.noop,
|
248
|
+
isExpired: _.noop
|
249
|
+
};
|
250
|
+
}
|
251
|
+
_.mixin(PersistentStorage.prototype, methods);
|
252
|
+
return PersistentStorage;
|
253
|
+
function now() {
|
254
|
+
return new Date().getTime();
|
255
|
+
}
|
256
|
+
function encode(val) {
|
257
|
+
return JSON.stringify(_.isUndefined(val) ? null : val);
|
258
|
+
}
|
259
|
+
function decode(val) {
|
260
|
+
return JSON.parse(val);
|
261
|
+
}
|
262
|
+
}();
|
263
|
+
var Transport = function() {
|
264
|
+
var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);
|
265
|
+
function Transport(o) {
|
266
|
+
o = o || {};
|
267
|
+
this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
|
268
|
+
this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;
|
269
|
+
}
|
270
|
+
Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
|
271
|
+
maxPendingRequests = num;
|
272
|
+
};
|
273
|
+
Transport.resetCache = function clearCache() {
|
274
|
+
requestCache = new LruCache(10);
|
275
|
+
};
|
276
|
+
_.mixin(Transport.prototype, {
|
277
|
+
_get: function(url, o, cb) {
|
278
|
+
var that = this, jqXhr;
|
279
|
+
if (jqXhr = pendingRequests[url]) {
|
280
|
+
jqXhr.done(done);
|
281
|
+
} else if (pendingRequestsCount < maxPendingRequests) {
|
282
|
+
pendingRequestsCount++;
|
283
|
+
pendingRequests[url] = this._send(url, o).done(done).always(always);
|
284
|
+
} else {
|
285
|
+
this.onDeckRequestArgs = [].slice.call(arguments, 0);
|
286
|
+
}
|
287
|
+
function done(resp) {
|
288
|
+
cb && cb(resp);
|
289
|
+
requestCache.set(url, resp);
|
290
|
+
}
|
291
|
+
function always() {
|
292
|
+
pendingRequestsCount--;
|
293
|
+
delete pendingRequests[url];
|
294
|
+
if (that.onDeckRequestArgs) {
|
295
|
+
that._get.apply(that, that.onDeckRequestArgs);
|
296
|
+
that.onDeckRequestArgs = null;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
},
|
300
|
+
get: function(url, o, cb) {
|
301
|
+
var that = this, resp;
|
302
|
+
if (_.isFunction(o)) {
|
303
|
+
cb = o;
|
304
|
+
o = {};
|
305
|
+
}
|
306
|
+
if (resp = requestCache.get(url)) {
|
307
|
+
_.defer(function() {
|
308
|
+
cb && cb(resp);
|
309
|
+
});
|
310
|
+
} else {
|
311
|
+
this._get(url, o, cb);
|
312
|
+
}
|
313
|
+
return !!resp;
|
314
|
+
}
|
315
|
+
});
|
316
|
+
return Transport;
|
317
|
+
function callbackToDeferred(fn) {
|
318
|
+
return function customSendWrapper(url, o) {
|
319
|
+
var deferred = $.Deferred();
|
320
|
+
fn(url, o, onSuccess, onError);
|
321
|
+
return deferred;
|
322
|
+
function onSuccess(resp) {
|
323
|
+
_.defer(function() {
|
324
|
+
deferred.resolve(resp);
|
325
|
+
});
|
326
|
+
}
|
327
|
+
function onError(err) {
|
328
|
+
_.defer(function() {
|
329
|
+
deferred.reject(err);
|
330
|
+
});
|
331
|
+
}
|
332
|
+
};
|
333
|
+
}
|
334
|
+
}();
|
335
|
+
var SearchIndex = function() {
|
336
|
+
function SearchIndex(o) {
|
337
|
+
o = o || {};
|
338
|
+
if (!o.datumTokenizer || !o.queryTokenizer) {
|
339
|
+
$.error("datumTokenizer and queryTokenizer are both required");
|
340
|
+
}
|
341
|
+
this.datumTokenizer = o.datumTokenizer;
|
342
|
+
this.queryTokenizer = o.queryTokenizer;
|
343
|
+
this.datums = [];
|
344
|
+
this.trie = newNode();
|
345
|
+
}
|
346
|
+
_.mixin(SearchIndex.prototype, {
|
347
|
+
bootstrap: function bootstrap(o) {
|
348
|
+
this.datums = o.datums;
|
349
|
+
this.trie = o.trie;
|
350
|
+
},
|
351
|
+
add: function(data) {
|
352
|
+
var that = this;
|
353
|
+
data = _.isArray(data) ? data : [ data ];
|
354
|
+
_.each(data, function(datum) {
|
355
|
+
var id, tokens;
|
356
|
+
id = that.datums.push(datum) - 1;
|
357
|
+
tokens = normalizeTokens(that.datumTokenizer(datum));
|
358
|
+
_.each(tokens, function(token) {
|
359
|
+
var node, chars, ch, ids;
|
360
|
+
node = that.trie;
|
361
|
+
chars = token.split("");
|
362
|
+
while (ch = chars.shift()) {
|
363
|
+
node = node.children[ch] || (node.children[ch] = newNode());
|
364
|
+
node.ids.push(id);
|
365
|
+
}
|
366
|
+
});
|
367
|
+
});
|
368
|
+
},
|
369
|
+
get: function get(query) {
|
370
|
+
var that = this, tokens, matches;
|
371
|
+
tokens = normalizeTokens(this.queryTokenizer(query));
|
372
|
+
_.each(tokens, function(token) {
|
373
|
+
var node, chars, ch, ids;
|
374
|
+
if (matches && matches.length === 0) {
|
375
|
+
return false;
|
376
|
+
}
|
377
|
+
node = that.trie;
|
378
|
+
chars = token.split("");
|
379
|
+
while (node && (ch = chars.shift())) {
|
380
|
+
node = node.children[ch];
|
381
|
+
}
|
382
|
+
if (node && chars.length === 0) {
|
383
|
+
ids = node.ids.slice(0);
|
384
|
+
matches = matches ? getIntersection(matches, ids) : ids;
|
385
|
+
} else {
|
386
|
+
matches = [];
|
387
|
+
return false;
|
388
|
+
}
|
389
|
+
});
|
390
|
+
return matches ? _.map(unique(matches), function(id) {
|
391
|
+
return that.datums[id];
|
392
|
+
}) : [];
|
393
|
+
},
|
394
|
+
serialize: function serialize() {
|
395
|
+
return {
|
396
|
+
datums: this.datums,
|
397
|
+
trie: this.trie
|
398
|
+
};
|
399
|
+
}
|
400
|
+
});
|
401
|
+
return SearchIndex;
|
402
|
+
function normalizeTokens(tokens) {
|
403
|
+
tokens = _.filter(tokens, function(token) {
|
404
|
+
return !!token;
|
405
|
+
});
|
406
|
+
tokens = _.map(tokens, function(token) {
|
407
|
+
return token.toLowerCase();
|
408
|
+
});
|
409
|
+
return tokens;
|
410
|
+
}
|
411
|
+
function newNode() {
|
412
|
+
return {
|
413
|
+
ids: [],
|
414
|
+
children: {}
|
415
|
+
};
|
416
|
+
}
|
417
|
+
function unique(array) {
|
418
|
+
var seen = {}, uniques = [];
|
419
|
+
for (var i = 0; i < array.length; i++) {
|
420
|
+
if (!seen[array[i]]) {
|
421
|
+
seen[array[i]] = true;
|
422
|
+
uniques.push(array[i]);
|
423
|
+
}
|
424
|
+
}
|
425
|
+
return uniques;
|
426
|
+
}
|
427
|
+
function getIntersection(arrayA, arrayB) {
|
428
|
+
var ai = 0, bi = 0, intersection = [];
|
429
|
+
arrayA = arrayA.sort(compare);
|
430
|
+
arrayB = arrayB.sort(compare);
|
431
|
+
while (ai < arrayA.length && bi < arrayB.length) {
|
432
|
+
if (arrayA[ai] < arrayB[bi]) {
|
433
|
+
ai++;
|
434
|
+
} else if (arrayA[ai] > arrayB[bi]) {
|
435
|
+
bi++;
|
436
|
+
} else {
|
437
|
+
intersection.push(arrayA[ai]);
|
438
|
+
ai++;
|
439
|
+
bi++;
|
440
|
+
}
|
441
|
+
}
|
442
|
+
return intersection;
|
443
|
+
function compare(a, b) {
|
444
|
+
return a - b;
|
445
|
+
}
|
446
|
+
}
|
447
|
+
}();
|
448
|
+
var oParser = function() {
|
449
|
+
return {
|
450
|
+
local: getLocal,
|
451
|
+
prefetch: getPrefetch,
|
452
|
+
remote: getRemote
|
453
|
+
};
|
454
|
+
function getLocal(o) {
|
455
|
+
var local = o.local || null;
|
456
|
+
if (_.isFunction(local)) {
|
457
|
+
local = local.call(null);
|
458
|
+
}
|
459
|
+
return local;
|
460
|
+
}
|
461
|
+
function getPrefetch(o) {
|
462
|
+
var prefetch, defaults;
|
463
|
+
defaults = {
|
464
|
+
url: null,
|
465
|
+
thumbprint: "",
|
466
|
+
ttl: 24 * 60 * 60 * 1e3,
|
467
|
+
filter: null,
|
468
|
+
ajax: {}
|
469
|
+
};
|
470
|
+
if (prefetch = o.prefetch || null) {
|
471
|
+
prefetch = _.isString(prefetch) ? {
|
472
|
+
url: prefetch
|
473
|
+
} : prefetch;
|
474
|
+
prefetch = _.mixin(defaults, prefetch);
|
475
|
+
prefetch.thumbprint = VERSION + prefetch.thumbprint;
|
476
|
+
prefetch.ajax.type = prefetch.ajax.type || "GET";
|
477
|
+
prefetch.ajax.dataType = prefetch.ajax.dataType || "json";
|
478
|
+
!prefetch.url && $.error("prefetch requires url to be set");
|
479
|
+
}
|
480
|
+
return prefetch;
|
481
|
+
}
|
482
|
+
function getRemote(o) {
|
483
|
+
var remote, defaults;
|
484
|
+
defaults = {
|
485
|
+
url: null,
|
486
|
+
wildcard: "%QUERY",
|
487
|
+
replace: null,
|
488
|
+
rateLimitBy: "debounce",
|
489
|
+
rateLimitWait: 300,
|
490
|
+
send: null,
|
491
|
+
filter: null,
|
492
|
+
ajax: {}
|
493
|
+
};
|
494
|
+
if (remote = o.remote || null) {
|
495
|
+
remote = _.isString(remote) ? {
|
496
|
+
url: remote
|
497
|
+
} : remote;
|
498
|
+
remote = _.mixin(defaults, remote);
|
499
|
+
remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);
|
500
|
+
remote.ajax.type = remote.ajax.type || "GET";
|
501
|
+
remote.ajax.dataType = remote.ajax.dataType || "json";
|
502
|
+
delete remote.rateLimitBy;
|
503
|
+
delete remote.rateLimitWait;
|
504
|
+
!remote.url && $.error("remote requires url to be set");
|
505
|
+
}
|
506
|
+
return remote;
|
507
|
+
function byDebounce(wait) {
|
508
|
+
return function(fn) {
|
509
|
+
return _.debounce(fn, wait);
|
510
|
+
};
|
511
|
+
}
|
512
|
+
function byThrottle(wait) {
|
513
|
+
return function(fn) {
|
514
|
+
return _.throttle(fn, wait);
|
515
|
+
};
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}();
|
519
|
+
var Bloodhound = window.Bloodhound = function() {
|
520
|
+
var keys;
|
521
|
+
keys = {
|
522
|
+
data: "data",
|
523
|
+
protocol: "protocol",
|
524
|
+
thumbprint: "thumbprint"
|
525
|
+
};
|
526
|
+
function Bloodhound(o) {
|
527
|
+
if (!o || !o.local && !o.prefetch && !o.remote) {
|
528
|
+
$.error("one of local, prefetch, or remote is required");
|
529
|
+
}
|
530
|
+
this.limit = o.limit || 5;
|
531
|
+
this.sorter = getSorter(o.sorter);
|
532
|
+
this.dupDetector = o.dupDetector || ignoreDuplicates;
|
533
|
+
this.local = oParser.local(o);
|
534
|
+
this.prefetch = oParser.prefetch(o);
|
535
|
+
this.remote = oParser.remote(o);
|
536
|
+
this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;
|
537
|
+
this.index = new SearchIndex({
|
538
|
+
datumTokenizer: o.datumTokenizer,
|
539
|
+
queryTokenizer: o.queryTokenizer
|
540
|
+
});
|
541
|
+
this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;
|
542
|
+
}
|
543
|
+
Bloodhound.tokenizers = {
|
544
|
+
whitespace: function whitespaceTokenizer(s) {
|
545
|
+
return s.split(/\s+/);
|
546
|
+
},
|
547
|
+
nonword: function nonwordTokenizer(s) {
|
548
|
+
return s.split(/\W+/);
|
549
|
+
}
|
550
|
+
};
|
551
|
+
_.mixin(Bloodhound.prototype, {
|
552
|
+
_loadPrefetch: function loadPrefetch(o) {
|
553
|
+
var that = this, serialized, deferred;
|
554
|
+
if (serialized = this._readFromStorage(o.thumbprint)) {
|
555
|
+
this.index.bootstrap(serialized);
|
556
|
+
deferred = $.Deferred().resolve();
|
557
|
+
} else {
|
558
|
+
deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);
|
559
|
+
}
|
560
|
+
return deferred;
|
561
|
+
function handlePrefetchResponse(resp) {
|
562
|
+
var filtered;
|
563
|
+
filtered = o.filter ? o.filter(resp) : resp;
|
564
|
+
that.add(filtered);
|
565
|
+
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);
|
566
|
+
}
|
567
|
+
},
|
568
|
+
_getFromRemote: function getFromRemote(query, cb) {
|
569
|
+
var that = this, url, uriEncodedQuery;
|
570
|
+
query = query || "";
|
571
|
+
uriEncodedQuery = encodeURIComponent(query);
|
572
|
+
url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
|
573
|
+
return this.transport.get(url, this.remote.ajax, handleRemoteResponse);
|
574
|
+
function handleRemoteResponse(resp) {
|
575
|
+
var filtered = that.remote.filter ? that.remote.filter(resp) : resp;
|
576
|
+
cb(filtered);
|
577
|
+
}
|
578
|
+
},
|
579
|
+
_saveToStorage: function saveToStorage(data, thumbprint, ttl) {
|
580
|
+
if (this.storage) {
|
581
|
+
this.storage.set(keys.data, data, ttl);
|
582
|
+
this.storage.set(keys.protocol, location.protocol, ttl);
|
583
|
+
this.storage.set(keys.thumbprint, thumbprint, ttl);
|
584
|
+
}
|
585
|
+
},
|
586
|
+
_readFromStorage: function readFromStorage(thumbprint) {
|
587
|
+
var stored = {}, isExpired;
|
588
|
+
if (this.storage) {
|
589
|
+
stored.data = this.storage.get(keys.data);
|
590
|
+
stored.protocol = this.storage.get(keys.protocol);
|
591
|
+
stored.thumbprint = this.storage.get(keys.thumbprint);
|
592
|
+
}
|
593
|
+
isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;
|
594
|
+
return stored.data && !isExpired ? stored.data : null;
|
595
|
+
},
|
596
|
+
initialize: function initialize() {
|
597
|
+
var that = this, deferred;
|
598
|
+
deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();
|
599
|
+
this.local && deferred.done(addLocalToIndex);
|
600
|
+
this.transport = this.remote ? new Transport(this.remote) : null;
|
601
|
+
this.initialize = function initialize() {
|
602
|
+
return deferred.promise();
|
603
|
+
};
|
604
|
+
return deferred.promise();
|
605
|
+
function addLocalToIndex() {
|
606
|
+
that.add(that.local);
|
607
|
+
}
|
608
|
+
},
|
609
|
+
add: function add(data) {
|
610
|
+
this.index.add(data);
|
611
|
+
},
|
612
|
+
get: function get(query, cb) {
|
613
|
+
var that = this, matches, cacheHit = false;
|
614
|
+
matches = this.index.get(query);
|
615
|
+
matches = this.sorter(matches).slice(0, this.limit);
|
616
|
+
if (matches.length < this.limit && this.transport) {
|
617
|
+
cacheHit = this._getFromRemote(query, returnRemoteMatches);
|
618
|
+
}
|
619
|
+
!cacheHit && cb && cb(matches);
|
620
|
+
function returnRemoteMatches(remoteMatches) {
|
621
|
+
var matchesWithBackfill = matches.slice(0);
|
622
|
+
_.each(remoteMatches, function(remoteMatch) {
|
623
|
+
var isDuplicate;
|
624
|
+
isDuplicate = _.some(matchesWithBackfill, function(match) {
|
625
|
+
return that.dupDetector(remoteMatch, match);
|
626
|
+
});
|
627
|
+
!isDuplicate && matchesWithBackfill.push(remoteMatch);
|
628
|
+
return matchesWithBackfill.length < that.limit;
|
629
|
+
});
|
630
|
+
cb && cb(that.sorter(matchesWithBackfill));
|
631
|
+
}
|
632
|
+
},
|
633
|
+
ttAdapter: function ttAdapter() {
|
634
|
+
return _.bind(this.get, this);
|
635
|
+
}
|
636
|
+
});
|
637
|
+
return Bloodhound;
|
638
|
+
function getSorter(sortFn) {
|
639
|
+
return _.isFunction(sortFn) ? sort : noSort;
|
640
|
+
function sort(array) {
|
641
|
+
return array.sort(sortFn);
|
642
|
+
}
|
643
|
+
function noSort(array) {
|
644
|
+
return array;
|
645
|
+
}
|
646
|
+
}
|
647
|
+
function ignoreDuplicates() {
|
648
|
+
return false;
|
649
|
+
}
|
650
|
+
}();
|
651
|
+
})(window.jQuery);
|