algoliasearch-rails 1.11.17 → 1.11.18
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 +4 -0
- data/README.md +48 -6
- data/VERSION +1 -1
- data/algoliasearch-rails.gemspec +22 -6
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.min.js +2 -2
- data/vendor/assets/javascripts/algolia/bloodhound.min.js +7 -0
- data/vendor/assets/javascripts/algolia/typeahead.jquery.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.js +2667 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.js +2667 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.js +2653 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.js +1717 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.min.js +37 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.js +1702 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.min.js +37 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.js +2732 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.min.js +50 -0
- metadata +36 -22
@@ -0,0 +1,37 @@
|
|
1
|
+
/*! algoliasearch 3.0.3 | © 2014, 2015 Algolia SAS | github.com/algolia/algoliasearch-client-js */
|
2
|
+
(function(m){var l;"undefined"!==typeof window?l=window:"undefined"!==typeof self&&(l=self);l.ALGOLIA_MIGRATION_LAYER=m()})(function(){return function l(n,k,e){function h(a,c){if(!k[a]){if(!n[a]){var d="function"==typeof require&&require;if(!c&&d)return d(a,!0);if(g)return g(a,!0);d=Error("Cannot find module '"+a+"'");throw d.code="MODULE_NOT_FOUND",d;}d=k[a]={exports:{}};n[a][0].call(d.exports,function(c){var d=n[a][1][c];return h(d?d:c)},d,d.exports,l,n,k,e)}return k[a].exports}for(var g="function"==
|
3
|
+
typeof require&&require,a=0;a<e.length;a++)h(e[a]);return h}({1:[function(l,n,k){function e(a,b){for(var c in b)a.setAttribute(c,b[c])}function h(a,b){a.onload=function(){this.onerror=this.onload=null;b(null,a)};a.onerror=function(){this.onerror=this.onload=null;b(Error("Failed to load "+this.src),a)}}function g(a,b){a.onreadystatechange=function(){if("complete"==this.readyState||"loaded"==this.readyState)this.onreadystatechange=null,b(null,a)}}n.exports=function(a,b,c){var d=document.head||document.getElementsByTagName("head")[0],
|
4
|
+
f=document.createElement("script");"function"===typeof b&&(c=b,b={});b=b||{};c=c||function(){};f.type=b.type||"text/javascript";f.charset=b.charset||"utf8";f.async="async"in b?!!b.async:!0;f.src=a;b.attrs&&e(f,b.attrs);b.text&&(f.text=""+b.text);("onload"in f?h:g)(f,c);f.onload||h(f,c);d.appendChild(f)}},{}],2:[function(l,n,k){n.exports=function(e){e=new RegExp("cdn\\.jsdelivr\\.net/algoliasearch/latest/"+e.replace(".","\\.")+"(?:\\.min)?\\.js$");for(var h=document.getElementsByTagName("script"),
|
5
|
+
g=!1,a=0,b=h.length;a<b;a++)if(h[a].src&&e.test(h[a].src)){g=!0;break}return g}},{}],3:[function(l,n,k){(function(e){function h(h){return function(){var a="AlgoliaSearch: loaded V2 script using "+h;e.console&&e.console.log&&e.console.log(a)}}n.exports=function(g){var a=l(1);g="//cdn.jsdelivr.net/algoliasearch/2/"+g+".min.js";e.console&&(e.console.warn?e.console.warn("-- AlgoliaSearch `latest` warning --\nWarning, you are using the `latest` version string from jsDelivr to load the AlgoliaSearch library.\nUsing `latest` is no more recommended, you should load //cdn.jsdelivr.net/algoliasearch/2/algoliasearch.min.js\n\nAlso, we updated the AlgoliaSearch JavaScript client to V3. If you want to upgrade,\nplease read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n-- /AlgoliaSearch `latest` warning --"):
|
6
|
+
e.console.log&&e.console.log("-- AlgoliaSearch `latest` warning --\nWarning, you are using the `latest` version string from jsDelivr to load the AlgoliaSearch library.\nUsing `latest` is no more recommended, you should load //cdn.jsdelivr.net/algoliasearch/2/algoliasearch.min.js\n\nAlso, we updated the AlgoliaSearch JavaScript client to V3. If you want to upgrade,\nplease read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n-- /AlgoliaSearch `latest` warning --"));
|
7
|
+
try{document.write("<script>window.ALGOLIA_SUPPORTS_DOCWRITE = true\x3c/script>"),!0===e.ALGOLIA_SUPPORTS_DOCWRITE?(document.write('<script src="'+g+'">\x3c/script>'),h("document.write")()):a(g,h("DOMElement"))}catch(b){a(g,h("DOMElement"))}}}).call(this,"undefined"!==typeof global?global:"undefined"!==typeof self?self:"undefined"!==typeof window?window:{})},{1:1}],4:[function(l,n,k){(function(e){n.exports=function(){e.AlgoliaSearch=function(){throw Error("-- AlgoliaSearch V2 => V3 error --\nYou are trying to use a new version of the AlgoliaSearch JavaScript client with an old notation.\nPlease read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n-- /AlgoliaSearch V2 => V3 error --");
|
8
|
+
};e.AlgoliaSearchHelper=function(){throw Error("-- AlgoliaSearch V2 => V3 error --\nYou are trying to use a new version of the AlgoliaSearch JavaScript client with an old notation.\nPlease read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n-- /AlgoliaSearch V2 => V3 error --");};AlgoliaExplainResults=function(){throw Error("-- AlgoliaSearch V2 => V3 error --\nYou are trying to use a new version of the AlgoliaSearch JavaScript client with an old notation.\nPlease read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n-- /AlgoliaSearch V2 => V3 error --");
|
9
|
+
}}}).call(this,"undefined"!==typeof global?global:"undefined"!==typeof self?self:"undefined"!==typeof window?window:{})},{}],5:[function(l,n,k){n=l(2);k=l(3);l=l(4);n("algoliasearch.jquery")?k("algoliasearch.jquery"):l()},{2:2,3:3,4:4}]},{},[5])(5)});
|
10
|
+
(function e$$0(l,n,k){function e(a,b){if(!n[a]){if(!l[a]){var c="function"==typeof require&&require;if(!b&&c)return c(a,!0);if(h)return h(a,!0);c=Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c;}c=n[a]={exports:{}};l[a][0].call(c.exports,function(b){var c=l[a][1][b];return e(c?c:b)},c,c.exports,e$$0,l,n,k)}return n[a].exports}for(var h="function"==typeof require&&require,g=0;g<k.length;g++)e(k[g]);return e})({1:[function(m,l,n){function k(){if(!g){g=!0;for(var a,b=h.length;b;){a=
|
11
|
+
h;h=[];for(var c=-1;++c<b;)a[c]();b=h.length}g=!1}}function e(){}m=l.exports={};var h=[],g=!1;m.nextTick=function(a){h.push(a);g||setTimeout(k,0)};m.title="browser";m.browser=!0;m.env={};m.argv=[];m.version="";m.versions={};m.on=e;m.addListener=e;m.once=e;m.off=e;m.removeListener=e;m.removeAllListeners=e;m.emit=e;m.binding=function(a){throw Error("process.binding is not supported");};m.cwd=function(){return"/"};m.chdir=function(a){throw Error("process.chdir is not supported");};m.umask=function(){return 0}},
|
12
|
+
{}],2:[function(m,l,n){(function(k){function e(a,b,c,d){if(!a)throw Error("Please provide an application ID. Usage: algoliasearch(applicationID, apiKey, opts)");if(!b)throw Error("Please provide an API key. Usage: algoliasearch(applicationID, apiKey, opts)");c=c||{};void 0===c.timeout&&(c.timeout=2E3);void 0===c.protocol&&(c.protocol=document&&document.location.protocol||"http:");void 0===c.hosts&&(c.hosts=[]);void 0===c.tld&&(c.tld="net");/:$/.test(c.protocol)||(c.protocol+=":");0===c.hosts.length&&
|
13
|
+
(c.hosts=g([a+"-1.algolia."+c.tld,a+"-2.algolia."+c.tld,a+"-3.algolia."+c.tld]),c.hosts.unshift(a+"-dsn.algolia."+c.tld));c.hosts=h(c.hosts,function(a){return c.protocol+"//"+a});this.applicationID=a;this.apiKey=b;this.hosts=c.hosts;this.currentHostIndex=0;this.requestTimeout=c.timeout;this.extraHeaders=[];this.cache={};this._request=d}function h(a,b){for(var c=[],d=0;d<a.length;++d)c.push(b(a[d],d));return c}function g(a){for(var b=a.length,c,d;0!==b;)d=Math.floor(Math.random()*b),--b,c=a[b],a[b]=
|
14
|
+
a[d],a[d]=c;return a}l.exports=e;e.prototype={deleteIndex:function(a,b){return this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){b={operation:"move",destination:b};return this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:b,callback:c})},copyIndex:function(a,b,c){b={operation:"copy",destination:b};return this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:b,
|
15
|
+
callback:c})},getLogs:function(a,b,c){if(0===arguments.length||"function"===typeof a)c=a,a=0,b=10;else if(1===arguments.length||"function"===typeof b)c=b,b=10;return this._jsonRequest({method:"GET",url:"/1/logs?offset="+a+"&length="+b,callback:c})},listIndexes:function(a,b){var c="";void 0===a||"function"===typeof a?b=a:c="?page="+a;return this._jsonRequest({method:"GET",url:"/1/indexes"+c,callback:b})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){return this._jsonRequest({method:"GET",
|
16
|
+
url:"/1/keys",callback:a})},getUserKeyACL:function(a,b){return this._jsonRequest({method:"GET",url:"/1/keys/"+a,callback:b})},deleteUserKey:function(a,b){return this._jsonRequest({method:"DELETE",url:"/1/keys/"+a,callback:b})},addUserKey:function(a,b){return this.addUserKeyWithValidity(a,{validity:0,maxQueriesPerIPPerHour:0,maxHitsPerQuery:0},b)},addUserKeyWithValidity:function(a,b,c){var d={};d.acl=a;d.validity=b.validity;d.maxQueriesPerIPPerHour=b.maxQueriesPerIPPerHour;d.maxHitsPerQuery=b.maxHitsPerQuery;
|
17
|
+
return this._jsonRequest({method:"POST",url:"/1/keys",body:d,callback:c})},setSecurityTags:function(a){if("[object Array]"===Object.prototype.toString.call(a)){for(var b=[],c=0;c<a.length;++c)if("[object Array]"===Object.prototype.toString.call(a[c])){for(var d=[],f=0;f<a[c].length;++f)d.push(a[c][f]);b.push("("+d.join(",")+")")}else b.push(a[c]);a=b.join(",")}this.tagFilters=a},setUserToken:function(a){this.userToken=a},startQueriesBatch:function(){this.batch=[]},addQueryInBatch:function(a,b,c){b=
|
18
|
+
"query="+encodeURIComponent(b);this._isUndefined(c)||null===c||(b=this._getSearchParams(c,b));this.batch.push({indexName:a,params:b})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a){for(var b={requests:[]},c=0;c<this.batch.length;++c)b.requests.push(this.batch[c]);return this._sendQueriesBatch(b,a)},setRequestTimeout:function(a){a&&(this.requestTimeout=parseInt(a,10))},Index:function(a,b){this.indexName=b;this.as=a;this.typeAheadValueOption=this.typeAheadArgs=null;this.cache={}},
|
19
|
+
setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){return this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,fallback:{method:"GET",url:"/1/indexes/*",body:{params:function(){for(var b="",d=0;d<a.requests.length;++d)var f="/1/indexes/"+encodeURIComponent(a.requests[d].indexName)+"?"+a.requests[d].params,b=b+(d+"="+encodeURIComponent(f)+"&");return b}()}},callback:b})},_jsonRequest:function(a){function b(h,g){function l(){f.currentHostIndex=
|
20
|
+
++f.currentHostIndex%f.hosts.length;e+=1;g.timeout=f.requestTimeout*(e+1);return b(h,g)}if(c&&void 0!==c[d])return f._request.resolve(c[d]);if(e>=f.hosts.length){if(!a.fallback||h===f._request.fallback)return f._request.reject(Error("Cannot connect to the AlgoliaSearch API. Send an email to support@algolia.com to report and resolve the issue."));e=0;g.method=a.fallback.method;g.url=a.fallback.url;g.body=a.fallback.body;g.timeout=f.requestTimeout*(e+1);f.currentHostIndex=0;f.forceFallback=!0;return b(f._request.fallback,
|
21
|
+
g)}var k=g.url,k=k+((-1===k.indexOf("?")?"?":"&")+"X-Algolia-API-Key="+f.apiKey),k=k+("&X-Algolia-Application-Id="+f.applicationID);f.userToken&&(k+="&X-Algolia-UserToken="+encodeURIComponent(f.userToken));f.tagFilters&&(k+="&X-Algolia-TagFilters="+encodeURIComponent(f.tagFilters));for(var m=0;m<f.extraHeaders.length;++m)k+="&"+f.extraHeaders[m].key+"="+f.extraHeaders[m].value;return h(f.hosts[f.currentHostIndex]+k,{body:g.body,method:g.method,timeout:g.timeout}).then(function(a){if(a instanceof Error)return l();
|
22
|
+
var b=a&&a.body&&a.body.message&&a.body.status||a.statusCode||a&&a.body&&200,e=200===b||201===b,b=!e&&4!==Math.floor(b/100)&&1!==Math.floor(b/100);e&&c&&(c[d]=a.body);return e?a.body:b?l():f._request.reject(Error(a.body&&a.body.message||"Unknown error"))},function(){f.forceFallback?(f.currentHostIndex=++f.currentHostIndex%f.hosts.length,e+=1):e=f.hosts.length;return b(h,g)})}var c=a.cache,d=a.url,f=this,e=0;void 0!==a.body&&(d+="_body_"+JSON.stringify(a.body));var h=f.forceFallback&&a.fallback,g=
|
23
|
+
h?a.fallback:a,h=b(h?f._request.fallback:f._request,{url:g.url,method:g.method,body:g.body,timeout:f.requestTimeout*(e+1)});if(a.callback)h.then(function(b){k.nextTick(function(){a.callback(null,b)})},function(b){k.nextTick(function(){a.callback(b)})});else return h},_getSearchParams:function(a,b){if(this._isUndefined(a)||null===a)return b;for(var c in a)null!==c&&a.hasOwnProperty(c)&&(b+=""===b?"":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):
|
24
|
+
a[c]));return b},_isUndefined:function(a){return void 0===a}};e.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){if(1===arguments.length||"function"===typeof b)c=b,b=void 0;return this.as._jsonRequest({method:void 0!==b?"PUT":"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+(void 0!==b?"/"+encodeURIComponent(b):""),body:a,callback:c})},addObjects:function(a,b){for(var c={requests:[]},d=0;d<a.length;++d)c.requests.push({action:"addObject",body:a[d]});
|
25
|
+
return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/batch",body:c,callback:b})},getObject:function(a,b,c){if(1===arguments.length||"function"===typeof b)c=b,b=void 0;var d="";if(void 0!==b)for(var d="?attributes=",f=0;f<b.length;++f)0!==f&&(d+=","),d+=b[f];return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/"+encodeURIComponent(a)+d,callback:c})},partialUpdateObject:function(a,b){return this.as._jsonRequest({method:"POST",
|
26
|
+
url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c={requests:[]},d=0;d<a.length;++d)c.requests.push({action:"partialUpdateObject",objectID:a[d].objectID,body:a[d]});return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/batch",body:c,callback:b})},saveObject:function(a,b){return this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(this.indexName)+
|
27
|
+
"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c={requests:[]},d=0;d<a.length;++d)c.requests.push({action:"updateObject",objectID:a[d].objectID,body:a[d]});return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/batch",body:c,callback:b})},deleteObject:function(a,b){if("function"===typeof a||"string"!==typeof a&&"number"!==typeof a){var c=Error("Cannot delete an object without an objectID");b=a;return"function"===
|
28
|
+
typeof b?b(c):this.as._request.reject(c)}return this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c){if(0===arguments.length||"function"===typeof a)c=a,a="";else if(1===arguments.length||"function"===typeof b)c=b,b=void 0;if("object"===typeof a&&null!==a)b=a,a=void 0;else if(void 0===a||null===a)a="";var d="";void 0!==a&&(d+="query="+encodeURIComponent(a));void 0!==b&&(d=this.as._getSearchParams(b,
|
29
|
+
d));return this._search(d,c)},browse:function(a,b,c){if(1===arguments.length||"function"===typeof b)c=b,b=void 0;var d="?page="+a;this.as._isUndefined(b)||(d+="&hitsPerPage="+b);return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/browse"+d,callback:c})},ttAdapter:function(a){var b=this;return function(c,d){b.search(c,a,function(a,b){a?d(a):d(b.hits)})}},waitTask:function(a,b){var c=this,d=this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+
|
30
|
+
"/task/"+a}).then(function(d){if("published"!==d.status)return(new c.as._request.delay(100)).then(function(){return c.waitTask(a,b)});if(b)k.nextTick(function(){b(null,d)});else return d},function(a){if(b)k.nextTick(function(){b(a)});else return a});if(!b)return d},clearIndex:function(a){return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/clear",callback:a})},getSettings:function(a){return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName)+
|
31
|
+
"/settings",callback:a})},setSettings:function(a,b){return this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){return this.as._jsonRequest({method:"DELETE",
|
32
|
+
url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c={};c.acl=a;return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys",body:c,callback:b})},addUserKeyWithValidity:function(a,b,c){var d={};d.acl=a;d.validity=b.validity;d.maxQueriesPerIPPerHour=b.maxQueriesPerIPPerHour;d.maxHitsPerQuery=b.maxHitsPerQuery;return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+
|
33
|
+
"/keys",body:d,callback:c})},_search:function(a,b){return this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:{params:a},fallback:{method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName),body:{params:a}},callback:b})},as:null,indexName:null,typeAheadArgs:null,typeAheadValueOption:null}}).call(this,m(1))},{1:1}],3:[function(m,l,n){(function(k){function e(b,c){return a.Deferred(function(d){var e=null;void 0!==c.body&&(e=JSON.stringify(c.body));
|
34
|
+
a.ajax(b,{type:c.method,timeout:c.timeout,dataType:"json",data:e,complete:function(a,c){"timeout"===c?d.resolve(Error("Timeout - Could not connect to endpoint "+b)):0===a.status?d.reject(Error("Network error")):d.resolve({statusCode:a.status,body:a.responseJSON})}})}).promise()}var h=m(5),g=m(4),h=h(e),a=k.jQuery;a.algolia={Client:h};e.fallback=function(b,c){return a.Deferred(function(a){g(b,c,function(b,c){b?a.reject(b):a.resolve(c)})}).promise()};e.reject=function(b){return a.Deferred(function(a){a.reject(b)}).promise()};
|
35
|
+
e.resolve=function(b){return a.Deferred(function(a){a.resolve(b)}).promise()};e.delay=function(b){return a.Deferred(function(a){setTimeout(function(){a.resolve()},b)}).promise()}}).call(this,"undefined"!==typeof global?global:"undefined"!==typeof self?self:"undefined"!==typeof window?window:{})},{4:4,5:5}],4:[function(m,l,n){l.exports=function(e,h,g){function a(){r||l||(r=!0,m||(c(),g(Error("Failed to load JSONP script"))))}function b(){"loaded"!==this.readyState&&"complete"!==this.readyState||a()}
|
36
|
+
function c(){clearTimeout(t);p.onload=null;p.onreadystatechange=null;p.onerror=null;n.removeChild(p);try{delete window[q],delete window[q+"_loaded"]}catch(a){window[q]=null,window[q+"_loaded"]=null}}function d(){l=!0;c();g(Error("Timeout - Could not connect to endpoint "+e))}function f(){r||l||(c(),g(Error("Failed to load JSONP script")))}if("GET"!==h.method)g(Error("Method "+h.method+" "+e+" is not supported by JSONP."));else{var m=!1,l=!1;k+=1;var n=document.getElementsByTagName("head")[0],p=document.createElement("script"),
|
37
|
+
q="algoliaJSONP_"+k,r=!1;window[q]=function(a){try{delete window[q]}catch(b){window[q]=void 0}l||(m=!0,c(),g(null,{body:a}))};e+="&callback="+q;h.body&&h.body.params&&(e+="&"+h.body.params);var t=setTimeout(d,h.timeout);p.onreadystatechange=b;p.onload=a;p.onerror=f;p.async=!0;p.defer=!0;p.src=e;n.appendChild(p)}};var k=0},{}],5:[function(m,l,n){l.exports=function(k){function e(e,g,a){return new (m(2))(e,g,a,k)}e.version="3.0.3";return e}},{2:2}]},{},[3]);
|
@@ -0,0 +1,2732 @@
|
|
1
|
+
/*! algoliasearch 3.0.3 | © 2014, 2015 Algolia SAS | github.com/algolia/algoliasearch-client-js */
|
2
|
+
(function(f){var g;if(typeof window!=='undefined'){g=window}else if(typeof self!=='undefined'){g=self}g.ALGOLIA_MIGRATION_LAYER=f()})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
3
|
+
|
4
|
+
module.exports = function load (src, opts, cb) {
|
5
|
+
var head = document.head || document.getElementsByTagName('head')[0]
|
6
|
+
var script = document.createElement('script')
|
7
|
+
|
8
|
+
if (typeof opts === 'function') {
|
9
|
+
cb = opts
|
10
|
+
opts = {}
|
11
|
+
}
|
12
|
+
|
13
|
+
opts = opts || {}
|
14
|
+
cb = cb || function() {}
|
15
|
+
|
16
|
+
script.type = opts.type || 'text/javascript'
|
17
|
+
script.charset = opts.charset || 'utf8';
|
18
|
+
script.async = 'async' in opts ? !!opts.async : true
|
19
|
+
script.src = src
|
20
|
+
|
21
|
+
if (opts.attrs) {
|
22
|
+
setAttributes(script, opts.attrs)
|
23
|
+
}
|
24
|
+
|
25
|
+
if (opts.text) {
|
26
|
+
script.text = '' + opts.text
|
27
|
+
}
|
28
|
+
|
29
|
+
var onend = 'onload' in script ? stdOnEnd : ieOnEnd
|
30
|
+
onend(script, cb)
|
31
|
+
|
32
|
+
// some good legacy browsers (firefox) fail the 'in' detection above
|
33
|
+
// so as a fallback we always set onload
|
34
|
+
// old IE will ignore this and new IE will set onload
|
35
|
+
if (!script.onload) {
|
36
|
+
stdOnEnd(script, cb);
|
37
|
+
}
|
38
|
+
|
39
|
+
head.appendChild(script)
|
40
|
+
}
|
41
|
+
|
42
|
+
function setAttributes(script, attrs) {
|
43
|
+
for (var attr in attrs) {
|
44
|
+
script.setAttribute(attr, attrs[attr]);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
function stdOnEnd (script, cb) {
|
49
|
+
script.onload = function () {
|
50
|
+
this.onerror = this.onload = null
|
51
|
+
cb(null, script)
|
52
|
+
}
|
53
|
+
script.onerror = function () {
|
54
|
+
// this.onload = null here is necessary
|
55
|
+
// because even IE9 works not like others
|
56
|
+
this.onerror = this.onload = null
|
57
|
+
cb(new Error('Failed to load ' + this.src), script)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
function ieOnEnd (script, cb) {
|
62
|
+
script.onreadystatechange = function () {
|
63
|
+
if (this.readyState != 'complete' && this.readyState != 'loaded') return
|
64
|
+
this.onreadystatechange = null
|
65
|
+
cb(null, script) // there is no way to catch loading errors in IE8
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
},{}],2:[function(require,module,exports){
|
70
|
+
// this module helps finding if the current page is using
|
71
|
+
// the cdn.jsdelivr.net/algoliasearch/latest/$BUILDNAME.min.js version
|
72
|
+
|
73
|
+
module.exports = isUsingLatest;
|
74
|
+
|
75
|
+
function isUsingLatest(buildName) {
|
76
|
+
var toFind = new RegExp('cdn\\.jsdelivr\\.net/algoliasearch/latest/' +
|
77
|
+
buildName.replace('.', '\\.') + // algoliasearch, algoliasearch.angular
|
78
|
+
'(?:\\.min)?\\.js$'); // [.min].js
|
79
|
+
|
80
|
+
var scripts = document.getElementsByTagName('script');
|
81
|
+
var found = false;
|
82
|
+
for (var currentScript = 0, nbScripts = scripts.length;
|
83
|
+
currentScript < nbScripts;
|
84
|
+
currentScript++) {
|
85
|
+
if (scripts[currentScript].src && toFind.test(scripts[currentScript].src)) {
|
86
|
+
found = true;
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
return found;
|
92
|
+
}
|
93
|
+
|
94
|
+
},{}],3:[function(require,module,exports){
|
95
|
+
(function (global){
|
96
|
+
module.exports = loadV2;
|
97
|
+
|
98
|
+
function loadV2(buildName) {
|
99
|
+
var loadScript = require(1);
|
100
|
+
var v2ScriptUrl = '//cdn.jsdelivr.net/algoliasearch/2/' + buildName + '.min.js';
|
101
|
+
|
102
|
+
var message =
|
103
|
+
'-- AlgoliaSearch `latest` warning --\n' +
|
104
|
+
'Warning, you are using the `latest` version string from jsDelivr to load the AlgoliaSearch library.\n' +
|
105
|
+
'Using `latest` is no more recommended, you should load //cdn.jsdelivr.net/algoliasearch/2/algoliasearch.min.js\n\n' +
|
106
|
+
'Also, we updated the AlgoliaSearch JavaScript client to V3. If you want to upgrade,\n' +
|
107
|
+
'please read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n' +
|
108
|
+
'-- /AlgoliaSearch `latest` warning --';
|
109
|
+
|
110
|
+
if (global.console) {
|
111
|
+
if (global.console.warn) {
|
112
|
+
global.console.warn(message);
|
113
|
+
} else if (global.console.log) {
|
114
|
+
global.console.log(message);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
// If current script loaded asynchronously,
|
119
|
+
// it will load the script with DOMElement
|
120
|
+
// otherwise, it will load the script with document.write
|
121
|
+
try {
|
122
|
+
// why \x3c? http://stackoverflow.com/a/236106/147079
|
123
|
+
document.write('\x3Cscript>window.ALGOLIA_SUPPORTS_DOCWRITE = true\x3C/script>');
|
124
|
+
|
125
|
+
if (global.ALGOLIA_SUPPORTS_DOCWRITE === true) {
|
126
|
+
document.write('\x3Cscript src="' + v2ScriptUrl + '">\x3C/script>');
|
127
|
+
scriptLoaded('document.write')();
|
128
|
+
} else {
|
129
|
+
loadScript(v2ScriptUrl, scriptLoaded('DOMElement'));
|
130
|
+
}
|
131
|
+
} catch(e) {
|
132
|
+
loadScript(v2ScriptUrl, scriptLoaded('DOMElement'));
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
function scriptLoaded(method) {
|
137
|
+
return function log() {
|
138
|
+
var message = 'AlgoliaSearch: loaded V2 script using ' + method;
|
139
|
+
|
140
|
+
global.console && global.console.log && global.console.log(message);
|
141
|
+
};
|
142
|
+
}
|
143
|
+
|
144
|
+
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
145
|
+
},{"1":1}],4:[function(require,module,exports){
|
146
|
+
(function (global){
|
147
|
+
/*global AlgoliaExplainResults:true*/
|
148
|
+
/*eslint no-unused-vars: [2, {"vars": "local"}]*/
|
149
|
+
|
150
|
+
module.exports = oldGlobals;
|
151
|
+
|
152
|
+
// put old window.AlgoliaSearch.. into window. again so that
|
153
|
+
// users upgrading to V3 without changing their code, will be warned
|
154
|
+
function oldGlobals() {
|
155
|
+
var message =
|
156
|
+
'-- AlgoliaSearch V2 => V3 error --\n' +
|
157
|
+
'You are trying to use a new version of the AlgoliaSearch JavaScript client with an old notation.\n' +
|
158
|
+
'Please read our migration guide at https://github.com/algolia/algoliasearch-client-js/wiki/Migration-guide-from-2.x.x-to-3.x.x\n' +
|
159
|
+
'-- /AlgoliaSearch V2 => V3 error --';
|
160
|
+
|
161
|
+
global.AlgoliaSearch = function() {
|
162
|
+
throw new Error(message);
|
163
|
+
};
|
164
|
+
|
165
|
+
global.AlgoliaSearchHelper = function() {
|
166
|
+
throw new Error(message);
|
167
|
+
};
|
168
|
+
|
169
|
+
// cannot use window.AlgoliaExplainResults on old IEs, dunno why
|
170
|
+
AlgoliaExplainResults = function() {
|
171
|
+
throw new Error(message);
|
172
|
+
};
|
173
|
+
}
|
174
|
+
|
175
|
+
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
176
|
+
},{}],5:[function(require,module,exports){
|
177
|
+
// This script will be browserified and prepended to the normal build
|
178
|
+
// directly in window, not wrapped in any module definition
|
179
|
+
// To avoid cases where we are loaded with /latest/ along with
|
180
|
+
migrationLayer("algoliasearch");
|
181
|
+
|
182
|
+
// Now onto the V2 related code:
|
183
|
+
// If the client is using /latest/$BUILDNAME.min.js, load V2 of the library
|
184
|
+
//
|
185
|
+
// Otherwise, setup a migration layer that will throw on old constructors like
|
186
|
+
// new AlgoliaSearch().
|
187
|
+
// So that users upgrading from v2 to v3 will have a clear information
|
188
|
+
// message on what to do if they did not read the migration guide
|
189
|
+
function migrationLayer(buildName) {
|
190
|
+
var isUsingLatest = require(2);
|
191
|
+
var loadV2 = require(3);
|
192
|
+
var oldGlobals = require(4);
|
193
|
+
|
194
|
+
if (isUsingLatest(buildName)) {
|
195
|
+
loadV2(buildName);
|
196
|
+
} else {
|
197
|
+
oldGlobals();
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
},{"2":2,"3":3,"4":4}]},{},[5])(5)
|
202
|
+
});(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.algoliasearch = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
203
|
+
(function (global){
|
204
|
+
// this is the standalone build entry of AlgoliaSearch
|
205
|
+
var createAlgoliasearch = require(6);
|
206
|
+
|
207
|
+
module.exports = createAlgoliasearch(request);
|
208
|
+
|
209
|
+
var Promise = global.Promise || require(3).Promise;
|
210
|
+
|
211
|
+
var JSONPRequest = require(5);
|
212
|
+
|
213
|
+
var support = {
|
214
|
+
hasXMLHttpRequest: 'XMLHttpRequest' in window,
|
215
|
+
hasXDomainRequest: 'XDomainRequest' in window,
|
216
|
+
cors: 'withCredentials' in new XMLHttpRequest(),
|
217
|
+
timeout: 'timeout' in new XMLHttpRequest()
|
218
|
+
};
|
219
|
+
|
220
|
+
function request(url, opts) {
|
221
|
+
return new Promise(function(resolve, reject) {
|
222
|
+
// no cors or XDomainRequest, no request
|
223
|
+
if (!support.cors && !support.hasXDomainRequest) {
|
224
|
+
// very old browser, not supported
|
225
|
+
reject(new Error('CORS not supported'));
|
226
|
+
return;
|
227
|
+
}
|
228
|
+
|
229
|
+
var body = null;
|
230
|
+
var req = support.cors ? new XMLHttpRequest() : new XDomainRequest();
|
231
|
+
var ontimeout;
|
232
|
+
var timedOut;
|
233
|
+
|
234
|
+
if (opts.body !== undefined) {
|
235
|
+
body = JSON.stringify(opts.body);
|
236
|
+
}
|
237
|
+
|
238
|
+
// do not rely on default XHR async flag, as some analytics code like hotjar
|
239
|
+
// breaks it and set it to false by default
|
240
|
+
if (req instanceof XMLHttpRequest) {
|
241
|
+
req.open(opts.method, url, true);
|
242
|
+
} else {
|
243
|
+
req.open(opts.method, url);
|
244
|
+
}
|
245
|
+
|
246
|
+
if (support.cors && body && opts.method !== 'GET') {
|
247
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
248
|
+
}
|
249
|
+
|
250
|
+
req.onload = load;
|
251
|
+
req.onerror = error;
|
252
|
+
|
253
|
+
if (support.timeout) {
|
254
|
+
// .timeout supported by both XHR and XDR,
|
255
|
+
// we do receive timeout event, tested
|
256
|
+
req.timeout = opts.timeout;
|
257
|
+
|
258
|
+
req.ontimeout = timeout;
|
259
|
+
} else {
|
260
|
+
ontimeout = setTimeout(timeout, opts.timeout);
|
261
|
+
}
|
262
|
+
|
263
|
+
req.send(body);
|
264
|
+
|
265
|
+
// event object not received in IE8, at least
|
266
|
+
// but we do not use it, still important to note
|
267
|
+
function load(/*event*/) {
|
268
|
+
// When browser does not supports req.timeout, we can
|
269
|
+
// have both a load and timeout event, since handled by a dumb setTimeout
|
270
|
+
if (timedOut) {
|
271
|
+
return;
|
272
|
+
}
|
273
|
+
|
274
|
+
if (!support.timeout) {
|
275
|
+
clearTimeout(ontimeout);
|
276
|
+
}
|
277
|
+
|
278
|
+
var response = null;
|
279
|
+
|
280
|
+
try {
|
281
|
+
response = JSON.parse(req.responseText);
|
282
|
+
} catch(e) {}
|
283
|
+
|
284
|
+
resolve({
|
285
|
+
body: response,
|
286
|
+
statusCode: req.status
|
287
|
+
});
|
288
|
+
}
|
289
|
+
|
290
|
+
function error(event) {
|
291
|
+
if (timedOut) {
|
292
|
+
return;
|
293
|
+
}
|
294
|
+
|
295
|
+
if (!support.timeout) {
|
296
|
+
clearTimeout(ontimeout);
|
297
|
+
}
|
298
|
+
|
299
|
+
// error event is trigerred both with XDR/XHR on:
|
300
|
+
// - DNS error
|
301
|
+
// - unallowed cross domain request
|
302
|
+
reject(new Error('Could not connect to host, error was:' + event));
|
303
|
+
}
|
304
|
+
|
305
|
+
function timeout() {
|
306
|
+
if (!support.timeout) {
|
307
|
+
timedOut = true;
|
308
|
+
req.abort();
|
309
|
+
}
|
310
|
+
|
311
|
+
resolve(new Error('Timeout - Could not connect to endpoint ' + url));
|
312
|
+
}
|
313
|
+
|
314
|
+
});
|
315
|
+
}
|
316
|
+
|
317
|
+
request.fallback = function(url, opts) {
|
318
|
+
return new Promise(function(resolve, reject) {
|
319
|
+
JSONPRequest(url, opts, function JSONPRequestDone(err, content) {
|
320
|
+
if (err) {
|
321
|
+
reject(err);
|
322
|
+
return;
|
323
|
+
}
|
324
|
+
|
325
|
+
resolve(content);
|
326
|
+
});
|
327
|
+
});
|
328
|
+
};
|
329
|
+
|
330
|
+
request.reject = function(val) {
|
331
|
+
return Promise.reject(val);
|
332
|
+
};
|
333
|
+
|
334
|
+
request.resolve = function(val) {
|
335
|
+
return Promise.resolve(val);
|
336
|
+
};
|
337
|
+
|
338
|
+
request.delay = function(ms) {
|
339
|
+
return new Promise(function(resolve/*, reject*/) {
|
340
|
+
setTimeout(resolve, ms);
|
341
|
+
});
|
342
|
+
};
|
343
|
+
|
344
|
+
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
345
|
+
},{"3":3,"5":5,"6":6}],2:[function(require,module,exports){
|
346
|
+
// shim for using process in browser
|
347
|
+
|
348
|
+
var process = module.exports = {};
|
349
|
+
var queue = [];
|
350
|
+
var draining = false;
|
351
|
+
|
352
|
+
function drainQueue() {
|
353
|
+
if (draining) {
|
354
|
+
return;
|
355
|
+
}
|
356
|
+
draining = true;
|
357
|
+
var currentQueue;
|
358
|
+
var len = queue.length;
|
359
|
+
while(len) {
|
360
|
+
currentQueue = queue;
|
361
|
+
queue = [];
|
362
|
+
var i = -1;
|
363
|
+
while (++i < len) {
|
364
|
+
currentQueue[i]();
|
365
|
+
}
|
366
|
+
len = queue.length;
|
367
|
+
}
|
368
|
+
draining = false;
|
369
|
+
}
|
370
|
+
process.nextTick = function (fun) {
|
371
|
+
queue.push(fun);
|
372
|
+
if (!draining) {
|
373
|
+
setTimeout(drainQueue, 0);
|
374
|
+
}
|
375
|
+
};
|
376
|
+
|
377
|
+
process.title = 'browser';
|
378
|
+
process.browser = true;
|
379
|
+
process.env = {};
|
380
|
+
process.argv = [];
|
381
|
+
process.version = ''; // empty string to avoid regexp issues
|
382
|
+
process.versions = {};
|
383
|
+
|
384
|
+
function noop() {}
|
385
|
+
|
386
|
+
process.on = noop;
|
387
|
+
process.addListener = noop;
|
388
|
+
process.once = noop;
|
389
|
+
process.off = noop;
|
390
|
+
process.removeListener = noop;
|
391
|
+
process.removeAllListeners = noop;
|
392
|
+
process.emit = noop;
|
393
|
+
|
394
|
+
process.binding = function (name) {
|
395
|
+
throw new Error('process.binding is not supported');
|
396
|
+
};
|
397
|
+
|
398
|
+
// TODO(shtylman)
|
399
|
+
process.cwd = function () { return '/' };
|
400
|
+
process.chdir = function (dir) {
|
401
|
+
throw new Error('process.chdir is not supported');
|
402
|
+
};
|
403
|
+
process.umask = function() { return 0; };
|
404
|
+
|
405
|
+
},{}],3:[function(require,module,exports){
|
406
|
+
(function (process,global){
|
407
|
+
/*!
|
408
|
+
* @overview es6-promise - a tiny implementation of Promises/A+.
|
409
|
+
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
410
|
+
* @license Licensed under MIT license
|
411
|
+
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
|
412
|
+
* @version 2.0.1
|
413
|
+
*/
|
414
|
+
|
415
|
+
(function() {
|
416
|
+
"use strict";
|
417
|
+
|
418
|
+
function $$utils$$objectOrFunction(x) {
|
419
|
+
return typeof x === 'function' || (typeof x === 'object' && x !== null);
|
420
|
+
}
|
421
|
+
|
422
|
+
function $$utils$$isFunction(x) {
|
423
|
+
return typeof x === 'function';
|
424
|
+
}
|
425
|
+
|
426
|
+
function $$utils$$isMaybeThenable(x) {
|
427
|
+
return typeof x === 'object' && x !== null;
|
428
|
+
}
|
429
|
+
|
430
|
+
var $$utils$$_isArray;
|
431
|
+
|
432
|
+
if (!Array.isArray) {
|
433
|
+
$$utils$$_isArray = function (x) {
|
434
|
+
return Object.prototype.toString.call(x) === '[object Array]';
|
435
|
+
};
|
436
|
+
} else {
|
437
|
+
$$utils$$_isArray = Array.isArray;
|
438
|
+
}
|
439
|
+
|
440
|
+
var $$utils$$isArray = $$utils$$_isArray;
|
441
|
+
var $$utils$$now = Date.now || function() { return new Date().getTime(); };
|
442
|
+
function $$utils$$F() { }
|
443
|
+
|
444
|
+
var $$utils$$o_create = (Object.create || function (o) {
|
445
|
+
if (arguments.length > 1) {
|
446
|
+
throw new Error('Second argument not supported');
|
447
|
+
}
|
448
|
+
if (typeof o !== 'object') {
|
449
|
+
throw new TypeError('Argument must be an object');
|
450
|
+
}
|
451
|
+
$$utils$$F.prototype = o;
|
452
|
+
return new $$utils$$F();
|
453
|
+
});
|
454
|
+
|
455
|
+
var $$asap$$len = 0;
|
456
|
+
|
457
|
+
var $$asap$$default = function asap(callback, arg) {
|
458
|
+
$$asap$$queue[$$asap$$len] = callback;
|
459
|
+
$$asap$$queue[$$asap$$len + 1] = arg;
|
460
|
+
$$asap$$len += 2;
|
461
|
+
if ($$asap$$len === 2) {
|
462
|
+
// If len is 1, that means that we need to schedule an async flush.
|
463
|
+
// If additional callbacks are queued before the queue is flushed, they
|
464
|
+
// will be processed by this flush that we are scheduling.
|
465
|
+
$$asap$$scheduleFlush();
|
466
|
+
}
|
467
|
+
};
|
468
|
+
|
469
|
+
var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {};
|
470
|
+
var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver;
|
471
|
+
|
472
|
+
// test for web worker but not in IE10
|
473
|
+
var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
|
474
|
+
typeof importScripts !== 'undefined' &&
|
475
|
+
typeof MessageChannel !== 'undefined';
|
476
|
+
|
477
|
+
// node
|
478
|
+
function $$asap$$useNextTick() {
|
479
|
+
return function() {
|
480
|
+
process.nextTick($$asap$$flush);
|
481
|
+
};
|
482
|
+
}
|
483
|
+
|
484
|
+
function $$asap$$useMutationObserver() {
|
485
|
+
var iterations = 0;
|
486
|
+
var observer = new $$asap$$BrowserMutationObserver($$asap$$flush);
|
487
|
+
var node = document.createTextNode('');
|
488
|
+
observer.observe(node, { characterData: true });
|
489
|
+
|
490
|
+
return function() {
|
491
|
+
node.data = (iterations = ++iterations % 2);
|
492
|
+
};
|
493
|
+
}
|
494
|
+
|
495
|
+
// web worker
|
496
|
+
function $$asap$$useMessageChannel() {
|
497
|
+
var channel = new MessageChannel();
|
498
|
+
channel.port1.onmessage = $$asap$$flush;
|
499
|
+
return function () {
|
500
|
+
channel.port2.postMessage(0);
|
501
|
+
};
|
502
|
+
}
|
503
|
+
|
504
|
+
function $$asap$$useSetTimeout() {
|
505
|
+
return function() {
|
506
|
+
setTimeout($$asap$$flush, 1);
|
507
|
+
};
|
508
|
+
}
|
509
|
+
|
510
|
+
var $$asap$$queue = new Array(1000);
|
511
|
+
|
512
|
+
function $$asap$$flush() {
|
513
|
+
for (var i = 0; i < $$asap$$len; i+=2) {
|
514
|
+
var callback = $$asap$$queue[i];
|
515
|
+
var arg = $$asap$$queue[i+1];
|
516
|
+
|
517
|
+
callback(arg);
|
518
|
+
|
519
|
+
$$asap$$queue[i] = undefined;
|
520
|
+
$$asap$$queue[i+1] = undefined;
|
521
|
+
}
|
522
|
+
|
523
|
+
$$asap$$len = 0;
|
524
|
+
}
|
525
|
+
|
526
|
+
var $$asap$$scheduleFlush;
|
527
|
+
|
528
|
+
// Decide what async method to use to triggering processing of queued callbacks:
|
529
|
+
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
|
530
|
+
$$asap$$scheduleFlush = $$asap$$useNextTick();
|
531
|
+
} else if ($$asap$$BrowserMutationObserver) {
|
532
|
+
$$asap$$scheduleFlush = $$asap$$useMutationObserver();
|
533
|
+
} else if ($$asap$$isWorker) {
|
534
|
+
$$asap$$scheduleFlush = $$asap$$useMessageChannel();
|
535
|
+
} else {
|
536
|
+
$$asap$$scheduleFlush = $$asap$$useSetTimeout();
|
537
|
+
}
|
538
|
+
|
539
|
+
function $$$internal$$noop() {}
|
540
|
+
var $$$internal$$PENDING = void 0;
|
541
|
+
var $$$internal$$FULFILLED = 1;
|
542
|
+
var $$$internal$$REJECTED = 2;
|
543
|
+
var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject();
|
544
|
+
|
545
|
+
function $$$internal$$selfFullfillment() {
|
546
|
+
return new TypeError("You cannot resolve a promise with itself");
|
547
|
+
}
|
548
|
+
|
549
|
+
function $$$internal$$cannotReturnOwn() {
|
550
|
+
return new TypeError('A promises callback cannot return that same promise.')
|
551
|
+
}
|
552
|
+
|
553
|
+
function $$$internal$$getThen(promise) {
|
554
|
+
try {
|
555
|
+
return promise.then;
|
556
|
+
} catch(error) {
|
557
|
+
$$$internal$$GET_THEN_ERROR.error = error;
|
558
|
+
return $$$internal$$GET_THEN_ERROR;
|
559
|
+
}
|
560
|
+
}
|
561
|
+
|
562
|
+
function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
|
563
|
+
try {
|
564
|
+
then.call(value, fulfillmentHandler, rejectionHandler);
|
565
|
+
} catch(e) {
|
566
|
+
return e;
|
567
|
+
}
|
568
|
+
}
|
569
|
+
|
570
|
+
function $$$internal$$handleForeignThenable(promise, thenable, then) {
|
571
|
+
$$asap$$default(function(promise) {
|
572
|
+
var sealed = false;
|
573
|
+
var error = $$$internal$$tryThen(then, thenable, function(value) {
|
574
|
+
if (sealed) { return; }
|
575
|
+
sealed = true;
|
576
|
+
if (thenable !== value) {
|
577
|
+
$$$internal$$resolve(promise, value);
|
578
|
+
} else {
|
579
|
+
$$$internal$$fulfill(promise, value);
|
580
|
+
}
|
581
|
+
}, function(reason) {
|
582
|
+
if (sealed) { return; }
|
583
|
+
sealed = true;
|
584
|
+
|
585
|
+
$$$internal$$reject(promise, reason);
|
586
|
+
}, 'Settle: ' + (promise._label || ' unknown promise'));
|
587
|
+
|
588
|
+
if (!sealed && error) {
|
589
|
+
sealed = true;
|
590
|
+
$$$internal$$reject(promise, error);
|
591
|
+
}
|
592
|
+
}, promise);
|
593
|
+
}
|
594
|
+
|
595
|
+
function $$$internal$$handleOwnThenable(promise, thenable) {
|
596
|
+
if (thenable._state === $$$internal$$FULFILLED) {
|
597
|
+
$$$internal$$fulfill(promise, thenable._result);
|
598
|
+
} else if (promise._state === $$$internal$$REJECTED) {
|
599
|
+
$$$internal$$reject(promise, thenable._result);
|
600
|
+
} else {
|
601
|
+
$$$internal$$subscribe(thenable, undefined, function(value) {
|
602
|
+
$$$internal$$resolve(promise, value);
|
603
|
+
}, function(reason) {
|
604
|
+
$$$internal$$reject(promise, reason);
|
605
|
+
});
|
606
|
+
}
|
607
|
+
}
|
608
|
+
|
609
|
+
function $$$internal$$handleMaybeThenable(promise, maybeThenable) {
|
610
|
+
if (maybeThenable.constructor === promise.constructor) {
|
611
|
+
$$$internal$$handleOwnThenable(promise, maybeThenable);
|
612
|
+
} else {
|
613
|
+
var then = $$$internal$$getThen(maybeThenable);
|
614
|
+
|
615
|
+
if (then === $$$internal$$GET_THEN_ERROR) {
|
616
|
+
$$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error);
|
617
|
+
} else if (then === undefined) {
|
618
|
+
$$$internal$$fulfill(promise, maybeThenable);
|
619
|
+
} else if ($$utils$$isFunction(then)) {
|
620
|
+
$$$internal$$handleForeignThenable(promise, maybeThenable, then);
|
621
|
+
} else {
|
622
|
+
$$$internal$$fulfill(promise, maybeThenable);
|
623
|
+
}
|
624
|
+
}
|
625
|
+
}
|
626
|
+
|
627
|
+
function $$$internal$$resolve(promise, value) {
|
628
|
+
if (promise === value) {
|
629
|
+
$$$internal$$reject(promise, $$$internal$$selfFullfillment());
|
630
|
+
} else if ($$utils$$objectOrFunction(value)) {
|
631
|
+
$$$internal$$handleMaybeThenable(promise, value);
|
632
|
+
} else {
|
633
|
+
$$$internal$$fulfill(promise, value);
|
634
|
+
}
|
635
|
+
}
|
636
|
+
|
637
|
+
function $$$internal$$publishRejection(promise) {
|
638
|
+
if (promise._onerror) {
|
639
|
+
promise._onerror(promise._result);
|
640
|
+
}
|
641
|
+
|
642
|
+
$$$internal$$publish(promise);
|
643
|
+
}
|
644
|
+
|
645
|
+
function $$$internal$$fulfill(promise, value) {
|
646
|
+
if (promise._state !== $$$internal$$PENDING) { return; }
|
647
|
+
|
648
|
+
promise._result = value;
|
649
|
+
promise._state = $$$internal$$FULFILLED;
|
650
|
+
|
651
|
+
if (promise._subscribers.length === 0) {
|
652
|
+
} else {
|
653
|
+
$$asap$$default($$$internal$$publish, promise);
|
654
|
+
}
|
655
|
+
}
|
656
|
+
|
657
|
+
function $$$internal$$reject(promise, reason) {
|
658
|
+
if (promise._state !== $$$internal$$PENDING) { return; }
|
659
|
+
promise._state = $$$internal$$REJECTED;
|
660
|
+
promise._result = reason;
|
661
|
+
|
662
|
+
$$asap$$default($$$internal$$publishRejection, promise);
|
663
|
+
}
|
664
|
+
|
665
|
+
function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
|
666
|
+
var subscribers = parent._subscribers;
|
667
|
+
var length = subscribers.length;
|
668
|
+
|
669
|
+
parent._onerror = null;
|
670
|
+
|
671
|
+
subscribers[length] = child;
|
672
|
+
subscribers[length + $$$internal$$FULFILLED] = onFulfillment;
|
673
|
+
subscribers[length + $$$internal$$REJECTED] = onRejection;
|
674
|
+
|
675
|
+
if (length === 0 && parent._state) {
|
676
|
+
$$asap$$default($$$internal$$publish, parent);
|
677
|
+
}
|
678
|
+
}
|
679
|
+
|
680
|
+
function $$$internal$$publish(promise) {
|
681
|
+
var subscribers = promise._subscribers;
|
682
|
+
var settled = promise._state;
|
683
|
+
|
684
|
+
if (subscribers.length === 0) { return; }
|
685
|
+
|
686
|
+
var child, callback, detail = promise._result;
|
687
|
+
|
688
|
+
for (var i = 0; i < subscribers.length; i += 3) {
|
689
|
+
child = subscribers[i];
|
690
|
+
callback = subscribers[i + settled];
|
691
|
+
|
692
|
+
if (child) {
|
693
|
+
$$$internal$$invokeCallback(settled, child, callback, detail);
|
694
|
+
} else {
|
695
|
+
callback(detail);
|
696
|
+
}
|
697
|
+
}
|
698
|
+
|
699
|
+
promise._subscribers.length = 0;
|
700
|
+
}
|
701
|
+
|
702
|
+
function $$$internal$$ErrorObject() {
|
703
|
+
this.error = null;
|
704
|
+
}
|
705
|
+
|
706
|
+
var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject();
|
707
|
+
|
708
|
+
function $$$internal$$tryCatch(callback, detail) {
|
709
|
+
try {
|
710
|
+
return callback(detail);
|
711
|
+
} catch(e) {
|
712
|
+
$$$internal$$TRY_CATCH_ERROR.error = e;
|
713
|
+
return $$$internal$$TRY_CATCH_ERROR;
|
714
|
+
}
|
715
|
+
}
|
716
|
+
|
717
|
+
function $$$internal$$invokeCallback(settled, promise, callback, detail) {
|
718
|
+
var hasCallback = $$utils$$isFunction(callback),
|
719
|
+
value, error, succeeded, failed;
|
720
|
+
|
721
|
+
if (hasCallback) {
|
722
|
+
value = $$$internal$$tryCatch(callback, detail);
|
723
|
+
|
724
|
+
if (value === $$$internal$$TRY_CATCH_ERROR) {
|
725
|
+
failed = true;
|
726
|
+
error = value.error;
|
727
|
+
value = null;
|
728
|
+
} else {
|
729
|
+
succeeded = true;
|
730
|
+
}
|
731
|
+
|
732
|
+
if (promise === value) {
|
733
|
+
$$$internal$$reject(promise, $$$internal$$cannotReturnOwn());
|
734
|
+
return;
|
735
|
+
}
|
736
|
+
|
737
|
+
} else {
|
738
|
+
value = detail;
|
739
|
+
succeeded = true;
|
740
|
+
}
|
741
|
+
|
742
|
+
if (promise._state !== $$$internal$$PENDING) {
|
743
|
+
// noop
|
744
|
+
} else if (hasCallback && succeeded) {
|
745
|
+
$$$internal$$resolve(promise, value);
|
746
|
+
} else if (failed) {
|
747
|
+
$$$internal$$reject(promise, error);
|
748
|
+
} else if (settled === $$$internal$$FULFILLED) {
|
749
|
+
$$$internal$$fulfill(promise, value);
|
750
|
+
} else if (settled === $$$internal$$REJECTED) {
|
751
|
+
$$$internal$$reject(promise, value);
|
752
|
+
}
|
753
|
+
}
|
754
|
+
|
755
|
+
function $$$internal$$initializePromise(promise, resolver) {
|
756
|
+
try {
|
757
|
+
resolver(function resolvePromise(value){
|
758
|
+
$$$internal$$resolve(promise, value);
|
759
|
+
}, function rejectPromise(reason) {
|
760
|
+
$$$internal$$reject(promise, reason);
|
761
|
+
});
|
762
|
+
} catch(e) {
|
763
|
+
$$$internal$$reject(promise, e);
|
764
|
+
}
|
765
|
+
}
|
766
|
+
|
767
|
+
function $$$enumerator$$makeSettledResult(state, position, value) {
|
768
|
+
if (state === $$$internal$$FULFILLED) {
|
769
|
+
return {
|
770
|
+
state: 'fulfilled',
|
771
|
+
value: value
|
772
|
+
};
|
773
|
+
} else {
|
774
|
+
return {
|
775
|
+
state: 'rejected',
|
776
|
+
reason: value
|
777
|
+
};
|
778
|
+
}
|
779
|
+
}
|
780
|
+
|
781
|
+
function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) {
|
782
|
+
this._instanceConstructor = Constructor;
|
783
|
+
this.promise = new Constructor($$$internal$$noop, label);
|
784
|
+
this._abortOnReject = abortOnReject;
|
785
|
+
|
786
|
+
if (this._validateInput(input)) {
|
787
|
+
this._input = input;
|
788
|
+
this.length = input.length;
|
789
|
+
this._remaining = input.length;
|
790
|
+
|
791
|
+
this._init();
|
792
|
+
|
793
|
+
if (this.length === 0) {
|
794
|
+
$$$internal$$fulfill(this.promise, this._result);
|
795
|
+
} else {
|
796
|
+
this.length = this.length || 0;
|
797
|
+
this._enumerate();
|
798
|
+
if (this._remaining === 0) {
|
799
|
+
$$$internal$$fulfill(this.promise, this._result);
|
800
|
+
}
|
801
|
+
}
|
802
|
+
} else {
|
803
|
+
$$$internal$$reject(this.promise, this._validationError());
|
804
|
+
}
|
805
|
+
}
|
806
|
+
|
807
|
+
$$$enumerator$$Enumerator.prototype._validateInput = function(input) {
|
808
|
+
return $$utils$$isArray(input);
|
809
|
+
};
|
810
|
+
|
811
|
+
$$$enumerator$$Enumerator.prototype._validationError = function() {
|
812
|
+
return new Error('Array Methods must be provided an Array');
|
813
|
+
};
|
814
|
+
|
815
|
+
$$$enumerator$$Enumerator.prototype._init = function() {
|
816
|
+
this._result = new Array(this.length);
|
817
|
+
};
|
818
|
+
|
819
|
+
var $$$enumerator$$default = $$$enumerator$$Enumerator;
|
820
|
+
|
821
|
+
$$$enumerator$$Enumerator.prototype._enumerate = function() {
|
822
|
+
var length = this.length;
|
823
|
+
var promise = this.promise;
|
824
|
+
var input = this._input;
|
825
|
+
|
826
|
+
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {
|
827
|
+
this._eachEntry(input[i], i);
|
828
|
+
}
|
829
|
+
};
|
830
|
+
|
831
|
+
$$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
|
832
|
+
var c = this._instanceConstructor;
|
833
|
+
if ($$utils$$isMaybeThenable(entry)) {
|
834
|
+
if (entry.constructor === c && entry._state !== $$$internal$$PENDING) {
|
835
|
+
entry._onerror = null;
|
836
|
+
this._settledAt(entry._state, i, entry._result);
|
837
|
+
} else {
|
838
|
+
this._willSettleAt(c.resolve(entry), i);
|
839
|
+
}
|
840
|
+
} else {
|
841
|
+
this._remaining--;
|
842
|
+
this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry);
|
843
|
+
}
|
844
|
+
};
|
845
|
+
|
846
|
+
$$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
|
847
|
+
var promise = this.promise;
|
848
|
+
|
849
|
+
if (promise._state === $$$internal$$PENDING) {
|
850
|
+
this._remaining--;
|
851
|
+
|
852
|
+
if (this._abortOnReject && state === $$$internal$$REJECTED) {
|
853
|
+
$$$internal$$reject(promise, value);
|
854
|
+
} else {
|
855
|
+
this._result[i] = this._makeResult(state, i, value);
|
856
|
+
}
|
857
|
+
}
|
858
|
+
|
859
|
+
if (this._remaining === 0) {
|
860
|
+
$$$internal$$fulfill(promise, this._result);
|
861
|
+
}
|
862
|
+
};
|
863
|
+
|
864
|
+
$$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) {
|
865
|
+
return value;
|
866
|
+
};
|
867
|
+
|
868
|
+
$$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
|
869
|
+
var enumerator = this;
|
870
|
+
|
871
|
+
$$$internal$$subscribe(promise, undefined, function(value) {
|
872
|
+
enumerator._settledAt($$$internal$$FULFILLED, i, value);
|
873
|
+
}, function(reason) {
|
874
|
+
enumerator._settledAt($$$internal$$REJECTED, i, reason);
|
875
|
+
});
|
876
|
+
};
|
877
|
+
|
878
|
+
var $$promise$all$$default = function all(entries, label) {
|
879
|
+
return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise;
|
880
|
+
};
|
881
|
+
|
882
|
+
var $$promise$race$$default = function race(entries, label) {
|
883
|
+
/*jshint validthis:true */
|
884
|
+
var Constructor = this;
|
885
|
+
|
886
|
+
var promise = new Constructor($$$internal$$noop, label);
|
887
|
+
|
888
|
+
if (!$$utils$$isArray(entries)) {
|
889
|
+
$$$internal$$reject(promise, new TypeError('You must pass an array to race.'));
|
890
|
+
return promise;
|
891
|
+
}
|
892
|
+
|
893
|
+
var length = entries.length;
|
894
|
+
|
895
|
+
function onFulfillment(value) {
|
896
|
+
$$$internal$$resolve(promise, value);
|
897
|
+
}
|
898
|
+
|
899
|
+
function onRejection(reason) {
|
900
|
+
$$$internal$$reject(promise, reason);
|
901
|
+
}
|
902
|
+
|
903
|
+
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {
|
904
|
+
$$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
|
905
|
+
}
|
906
|
+
|
907
|
+
return promise;
|
908
|
+
};
|
909
|
+
|
910
|
+
var $$promise$resolve$$default = function resolve(object, label) {
|
911
|
+
/*jshint validthis:true */
|
912
|
+
var Constructor = this;
|
913
|
+
|
914
|
+
if (object && typeof object === 'object' && object.constructor === Constructor) {
|
915
|
+
return object;
|
916
|
+
}
|
917
|
+
|
918
|
+
var promise = new Constructor($$$internal$$noop, label);
|
919
|
+
$$$internal$$resolve(promise, object);
|
920
|
+
return promise;
|
921
|
+
};
|
922
|
+
|
923
|
+
var $$promise$reject$$default = function reject(reason, label) {
|
924
|
+
/*jshint validthis:true */
|
925
|
+
var Constructor = this;
|
926
|
+
var promise = new Constructor($$$internal$$noop, label);
|
927
|
+
$$$internal$$reject(promise, reason);
|
928
|
+
return promise;
|
929
|
+
};
|
930
|
+
|
931
|
+
var $$es6$promise$promise$$counter = 0;
|
932
|
+
|
933
|
+
function $$es6$promise$promise$$needsResolver() {
|
934
|
+
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
|
935
|
+
}
|
936
|
+
|
937
|
+
function $$es6$promise$promise$$needsNew() {
|
938
|
+
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
|
939
|
+
}
|
940
|
+
|
941
|
+
var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise;
|
942
|
+
|
943
|
+
/**
|
944
|
+
Promise objects represent the eventual result of an asynchronous operation. The
|
945
|
+
primary way of interacting with a promise is through its `then` method, which
|
946
|
+
registers callbacks to receive either a promise’s eventual value or the reason
|
947
|
+
why the promise cannot be fulfilled.
|
948
|
+
|
949
|
+
Terminology
|
950
|
+
-----------
|
951
|
+
|
952
|
+
- `promise` is an object or function with a `then` method whose behavior conforms to this specification.
|
953
|
+
- `thenable` is an object or function that defines a `then` method.
|
954
|
+
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
|
955
|
+
- `exception` is a value that is thrown using the throw statement.
|
956
|
+
- `reason` is a value that indicates why a promise was rejected.
|
957
|
+
- `settled` the final resting state of a promise, fulfilled or rejected.
|
958
|
+
|
959
|
+
A promise can be in one of three states: pending, fulfilled, or rejected.
|
960
|
+
|
961
|
+
Promises that are fulfilled have a fulfillment value and are in the fulfilled
|
962
|
+
state. Promises that are rejected have a rejection reason and are in the
|
963
|
+
rejected state. A fulfillment value is never a thenable.
|
964
|
+
|
965
|
+
Promises can also be said to *resolve* a value. If this value is also a
|
966
|
+
promise, then the original promise's settled state will match the value's
|
967
|
+
settled state. So a promise that *resolves* a promise that rejects will
|
968
|
+
itself reject, and a promise that *resolves* a promise that fulfills will
|
969
|
+
itself fulfill.
|
970
|
+
|
971
|
+
|
972
|
+
Basic Usage:
|
973
|
+
------------
|
974
|
+
|
975
|
+
```js
|
976
|
+
var promise = new Promise(function(resolve, reject) {
|
977
|
+
// on success
|
978
|
+
resolve(value);
|
979
|
+
|
980
|
+
// on failure
|
981
|
+
reject(reason);
|
982
|
+
});
|
983
|
+
|
984
|
+
promise.then(function(value) {
|
985
|
+
// on fulfillment
|
986
|
+
}, function(reason) {
|
987
|
+
// on rejection
|
988
|
+
});
|
989
|
+
```
|
990
|
+
|
991
|
+
Advanced Usage:
|
992
|
+
---------------
|
993
|
+
|
994
|
+
Promises shine when abstracting away asynchronous interactions such as
|
995
|
+
`XMLHttpRequest`s.
|
996
|
+
|
997
|
+
```js
|
998
|
+
function getJSON(url) {
|
999
|
+
return new Promise(function(resolve, reject){
|
1000
|
+
var xhr = new XMLHttpRequest();
|
1001
|
+
|
1002
|
+
xhr.open('GET', url);
|
1003
|
+
xhr.onreadystatechange = handler;
|
1004
|
+
xhr.responseType = 'json';
|
1005
|
+
xhr.setRequestHeader('Accept', 'application/json');
|
1006
|
+
xhr.send();
|
1007
|
+
|
1008
|
+
function handler() {
|
1009
|
+
if (this.readyState === this.DONE) {
|
1010
|
+
if (this.status === 200) {
|
1011
|
+
resolve(this.response);
|
1012
|
+
} else {
|
1013
|
+
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
|
1014
|
+
}
|
1015
|
+
}
|
1016
|
+
};
|
1017
|
+
});
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
getJSON('/posts.json').then(function(json) {
|
1021
|
+
// on fulfillment
|
1022
|
+
}, function(reason) {
|
1023
|
+
// on rejection
|
1024
|
+
});
|
1025
|
+
```
|
1026
|
+
|
1027
|
+
Unlike callbacks, promises are great composable primitives.
|
1028
|
+
|
1029
|
+
```js
|
1030
|
+
Promise.all([
|
1031
|
+
getJSON('/posts'),
|
1032
|
+
getJSON('/comments')
|
1033
|
+
]).then(function(values){
|
1034
|
+
values[0] // => postsJSON
|
1035
|
+
values[1] // => commentsJSON
|
1036
|
+
|
1037
|
+
return values;
|
1038
|
+
});
|
1039
|
+
```
|
1040
|
+
|
1041
|
+
@class Promise
|
1042
|
+
@param {function} resolver
|
1043
|
+
Useful for tooling.
|
1044
|
+
@constructor
|
1045
|
+
*/
|
1046
|
+
function $$es6$promise$promise$$Promise(resolver) {
|
1047
|
+
this._id = $$es6$promise$promise$$counter++;
|
1048
|
+
this._state = undefined;
|
1049
|
+
this._result = undefined;
|
1050
|
+
this._subscribers = [];
|
1051
|
+
|
1052
|
+
if ($$$internal$$noop !== resolver) {
|
1053
|
+
if (!$$utils$$isFunction(resolver)) {
|
1054
|
+
$$es6$promise$promise$$needsResolver();
|
1055
|
+
}
|
1056
|
+
|
1057
|
+
if (!(this instanceof $$es6$promise$promise$$Promise)) {
|
1058
|
+
$$es6$promise$promise$$needsNew();
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
$$$internal$$initializePromise(this, resolver);
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
$$es6$promise$promise$$Promise.all = $$promise$all$$default;
|
1066
|
+
$$es6$promise$promise$$Promise.race = $$promise$race$$default;
|
1067
|
+
$$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default;
|
1068
|
+
$$es6$promise$promise$$Promise.reject = $$promise$reject$$default;
|
1069
|
+
|
1070
|
+
$$es6$promise$promise$$Promise.prototype = {
|
1071
|
+
constructor: $$es6$promise$promise$$Promise,
|
1072
|
+
|
1073
|
+
/**
|
1074
|
+
The primary way of interacting with a promise is through its `then` method,
|
1075
|
+
which registers callbacks to receive either a promise's eventual value or the
|
1076
|
+
reason why the promise cannot be fulfilled.
|
1077
|
+
|
1078
|
+
```js
|
1079
|
+
findUser().then(function(user){
|
1080
|
+
// user is available
|
1081
|
+
}, function(reason){
|
1082
|
+
// user is unavailable, and you are given the reason why
|
1083
|
+
});
|
1084
|
+
```
|
1085
|
+
|
1086
|
+
Chaining
|
1087
|
+
--------
|
1088
|
+
|
1089
|
+
The return value of `then` is itself a promise. This second, 'downstream'
|
1090
|
+
promise is resolved with the return value of the first promise's fulfillment
|
1091
|
+
or rejection handler, or rejected if the handler throws an exception.
|
1092
|
+
|
1093
|
+
```js
|
1094
|
+
findUser().then(function (user) {
|
1095
|
+
return user.name;
|
1096
|
+
}, function (reason) {
|
1097
|
+
return 'default name';
|
1098
|
+
}).then(function (userName) {
|
1099
|
+
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
|
1100
|
+
// will be `'default name'`
|
1101
|
+
});
|
1102
|
+
|
1103
|
+
findUser().then(function (user) {
|
1104
|
+
throw new Error('Found user, but still unhappy');
|
1105
|
+
}, function (reason) {
|
1106
|
+
throw new Error('`findUser` rejected and we're unhappy');
|
1107
|
+
}).then(function (value) {
|
1108
|
+
// never reached
|
1109
|
+
}, function (reason) {
|
1110
|
+
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
|
1111
|
+
// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
|
1112
|
+
});
|
1113
|
+
```
|
1114
|
+
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
|
1115
|
+
|
1116
|
+
```js
|
1117
|
+
findUser().then(function (user) {
|
1118
|
+
throw new PedagogicalException('Upstream error');
|
1119
|
+
}).then(function (value) {
|
1120
|
+
// never reached
|
1121
|
+
}).then(function (value) {
|
1122
|
+
// never reached
|
1123
|
+
}, function (reason) {
|
1124
|
+
// The `PedgagocialException` is propagated all the way down to here
|
1125
|
+
});
|
1126
|
+
```
|
1127
|
+
|
1128
|
+
Assimilation
|
1129
|
+
------------
|
1130
|
+
|
1131
|
+
Sometimes the value you want to propagate to a downstream promise can only be
|
1132
|
+
retrieved asynchronously. This can be achieved by returning a promise in the
|
1133
|
+
fulfillment or rejection handler. The downstream promise will then be pending
|
1134
|
+
until the returned promise is settled. This is called *assimilation*.
|
1135
|
+
|
1136
|
+
```js
|
1137
|
+
findUser().then(function (user) {
|
1138
|
+
return findCommentsByAuthor(user);
|
1139
|
+
}).then(function (comments) {
|
1140
|
+
// The user's comments are now available
|
1141
|
+
});
|
1142
|
+
```
|
1143
|
+
|
1144
|
+
If the assimliated promise rejects, then the downstream promise will also reject.
|
1145
|
+
|
1146
|
+
```js
|
1147
|
+
findUser().then(function (user) {
|
1148
|
+
return findCommentsByAuthor(user);
|
1149
|
+
}).then(function (comments) {
|
1150
|
+
// If `findCommentsByAuthor` fulfills, we'll have the value here
|
1151
|
+
}, function (reason) {
|
1152
|
+
// If `findCommentsByAuthor` rejects, we'll have the reason here
|
1153
|
+
});
|
1154
|
+
```
|
1155
|
+
|
1156
|
+
Simple Example
|
1157
|
+
--------------
|
1158
|
+
|
1159
|
+
Synchronous Example
|
1160
|
+
|
1161
|
+
```javascript
|
1162
|
+
var result;
|
1163
|
+
|
1164
|
+
try {
|
1165
|
+
result = findResult();
|
1166
|
+
// success
|
1167
|
+
} catch(reason) {
|
1168
|
+
// failure
|
1169
|
+
}
|
1170
|
+
```
|
1171
|
+
|
1172
|
+
Errback Example
|
1173
|
+
|
1174
|
+
```js
|
1175
|
+
findResult(function(result, err){
|
1176
|
+
if (err) {
|
1177
|
+
// failure
|
1178
|
+
} else {
|
1179
|
+
// success
|
1180
|
+
}
|
1181
|
+
});
|
1182
|
+
```
|
1183
|
+
|
1184
|
+
Promise Example;
|
1185
|
+
|
1186
|
+
```javascript
|
1187
|
+
findResult().then(function(result){
|
1188
|
+
// success
|
1189
|
+
}, function(reason){
|
1190
|
+
// failure
|
1191
|
+
});
|
1192
|
+
```
|
1193
|
+
|
1194
|
+
Advanced Example
|
1195
|
+
--------------
|
1196
|
+
|
1197
|
+
Synchronous Example
|
1198
|
+
|
1199
|
+
```javascript
|
1200
|
+
var author, books;
|
1201
|
+
|
1202
|
+
try {
|
1203
|
+
author = findAuthor();
|
1204
|
+
books = findBooksByAuthor(author);
|
1205
|
+
// success
|
1206
|
+
} catch(reason) {
|
1207
|
+
// failure
|
1208
|
+
}
|
1209
|
+
```
|
1210
|
+
|
1211
|
+
Errback Example
|
1212
|
+
|
1213
|
+
```js
|
1214
|
+
|
1215
|
+
function foundBooks(books) {
|
1216
|
+
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
function failure(reason) {
|
1220
|
+
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
findAuthor(function(author, err){
|
1224
|
+
if (err) {
|
1225
|
+
failure(err);
|
1226
|
+
// failure
|
1227
|
+
} else {
|
1228
|
+
try {
|
1229
|
+
findBoooksByAuthor(author, function(books, err) {
|
1230
|
+
if (err) {
|
1231
|
+
failure(err);
|
1232
|
+
} else {
|
1233
|
+
try {
|
1234
|
+
foundBooks(books);
|
1235
|
+
} catch(reason) {
|
1236
|
+
failure(reason);
|
1237
|
+
}
|
1238
|
+
}
|
1239
|
+
});
|
1240
|
+
} catch(error) {
|
1241
|
+
failure(err);
|
1242
|
+
}
|
1243
|
+
// success
|
1244
|
+
}
|
1245
|
+
});
|
1246
|
+
```
|
1247
|
+
|
1248
|
+
Promise Example;
|
1249
|
+
|
1250
|
+
```javascript
|
1251
|
+
findAuthor().
|
1252
|
+
then(findBooksByAuthor).
|
1253
|
+
then(function(books){
|
1254
|
+
// found books
|
1255
|
+
}).catch(function(reason){
|
1256
|
+
// something went wrong
|
1257
|
+
});
|
1258
|
+
```
|
1259
|
+
|
1260
|
+
@method then
|
1261
|
+
@param {Function} onFulfilled
|
1262
|
+
@param {Function} onRejected
|
1263
|
+
Useful for tooling.
|
1264
|
+
@return {Promise}
|
1265
|
+
*/
|
1266
|
+
then: function(onFulfillment, onRejection) {
|
1267
|
+
var parent = this;
|
1268
|
+
var state = parent._state;
|
1269
|
+
|
1270
|
+
if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) {
|
1271
|
+
return this;
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
var child = new this.constructor($$$internal$$noop);
|
1275
|
+
var result = parent._result;
|
1276
|
+
|
1277
|
+
if (state) {
|
1278
|
+
var callback = arguments[state - 1];
|
1279
|
+
$$asap$$default(function(){
|
1280
|
+
$$$internal$$invokeCallback(state, child, callback, result);
|
1281
|
+
});
|
1282
|
+
} else {
|
1283
|
+
$$$internal$$subscribe(parent, child, onFulfillment, onRejection);
|
1284
|
+
}
|
1285
|
+
|
1286
|
+
return child;
|
1287
|
+
},
|
1288
|
+
|
1289
|
+
/**
|
1290
|
+
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
|
1291
|
+
as the catch block of a try/catch statement.
|
1292
|
+
|
1293
|
+
```js
|
1294
|
+
function findAuthor(){
|
1295
|
+
throw new Error('couldn't find that author');
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
// synchronous
|
1299
|
+
try {
|
1300
|
+
findAuthor();
|
1301
|
+
} catch(reason) {
|
1302
|
+
// something went wrong
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
// async with promises
|
1306
|
+
findAuthor().catch(function(reason){
|
1307
|
+
// something went wrong
|
1308
|
+
});
|
1309
|
+
```
|
1310
|
+
|
1311
|
+
@method catch
|
1312
|
+
@param {Function} onRejection
|
1313
|
+
Useful for tooling.
|
1314
|
+
@return {Promise}
|
1315
|
+
*/
|
1316
|
+
'catch': function(onRejection) {
|
1317
|
+
return this.then(null, onRejection);
|
1318
|
+
}
|
1319
|
+
};
|
1320
|
+
|
1321
|
+
var $$es6$promise$polyfill$$default = function polyfill() {
|
1322
|
+
var local;
|
1323
|
+
|
1324
|
+
if (typeof global !== 'undefined') {
|
1325
|
+
local = global;
|
1326
|
+
} else if (typeof window !== 'undefined' && window.document) {
|
1327
|
+
local = window;
|
1328
|
+
} else {
|
1329
|
+
local = self;
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
var es6PromiseSupport =
|
1333
|
+
"Promise" in local &&
|
1334
|
+
// Some of these methods are missing from
|
1335
|
+
// Firefox/Chrome experimental implementations
|
1336
|
+
"resolve" in local.Promise &&
|
1337
|
+
"reject" in local.Promise &&
|
1338
|
+
"all" in local.Promise &&
|
1339
|
+
"race" in local.Promise &&
|
1340
|
+
// Older version of the spec had a resolver object
|
1341
|
+
// as the arg rather than a function
|
1342
|
+
(function() {
|
1343
|
+
var resolve;
|
1344
|
+
new local.Promise(function(r) { resolve = r; });
|
1345
|
+
return $$utils$$isFunction(resolve);
|
1346
|
+
}());
|
1347
|
+
|
1348
|
+
if (!es6PromiseSupport) {
|
1349
|
+
local.Promise = $$es6$promise$promise$$default;
|
1350
|
+
}
|
1351
|
+
};
|
1352
|
+
|
1353
|
+
var es6$promise$umd$$ES6Promise = {
|
1354
|
+
'Promise': $$es6$promise$promise$$default,
|
1355
|
+
'polyfill': $$es6$promise$polyfill$$default
|
1356
|
+
};
|
1357
|
+
|
1358
|
+
/* global define:true module:true window: true */
|
1359
|
+
if (typeof define === 'function' && define['amd']) {
|
1360
|
+
define(function() { return es6$promise$umd$$ES6Promise; });
|
1361
|
+
} else if (typeof module !== 'undefined' && module['exports']) {
|
1362
|
+
module['exports'] = es6$promise$umd$$ES6Promise;
|
1363
|
+
} else if (typeof this !== 'undefined') {
|
1364
|
+
this['ES6Promise'] = es6$promise$umd$$ES6Promise;
|
1365
|
+
}
|
1366
|
+
}).call(this);
|
1367
|
+
}).call(this,require(2),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
1368
|
+
},{"2":2}],4:[function(require,module,exports){
|
1369
|
+
(function (process){
|
1370
|
+
module.exports = AlgoliaSearch;
|
1371
|
+
|
1372
|
+
/*
|
1373
|
+
* Algolia Search library initialization
|
1374
|
+
* https://www.algolia.com/
|
1375
|
+
*
|
1376
|
+
* @param {string} applicationID - Your applicationID, found in your dashboard
|
1377
|
+
* @param {string} apiKey - Your API key, found in your dashboard
|
1378
|
+
* @param {Object} [opts]
|
1379
|
+
* @param {number} [opts.timeout=2000] - The request timeout set in milliseconds, another request will be issued after this timeout
|
1380
|
+
* @param {string} [opts.protocol='http:'] - The protocol used to query Algolia Search API.
|
1381
|
+
* Set to 'https:' to force using https. Default to document.location.protocol in browsers
|
1382
|
+
* @param {string[]} [opts.hosts=[
|
1383
|
+
* this.applicationID + '-1.algolia.' + opts.tld,
|
1384
|
+
* this.applicationID + '-2.algolia.' + opts.tld,
|
1385
|
+
* this.applicationID + '-3.algolia.' + opts.tld]
|
1386
|
+
* ] - The hosts to use for Algolia Search API. It this your responsibility to shuffle the hosts and add a DSN host in it
|
1387
|
+
* @param {string} [opts.tld='net'] - The tld to use when computing hosts default list
|
1388
|
+
*/
|
1389
|
+
function AlgoliaSearch(applicationID, apiKey, opts, _request) {
|
1390
|
+
var usage = 'Usage: algoliasearch(applicationID, apiKey, opts)';
|
1391
|
+
|
1392
|
+
if (!applicationID) {
|
1393
|
+
throw new Error('Please provide an application ID. ' + usage);
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
if (!apiKey) {
|
1397
|
+
throw new Error('Please provide an API key. ' + usage);
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
opts = opts || {};
|
1401
|
+
|
1402
|
+
// now setting default options
|
1403
|
+
// could not find a tiny module to do that, let's go manual
|
1404
|
+
if (opts.timeout === undefined) {
|
1405
|
+
opts.timeout = 2000;
|
1406
|
+
}
|
1407
|
+
|
1408
|
+
if (opts.protocol === undefined) {
|
1409
|
+
opts.protocol = document && document.location.protocol || 'http:';
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
if (opts.hosts === undefined) {
|
1413
|
+
opts.hosts = []; // filled later on, has dependencies
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
if (opts.tld === undefined) {
|
1417
|
+
opts.tld = 'net';
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
// while we advocate for colon-at-the-end values: 'http:' for `opts.protocol`
|
1421
|
+
// we also accept `http` and `https`. It's a common error.
|
1422
|
+
if (!/:$/.test(opts.protocol)) {
|
1423
|
+
opts.protocol = opts.protocol + ':';
|
1424
|
+
}
|
1425
|
+
|
1426
|
+
// no hosts given, add defaults
|
1427
|
+
if (opts.hosts.length === 0) {
|
1428
|
+
opts.hosts = shuffle([
|
1429
|
+
applicationID + '-1.algolia.' + opts.tld,
|
1430
|
+
applicationID + '-2.algolia.' + opts.tld,
|
1431
|
+
applicationID + '-3.algolia.' + opts.tld
|
1432
|
+
]);
|
1433
|
+
|
1434
|
+
// add default dsn host
|
1435
|
+
opts.hosts.unshift(applicationID + '-dsn.algolia.' + opts.tld);
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
opts.hosts = map(opts.hosts, function prependProtocol(host) {
|
1439
|
+
return opts.protocol + '//' + host;
|
1440
|
+
});
|
1441
|
+
|
1442
|
+
this.applicationID = applicationID;
|
1443
|
+
this.apiKey = apiKey;
|
1444
|
+
this.hosts = opts.hosts;
|
1445
|
+
|
1446
|
+
this.currentHostIndex = 0;
|
1447
|
+
this.requestTimeout = opts.timeout;
|
1448
|
+
this.extraHeaders = [];
|
1449
|
+
this.cache = {};
|
1450
|
+
this._request = _request;
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
AlgoliaSearch.prototype = {
|
1454
|
+
/*
|
1455
|
+
* Delete an index
|
1456
|
+
*
|
1457
|
+
* @param indexName the name of index to delete
|
1458
|
+
* @param callback the result callback with two arguments
|
1459
|
+
* error: null or Error('message')
|
1460
|
+
* content: the server answer that contains the task ID
|
1461
|
+
*/
|
1462
|
+
deleteIndex: function(indexName, callback) {
|
1463
|
+
return this._jsonRequest({ method: 'DELETE',
|
1464
|
+
url: '/1/indexes/' + encodeURIComponent(indexName),
|
1465
|
+
callback: callback });
|
1466
|
+
},
|
1467
|
+
/**
|
1468
|
+
* Move an existing index.
|
1469
|
+
* @param srcIndexName the name of index to copy.
|
1470
|
+
* @param dstIndexName the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).
|
1471
|
+
* @param callback the result callback with two arguments
|
1472
|
+
* error: null or Error('message')
|
1473
|
+
* content: the server answer that contains the task ID
|
1474
|
+
*/
|
1475
|
+
moveIndex: function(srcIndexName, dstIndexName, callback) {
|
1476
|
+
var postObj = {operation: 'move', destination: dstIndexName};
|
1477
|
+
return this._jsonRequest({ method: 'POST',
|
1478
|
+
url: '/1/indexes/' + encodeURIComponent(srcIndexName) + '/operation',
|
1479
|
+
body: postObj,
|
1480
|
+
callback: callback });
|
1481
|
+
|
1482
|
+
},
|
1483
|
+
/**
|
1484
|
+
* Copy an existing index.
|
1485
|
+
* @param srcIndexName the name of index to copy.
|
1486
|
+
* @param dstIndexName the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).
|
1487
|
+
* @param callback the result callback with two arguments
|
1488
|
+
* error: null or Error('message')
|
1489
|
+
* content: the server answer that contains the task ID
|
1490
|
+
*/
|
1491
|
+
copyIndex: function(srcIndexName, dstIndexName, callback) {
|
1492
|
+
var postObj = {operation: 'copy', destination: dstIndexName};
|
1493
|
+
return this._jsonRequest({ method: 'POST',
|
1494
|
+
url: '/1/indexes/' + encodeURIComponent(srcIndexName) + '/operation',
|
1495
|
+
body: postObj,
|
1496
|
+
callback: callback });
|
1497
|
+
},
|
1498
|
+
/**
|
1499
|
+
* Return last log entries.
|
1500
|
+
* @param offset Specify the first entry to retrieve (0-based, 0 is the most recent log entry).
|
1501
|
+
* @param length Specify the maximum number of entries to retrieve starting at offset. Maximum allowed value: 1000.
|
1502
|
+
* @param callback the result callback with two arguments
|
1503
|
+
* error: null or Error('message')
|
1504
|
+
* content: the server answer that contains the task ID
|
1505
|
+
*/
|
1506
|
+
getLogs: function(offset, length, callback) {
|
1507
|
+
if (arguments.length === 0 || typeof offset === 'function') {
|
1508
|
+
// getLogs([cb])
|
1509
|
+
callback = offset;
|
1510
|
+
offset = 0;
|
1511
|
+
length = 10;
|
1512
|
+
} else if (arguments.length === 1 || typeof length === 'function') {
|
1513
|
+
// getLogs(1, [cb)]
|
1514
|
+
callback = length;
|
1515
|
+
length = 10;
|
1516
|
+
}
|
1517
|
+
|
1518
|
+
return this._jsonRequest({ method: 'GET',
|
1519
|
+
url: '/1/logs?offset=' + offset + '&length=' + length,
|
1520
|
+
callback: callback });
|
1521
|
+
},
|
1522
|
+
/*
|
1523
|
+
* List all existing indexes (paginated)
|
1524
|
+
*
|
1525
|
+
* @param page The page to retrieve, starting at 0.
|
1526
|
+
* @param callback the result callback with two arguments
|
1527
|
+
* error: null or Error('message')
|
1528
|
+
* content: the server answer with index list
|
1529
|
+
*/
|
1530
|
+
listIndexes: function(page, callback) {
|
1531
|
+
var params = '';
|
1532
|
+
|
1533
|
+
if (page === undefined || typeof page === 'function') {
|
1534
|
+
callback = page;
|
1535
|
+
} else {
|
1536
|
+
params = '?page=' + page;
|
1537
|
+
}
|
1538
|
+
|
1539
|
+
return this._jsonRequest({ method: 'GET',
|
1540
|
+
url: '/1/indexes' + params,
|
1541
|
+
callback: callback });
|
1542
|
+
},
|
1543
|
+
|
1544
|
+
/*
|
1545
|
+
* Get the index object initialized
|
1546
|
+
*
|
1547
|
+
* @param indexName the name of index
|
1548
|
+
* @param callback the result callback with one argument (the Index instance)
|
1549
|
+
*/
|
1550
|
+
initIndex: function(indexName) {
|
1551
|
+
return new this.Index(this, indexName);
|
1552
|
+
},
|
1553
|
+
/*
|
1554
|
+
* List all existing user keys with their associated ACLs
|
1555
|
+
*
|
1556
|
+
* @param callback the result callback with two arguments
|
1557
|
+
* error: null or Error('message')
|
1558
|
+
* content: the server answer with user keys list
|
1559
|
+
*/
|
1560
|
+
listUserKeys: function(callback) {
|
1561
|
+
return this._jsonRequest({ method: 'GET',
|
1562
|
+
url: '/1/keys',
|
1563
|
+
callback: callback });
|
1564
|
+
},
|
1565
|
+
/*
|
1566
|
+
* Get ACL of a user key
|
1567
|
+
*
|
1568
|
+
* @param key
|
1569
|
+
* @param callback the result callback with two arguments
|
1570
|
+
* error: null or Error('message')
|
1571
|
+
* content: the server answer with user keys list
|
1572
|
+
*/
|
1573
|
+
getUserKeyACL: function(key, callback) {
|
1574
|
+
return this._jsonRequest({ method: 'GET',
|
1575
|
+
url: '/1/keys/' + key,
|
1576
|
+
callback: callback });
|
1577
|
+
},
|
1578
|
+
/*
|
1579
|
+
* Delete an existing user key
|
1580
|
+
* @param key
|
1581
|
+
* @param callback the result callback with two arguments
|
1582
|
+
* error: null or Error('message')
|
1583
|
+
* content: the server answer with user keys list
|
1584
|
+
*/
|
1585
|
+
deleteUserKey: function(key, callback) {
|
1586
|
+
return this._jsonRequest({ method: 'DELETE',
|
1587
|
+
url: '/1/keys/' + key,
|
1588
|
+
callback: callback });
|
1589
|
+
},
|
1590
|
+
/*
|
1591
|
+
* Add an existing user key
|
1592
|
+
*
|
1593
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
1594
|
+
* can contains the following values:
|
1595
|
+
* - search: allow to search (https and http)
|
1596
|
+
* - addObject: allows to add/update an object in the index (https only)
|
1597
|
+
* - deleteObject : allows to delete an existing object (https only)
|
1598
|
+
* - deleteIndex : allows to delete index content (https only)
|
1599
|
+
* - settings : allows to get index settings (https only)
|
1600
|
+
* - editSettings : allows to change index settings (https only)
|
1601
|
+
* @param callback the result callback with two arguments
|
1602
|
+
* error: null or Error('message')
|
1603
|
+
* content: the server answer with user keys list
|
1604
|
+
*/
|
1605
|
+
addUserKey: function(acls, callback) {
|
1606
|
+
return this.addUserKeyWithValidity(acls, {
|
1607
|
+
validity: 0,
|
1608
|
+
maxQueriesPerIPPerHour: 0,
|
1609
|
+
maxHitsPerQuery: 0
|
1610
|
+
}, callback);
|
1611
|
+
},
|
1612
|
+
/*
|
1613
|
+
* Add an existing user key
|
1614
|
+
*
|
1615
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
1616
|
+
* can contains the following values:
|
1617
|
+
* - search: allow to search (https and http)
|
1618
|
+
* - addObject: allows to add/update an object in the index (https only)
|
1619
|
+
* - deleteObject : allows to delete an existing object (https only)
|
1620
|
+
* - deleteIndex : allows to delete index content (https only)
|
1621
|
+
* - settings : allows to get index settings (https only)
|
1622
|
+
* - editSettings : allows to change index settings (https only)
|
1623
|
+
* @param params.validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
|
1624
|
+
* @param params.maxQueriesPerIPPerHour Specify the maximum number of API calls allowed from an IP address per hour.
|
1625
|
+
* @param params.maxHitsPerQuery Specify the maximum number of hits this API key can retrieve in one call.
|
1626
|
+
* @param callback the result callback with two arguments
|
1627
|
+
* error: null or Error('message')
|
1628
|
+
* content: the server answer with user keys list
|
1629
|
+
*/
|
1630
|
+
addUserKeyWithValidity: function(acls, params, callback) {
|
1631
|
+
var aclsObject = {};
|
1632
|
+
aclsObject.acl = acls;
|
1633
|
+
aclsObject.validity = params.validity;
|
1634
|
+
aclsObject.maxQueriesPerIPPerHour = params.maxQueriesPerIPPerHour;
|
1635
|
+
aclsObject.maxHitsPerQuery = params.maxHitsPerQuery;
|
1636
|
+
return this._jsonRequest({ method: 'POST',
|
1637
|
+
url: '/1/keys',
|
1638
|
+
body: aclsObject,
|
1639
|
+
callback: callback });
|
1640
|
+
},
|
1641
|
+
|
1642
|
+
/**
|
1643
|
+
* Set the extra security tagFilters header
|
1644
|
+
* @param {string|array} tags The list of tags defining the current security filters
|
1645
|
+
*/
|
1646
|
+
setSecurityTags: function(tags) {
|
1647
|
+
if (Object.prototype.toString.call(tags) === '[object Array]') {
|
1648
|
+
var strTags = [];
|
1649
|
+
for (var i = 0; i < tags.length; ++i) {
|
1650
|
+
if (Object.prototype.toString.call(tags[i]) === '[object Array]') {
|
1651
|
+
var oredTags = [];
|
1652
|
+
for (var j = 0; j < tags[i].length; ++j) {
|
1653
|
+
oredTags.push(tags[i][j]);
|
1654
|
+
}
|
1655
|
+
strTags.push('(' + oredTags.join(',') + ')');
|
1656
|
+
} else {
|
1657
|
+
strTags.push(tags[i]);
|
1658
|
+
}
|
1659
|
+
}
|
1660
|
+
tags = strTags.join(',');
|
1661
|
+
}
|
1662
|
+
this.tagFilters = tags;
|
1663
|
+
},
|
1664
|
+
|
1665
|
+
/**
|
1666
|
+
* Set the extra user token header
|
1667
|
+
* @param {string} userToken The token identifying a uniq user (used to apply rate limits)
|
1668
|
+
*/
|
1669
|
+
setUserToken: function(userToken) {
|
1670
|
+
this.userToken = userToken;
|
1671
|
+
},
|
1672
|
+
|
1673
|
+
/*
|
1674
|
+
* Initialize a new batch of search queries
|
1675
|
+
*/
|
1676
|
+
startQueriesBatch: function() {
|
1677
|
+
this.batch = [];
|
1678
|
+
},
|
1679
|
+
/*
|
1680
|
+
* Add a search query in the batch
|
1681
|
+
*
|
1682
|
+
* @param query the full text query
|
1683
|
+
* @param args (optional) if set, contains an object with query parameters:
|
1684
|
+
* - attributes: an array of object attribute names to retrieve
|
1685
|
+
* (if not set all attributes are retrieve)
|
1686
|
+
* - attributesToHighlight: an array of object attribute names to highlight
|
1687
|
+
* (if not set indexed attributes are highlighted)
|
1688
|
+
* - minWordSizefor1Typo: the minimum number of characters to accept one typo.
|
1689
|
+
* Defaults to 3.
|
1690
|
+
* - minWordSizefor2Typos: the minimum number of characters to accept two typos.
|
1691
|
+
* Defaults to 7.
|
1692
|
+
* - getRankingInfo: if set, the result hits will contain ranking information in
|
1693
|
+
* _rankingInfo attribute
|
1694
|
+
* - page: (pagination parameter) page to retrieve (zero base). Defaults to 0.
|
1695
|
+
* - hitsPerPage: (pagination parameter) number of hits per page. Defaults to 10.
|
1696
|
+
*/
|
1697
|
+
addQueryInBatch: function(indexName, query, args) {
|
1698
|
+
var params = 'query=' + encodeURIComponent(query);
|
1699
|
+
if (!this._isUndefined(args) && args !== null) {
|
1700
|
+
params = this._getSearchParams(args, params);
|
1701
|
+
}
|
1702
|
+
this.batch.push({ indexName: indexName, params: params });
|
1703
|
+
},
|
1704
|
+
/*
|
1705
|
+
* Clear all queries in cache
|
1706
|
+
*/
|
1707
|
+
clearCache: function() {
|
1708
|
+
this.cache = {};
|
1709
|
+
},
|
1710
|
+
/*
|
1711
|
+
* Launch the batch of queries using XMLHttpRequest.
|
1712
|
+
* (Optimized for browser using a POST query to minimize number of OPTIONS queries)
|
1713
|
+
*
|
1714
|
+
* @param callback the function that will receive results
|
1715
|
+
*/
|
1716
|
+
sendQueriesBatch: function(callback) {
|
1717
|
+
var as = this;
|
1718
|
+
var params = {requests: []};
|
1719
|
+
|
1720
|
+
for (var i = 0; i < as.batch.length; ++i) {
|
1721
|
+
params.requests.push(as.batch[i]);
|
1722
|
+
}
|
1723
|
+
|
1724
|
+
return this._sendQueriesBatch(params, callback);
|
1725
|
+
},
|
1726
|
+
|
1727
|
+
/**
|
1728
|
+
* Set the number of milliseconds a request can take before automatically being terminated.
|
1729
|
+
*
|
1730
|
+
* @param {Number} milliseconds
|
1731
|
+
*/
|
1732
|
+
setRequestTimeout: function(milliseconds) {
|
1733
|
+
if (milliseconds) {
|
1734
|
+
this.requestTimeout = parseInt(milliseconds, 10);
|
1735
|
+
}
|
1736
|
+
},
|
1737
|
+
|
1738
|
+
/*
|
1739
|
+
* Index class constructor.
|
1740
|
+
* You should not use this method directly but use initIndex() function
|
1741
|
+
*/
|
1742
|
+
Index: function(algoliasearch, indexName) {
|
1743
|
+
this.indexName = indexName;
|
1744
|
+
this.as = algoliasearch;
|
1745
|
+
this.typeAheadArgs = null;
|
1746
|
+
this.typeAheadValueOption = null;
|
1747
|
+
|
1748
|
+
// make sure every index instance has it's own cache
|
1749
|
+
this.cache = {};
|
1750
|
+
},
|
1751
|
+
/**
|
1752
|
+
* Add an extra field to the HTTP request
|
1753
|
+
*
|
1754
|
+
* @param key the header field name
|
1755
|
+
* @param value the header field value
|
1756
|
+
*/
|
1757
|
+
setExtraHeader: function(key, value) {
|
1758
|
+
this.extraHeaders.push({ key: key, value: value});
|
1759
|
+
},
|
1760
|
+
|
1761
|
+
_sendQueriesBatch: function(params, callback) {
|
1762
|
+
return this._jsonRequest({ cache: this.cache,
|
1763
|
+
method: 'POST',
|
1764
|
+
url: '/1/indexes/*/queries',
|
1765
|
+
body: params,
|
1766
|
+
fallback: {
|
1767
|
+
method: 'GET',
|
1768
|
+
url: '/1/indexes/*',
|
1769
|
+
body: {params: (function() {
|
1770
|
+
var reqParams = '';
|
1771
|
+
for (var i = 0; i < params.requests.length; ++i) {
|
1772
|
+
var q = '/1/indexes/' + encodeURIComponent(params.requests[i].indexName) + '?' + params.requests[i].params;
|
1773
|
+
reqParams += i + '=' + encodeURIComponent(q) + '&';
|
1774
|
+
}
|
1775
|
+
return reqParams;
|
1776
|
+
}())}
|
1777
|
+
},
|
1778
|
+
callback: callback
|
1779
|
+
});
|
1780
|
+
},
|
1781
|
+
/*
|
1782
|
+
* Wrapper that try all hosts to maximize the quality of service
|
1783
|
+
*/
|
1784
|
+
_jsonRequest: function(opts) {
|
1785
|
+
// handle opts.fallback, automatically use fallback (JSONP in browser plugins, wrapped with $plugin-promises)
|
1786
|
+
// so if an error occurs and max tries => use fallback
|
1787
|
+
// set tries to 0 again
|
1788
|
+
// if fallback used and no more tries, return error
|
1789
|
+
// fallback parameters are in opts.fallback
|
1790
|
+
// call request.fallback or request accordingly, same promise chain otherwise
|
1791
|
+
// put callback& params in front if problem
|
1792
|
+
var cache = opts.cache;
|
1793
|
+
var cacheID = opts.url;
|
1794
|
+
var client = this;
|
1795
|
+
var tries = 0;
|
1796
|
+
|
1797
|
+
// as we use POST requests to pass parameters (like query='aa'),
|
1798
|
+
// the cacheID must be different between calls
|
1799
|
+
if (opts.body !== undefined) {
|
1800
|
+
cacheID += '_body_' + JSON.stringify(opts.body);
|
1801
|
+
}
|
1802
|
+
|
1803
|
+
function doRequest(requester, reqOpts) {
|
1804
|
+
// handle cache existence
|
1805
|
+
if (cache && cache[cacheID] !== undefined) {
|
1806
|
+
return client._request.resolve(cache[cacheID]);
|
1807
|
+
}
|
1808
|
+
|
1809
|
+
if (tries >= client.hosts.length) {
|
1810
|
+
if (!opts.fallback || requester === client._request.fallback) {
|
1811
|
+
// could not get a response even using the fallback if one was available
|
1812
|
+
return client._request.reject(new Error(
|
1813
|
+
'Cannot connect to the AlgoliaSearch API.' +
|
1814
|
+
' Send an email to support@algolia.com to report and resolve the issue.'
|
1815
|
+
));
|
1816
|
+
}
|
1817
|
+
|
1818
|
+
tries = 0;
|
1819
|
+
reqOpts.method = opts.fallback.method;
|
1820
|
+
reqOpts.url = opts.fallback.url;
|
1821
|
+
reqOpts.body = opts.fallback.body;
|
1822
|
+
reqOpts.timeout = client.requestTimeout * (tries + 1);
|
1823
|
+
client.currentHostIndex = 0;
|
1824
|
+
client.forceFallback = true;
|
1825
|
+
return doRequest(client._request.fallback, reqOpts);
|
1826
|
+
}
|
1827
|
+
|
1828
|
+
var url = reqOpts.url;
|
1829
|
+
|
1830
|
+
url += (url.indexOf('?') === -1 ? '?' : '&') + 'X-Algolia-API-Key=' + client.apiKey;
|
1831
|
+
url += '&X-Algolia-Application-Id=' + client.applicationID;
|
1832
|
+
|
1833
|
+
if (client.userToken) {
|
1834
|
+
url += '&X-Algolia-UserToken=' + encodeURIComponent(client.userToken);
|
1835
|
+
}
|
1836
|
+
|
1837
|
+
if (client.tagFilters) {
|
1838
|
+
url += '&X-Algolia-TagFilters=' + encodeURIComponent(client.tagFilters);
|
1839
|
+
}
|
1840
|
+
|
1841
|
+
for (var i = 0; i < client.extraHeaders.length; ++i) {
|
1842
|
+
url += '&' + client.extraHeaders[i].key + '=' + client.extraHeaders[i].value;
|
1843
|
+
}
|
1844
|
+
|
1845
|
+
return requester(client.hosts[client.currentHostIndex] + url, {
|
1846
|
+
body: reqOpts.body,
|
1847
|
+
method: reqOpts.method,
|
1848
|
+
timeout: reqOpts.timeout
|
1849
|
+
})
|
1850
|
+
.then(function success(httpResponse) {
|
1851
|
+
// timeout case, retry immediately
|
1852
|
+
if (httpResponse instanceof Error) {
|
1853
|
+
return retryRequest();
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
var status =
|
1857
|
+
// When in browser mode, using XDR or JSONP
|
1858
|
+
// We rely on our own API response `status`, only
|
1859
|
+
// provided when an error occurs, we also expect a .message along
|
1860
|
+
// Otherwise, it could be a `waitTask` status, that's the only
|
1861
|
+
// case where we have a response.status that's not the http statusCode
|
1862
|
+
httpResponse && httpResponse.body && httpResponse.body.message && httpResponse.body.status ||
|
1863
|
+
|
1864
|
+
// this is important to check the request statusCode AFTER the body eventual
|
1865
|
+
// statusCode because some implementations (jQuery XDomainRequest transport) may
|
1866
|
+
// send statusCode 200 while we had an error
|
1867
|
+
httpResponse.statusCode ||
|
1868
|
+
|
1869
|
+
// When in browser mode, using XDR or JSONP
|
1870
|
+
// we default to success when no error (no response.status && response.message)
|
1871
|
+
// If there was a JSON.parse() error then body is null and it fails
|
1872
|
+
httpResponse && httpResponse.body && 200;
|
1873
|
+
|
1874
|
+
var ok = status === 200 || status === 201;
|
1875
|
+
var retry = !ok && Math.floor(status / 100) !== 4 && Math.floor(status / 100) !== 1;
|
1876
|
+
|
1877
|
+
if (ok && cache) {
|
1878
|
+
cache[cacheID] = httpResponse.body;
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
if (ok) {
|
1882
|
+
return httpResponse.body;
|
1883
|
+
}
|
1884
|
+
|
1885
|
+
if (retry) {
|
1886
|
+
return retryRequest();
|
1887
|
+
}
|
1888
|
+
|
1889
|
+
var unrecoverableError = new Error(
|
1890
|
+
httpResponse.body && httpResponse.body.message || 'Unknown error'
|
1891
|
+
);
|
1892
|
+
|
1893
|
+
return client._request.reject(unrecoverableError);
|
1894
|
+
}, tryFallback);
|
1895
|
+
|
1896
|
+
function retryRequest() {
|
1897
|
+
client.currentHostIndex = ++client.currentHostIndex % client.hosts.length;
|
1898
|
+
tries += 1;
|
1899
|
+
reqOpts.timeout = client.requestTimeout * (tries + 1);
|
1900
|
+
return doRequest(requester, reqOpts);
|
1901
|
+
}
|
1902
|
+
|
1903
|
+
function tryFallback() {
|
1904
|
+
// if we are switching to fallback right now, set tries to maximum
|
1905
|
+
if (!client.forceFallback) {
|
1906
|
+
// next time doRequest is called, simulate we tried all hosts
|
1907
|
+
tries = client.hosts.length;
|
1908
|
+
} else {
|
1909
|
+
// we were already using the fallback, but something went wrong (script error)
|
1910
|
+
client.currentHostIndex = ++client.currentHostIndex % client.hosts.length;
|
1911
|
+
tries += 1;
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
return doRequest(requester, reqOpts);
|
1915
|
+
}
|
1916
|
+
}
|
1917
|
+
|
1918
|
+
// we can use a fallback if forced AND fallback parameters are available
|
1919
|
+
var useFallback = client.forceFallback && opts.fallback;
|
1920
|
+
var requestOptions = useFallback ? opts.fallback : opts;
|
1921
|
+
|
1922
|
+
var promise = doRequest(
|
1923
|
+
useFallback ? client._request.fallback : client._request, {
|
1924
|
+
url: requestOptions.url,
|
1925
|
+
method: requestOptions.method,
|
1926
|
+
body: requestOptions.body,
|
1927
|
+
timeout: client.requestTimeout * (tries + 1)
|
1928
|
+
}
|
1929
|
+
);
|
1930
|
+
|
1931
|
+
// either we have a callback
|
1932
|
+
// either we are using promises
|
1933
|
+
if (opts.callback) {
|
1934
|
+
promise.then(function okCb(content) {
|
1935
|
+
process.nextTick(function() {
|
1936
|
+
opts.callback(null, content);
|
1937
|
+
});
|
1938
|
+
}, function nookCb(err) {
|
1939
|
+
process.nextTick(function() {
|
1940
|
+
opts.callback(err);
|
1941
|
+
});
|
1942
|
+
});
|
1943
|
+
} else {
|
1944
|
+
return promise;
|
1945
|
+
}
|
1946
|
+
},
|
1947
|
+
|
1948
|
+
/*
|
1949
|
+
* Transform search param object in query string
|
1950
|
+
*/
|
1951
|
+
_getSearchParams: function(args, params) {
|
1952
|
+
if (this._isUndefined(args) || args === null) {
|
1953
|
+
return params;
|
1954
|
+
}
|
1955
|
+
for (var key in args) {
|
1956
|
+
if (key !== null && args.hasOwnProperty(key)) {
|
1957
|
+
params += params === '' ? '' : '&';
|
1958
|
+
params += key + '=' + encodeURIComponent(Object.prototype.toString.call(args[key]) === '[object Array]' ? JSON.stringify(args[key]) : args[key]);
|
1959
|
+
}
|
1960
|
+
}
|
1961
|
+
return params;
|
1962
|
+
},
|
1963
|
+
_isUndefined: function(obj) {
|
1964
|
+
return obj === void 0;
|
1965
|
+
}
|
1966
|
+
};
|
1967
|
+
|
1968
|
+
/*
|
1969
|
+
* Contains all the functions related to one index
|
1970
|
+
* You should use AlgoliaSearch.initIndex(indexName) to retrieve this object
|
1971
|
+
*/
|
1972
|
+
AlgoliaSearch.prototype.Index.prototype = {
|
1973
|
+
/*
|
1974
|
+
* Clear all queries in cache
|
1975
|
+
*/
|
1976
|
+
clearCache: function() {
|
1977
|
+
this.cache = {};
|
1978
|
+
},
|
1979
|
+
/*
|
1980
|
+
* Add an object in this index
|
1981
|
+
*
|
1982
|
+
* @param content contains the javascript object to add inside the index
|
1983
|
+
* @param objectID (optional) an objectID you want to attribute to this object
|
1984
|
+
* (if the attribute already exist the old object will be overwrite)
|
1985
|
+
* @param callback (optional) the result callback with two arguments:
|
1986
|
+
* error: null or Error('message')
|
1987
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
1988
|
+
*/
|
1989
|
+
addObject: function(content, objectID, callback) {
|
1990
|
+
var indexObj = this;
|
1991
|
+
|
1992
|
+
if (arguments.length === 1 || typeof objectID === 'function') {
|
1993
|
+
callback = objectID;
|
1994
|
+
objectID = undefined;
|
1995
|
+
}
|
1996
|
+
|
1997
|
+
return this.as._jsonRequest({
|
1998
|
+
method: objectID !== undefined ?
|
1999
|
+
'PUT' : // update or create
|
2000
|
+
'POST', // create (API generates an objectID)
|
2001
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + // create
|
2002
|
+
(objectID !== undefined ? '/' + encodeURIComponent(objectID) : ''), // update or create
|
2003
|
+
body: content,
|
2004
|
+
callback: callback
|
2005
|
+
});
|
2006
|
+
},
|
2007
|
+
/*
|
2008
|
+
* Add several objects
|
2009
|
+
*
|
2010
|
+
* @param objects contains an array of objects to add
|
2011
|
+
* @param callback (optional) the result callback with two arguments:
|
2012
|
+
* error: null or Error('message')
|
2013
|
+
* content: the server answer that updateAt and taskID
|
2014
|
+
*/
|
2015
|
+
addObjects: function(objects, callback) {
|
2016
|
+
var indexObj = this;
|
2017
|
+
var postObj = {requests: []};
|
2018
|
+
for (var i = 0; i < objects.length; ++i) {
|
2019
|
+
var request = { action: 'addObject',
|
2020
|
+
body: objects[i] };
|
2021
|
+
postObj.requests.push(request);
|
2022
|
+
}
|
2023
|
+
return this.as._jsonRequest({ method: 'POST',
|
2024
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
2025
|
+
body: postObj,
|
2026
|
+
callback: callback });
|
2027
|
+
},
|
2028
|
+
/*
|
2029
|
+
* Get an object from this index
|
2030
|
+
*
|
2031
|
+
* @param objectID the unique identifier of the object to retrieve
|
2032
|
+
* @param attrs (optional) if set, contains the array of attribute names to retrieve
|
2033
|
+
* @param callback (optional) the result callback with two arguments
|
2034
|
+
* error: null or Error('message')
|
2035
|
+
* content: the object to retrieve or the error message if a failure occured
|
2036
|
+
*/
|
2037
|
+
getObject: function(objectID, attrs, callback) {
|
2038
|
+
var indexObj = this;
|
2039
|
+
|
2040
|
+
if (arguments.length === 1 || typeof attrs === 'function') {
|
2041
|
+
callback = attrs;
|
2042
|
+
attrs = undefined;
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
var params = '';
|
2046
|
+
if (attrs !== undefined) {
|
2047
|
+
params = '?attributes=';
|
2048
|
+
for (var i = 0; i < attrs.length; ++i) {
|
2049
|
+
if (i !== 0) {
|
2050
|
+
params += ',';
|
2051
|
+
}
|
2052
|
+
params += attrs[i];
|
2053
|
+
}
|
2054
|
+
}
|
2055
|
+
|
2056
|
+
return this.as._jsonRequest({
|
2057
|
+
method: 'GET',
|
2058
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(objectID) + params,
|
2059
|
+
callback: callback
|
2060
|
+
});
|
2061
|
+
},
|
2062
|
+
|
2063
|
+
/*
|
2064
|
+
* Update partially an object (only update attributes passed in argument)
|
2065
|
+
*
|
2066
|
+
* @param partialObject contains the javascript attributes to override, the
|
2067
|
+
* object must contains an objectID attribute
|
2068
|
+
* @param callback (optional) the result callback with two arguments:
|
2069
|
+
* error: null or Error('message')
|
2070
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
2071
|
+
*/
|
2072
|
+
partialUpdateObject: function(partialObject, callback) {
|
2073
|
+
var indexObj = this;
|
2074
|
+
return this.as._jsonRequest({ method: 'POST',
|
2075
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(partialObject.objectID) + '/partial',
|
2076
|
+
body: partialObject,
|
2077
|
+
callback: callback });
|
2078
|
+
},
|
2079
|
+
/*
|
2080
|
+
* Partially Override the content of several objects
|
2081
|
+
*
|
2082
|
+
* @param objects contains an array of objects to update (each object must contains a objectID attribute)
|
2083
|
+
* @param callback (optional) the result callback with two arguments:
|
2084
|
+
* error: null or Error('message')
|
2085
|
+
* content: the server answer that updateAt and taskID
|
2086
|
+
*/
|
2087
|
+
partialUpdateObjects: function(objects, callback) {
|
2088
|
+
var indexObj = this;
|
2089
|
+
var postObj = {requests: []};
|
2090
|
+
for (var i = 0; i < objects.length; ++i) {
|
2091
|
+
var request = { action: 'partialUpdateObject',
|
2092
|
+
objectID: objects[i].objectID,
|
2093
|
+
body: objects[i] };
|
2094
|
+
postObj.requests.push(request);
|
2095
|
+
}
|
2096
|
+
return this.as._jsonRequest({ method: 'POST',
|
2097
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
2098
|
+
body: postObj,
|
2099
|
+
callback: callback });
|
2100
|
+
},
|
2101
|
+
/*
|
2102
|
+
* Override the content of object
|
2103
|
+
*
|
2104
|
+
* @param object contains the javascript object to save, the object must contains an objectID attribute
|
2105
|
+
* @param callback (optional) the result callback with two arguments:
|
2106
|
+
* error: null or Error('message')
|
2107
|
+
* content: the server answer that updateAt and taskID
|
2108
|
+
*/
|
2109
|
+
saveObject: function(object, callback) {
|
2110
|
+
var indexObj = this;
|
2111
|
+
return this.as._jsonRequest({ method: 'PUT',
|
2112
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(object.objectID),
|
2113
|
+
body: object,
|
2114
|
+
callback: callback });
|
2115
|
+
},
|
2116
|
+
/*
|
2117
|
+
* Override the content of several objects
|
2118
|
+
*
|
2119
|
+
* @param objects contains an array of objects to update (each object must contains a objectID attribute)
|
2120
|
+
* @param callback (optional) the result callback with two arguments:
|
2121
|
+
* error: null or Error('message')
|
2122
|
+
* content: the server answer that updateAt and taskID
|
2123
|
+
*/
|
2124
|
+
saveObjects: function(objects, callback) {
|
2125
|
+
var indexObj = this;
|
2126
|
+
var postObj = {requests: []};
|
2127
|
+
for (var i = 0; i < objects.length; ++i) {
|
2128
|
+
var request = { action: 'updateObject',
|
2129
|
+
objectID: objects[i].objectID,
|
2130
|
+
body: objects[i] };
|
2131
|
+
postObj.requests.push(request);
|
2132
|
+
}
|
2133
|
+
return this.as._jsonRequest({ method: 'POST',
|
2134
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
2135
|
+
body: postObj,
|
2136
|
+
callback: callback });
|
2137
|
+
},
|
2138
|
+
/*
|
2139
|
+
* Delete an object from the index
|
2140
|
+
*
|
2141
|
+
* @param objectID the unique identifier of object to delete
|
2142
|
+
* @param callback (optional) the result callback with two arguments:
|
2143
|
+
* error: null or Error('message')
|
2144
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
2145
|
+
*/
|
2146
|
+
deleteObject: function(objectID, callback) {
|
2147
|
+
if (typeof objectID === 'function' || typeof objectID !== 'string' && typeof objectID !== 'number') {
|
2148
|
+
var err = new Error('Cannot delete an object without an objectID');
|
2149
|
+
callback = objectID;
|
2150
|
+
if (typeof callback === 'function') {
|
2151
|
+
return callback(err);
|
2152
|
+
}
|
2153
|
+
|
2154
|
+
return this.as._request.reject(err);
|
2155
|
+
}
|
2156
|
+
|
2157
|
+
var indexObj = this;
|
2158
|
+
return this.as._jsonRequest({ method: 'DELETE',
|
2159
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(objectID),
|
2160
|
+
callback: callback });
|
2161
|
+
},
|
2162
|
+
/*
|
2163
|
+
* Search inside the index using XMLHttpRequest request (Using a POST query to
|
2164
|
+
* minimize number of OPTIONS queries: Cross-Origin Resource Sharing).
|
2165
|
+
*
|
2166
|
+
* @param query the full text query
|
2167
|
+
* @param args (optional) if set, contains an object with query parameters:
|
2168
|
+
* - page: (integer) Pagination parameter used to select the page to retrieve.
|
2169
|
+
* Page is zero-based and defaults to 0. Thus, to retrieve the 10th page you need to set page=9
|
2170
|
+
* - hitsPerPage: (integer) Pagination parameter used to select the number of hits per page. Defaults to 20.
|
2171
|
+
* - attributesToRetrieve: a string that contains the list of object attributes you want to retrieve (let you minimize the answer size).
|
2172
|
+
* Attributes are separated with a comma (for example "name,address").
|
2173
|
+
* You can also use an array (for example ["name","address"]).
|
2174
|
+
* By default, all attributes are retrieved. You can also use '*' to retrieve all values when an attributesToRetrieve setting is specified for your index.
|
2175
|
+
* - attributesToHighlight: a string that contains the list of attributes you want to highlight according to the query.
|
2176
|
+
* Attributes are separated by a comma. You can also use an array (for example ["name","address"]).
|
2177
|
+
* If an attribute has no match for the query, the raw value is returned. By default all indexed text attributes are highlighted.
|
2178
|
+
* You can use `*` if you want to highlight all textual attributes. Numerical attributes are not highlighted.
|
2179
|
+
* A matchLevel is returned for each highlighted attribute and can contain:
|
2180
|
+
* - full: if all the query terms were found in the attribute,
|
2181
|
+
* - partial: if only some of the query terms were found,
|
2182
|
+
* - none: if none of the query terms were found.
|
2183
|
+
* - attributesToSnippet: a string that contains the list of attributes to snippet alongside the number of words to return (syntax is `attributeName:nbWords`).
|
2184
|
+
* Attributes are separated by a comma (Example: attributesToSnippet=name:10,content:10).
|
2185
|
+
* You can also use an array (Example: attributesToSnippet: ['name:10','content:10']). By default no snippet is computed.
|
2186
|
+
* - minWordSizefor1Typo: the minimum number of characters in a query word to accept one typo in this word. Defaults to 3.
|
2187
|
+
* - minWordSizefor2Typos: the minimum number of characters in a query word to accept two typos in this word. Defaults to 7.
|
2188
|
+
* - getRankingInfo: if set to 1, the result hits will contain ranking information in _rankingInfo attribute.
|
2189
|
+
* - aroundLatLng: search for entries around a given latitude/longitude (specified as two floats separated by a comma).
|
2190
|
+
* For example aroundLatLng=47.316669,5.016670).
|
2191
|
+
* You can specify the maximum distance in meters with the aroundRadius parameter (in meters) and the precision for ranking with aroundPrecision
|
2192
|
+
* (for example if you set aroundPrecision=100, two objects that are distant of less than 100m will be considered as identical for "geo" ranking parameter).
|
2193
|
+
* At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form {"_geoloc":{"lat":48.853409, "lng":2.348800}})
|
2194
|
+
* - insideBoundingBox: search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng).
|
2195
|
+
* For example insideBoundingBox=47.3165,4.9665,47.3424,5.0201).
|
2196
|
+
* At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form {"_geoloc":{"lat":48.853409, "lng":2.348800}})
|
2197
|
+
* - numericFilters: a string that contains the list of numeric filters you want to apply separated by a comma.
|
2198
|
+
* The syntax of one filter is `attributeName` followed by `operand` followed by `value`. Supported operands are `<`, `<=`, `=`, `>` and `>=`.
|
2199
|
+
* You can have multiple conditions on one attribute like for example numericFilters=price>100,price<1000.
|
2200
|
+
* You can also use an array (for example numericFilters: ["price>100","price<1000"]).
|
2201
|
+
* - tagFilters: filter the query by a set of tags. You can AND tags by separating them by commas.
|
2202
|
+
* To OR tags, you must add parentheses. For example, tags=tag1,(tag2,tag3) means tag1 AND (tag2 OR tag3).
|
2203
|
+
* You can also use an array, for example tagFilters: ["tag1",["tag2","tag3"]] means tag1 AND (tag2 OR tag3).
|
2204
|
+
* At indexing, tags should be added in the _tags** attribute of objects (for example {"_tags":["tag1","tag2"]}).
|
2205
|
+
* - facetFilters: filter the query by a list of facets.
|
2206
|
+
* Facets are separated by commas and each facet is encoded as `attributeName:value`.
|
2207
|
+
* For example: `facetFilters=category:Book,author:John%20Doe`.
|
2208
|
+
* You can also use an array (for example `["category:Book","author:John%20Doe"]`).
|
2209
|
+
* - facets: List of object attributes that you want to use for faceting.
|
2210
|
+
* Comma separated list: `"category,author"` or array `['category','author']`
|
2211
|
+
* Only attributes that have been added in **attributesForFaceting** index setting can be used in this parameter.
|
2212
|
+
* You can also use `*` to perform faceting on all attributes specified in **attributesForFaceting**.
|
2213
|
+
* - queryType: select how the query words are interpreted, it can be one of the following value:
|
2214
|
+
* - prefixAll: all query words are interpreted as prefixes,
|
2215
|
+
* - prefixLast: only the last word is interpreted as a prefix (default behavior),
|
2216
|
+
* - prefixNone: no query word is interpreted as a prefix. This option is not recommended.
|
2217
|
+
* - optionalWords: a string that contains the list of words that should be considered as optional when found in the query.
|
2218
|
+
* Comma separated and array are accepted.
|
2219
|
+
* - distinct: If set to 1, enable the distinct feature (disabled by default) if the attributeForDistinct index setting is set.
|
2220
|
+
* This feature is similar to the SQL "distinct" keyword: when enabled in a query with the distinct=1 parameter,
|
2221
|
+
* all hits containing a duplicate value for the attributeForDistinct attribute are removed from results.
|
2222
|
+
* For example, if the chosen attribute is show_name and several hits have the same value for show_name, then only the best
|
2223
|
+
* one is kept and others are removed.
|
2224
|
+
* - restrictSearchableAttributes: List of attributes you want to use for textual search (must be a subset of the attributesToIndex index setting)
|
2225
|
+
* either comma separated or as an array
|
2226
|
+
* @param callback the result callback with two arguments:
|
2227
|
+
* error: null or Error('message'). If false, the content contains the error.
|
2228
|
+
* content: the server answer that contains the list of results.
|
2229
|
+
*/
|
2230
|
+
search: function(query, args, callback) {
|
2231
|
+
if (arguments.length === 0 || typeof query === 'function') {
|
2232
|
+
// .search(), .search(cb)
|
2233
|
+
callback = query;
|
2234
|
+
query = '';
|
2235
|
+
} else if (arguments.length === 1 || typeof args === 'function') {
|
2236
|
+
// .search(query/args), .search(query, cb)
|
2237
|
+
callback = args;
|
2238
|
+
args = undefined;
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
// .search(args), careful: typeof null === 'object'
|
2242
|
+
if (typeof query === 'object' && query !== null) {
|
2243
|
+
args = query;
|
2244
|
+
query = undefined;
|
2245
|
+
} else if (query === undefined || query === null) { // .search(undefined/null)
|
2246
|
+
query = '';
|
2247
|
+
}
|
2248
|
+
|
2249
|
+
var params = '';
|
2250
|
+
|
2251
|
+
if (query !== undefined) {
|
2252
|
+
params += 'query=' + encodeURIComponent(query);
|
2253
|
+
}
|
2254
|
+
|
2255
|
+
if (args !== undefined) {
|
2256
|
+
params = this.as._getSearchParams(args, params);
|
2257
|
+
}
|
2258
|
+
|
2259
|
+
return this._search(params, callback);
|
2260
|
+
},
|
2261
|
+
|
2262
|
+
/*
|
2263
|
+
* Browse all index content
|
2264
|
+
*
|
2265
|
+
* @param page Pagination parameter used to select the page to retrieve.
|
2266
|
+
* Page is zero-based and defaults to 0. Thus, to retrieve the 10th page you need to set page=9
|
2267
|
+
* @param hitsPerPage: Pagination parameter used to select the number of hits per page. Defaults to 1000.
|
2268
|
+
* @param callback the result callback with two arguments:
|
2269
|
+
* error: null or Error('message'). If false, the content contains the error.
|
2270
|
+
* content: the server answer that contains the list of results.
|
2271
|
+
*/
|
2272
|
+
browse: function(page, hitsPerPage, callback) {
|
2273
|
+
var indexObj = this;
|
2274
|
+
|
2275
|
+
if (arguments.length === 1 || typeof hitsPerPage === 'function') {
|
2276
|
+
callback = hitsPerPage;
|
2277
|
+
hitsPerPage = undefined;
|
2278
|
+
}
|
2279
|
+
|
2280
|
+
var params = '?page=' + page;
|
2281
|
+
if (!this.as._isUndefined(hitsPerPage)) {
|
2282
|
+
params += '&hitsPerPage=' + hitsPerPage;
|
2283
|
+
}
|
2284
|
+
return this.as._jsonRequest({ method: 'GET',
|
2285
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/browse' + params,
|
2286
|
+
callback: callback });
|
2287
|
+
},
|
2288
|
+
|
2289
|
+
/*
|
2290
|
+
* Get a Typeahead.js adapter
|
2291
|
+
* @param searchParams contains an object with query parameters (see search for details)
|
2292
|
+
*/
|
2293
|
+
ttAdapter: function(params) {
|
2294
|
+
var self = this;
|
2295
|
+
return function(query, cb) {
|
2296
|
+
self.search(query, params, function(err, content) {
|
2297
|
+
if (err) {
|
2298
|
+
cb(err);
|
2299
|
+
return;
|
2300
|
+
}
|
2301
|
+
|
2302
|
+
cb(content.hits);
|
2303
|
+
});
|
2304
|
+
};
|
2305
|
+
},
|
2306
|
+
|
2307
|
+
/*
|
2308
|
+
* Wait the publication of a task on the server.
|
2309
|
+
* All server task are asynchronous and you can check with this method that the task is published.
|
2310
|
+
*
|
2311
|
+
* @param taskID the id of the task returned by server
|
2312
|
+
* @param callback the result callback with with two arguments:
|
2313
|
+
* error: null or Error('message')
|
2314
|
+
* content: the server answer that contains the list of results
|
2315
|
+
*/
|
2316
|
+
waitTask: function(taskID, callback) {
|
2317
|
+
// waitTask() must be handled differently from other methods,
|
2318
|
+
// it's a recursive method using a timeout
|
2319
|
+
var indexObj = this;
|
2320
|
+
|
2321
|
+
var promise = this.as._jsonRequest({
|
2322
|
+
method: 'GET',
|
2323
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/task/' + taskID
|
2324
|
+
}).then(function success(content) {
|
2325
|
+
if (content.status !== 'published') {
|
2326
|
+
return new indexObj.as._request.delay(100).then(function() {
|
2327
|
+
return indexObj.waitTask(taskID, callback);
|
2328
|
+
});
|
2329
|
+
}
|
2330
|
+
|
2331
|
+
if (callback) {
|
2332
|
+
process.nextTick(function() {
|
2333
|
+
callback(null, content);
|
2334
|
+
});
|
2335
|
+
} else {
|
2336
|
+
return content;
|
2337
|
+
}
|
2338
|
+
}, function failure(err) {
|
2339
|
+
if (callback) {
|
2340
|
+
process.nextTick(function() {
|
2341
|
+
callback(err);
|
2342
|
+
});
|
2343
|
+
} else {
|
2344
|
+
return err;
|
2345
|
+
}
|
2346
|
+
});
|
2347
|
+
|
2348
|
+
if (!callback) {
|
2349
|
+
return promise;
|
2350
|
+
}
|
2351
|
+
},
|
2352
|
+
|
2353
|
+
/*
|
2354
|
+
* This function deletes the index content. Settings and index specific API keys are kept untouched.
|
2355
|
+
*
|
2356
|
+
* @param callback (optional) the result callback with two arguments
|
2357
|
+
* error: null or Error('message')
|
2358
|
+
* content: the settings object or the error message if a failure occured
|
2359
|
+
*/
|
2360
|
+
clearIndex: function(callback) {
|
2361
|
+
var indexObj = this;
|
2362
|
+
return this.as._jsonRequest({ method: 'POST',
|
2363
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/clear',
|
2364
|
+
callback: callback });
|
2365
|
+
},
|
2366
|
+
/*
|
2367
|
+
* Get settings of this index
|
2368
|
+
*
|
2369
|
+
* @param callback (optional) the result callback with two arguments
|
2370
|
+
* error: null or Error('message')
|
2371
|
+
* content: the settings object or the error message if a failure occured
|
2372
|
+
*/
|
2373
|
+
getSettings: function(callback) {
|
2374
|
+
var indexObj = this;
|
2375
|
+
return this.as._jsonRequest({ method: 'GET',
|
2376
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/settings',
|
2377
|
+
callback: callback });
|
2378
|
+
},
|
2379
|
+
|
2380
|
+
/*
|
2381
|
+
* Set settings for this index
|
2382
|
+
*
|
2383
|
+
* @param settigns the settings object that can contains :
|
2384
|
+
* - minWordSizefor1Typo: (integer) the minimum number of characters to accept one typo (default = 3).
|
2385
|
+
* - minWordSizefor2Typos: (integer) the minimum number of characters to accept two typos (default = 7).
|
2386
|
+
* - hitsPerPage: (integer) the number of hits per page (default = 10).
|
2387
|
+
* - attributesToRetrieve: (array of strings) default list of attributes to retrieve in objects.
|
2388
|
+
* If set to null, all attributes are retrieved.
|
2389
|
+
* - attributesToHighlight: (array of strings) default list of attributes to highlight.
|
2390
|
+
* If set to null, all indexed attributes are highlighted.
|
2391
|
+
* - attributesToSnippet**: (array of strings) default list of attributes to snippet alongside the number of words to return (syntax is attributeName:nbWords).
|
2392
|
+
* By default no snippet is computed. If set to null, no snippet is computed.
|
2393
|
+
* - attributesToIndex: (array of strings) the list of fields you want to index.
|
2394
|
+
* If set to null, all textual and numerical attributes of your objects are indexed, but you should update it to get optimal results.
|
2395
|
+
* This parameter has two important uses:
|
2396
|
+
* - Limit the attributes to index: For example if you store a binary image in base64, you want to store it and be able to
|
2397
|
+
* retrieve it but you don't want to search in the base64 string.
|
2398
|
+
* - Control part of the ranking*: (see the ranking parameter for full explanation) Matches in attributes at the beginning of
|
2399
|
+
* the list will be considered more important than matches in attributes further down the list.
|
2400
|
+
* In one attribute, matching text at the beginning of the attribute will be considered more important than text after, you can disable
|
2401
|
+
* this behavior if you add your attribute inside `unordered(AttributeName)`, for example attributesToIndex: ["title", "unordered(text)"].
|
2402
|
+
* - attributesForFaceting: (array of strings) The list of fields you want to use for faceting.
|
2403
|
+
* All strings in the attribute selected for faceting are extracted and added as a facet. If set to null, no attribute is used for faceting.
|
2404
|
+
* - attributeForDistinct: (string) The attribute name used for the Distinct feature. This feature is similar to the SQL "distinct" keyword: when enabled
|
2405
|
+
* in query with the distinct=1 parameter, all hits containing a duplicate value for this attribute are removed from results.
|
2406
|
+
* For example, if the chosen attribute is show_name and several hits have the same value for show_name, then only the best one is kept and others are removed.
|
2407
|
+
* - ranking: (array of strings) controls the way results are sorted.
|
2408
|
+
* We have six available criteria:
|
2409
|
+
* - typo: sort according to number of typos,
|
2410
|
+
* - geo: sort according to decreassing distance when performing a geo-location based search,
|
2411
|
+
* - proximity: sort according to the proximity of query words in hits,
|
2412
|
+
* - attribute: sort according to the order of attributes defined by attributesToIndex,
|
2413
|
+
* - exact:
|
2414
|
+
* - if the user query contains one word: sort objects having an attribute that is exactly the query word before others.
|
2415
|
+
* For example if you search for the "V" TV show, you want to find it with the "V" query and avoid to have all popular TV
|
2416
|
+
* show starting by the v letter before it.
|
2417
|
+
* - if the user query contains multiple words: sort according to the number of words that matched exactly (and not as a prefix).
|
2418
|
+
* - custom: sort according to a user defined formula set in **customRanking** attribute.
|
2419
|
+
* The standard order is ["typo", "geo", "proximity", "attribute", "exact", "custom"]
|
2420
|
+
* - customRanking: (array of strings) lets you specify part of the ranking.
|
2421
|
+
* The syntax of this condition is an array of strings containing attributes prefixed by asc (ascending order) or desc (descending order) operator.
|
2422
|
+
* For example `"customRanking" => ["desc(population)", "asc(name)"]`
|
2423
|
+
* - queryType: Select how the query words are interpreted, it can be one of the following value:
|
2424
|
+
* - prefixAll: all query words are interpreted as prefixes,
|
2425
|
+
* - prefixLast: only the last word is interpreted as a prefix (default behavior),
|
2426
|
+
* - prefixNone: no query word is interpreted as a prefix. This option is not recommended.
|
2427
|
+
* - highlightPreTag: (string) Specify the string that is inserted before the highlighted parts in the query result (default to "<em>").
|
2428
|
+
* - highlightPostTag: (string) Specify the string that is inserted after the highlighted parts in the query result (default to "</em>").
|
2429
|
+
* - optionalWords: (array of strings) Specify a list of words that should be considered as optional when found in the query.
|
2430
|
+
* @param callback (optional) the result callback with two arguments
|
2431
|
+
* error: null or Error('message')
|
2432
|
+
* content: the server answer or the error message if a failure occured
|
2433
|
+
*/
|
2434
|
+
setSettings: function(settings, callback) {
|
2435
|
+
var indexObj = this;
|
2436
|
+
return this.as._jsonRequest({ method: 'PUT',
|
2437
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/settings',
|
2438
|
+
body: settings,
|
2439
|
+
callback: callback });
|
2440
|
+
},
|
2441
|
+
/*
|
2442
|
+
* List all existing user keys associated to this index
|
2443
|
+
*
|
2444
|
+
* @param callback the result callback with two arguments
|
2445
|
+
* error: null or Error('message')
|
2446
|
+
* content: the server answer with user keys list
|
2447
|
+
*/
|
2448
|
+
listUserKeys: function(callback) {
|
2449
|
+
var indexObj = this;
|
2450
|
+
return this.as._jsonRequest({ method: 'GET',
|
2451
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
2452
|
+
callback: callback });
|
2453
|
+
},
|
2454
|
+
/*
|
2455
|
+
* Get ACL of a user key associated to this index
|
2456
|
+
*
|
2457
|
+
* @param key
|
2458
|
+
* @param callback the result callback with two arguments
|
2459
|
+
* error: null or Error('message')
|
2460
|
+
* content: the server answer with user keys list
|
2461
|
+
*/
|
2462
|
+
getUserKeyACL: function(key, callback) {
|
2463
|
+
var indexObj = this;
|
2464
|
+
return this.as._jsonRequest({ method: 'GET',
|
2465
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys/' + key,
|
2466
|
+
callback: callback });
|
2467
|
+
},
|
2468
|
+
/*
|
2469
|
+
* Delete an existing user key associated to this index
|
2470
|
+
*
|
2471
|
+
* @param key
|
2472
|
+
* @param callback the result callback with two arguments
|
2473
|
+
* error: null or Error('message')
|
2474
|
+
* content: the server answer with user keys list
|
2475
|
+
*/
|
2476
|
+
deleteUserKey: function(key, callback) {
|
2477
|
+
var indexObj = this;
|
2478
|
+
return this.as._jsonRequest({ method: 'DELETE',
|
2479
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys/' + key,
|
2480
|
+
callback: callback });
|
2481
|
+
},
|
2482
|
+
/*
|
2483
|
+
* Add an existing user key associated to this index
|
2484
|
+
*
|
2485
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
2486
|
+
* can contains the following values:
|
2487
|
+
* - search: allow to search (https and http)
|
2488
|
+
* - addObject: allows to add/update an object in the index (https only)
|
2489
|
+
* - deleteObject : allows to delete an existing object (https only)
|
2490
|
+
* - deleteIndex : allows to delete index content (https only)
|
2491
|
+
* - settings : allows to get index settings (https only)
|
2492
|
+
* - editSettings : allows to change index settings (https only)
|
2493
|
+
* @param callback the result callback with two arguments
|
2494
|
+
* error: null or Error('message')
|
2495
|
+
* content: the server answer with user keys list
|
2496
|
+
*/
|
2497
|
+
addUserKey: function(acls, callback) {
|
2498
|
+
var indexObj = this;
|
2499
|
+
var aclsObject = {};
|
2500
|
+
aclsObject.acl = acls;
|
2501
|
+
return this.as._jsonRequest({ method: 'POST',
|
2502
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
2503
|
+
body: aclsObject,
|
2504
|
+
callback: callback });
|
2505
|
+
},
|
2506
|
+
/*
|
2507
|
+
* Add an existing user key associated to this index
|
2508
|
+
*
|
2509
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
2510
|
+
* can contains the following values:
|
2511
|
+
* - search: allow to search (https and http)
|
2512
|
+
* - addObject: allows to add/update an object in the index (https only)
|
2513
|
+
* - deleteObject : allows to delete an existing object (https only)
|
2514
|
+
* - deleteIndex : allows to delete index content (https only)
|
2515
|
+
* - settings : allows to get index settings (https only)
|
2516
|
+
* - editSettings : allows to change index settings (https only)
|
2517
|
+
* @param params.validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
|
2518
|
+
* @param params.maxQueriesPerIPPerHour Specify the maximum number of API calls allowed from an IP address per hour.
|
2519
|
+
* @param params.maxHitsPerQuery Specify the maximum number of hits this API key can retrieve in one call.
|
2520
|
+
* @param callback the result callback with two arguments
|
2521
|
+
* error: null or Error('message')
|
2522
|
+
* content: the server answer with user keys list
|
2523
|
+
*/
|
2524
|
+
addUserKeyWithValidity: function(acls, params, callback) {
|
2525
|
+
var indexObj = this;
|
2526
|
+
var aclsObject = {};
|
2527
|
+
aclsObject.acl = acls;
|
2528
|
+
aclsObject.validity = params.validity;
|
2529
|
+
aclsObject.maxQueriesPerIPPerHour = params.maxQueriesPerIPPerHour;
|
2530
|
+
aclsObject.maxHitsPerQuery = params.maxHitsPerQuery;
|
2531
|
+
return this.as._jsonRequest({ method: 'POST',
|
2532
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
2533
|
+
body: aclsObject,
|
2534
|
+
callback: callback });
|
2535
|
+
},
|
2536
|
+
///
|
2537
|
+
/// Internal methods only after this line
|
2538
|
+
///
|
2539
|
+
_search: function(params, callback) {
|
2540
|
+
return this.as._jsonRequest({ cache: this.cache,
|
2541
|
+
method: 'POST',
|
2542
|
+
url: '/1/indexes/' + encodeURIComponent(this.indexName) + '/query',
|
2543
|
+
body: {params: params},
|
2544
|
+
fallback: {
|
2545
|
+
method: 'GET',
|
2546
|
+
url: '/1/indexes/' + encodeURIComponent(this.indexName),
|
2547
|
+
body: {params: params}
|
2548
|
+
},
|
2549
|
+
callback: callback
|
2550
|
+
});
|
2551
|
+
},
|
2552
|
+
|
2553
|
+
// internal attributes
|
2554
|
+
as: null,
|
2555
|
+
indexName: null,
|
2556
|
+
typeAheadArgs: null,
|
2557
|
+
typeAheadValueOption: null
|
2558
|
+
};
|
2559
|
+
|
2560
|
+
// extracted from https://github.com/component/map/blob/master/index.js
|
2561
|
+
// without the crazy toFunction thing
|
2562
|
+
function map(arr, fn){
|
2563
|
+
var ret = [];
|
2564
|
+
for (var i = 0; i < arr.length; ++i) {
|
2565
|
+
ret.push(fn(arr[i], i));
|
2566
|
+
}
|
2567
|
+
return ret;
|
2568
|
+
}
|
2569
|
+
|
2570
|
+
// extracted from https://github.com/coolaj86/knuth-shuffle
|
2571
|
+
// not compatible with browserify
|
2572
|
+
function shuffle(array) {
|
2573
|
+
/*eslint-disable*/
|
2574
|
+
var currentIndex = array.length
|
2575
|
+
, temporaryValue
|
2576
|
+
, randomIndex
|
2577
|
+
;
|
2578
|
+
|
2579
|
+
// While there remain elements to shuffle...
|
2580
|
+
while (0 !== currentIndex) {
|
2581
|
+
|
2582
|
+
// Pick a remaining element...
|
2583
|
+
randomIndex = Math.floor(Math.random() * currentIndex);
|
2584
|
+
currentIndex -= 1;
|
2585
|
+
|
2586
|
+
// And swap it with the current element.
|
2587
|
+
temporaryValue = array[currentIndex];
|
2588
|
+
array[currentIndex] = array[randomIndex];
|
2589
|
+
array[randomIndex] = temporaryValue;
|
2590
|
+
}
|
2591
|
+
|
2592
|
+
return array;
|
2593
|
+
}
|
2594
|
+
|
2595
|
+
}).call(this,require(2))
|
2596
|
+
},{"2":2}],5:[function(require,module,exports){
|
2597
|
+
module.exports = JSONPRequest;
|
2598
|
+
|
2599
|
+
var JSONPCounter = 0;
|
2600
|
+
|
2601
|
+
function JSONPRequest(url, opts, cb) {
|
2602
|
+
if (opts.method !== 'GET') {
|
2603
|
+
cb(new Error('Method ' + opts.method + ' ' + url + ' is not supported by JSONP.'));
|
2604
|
+
return;
|
2605
|
+
}
|
2606
|
+
|
2607
|
+
var cbCalled = false;
|
2608
|
+
var timedOut = false;
|
2609
|
+
|
2610
|
+
JSONPCounter += 1;
|
2611
|
+
var head = document.getElementsByTagName('head')[0];
|
2612
|
+
var script = document.createElement('script');
|
2613
|
+
var cbName = 'algoliaJSONP_' + JSONPCounter;
|
2614
|
+
var done = false;
|
2615
|
+
|
2616
|
+
window[cbName] = function(data) {
|
2617
|
+
try {
|
2618
|
+
delete window[cbName];
|
2619
|
+
} catch (e) {
|
2620
|
+
window[cbName] = undefined;
|
2621
|
+
}
|
2622
|
+
|
2623
|
+
if (timedOut) {
|
2624
|
+
return;
|
2625
|
+
}
|
2626
|
+
|
2627
|
+
cbCalled = true;
|
2628
|
+
|
2629
|
+
clean();
|
2630
|
+
|
2631
|
+
cb(null, {
|
2632
|
+
body: data/*,
|
2633
|
+
// We do not send the statusCode, there's no statusCode in JSONP, it will be
|
2634
|
+
// computed using data.status && data.message like with XDR
|
2635
|
+
statusCode*/
|
2636
|
+
});
|
2637
|
+
};
|
2638
|
+
|
2639
|
+
// add callback by hand
|
2640
|
+
url += '&callback=' + cbName;
|
2641
|
+
|
2642
|
+
// add body params by hand
|
2643
|
+
if (opts.body && opts.body.params) {
|
2644
|
+
url += '&' + opts.body.params;
|
2645
|
+
}
|
2646
|
+
|
2647
|
+
var ontimeout = setTimeout(timeout, opts.timeout);
|
2648
|
+
|
2649
|
+
// script onreadystatechange needed only for
|
2650
|
+
// <= IE8
|
2651
|
+
// https://github.com/angular/angular.js/issues/4523
|
2652
|
+
script.onreadystatechange = readystatechange;
|
2653
|
+
script.onload = success;
|
2654
|
+
script.onerror = error;
|
2655
|
+
|
2656
|
+
script.async = true;
|
2657
|
+
script.defer = true;
|
2658
|
+
script.src = url;
|
2659
|
+
head.appendChild(script);
|
2660
|
+
|
2661
|
+
function success() {
|
2662
|
+
if (done || timedOut) {
|
2663
|
+
return;
|
2664
|
+
}
|
2665
|
+
|
2666
|
+
done = true;
|
2667
|
+
|
2668
|
+
// script loaded but did not call the fn => script loading error
|
2669
|
+
if (!cbCalled) {
|
2670
|
+
clean();
|
2671
|
+
cb(new Error('Failed to load JSONP script'));
|
2672
|
+
}
|
2673
|
+
}
|
2674
|
+
|
2675
|
+
function readystatechange() {
|
2676
|
+
if (this.readyState === 'loaded' || this.readyState === 'complete') {
|
2677
|
+
success();
|
2678
|
+
}
|
2679
|
+
}
|
2680
|
+
|
2681
|
+
function clean() {
|
2682
|
+
clearTimeout(ontimeout);
|
2683
|
+
script.onload = null;
|
2684
|
+
script.onreadystatechange = null;
|
2685
|
+
script.onerror = null;
|
2686
|
+
head.removeChild(script);
|
2687
|
+
|
2688
|
+
try {
|
2689
|
+
delete window[cbName];
|
2690
|
+
delete window[cbName + '_loaded'];
|
2691
|
+
} catch (e) {
|
2692
|
+
window[cbName] = null;
|
2693
|
+
window[cbName + '_loaded'] = null;
|
2694
|
+
}
|
2695
|
+
}
|
2696
|
+
|
2697
|
+
function timeout() {
|
2698
|
+
timedOut = true;
|
2699
|
+
clean();
|
2700
|
+
cb(new Error('Timeout - Could not connect to endpoint ' + url));
|
2701
|
+
}
|
2702
|
+
|
2703
|
+
function error() {
|
2704
|
+
if (done || timedOut) {
|
2705
|
+
return;
|
2706
|
+
}
|
2707
|
+
|
2708
|
+
clean();
|
2709
|
+
cb(new Error('Failed to load JSONP script'));
|
2710
|
+
}
|
2711
|
+
}
|
2712
|
+
|
2713
|
+
},{}],6:[function(require,module,exports){
|
2714
|
+
// this file is a `factory of algoliasearch()`
|
2715
|
+
// Given a `request` param, it will provide you an AlgoliaSearch client
|
2716
|
+
// using this particular request
|
2717
|
+
module.exports = createAlgoliasearch;
|
2718
|
+
|
2719
|
+
function createAlgoliasearch(request) {
|
2720
|
+
function algoliasearch(applicationID, apiKey, opts) {
|
2721
|
+
var AlgoliaSearch = require(4);
|
2722
|
+
|
2723
|
+
return new AlgoliaSearch(applicationID, apiKey, opts, request);
|
2724
|
+
}
|
2725
|
+
|
2726
|
+
algoliasearch.version = "3.0.3";
|
2727
|
+
|
2728
|
+
return algoliasearch;
|
2729
|
+
}
|
2730
|
+
|
2731
|
+
},{"4":4}]},{},[1])(1)
|
2732
|
+
});
|