algoliasearch-rails 1.11.17 → 1.11.18

Sign up to get free protection for your applications and to get access to all the features.
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
+ });