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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +4 -0
  3. data/README.md +48 -6
  4. data/VERSION +1 -1
  5. data/algoliasearch-rails.gemspec +22 -6
  6. data/vendor/assets/javascripts/algolia/algoliasearch.angular.js +1446 -1378
  7. data/vendor/assets/javascripts/algolia/algoliasearch.angular.min.js +2 -2
  8. data/vendor/assets/javascripts/algolia/algoliasearch.jquery.js +1446 -1378
  9. data/vendor/assets/javascripts/algolia/algoliasearch.jquery.min.js +2 -2
  10. data/vendor/assets/javascripts/algolia/algoliasearch.js +1446 -1378
  11. data/vendor/assets/javascripts/algolia/algoliasearch.min.js +2 -2
  12. data/vendor/assets/javascripts/algolia/bloodhound.min.js +7 -0
  13. data/vendor/assets/javascripts/algolia/typeahead.jquery.min.js +7 -0
  14. data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.js +2667 -0
  15. data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.min.js +7 -0
  16. data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.js +2667 -0
  17. data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.min.js +7 -0
  18. data/vendor/assets/javascripts/algolia/v2/algoliasearch.js +2653 -0
  19. data/vendor/assets/javascripts/algolia/v2/algoliasearch.min.js +7 -0
  20. data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.js +1717 -0
  21. data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.min.js +37 -0
  22. data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.js +1702 -0
  23. data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.min.js +37 -0
  24. data/vendor/assets/javascripts/algolia/v3/algoliasearch.js +2732 -0
  25. data/vendor/assets/javascripts/algolia/v3/algoliasearch.min.js +50 -0
  26. 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
+ });