algoliasearch-rails 1.11.17 → 1.11.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog +4 -0
- data/README.md +48 -6
- data/VERSION +1 -1
- data/algoliasearch-rails.gemspec +22 -6
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.js +1446 -1378
- data/vendor/assets/javascripts/algolia/algoliasearch.min.js +2 -2
- data/vendor/assets/javascripts/algolia/bloodhound.min.js +7 -0
- data/vendor/assets/javascripts/algolia/typeahead.jquery.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.js +2667 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.js +2667 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.js +2653 -0
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.min.js +7 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.js +1717 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.min.js +37 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.js +1702 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.min.js +37 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.js +2732 -0
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.min.js +50 -0
- metadata +36 -22
@@ -0,0 +1,7 @@
|
|
1
|
+
/*!
|
2
|
+
* algoliasearch 2.9.4
|
3
|
+
* https://github.com/algolia/algoliasearch-client-js
|
4
|
+
* Copyright 2014 Algolia SAS; Licensed MIT
|
5
|
+
*/
|
6
|
+
|
7
|
+
function AlgoliaExplainResults(a,b,c){function d(a,b){var c=[];if("object"==typeof a&&"matchedWords"in a&&"value"in a){for(var e=!1,f=0;f<a.matchedWords.length;++f){var g=a.matchedWords[f];g in b||(b[g]=1,e=!0)}e&&c.push(a.value)}else if("[object Array]"===Object.prototype.toString.call(a))for(var h=0;h<a.length;++h){var i=d(a[h],b);c=c.concat(i)}else if("object"==typeof a)for(var j in a)a.hasOwnProperty(j)&&(c=c.concat(d(a[j],b)));return c}function e(a,b,c){var f=a._highlightResult||a;if(-1===c.indexOf("."))return c in f?d(f[c],b):[];for(var g=c.split("."),h=f,i=0;i<g.length;++i){if("[object Array]"===Object.prototype.toString.call(h)){for(var j=[],k=0;k<h.length;++k)j=j.concat(e(h[k],b,g.slice(i).join(".")));return j}if(!(g[i]in h))return[];h=h[g[i]]}return d(h,b)}var f={},g={},h=e(a,g,b);if(f.title=h.length>0?h[0]:"",f.subtitles=[],"undefined"!=typeof c)for(var i=0;i<c.length;++i)for(var j=e(a,g,c[i]),k=0;k<j.length;++k)f.subtitles.push({attr:c[i],value:j[k]});return f}var ALGOLIA_VERSION="2.9.4",AlgoliaSearch=function(a,b,c,d,e){var f=this;this.applicationID=a,this.apiKey=b,this.dsn=!0,this.dsnHost=null,this.hosts=[],this.currentHostIndex=0,this.requestTimeoutInMs=2e3,this.extraHeaders=[],this.jsonp=null,this.options={},this.cache={};var g,h="net";if("string"==typeof c)g=c;else{var i=c||{};this.options=i,this._isUndefined(i.method)||(g=i.method),this._isUndefined(i.tld)||(h=i.tld),this._isUndefined(i.dsn)||(this.dsn=i.dsn),this._isUndefined(i.hosts)||(e=i.hosts),this._isUndefined(i.dsnHost)||(this.dsnHost=i.dsnHost),this._isUndefined(i.requestTimeoutInMs)||(this.requestTimeoutInMs=+i.requestTimeoutInMs),this._isUndefined(i.jsonp)||(this.jsonp=i.jsonp)}this._isUndefined(e)&&(e=[this.applicationID+"-1.algolia."+h,this.applicationID+"-2.algolia."+h,this.applicationID+"-3.algolia."+h]),this.host_protocol="http://",this._isUndefined(g)||null===g?this.host_protocol=("https:"==document.location.protocol?"https":"http")+"://":("https"===g||"HTTPS"===g)&&(this.host_protocol="https://");for(var j=0;j<e.length;++j)Math.random()>.5&&this.hosts.reverse(),this.hosts.push(this.host_protocol+e[j]);Math.random()>.5&&this.hosts.reverse(),(this.dsn||null!=this.dsnHost)&&this.hosts.unshift(this.dsnHost?this.host_protocol+this.dsnHost:this.host_protocol+this.applicationID+"-dsn.algolia."+h),this.options.angular&&this.options.angular.$injector.invoke(["$http","$q",function(a,b){f.options.angular.$q=b,f.options.angular.$http=a}])};AlgoliaSearch.JSONPCounter=0,AlgoliaSearch.prototype={deleteIndex:function(a,b){return this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){var d={operation:"move",destination:b};return this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},copyIndex:function(a,b,c){var d={operation:"copy",destination:b};return this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},getLogs:function(a,b,c){return this._isUndefined(b)&&(b=0),this._isUndefined(c)&&(c=10),this._jsonRequest({method:"GET",url:"/1/logs?offset="+b+"&length="+c,callback:a})},listIndexes:function(a,b){var c="undefined"!=typeof b?"?page="+b:"";return this._jsonRequest({method:"GET",url:"/1/indexes"+c,callback:a})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){return this._jsonRequest({method:"GET",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,0,0,0,b)},addUserKeyWithValidity:function(a,b,c,d,e){var f={};return f.acl=a,f.validity=b,f.maxQueriesPerIPPerHour=c,f.maxHitsPerQuery=d,this._jsonRequest({method:"POST",url:"/1/keys",body:f,callback:e})},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=[],e=0;e<a[c].length;++e)d.push(a[c][e]);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){var d="query="+encodeURIComponent(b);this._isUndefined(c)||null===c||(d=this._getSearchParams(c,d)),this.batch.push({indexName:a,params:d})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a,b){for(var c=this,d={requests:[]},e=0;e<c.batch.length;++e)d.requests.push(c.batch[e]);if(window.clearTimeout(c.onDelayTrigger),this._isUndefined(b)||null===b||!(b>0))return this._sendQueriesBatch(d,a);var f=window.setTimeout(function(){c._sendQueriesBatch(d,a)},b);c.onDelayTrigger=f},setRequestTimeout:function(a){a&&(this.requestTimeoutInMs=parseInt(a,10))},Index:function(a,b){this.indexName=b,this.as=a,this.typeAheadArgs=null,this.typeAheadValueOption=null,this.cache={}},setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){if(null===this.jsonp){var c=this;return this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:function(d,e){d?(c.jsonp=!1,b&&b(d,e)):(c.jsonp=!0,c._sendQueriesBatch(a,b))}})}if(this.jsonp){for(var d="",e=0;e<a.requests.length;++e){var f="/1/indexes/"+encodeURIComponent(a.requests[e].indexName)+"?"+a.requests[e].params;d+=e+"="+encodeURIComponent(f)+"&"}var g={params:d};return this._jsonRequest({cache:this.cache,method:"GET",url:"/1/indexes/*",body:g,callback:b})}return this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:b})},_jsonRequest:function(a){var b=this,c=a.callback,d=null,e=a.url,f=null;if(this.options.jQuery?(f=this.options.jQuery.$.Deferred(),f.promise=f.promise()):this.options.angular&&(f=this.options.angular.$q.defer()),this._isUndefined(a.body)||(e=a.url+"_body_"+JSON.stringify(a.body)),!this._isUndefined(a.cache)&&(d=a.cache,!this._isUndefined(d[e])))return!this._isUndefined(c)&&c&&setTimeout(function(){c(!0,d[e])},1),f&&f.resolve(d[e]),f&&f.promise;a.successiveRetryCount=0;var g=function(){if(a.successiveRetryCount>=b.hosts.length){var h={message:"Cannot connect the Algolia's Search API. Please send an email to support@algolia.com to report the issue."};return!b._isUndefined(c)&&c&&(a.successiveRetryCount=0,c(!1,h)),void(f&&f.reject(h))}a.callback=function(h,i,j){i&&!b._isUndefined(a.cache)&&(d[e]=j),!i&&h?(b.currentHostIndex=++b.currentHostIndex%b.hosts.length,a.successiveRetryCount+=1,g()):(a.successiveRetryCount=0,f&&(i?f.resolve(j):f.reject(j)),!b._isUndefined(c)&&c&&c(i,j))},a.hostname=b.hosts[b.currentHostIndex],b._jsonRequestByHost(a)};return g(),f&&f.promise},_jsonRequestByHost:function(a){var b=a.hostname+a.url;this.jsonp?this._makeJsonpRequestByHost(b,a):this.options.jQuery?this._makejQueryRequestByHost(b,a):this.options.angular?this._makeAngularRequestByHost(b,a):this._makeXmlHttpRequestByHost(b,a)},_makeAngularRequestByHost:function(a,b){var c=null;this._isUndefined(b.body)||(c=JSON.stringify(b.body)),a+=(-1===a.indexOf("?")?"?":"&")+"X-Algolia-API-Key="+this.apiKey,a+="&X-Algolia-Application-Id="+this.applicationID,this.userToken&&(a+="&X-Algolia-UserToken="+encodeURIComponent(this.userToken)),this.tagFilters&&(a+="&X-Algolia-TagFilters="+encodeURIComponent(this.tagFilters));for(var d=0;d<this.extraHeaders.length;++d)a+="&"+this.extraHeaders[d].key+"="+this.extraHeaders[d].value;this.options.angular.$http({url:a,method:b.method,data:c,cache:!1,timeout:this.requestTimeoutInMs*(b.successiveRetryCount+1)}).then(function(a){b.callback(!1,!0,a.data)},function(a){0===a.status?b.callback(!0,!1,a.data):400==a.status||403===a.status||404===a.status?b.callback(!1,!1,a.data):b.callback(!0,!1,a.data)})},_makejQueryRequestByHost:function(a,b){var c=null;this._isUndefined(b.body)||(c=JSON.stringify(b.body)),a+=(-1===a.indexOf("?")?"?":"&")+"X-Algolia-API-Key="+this.apiKey,a+="&X-Algolia-Application-Id="+this.applicationID,this.userToken&&(a+="&X-Algolia-UserToken="+encodeURIComponent(this.userToken)),this.tagFilters&&(a+="&X-Algolia-TagFilters="+encodeURIComponent(this.tagFilters));for(var d=0;d<this.extraHeaders.length;++d)a+="&"+this.extraHeaders[d].key+"="+this.extraHeaders[d].value;this.options.jQuery.$.ajax(a,{type:b.method,timeout:this.requestTimeoutInMs*(b.successiveRetryCount+1),dataType:"json",data:c,error:function(c,d,e){"timeout"===d?b.callback(!0,!1,{message:"Timeout - Could not connect to endpoint "+a}):400===c.status||403===c.status||404===c.status?b.callback(!1,!1,c.responseJSON):b.callback(!0,!1,{message:e})},success:function(a){b.callback(!1,!0,a)}})},_makeJsonpRequestByHost:function(a,b){if("GET"!==b.method)return void b.callback(!0,!1,{message:"Method "+b.method+" "+a+" is not supported by JSONP."});var c=!1,d=!1;AlgoliaSearch.JSONPCounter+=1;var e,f,g,h=document.getElementsByTagName("head")[0],i=document.createElement("script"),j="algoliaJSONP_"+AlgoliaSearch.JSONPCounter,k=!1;window[j]=function(a){try{delete window[j]}catch(e){window[j]=void 0}if(!d){var f=a&&a.message&&a.status||a&&200,g=200===f,h=!g&&400!==f&&403!==f&&404!==f;c=!0,b.callback(h,g,a)}},i.type="text/javascript",a+="?callback="+j+"&X-Algolia-Application-Id="+this.applicationID+"&X-Algolia-API-Key="+this.apiKey,this.tagFilters&&(a+="&X-Algolia-TagFilters="+encodeURIComponent(this.tagFilters)),this.userToken&&(a+="&X-Algolia-UserToken="+encodeURIComponent(this.userToken));for(var l=0;l<this.extraHeaders.length;++l)a+="&"+this.extraHeaders[l].key+"="+this.extraHeaders[l].value;b.body&&b.body.params&&(a+="&"+b.body.params),e=setTimeout(function(){d=!0,g(),b.callback(!0,!1,{message:"Timeout - Failed to load JSONP script."})},this.requestTimeoutInMs),f=function(){k||d||(k=!0,g(),c||b.callback(!0,!1,{message:"Failed to load JSONP script."}))},g=function(){clearTimeout(e),i.onload=null,i.onreadystatechange=null,i.onerror=null,h.removeChild(i);try{delete window[j],delete window[j+"_loaded"]}catch(a){window[j]=null,window[j+"_loaded"]=null}},i.onreadystatechange=function(){("loaded"===this.readyState||"complete"===this.readyState)&&f()},i.onload=function(){f()},i.onerror=function(){k||d||(g(),b.callback(!0,!1,{message:"Failed to load JSONP script."}))},i.async=!0,i.defer=!0,i.src=a,h.appendChild(i)},_makeXmlHttpRequestByHost:function(a,b){if(!this._support.cors&&!this._support.hasXDomainRequest)return void b.callback(!1,!1,{message:"CORS not supported"});var c,d,e,f=null,g=this._support.cors?new XMLHttpRequest:new XDomainRequest,h=this;this._isUndefined(b.body)||(f=JSON.stringify(b.body)),a+=(-1===a.indexOf("?")?"?":"&")+"X-Algolia-API-Key="+this.apiKey,a+="&X-Algolia-Application-Id="+this.applicationID,this.userToken&&(a+="&X-Algolia-UserToken="+encodeURIComponent(this.userToken)),this.tagFilters&&(a+="&X-Algolia-TagFilters="+encodeURIComponent(this.tagFilters));for(var i=0;i<this.extraHeaders.length;++i)a+="&"+this.extraHeaders[i].key+"="+this.extraHeaders[i].value;e=function(){h._support.timeout||(d=!0,g.abort()),b.callback(!0,!1,{message:"Timeout - Could not connect to endpoint "+a})},g instanceof XMLHttpRequest?g.open(b.method,a,!0):g.open(b.method,a),this._support.cors&&null!==f&&"GET"!==b.method&&g.setRequestHeader("Content-type","application/x-www-form-urlencoded"),g.onload=function(){if(!d){h._support.timeout||clearTimeout(c);var a=null;try{a=JSON.parse(g.responseText)}catch(e){}var f=g.status||a&&a.message&&a.status||a&&200,i=200===f||201===f,j=!i&&400!==f&&403!==f&&404!==f;b.callback(j,i,a)}},this._support.timeout?(g.timeout=this.requestTimeoutInMs*(b.successiveRetryCount+1),g.ontimeout=e):c=setTimeout(e,this.requestTimeoutInMs*(b.successiveRetryCount+1)),g.onerror=function(a){d||(h._support.timeout||clearTimeout(c),b.callback(!0,!1,{message:"Could not connect to host",error:a}))},g.send(f)},_getSearchParams:function(a,b){if(this._isUndefined(a)||null===a)return b;for(var c in a)null!==c&&a.hasOwnProperty(c)&&(b+=0===b.length?"?":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):a[c]));return b},_isUndefined:function(a){return void 0===a},_support:{hasXMLHttpRequest:"XMLHttpRequest"in window,hasXDomainRequest:"XDomainRequest"in window,cors:"withCredentials"in new XMLHttpRequest,timeout:"timeout"in new XMLHttpRequest}},AlgoliaSearch.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){var d=this;return this.as._jsonRequest(this.as._isUndefined(c)?{method:"POST",url:"/1/indexes/"+encodeURIComponent(d.indexName),body:a,callback:b}:{method:"PUT",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(c),body:a,callback:b})},addObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"addObject",body:a[e]};d.requests.push(f)}return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},getObject:function(a,b,c){"[object Array]"!==Object.prototype.toString.call(b)||c||(c=b,b=null);var d=this,e="";if(!this.as._isUndefined(c)){e="?attributes=";for(var f=0;f<c.length;++f)0!==f&&(e+=","),e+=c[f]}return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(a)+e,callback:b})},partialUpdateObject:function(a,b){var c=this;return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"partialUpdateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},saveObject:function(a,b){var c=this;return this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"updateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},deleteObject:function(a,b){if(null===a||0===a.length)return void b(!1,{message:"empty objectID"});var c=this;return this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c,d){(void 0===a||null===a)&&(a=""),"function"==typeof a&&(b=a,a=""),"object"!=typeof b||!this.as._isUndefined(c)&&c||(c=b,b=null);var e=this,f="query="+encodeURIComponent(a);if(this.as._isUndefined(c)||null===c||(f=this.as._getSearchParams(c,f)),window.clearTimeout(e.onDelayTrigger),this.as._isUndefined(d)||null===d||!(d>0))return this._search(f,b);var g=window.setTimeout(function(){e._search(f,b)},d);e.onDelayTrigger=g},browse:function(a,b,c){+b>0&&(this.as._isUndefined(c)||!c)&&(c=b,b=null);var d=this,e="?page="+a;return this.as._isUndefined(c)||(e+="&hitsPerPage="+c),this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/browse"+e,callback:b})},ttAdapter:function(a){var b=this;return function(c,d){b.search(c,function(a,b){d(a?b.hits:b&&b.message)},a)}},waitTask:function(a,b){var c=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/task/"+a,callback:function(d,e){d?"published"===e.status?b(!0,e):setTimeout(function(){c.waitTask(a,b)},100):b(!1,e)}})},clearIndex:function(a){var b=this;return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/clear",callback:a})},getSettings:function(a){var b=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/settings",callback:a})},setSettings:function(a,b){var c=this;return this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){var b=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){var c=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){var c=this;return this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c=this,d={};return d.acl=a,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys",body:d,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};return g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(f.indexName)+"/keys",body:g,callback:e})},_search:function(a,b){var c={params:a};if(null===this.as.jsonp){var d=this;return this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:c,callback:function(c,e){var f=e&&e.status;c||f&&4===Math.floor(f/100)||1===Math.floor(f/100)?(d.as.jsonp=!1,b&&b(c,e)):(d.as.jsonp=!0,d._search(a,b))}})}return this.as._jsonRequest(this.as.jsonp?{cache:this.cache,method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName),body:c,callback:b}:{cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:c,callback:b})},as:null,indexName:null,typeAheadArgs:null,typeAheadValueOption:null},function(){var a=function(a){a=a||{};for(var b=1;b<arguments.length;b++)if(arguments[b])for(var c in arguments[b])arguments[b].hasOwnProperty(c)&&(a[c]=arguments[b][c]);return a};window.AlgoliaSearchHelper=function(b,c,d){var e={facets:[],disjunctiveFacets:[],hitsPerPage:20,defaultFacetFilters:[]};this.init(b,c,a({},e,d))},AlgoliaSearchHelper.prototype={init:function(a,b,c){this.client=a,this.index=b,this.options=c,this.page=0,this.refinements={},this.excludes={},this.disjunctiveRefinements={},this.extraQueries=[]},search:function(a,b,c){this.q=a,this.searchCallback=b,this.searchParams=c||{},this.page=this.page||0,this.refinements=this.refinements||{},this.disjunctiveRefinements=this.disjunctiveRefinements||{},this._search()},clearRefinements:function(){this.disjunctiveRefinements={},this.refinements={}},addDisjunctiveRefine:function(a,b){this.disjunctiveRefinements=this.disjunctiveRefinements||{},this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{},this.disjunctiveRefinements[a][b]=!0},removeDisjunctiveRefine:function(a,b){this.disjunctiveRefinements=this.disjunctiveRefinements||{},this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};try{delete this.disjunctiveRefinements[a][b]}catch(c){this.disjunctiveRefinements[a][b]=void 0}},addRefine:function(a,b){var c=a+":"+b;this.refinements=this.refinements||{},this.refinements[c]=!0},removeRefine:function(a,b){var c=a+":"+b;this.refinements=this.refinements||{},this.refinements[c]=!1},addExclude:function(a,b){var c=a+":-"+b;this.excludes=this.excludes||{},this.excludes[c]=!0},removeExclude:function(a,b){var c=a+":-"+b;this.excludes=this.excludes||{},this.excludes[c]=!1},toggleExclude:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":-"+b;return this.excludes[d]=!this.excludes[d],this.page=0,this._search(),!0}return!1},toggleRefine:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":"+b;return this.refinements[d]=!this.refinements[d],this.page=0,this._search(),!0}this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};for(var e=0;e<this.options.disjunctiveFacets.length;++e)if(this.options.disjunctiveFacets[e]==a)return this.disjunctiveRefinements[a][b]=!this.disjunctiveRefinements[a][b],this.page=0,this._search(),!0;return!1},isRefined:function(a,b){var c=a+":"+b;return this.refinements[c]?!0:this.disjunctiveRefinements[a]&&this.disjunctiveRefinements[a][b]?!0:!1},isExcluded:function(a,b){var c=a+":-"+b;return this.excludes[c]?!0:!1},nextPage:function(){this._gotoPage(this.page+1)},previousPage:function(){this.page>0&&this._gotoPage(this.page-1)},gotoPage:function(a){this._gotoPage(a)},setPage:function(a){this.page=a},setIndex:function(a){this.index=a},getIndex:function(){return this.index},clearExtraQueries:function(){this.extraQueries=[]},addExtraQuery:function(a,b,c){this.extraQueries.push({index:a,query:b,params:c||{}})},_gotoPage:function(a){this.page=a,this._search()},_search:function(){this.client.startQueriesBatch(),this.client.addQueryInBatch(this.index,this.q,this._getHitsSearchParams());var a=[],b={},c=0;for(c=0;c<this.options.disjunctiveFacets.length;++c){var d=this.options.disjunctiveFacets[c];this._hasDisjunctiveRefinements(d)?a.push(d):b[d]=!0}for(c=0;c<a.length;++c)this.client.addQueryInBatch(this.index,this.q,this._getDisjunctiveFacetSearchParams(a[c]));for(c=0;c<this.extraQueries.length;++c)this.client.addQueryInBatch(this.extraQueries[c].index,this.extraQueries[c].query,this.extraQueries[c].params);var e=this;this.client.sendQueriesBatch(function(d,f){if(!d)return void e.searchCallback(!1,f);var g=f.results[0];g.disjunctiveFacets=g.disjunctiveFacets||{},g.facets_stats=g.facets_stats||{};for(var h in b)if(g.facets[h]&&!g.disjunctiveFacets[h]){g.disjunctiveFacets[h]=g.facets[h];try{delete g.facets[h]}catch(i){g.facets[h]=void 0}}for(c=0;c<a.length;++c){for(var j in f.results[c+1].facets)if(g.disjunctiveFacets[j]=f.results[c+1].facets[j],e.disjunctiveRefinements[j])for(var k in e.disjunctiveRefinements[j])!g.disjunctiveFacets[j][k]&&e.disjunctiveRefinements[j][k]&&(g.disjunctiveFacets[j][k]=0);for(var l in f.results[c+1].facets_stats)g.facets_stats[l]=f.results[c+1].facets_stats[l]}g.facetStats=g.facets_stats;for(var m in e.excludes)if(e.excludes[m]){var i=m.indexOf(":-"),h=m.slice(0,i),k=m.slice(i+2);g.facets[h]=g.facets[h]||{},g.facets[h][k]||(g.facets[h][k]=0)}if(0===e.extraQueries.length)e.searchCallback(!0,g);else{var n={results:[g]};for(c=0;c<e.extraQueries.length;++c)n.results.push(f.results[1+a.length+c]);e.searchCallback(!0,n)}})},_getHitsSearchParams:function(){var b=[],c=0;for(c=0;c<this.options.facets.length;++c)b.push(this.options.facets[c]);for(c=0;c<this.options.disjunctiveFacets.length;++c){var d=this.options.disjunctiveFacets[c];this._hasDisjunctiveRefinements(d)||b.push(d)}return a({},{hitsPerPage:this.options.hitsPerPage,page:this.page,facets:b,facetFilters:this._getFacetFilters()},this.searchParams)},_getDisjunctiveFacetSearchParams:function(b){return a({},this.searchParams,{hitsPerPage:1,page:0,attributesToRetrieve:[],attributesToHighlight:[],attributesToSnippet:[],facets:b,facetFilters:this._getFacetFilters(b),analytics:!1})},_hasDisjunctiveRefinements:function(a){for(var b in this.disjunctiveRefinements[a])if(this.disjunctiveRefinements[a][b])return!0;return!1},_getFacetFilters:function(a){var b=[];if(this.options.defaultFacetFilters)for(var c=0;c<this.options.defaultFacetFilters.length;++c)b.push(this.options.defaultFacetFilters[c]);for(var d in this.refinements)this.refinements[d]&&b.push(d);for(var d in this.excludes)this.excludes[d]&&b.push(d);for(var e in this.disjunctiveRefinements)if(e!=a){var f=[];for(var g in this.disjunctiveRefinements[e])this.disjunctiveRefinements[e][g]&&f.push(e+":"+g);f.length>0&&b.push(f)}return b}}}(),function(){window.AlgoliaPlaces=function(a,b){this.init(a,b)},AlgoliaPlaces.prototype={init:function(a,b){this.client=new AlgoliaSearch(a,b,"http",!0,["places-1.algolia.io","places-2.algolia.io","places-3.algolia.io"]),this.cache={}},search:function(a,b,c){var d="query="+encodeURIComponent(a);this.client._isUndefined(c)||null==c||(d=this.client._getSearchParams(c,d));var e={params:d,apiKey:this.client.apiKey,appID:this.client.applicationID};this.client._jsonRequest({cache:this.cache,method:"POST",url:"/1/places/query",body:e,callback:b,removeCustomHTTPHeaders:!0})}}}(),"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(a){return 10>a?"0"+a:a}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return"string"==typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g,h=gap,i=b[a];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(a)),"function"==typeof rep&&(i=rep.call(b,a,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,g=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,c=0;f>c;c+=1)g[c]=str(c,i)||"null";return e=0===g.length?"[]":gap?"[\n"+gap+g.join(",\n"+gap)+"\n"+h+"]":"["+g.join(",")+"]",gap=h,e}if(rep&&"object"==typeof rep)for(f=rep.length,c=0;f>c;c+=1)"string"==typeof rep[c]&&(d=rep[c],e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));return e=0===g.length?"{}":gap?"{\n"+gap+g.join(",\n"+gap)+"\n"+h+"}":"{"+g.join(",")+"}",gap=h,e}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx,escapable,gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(a,b,c){var d;if(gap="",indent="","number"==typeof c)for(d=0;c>d;d+=1)indent+=" ";else"string"==typeof c&&(indent=c);if(rep=b,b&&"function"!=typeof b&&("object"!=typeof b||"number"!=typeof b.length))throw new Error("JSON.stringify");return str("",{"":a})}),"function"!=typeof JSON.parse&&(cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&"object"==typeof e)for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),void 0!==d?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}();
|
@@ -0,0 +1,1717 @@
|
|
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.angular");
|
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 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
|
+
// shim for using process in browser
|
204
|
+
|
205
|
+
var process = module.exports = {};
|
206
|
+
var queue = [];
|
207
|
+
var draining = false;
|
208
|
+
|
209
|
+
function drainQueue() {
|
210
|
+
if (draining) {
|
211
|
+
return;
|
212
|
+
}
|
213
|
+
draining = true;
|
214
|
+
var currentQueue;
|
215
|
+
var len = queue.length;
|
216
|
+
while(len) {
|
217
|
+
currentQueue = queue;
|
218
|
+
queue = [];
|
219
|
+
var i = -1;
|
220
|
+
while (++i < len) {
|
221
|
+
currentQueue[i]();
|
222
|
+
}
|
223
|
+
len = queue.length;
|
224
|
+
}
|
225
|
+
draining = false;
|
226
|
+
}
|
227
|
+
process.nextTick = function (fun) {
|
228
|
+
queue.push(fun);
|
229
|
+
if (!draining) {
|
230
|
+
setTimeout(drainQueue, 0);
|
231
|
+
}
|
232
|
+
};
|
233
|
+
|
234
|
+
process.title = 'browser';
|
235
|
+
process.browser = true;
|
236
|
+
process.env = {};
|
237
|
+
process.argv = [];
|
238
|
+
process.version = ''; // empty string to avoid regexp issues
|
239
|
+
process.versions = {};
|
240
|
+
|
241
|
+
function noop() {}
|
242
|
+
|
243
|
+
process.on = noop;
|
244
|
+
process.addListener = noop;
|
245
|
+
process.once = noop;
|
246
|
+
process.off = noop;
|
247
|
+
process.removeListener = noop;
|
248
|
+
process.removeAllListeners = noop;
|
249
|
+
process.emit = noop;
|
250
|
+
|
251
|
+
process.binding = function (name) {
|
252
|
+
throw new Error('process.binding is not supported');
|
253
|
+
};
|
254
|
+
|
255
|
+
// TODO(shtylman)
|
256
|
+
process.cwd = function () { return '/' };
|
257
|
+
process.chdir = function (dir) {
|
258
|
+
throw new Error('process.chdir is not supported');
|
259
|
+
};
|
260
|
+
process.umask = function() { return 0; };
|
261
|
+
|
262
|
+
},{}],2:[function(require,module,exports){
|
263
|
+
(function (process){
|
264
|
+
module.exports = AlgoliaSearch;
|
265
|
+
|
266
|
+
/*
|
267
|
+
* Algolia Search library initialization
|
268
|
+
* https://www.algolia.com/
|
269
|
+
*
|
270
|
+
* @param {string} applicationID - Your applicationID, found in your dashboard
|
271
|
+
* @param {string} apiKey - Your API key, found in your dashboard
|
272
|
+
* @param {Object} [opts]
|
273
|
+
* @param {number} [opts.timeout=2000] - The request timeout set in milliseconds, another request will be issued after this timeout
|
274
|
+
* @param {string} [opts.protocol='http:'] - The protocol used to query Algolia Search API.
|
275
|
+
* Set to 'https:' to force using https. Default to document.location.protocol in browsers
|
276
|
+
* @param {string[]} [opts.hosts=[
|
277
|
+
* this.applicationID + '-1.algolia.' + opts.tld,
|
278
|
+
* this.applicationID + '-2.algolia.' + opts.tld,
|
279
|
+
* this.applicationID + '-3.algolia.' + opts.tld]
|
280
|
+
* ] - The hosts to use for Algolia Search API. It this your responsibility to shuffle the hosts and add a DSN host in it
|
281
|
+
* @param {string} [opts.tld='net'] - The tld to use when computing hosts default list
|
282
|
+
*/
|
283
|
+
function AlgoliaSearch(applicationID, apiKey, opts, _request) {
|
284
|
+
var usage = 'Usage: algoliasearch(applicationID, apiKey, opts)';
|
285
|
+
|
286
|
+
if (!applicationID) {
|
287
|
+
throw new Error('Please provide an application ID. ' + usage);
|
288
|
+
}
|
289
|
+
|
290
|
+
if (!apiKey) {
|
291
|
+
throw new Error('Please provide an API key. ' + usage);
|
292
|
+
}
|
293
|
+
|
294
|
+
opts = opts || {};
|
295
|
+
|
296
|
+
// now setting default options
|
297
|
+
// could not find a tiny module to do that, let's go manual
|
298
|
+
if (opts.timeout === undefined) {
|
299
|
+
opts.timeout = 2000;
|
300
|
+
}
|
301
|
+
|
302
|
+
if (opts.protocol === undefined) {
|
303
|
+
opts.protocol = document && document.location.protocol || 'http:';
|
304
|
+
}
|
305
|
+
|
306
|
+
if (opts.hosts === undefined) {
|
307
|
+
opts.hosts = []; // filled later on, has dependencies
|
308
|
+
}
|
309
|
+
|
310
|
+
if (opts.tld === undefined) {
|
311
|
+
opts.tld = 'net';
|
312
|
+
}
|
313
|
+
|
314
|
+
// while we advocate for colon-at-the-end values: 'http:' for `opts.protocol`
|
315
|
+
// we also accept `http` and `https`. It's a common error.
|
316
|
+
if (!/:$/.test(opts.protocol)) {
|
317
|
+
opts.protocol = opts.protocol + ':';
|
318
|
+
}
|
319
|
+
|
320
|
+
// no hosts given, add defaults
|
321
|
+
if (opts.hosts.length === 0) {
|
322
|
+
opts.hosts = shuffle([
|
323
|
+
applicationID + '-1.algolia.' + opts.tld,
|
324
|
+
applicationID + '-2.algolia.' + opts.tld,
|
325
|
+
applicationID + '-3.algolia.' + opts.tld
|
326
|
+
]);
|
327
|
+
|
328
|
+
// add default dsn host
|
329
|
+
opts.hosts.unshift(applicationID + '-dsn.algolia.' + opts.tld);
|
330
|
+
}
|
331
|
+
|
332
|
+
opts.hosts = map(opts.hosts, function prependProtocol(host) {
|
333
|
+
return opts.protocol + '//' + host;
|
334
|
+
});
|
335
|
+
|
336
|
+
this.applicationID = applicationID;
|
337
|
+
this.apiKey = apiKey;
|
338
|
+
this.hosts = opts.hosts;
|
339
|
+
|
340
|
+
this.currentHostIndex = 0;
|
341
|
+
this.requestTimeout = opts.timeout;
|
342
|
+
this.extraHeaders = [];
|
343
|
+
this.cache = {};
|
344
|
+
this._request = _request;
|
345
|
+
}
|
346
|
+
|
347
|
+
AlgoliaSearch.prototype = {
|
348
|
+
/*
|
349
|
+
* Delete an index
|
350
|
+
*
|
351
|
+
* @param indexName the name of index to delete
|
352
|
+
* @param callback the result callback with two arguments
|
353
|
+
* error: null or Error('message')
|
354
|
+
* content: the server answer that contains the task ID
|
355
|
+
*/
|
356
|
+
deleteIndex: function(indexName, callback) {
|
357
|
+
return this._jsonRequest({ method: 'DELETE',
|
358
|
+
url: '/1/indexes/' + encodeURIComponent(indexName),
|
359
|
+
callback: callback });
|
360
|
+
},
|
361
|
+
/**
|
362
|
+
* Move an existing index.
|
363
|
+
* @param srcIndexName the name of index to copy.
|
364
|
+
* @param dstIndexName the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).
|
365
|
+
* @param callback the result callback with two arguments
|
366
|
+
* error: null or Error('message')
|
367
|
+
* content: the server answer that contains the task ID
|
368
|
+
*/
|
369
|
+
moveIndex: function(srcIndexName, dstIndexName, callback) {
|
370
|
+
var postObj = {operation: 'move', destination: dstIndexName};
|
371
|
+
return this._jsonRequest({ method: 'POST',
|
372
|
+
url: '/1/indexes/' + encodeURIComponent(srcIndexName) + '/operation',
|
373
|
+
body: postObj,
|
374
|
+
callback: callback });
|
375
|
+
|
376
|
+
},
|
377
|
+
/**
|
378
|
+
* Copy an existing index.
|
379
|
+
* @param srcIndexName the name of index to copy.
|
380
|
+
* @param dstIndexName the new index name that will contains a copy of srcIndexName (destination will be overriten if it already exist).
|
381
|
+
* @param callback the result callback with two arguments
|
382
|
+
* error: null or Error('message')
|
383
|
+
* content: the server answer that contains the task ID
|
384
|
+
*/
|
385
|
+
copyIndex: function(srcIndexName, dstIndexName, callback) {
|
386
|
+
var postObj = {operation: 'copy', destination: dstIndexName};
|
387
|
+
return this._jsonRequest({ method: 'POST',
|
388
|
+
url: '/1/indexes/' + encodeURIComponent(srcIndexName) + '/operation',
|
389
|
+
body: postObj,
|
390
|
+
callback: callback });
|
391
|
+
},
|
392
|
+
/**
|
393
|
+
* Return last log entries.
|
394
|
+
* @param offset Specify the first entry to retrieve (0-based, 0 is the most recent log entry).
|
395
|
+
* @param length Specify the maximum number of entries to retrieve starting at offset. Maximum allowed value: 1000.
|
396
|
+
* @param callback the result callback with two arguments
|
397
|
+
* error: null or Error('message')
|
398
|
+
* content: the server answer that contains the task ID
|
399
|
+
*/
|
400
|
+
getLogs: function(offset, length, callback) {
|
401
|
+
if (arguments.length === 0 || typeof offset === 'function') {
|
402
|
+
// getLogs([cb])
|
403
|
+
callback = offset;
|
404
|
+
offset = 0;
|
405
|
+
length = 10;
|
406
|
+
} else if (arguments.length === 1 || typeof length === 'function') {
|
407
|
+
// getLogs(1, [cb)]
|
408
|
+
callback = length;
|
409
|
+
length = 10;
|
410
|
+
}
|
411
|
+
|
412
|
+
return this._jsonRequest({ method: 'GET',
|
413
|
+
url: '/1/logs?offset=' + offset + '&length=' + length,
|
414
|
+
callback: callback });
|
415
|
+
},
|
416
|
+
/*
|
417
|
+
* List all existing indexes (paginated)
|
418
|
+
*
|
419
|
+
* @param page The page to retrieve, starting at 0.
|
420
|
+
* @param callback the result callback with two arguments
|
421
|
+
* error: null or Error('message')
|
422
|
+
* content: the server answer with index list
|
423
|
+
*/
|
424
|
+
listIndexes: function(page, callback) {
|
425
|
+
var params = '';
|
426
|
+
|
427
|
+
if (page === undefined || typeof page === 'function') {
|
428
|
+
callback = page;
|
429
|
+
} else {
|
430
|
+
params = '?page=' + page;
|
431
|
+
}
|
432
|
+
|
433
|
+
return this._jsonRequest({ method: 'GET',
|
434
|
+
url: '/1/indexes' + params,
|
435
|
+
callback: callback });
|
436
|
+
},
|
437
|
+
|
438
|
+
/*
|
439
|
+
* Get the index object initialized
|
440
|
+
*
|
441
|
+
* @param indexName the name of index
|
442
|
+
* @param callback the result callback with one argument (the Index instance)
|
443
|
+
*/
|
444
|
+
initIndex: function(indexName) {
|
445
|
+
return new this.Index(this, indexName);
|
446
|
+
},
|
447
|
+
/*
|
448
|
+
* List all existing user keys with their associated ACLs
|
449
|
+
*
|
450
|
+
* @param callback the result callback with two arguments
|
451
|
+
* error: null or Error('message')
|
452
|
+
* content: the server answer with user keys list
|
453
|
+
*/
|
454
|
+
listUserKeys: function(callback) {
|
455
|
+
return this._jsonRequest({ method: 'GET',
|
456
|
+
url: '/1/keys',
|
457
|
+
callback: callback });
|
458
|
+
},
|
459
|
+
/*
|
460
|
+
* Get ACL of a user key
|
461
|
+
*
|
462
|
+
* @param key
|
463
|
+
* @param callback the result callback with two arguments
|
464
|
+
* error: null or Error('message')
|
465
|
+
* content: the server answer with user keys list
|
466
|
+
*/
|
467
|
+
getUserKeyACL: function(key, callback) {
|
468
|
+
return this._jsonRequest({ method: 'GET',
|
469
|
+
url: '/1/keys/' + key,
|
470
|
+
callback: callback });
|
471
|
+
},
|
472
|
+
/*
|
473
|
+
* Delete an existing user key
|
474
|
+
* @param key
|
475
|
+
* @param callback the result callback with two arguments
|
476
|
+
* error: null or Error('message')
|
477
|
+
* content: the server answer with user keys list
|
478
|
+
*/
|
479
|
+
deleteUserKey: function(key, callback) {
|
480
|
+
return this._jsonRequest({ method: 'DELETE',
|
481
|
+
url: '/1/keys/' + key,
|
482
|
+
callback: callback });
|
483
|
+
},
|
484
|
+
/*
|
485
|
+
* Add an existing user key
|
486
|
+
*
|
487
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
488
|
+
* can contains the following values:
|
489
|
+
* - search: allow to search (https and http)
|
490
|
+
* - addObject: allows to add/update an object in the index (https only)
|
491
|
+
* - deleteObject : allows to delete an existing object (https only)
|
492
|
+
* - deleteIndex : allows to delete index content (https only)
|
493
|
+
* - settings : allows to get index settings (https only)
|
494
|
+
* - editSettings : allows to change index settings (https only)
|
495
|
+
* @param callback the result callback with two arguments
|
496
|
+
* error: null or Error('message')
|
497
|
+
* content: the server answer with user keys list
|
498
|
+
*/
|
499
|
+
addUserKey: function(acls, callback) {
|
500
|
+
return this.addUserKeyWithValidity(acls, {
|
501
|
+
validity: 0,
|
502
|
+
maxQueriesPerIPPerHour: 0,
|
503
|
+
maxHitsPerQuery: 0
|
504
|
+
}, callback);
|
505
|
+
},
|
506
|
+
/*
|
507
|
+
* Add an existing user key
|
508
|
+
*
|
509
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
510
|
+
* can contains the following values:
|
511
|
+
* - search: allow to search (https and http)
|
512
|
+
* - addObject: allows to add/update an object in the index (https only)
|
513
|
+
* - deleteObject : allows to delete an existing object (https only)
|
514
|
+
* - deleteIndex : allows to delete index content (https only)
|
515
|
+
* - settings : allows to get index settings (https only)
|
516
|
+
* - editSettings : allows to change index settings (https only)
|
517
|
+
* @param params.validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
|
518
|
+
* @param params.maxQueriesPerIPPerHour Specify the maximum number of API calls allowed from an IP address per hour.
|
519
|
+
* @param params.maxHitsPerQuery Specify the maximum number of hits this API key can retrieve in one call.
|
520
|
+
* @param callback the result callback with two arguments
|
521
|
+
* error: null or Error('message')
|
522
|
+
* content: the server answer with user keys list
|
523
|
+
*/
|
524
|
+
addUserKeyWithValidity: function(acls, params, callback) {
|
525
|
+
var aclsObject = {};
|
526
|
+
aclsObject.acl = acls;
|
527
|
+
aclsObject.validity = params.validity;
|
528
|
+
aclsObject.maxQueriesPerIPPerHour = params.maxQueriesPerIPPerHour;
|
529
|
+
aclsObject.maxHitsPerQuery = params.maxHitsPerQuery;
|
530
|
+
return this._jsonRequest({ method: 'POST',
|
531
|
+
url: '/1/keys',
|
532
|
+
body: aclsObject,
|
533
|
+
callback: callback });
|
534
|
+
},
|
535
|
+
|
536
|
+
/**
|
537
|
+
* Set the extra security tagFilters header
|
538
|
+
* @param {string|array} tags The list of tags defining the current security filters
|
539
|
+
*/
|
540
|
+
setSecurityTags: function(tags) {
|
541
|
+
if (Object.prototype.toString.call(tags) === '[object Array]') {
|
542
|
+
var strTags = [];
|
543
|
+
for (var i = 0; i < tags.length; ++i) {
|
544
|
+
if (Object.prototype.toString.call(tags[i]) === '[object Array]') {
|
545
|
+
var oredTags = [];
|
546
|
+
for (var j = 0; j < tags[i].length; ++j) {
|
547
|
+
oredTags.push(tags[i][j]);
|
548
|
+
}
|
549
|
+
strTags.push('(' + oredTags.join(',') + ')');
|
550
|
+
} else {
|
551
|
+
strTags.push(tags[i]);
|
552
|
+
}
|
553
|
+
}
|
554
|
+
tags = strTags.join(',');
|
555
|
+
}
|
556
|
+
this.tagFilters = tags;
|
557
|
+
},
|
558
|
+
|
559
|
+
/**
|
560
|
+
* Set the extra user token header
|
561
|
+
* @param {string} userToken The token identifying a uniq user (used to apply rate limits)
|
562
|
+
*/
|
563
|
+
setUserToken: function(userToken) {
|
564
|
+
this.userToken = userToken;
|
565
|
+
},
|
566
|
+
|
567
|
+
/*
|
568
|
+
* Initialize a new batch of search queries
|
569
|
+
*/
|
570
|
+
startQueriesBatch: function() {
|
571
|
+
this.batch = [];
|
572
|
+
},
|
573
|
+
/*
|
574
|
+
* Add a search query in the batch
|
575
|
+
*
|
576
|
+
* @param query the full text query
|
577
|
+
* @param args (optional) if set, contains an object with query parameters:
|
578
|
+
* - attributes: an array of object attribute names to retrieve
|
579
|
+
* (if not set all attributes are retrieve)
|
580
|
+
* - attributesToHighlight: an array of object attribute names to highlight
|
581
|
+
* (if not set indexed attributes are highlighted)
|
582
|
+
* - minWordSizefor1Typo: the minimum number of characters to accept one typo.
|
583
|
+
* Defaults to 3.
|
584
|
+
* - minWordSizefor2Typos: the minimum number of characters to accept two typos.
|
585
|
+
* Defaults to 7.
|
586
|
+
* - getRankingInfo: if set, the result hits will contain ranking information in
|
587
|
+
* _rankingInfo attribute
|
588
|
+
* - page: (pagination parameter) page to retrieve (zero base). Defaults to 0.
|
589
|
+
* - hitsPerPage: (pagination parameter) number of hits per page. Defaults to 10.
|
590
|
+
*/
|
591
|
+
addQueryInBatch: function(indexName, query, args) {
|
592
|
+
var params = 'query=' + encodeURIComponent(query);
|
593
|
+
if (!this._isUndefined(args) && args !== null) {
|
594
|
+
params = this._getSearchParams(args, params);
|
595
|
+
}
|
596
|
+
this.batch.push({ indexName: indexName, params: params });
|
597
|
+
},
|
598
|
+
/*
|
599
|
+
* Clear all queries in cache
|
600
|
+
*/
|
601
|
+
clearCache: function() {
|
602
|
+
this.cache = {};
|
603
|
+
},
|
604
|
+
/*
|
605
|
+
* Launch the batch of queries using XMLHttpRequest.
|
606
|
+
* (Optimized for browser using a POST query to minimize number of OPTIONS queries)
|
607
|
+
*
|
608
|
+
* @param callback the function that will receive results
|
609
|
+
*/
|
610
|
+
sendQueriesBatch: function(callback) {
|
611
|
+
var as = this;
|
612
|
+
var params = {requests: []};
|
613
|
+
|
614
|
+
for (var i = 0; i < as.batch.length; ++i) {
|
615
|
+
params.requests.push(as.batch[i]);
|
616
|
+
}
|
617
|
+
|
618
|
+
return this._sendQueriesBatch(params, callback);
|
619
|
+
},
|
620
|
+
|
621
|
+
/**
|
622
|
+
* Set the number of milliseconds a request can take before automatically being terminated.
|
623
|
+
*
|
624
|
+
* @param {Number} milliseconds
|
625
|
+
*/
|
626
|
+
setRequestTimeout: function(milliseconds) {
|
627
|
+
if (milliseconds) {
|
628
|
+
this.requestTimeout = parseInt(milliseconds, 10);
|
629
|
+
}
|
630
|
+
},
|
631
|
+
|
632
|
+
/*
|
633
|
+
* Index class constructor.
|
634
|
+
* You should not use this method directly but use initIndex() function
|
635
|
+
*/
|
636
|
+
Index: function(algoliasearch, indexName) {
|
637
|
+
this.indexName = indexName;
|
638
|
+
this.as = algoliasearch;
|
639
|
+
this.typeAheadArgs = null;
|
640
|
+
this.typeAheadValueOption = null;
|
641
|
+
|
642
|
+
// make sure every index instance has it's own cache
|
643
|
+
this.cache = {};
|
644
|
+
},
|
645
|
+
/**
|
646
|
+
* Add an extra field to the HTTP request
|
647
|
+
*
|
648
|
+
* @param key the header field name
|
649
|
+
* @param value the header field value
|
650
|
+
*/
|
651
|
+
setExtraHeader: function(key, value) {
|
652
|
+
this.extraHeaders.push({ key: key, value: value});
|
653
|
+
},
|
654
|
+
|
655
|
+
_sendQueriesBatch: function(params, callback) {
|
656
|
+
return this._jsonRequest({ cache: this.cache,
|
657
|
+
method: 'POST',
|
658
|
+
url: '/1/indexes/*/queries',
|
659
|
+
body: params,
|
660
|
+
fallback: {
|
661
|
+
method: 'GET',
|
662
|
+
url: '/1/indexes/*',
|
663
|
+
body: {params: (function() {
|
664
|
+
var reqParams = '';
|
665
|
+
for (var i = 0; i < params.requests.length; ++i) {
|
666
|
+
var q = '/1/indexes/' + encodeURIComponent(params.requests[i].indexName) + '?' + params.requests[i].params;
|
667
|
+
reqParams += i + '=' + encodeURIComponent(q) + '&';
|
668
|
+
}
|
669
|
+
return reqParams;
|
670
|
+
}())}
|
671
|
+
},
|
672
|
+
callback: callback
|
673
|
+
});
|
674
|
+
},
|
675
|
+
/*
|
676
|
+
* Wrapper that try all hosts to maximize the quality of service
|
677
|
+
*/
|
678
|
+
_jsonRequest: function(opts) {
|
679
|
+
// handle opts.fallback, automatically use fallback (JSONP in browser plugins, wrapped with $plugin-promises)
|
680
|
+
// so if an error occurs and max tries => use fallback
|
681
|
+
// set tries to 0 again
|
682
|
+
// if fallback used and no more tries, return error
|
683
|
+
// fallback parameters are in opts.fallback
|
684
|
+
// call request.fallback or request accordingly, same promise chain otherwise
|
685
|
+
// put callback& params in front if problem
|
686
|
+
var cache = opts.cache;
|
687
|
+
var cacheID = opts.url;
|
688
|
+
var client = this;
|
689
|
+
var tries = 0;
|
690
|
+
|
691
|
+
// as we use POST requests to pass parameters (like query='aa'),
|
692
|
+
// the cacheID must be different between calls
|
693
|
+
if (opts.body !== undefined) {
|
694
|
+
cacheID += '_body_' + JSON.stringify(opts.body);
|
695
|
+
}
|
696
|
+
|
697
|
+
function doRequest(requester, reqOpts) {
|
698
|
+
// handle cache existence
|
699
|
+
if (cache && cache[cacheID] !== undefined) {
|
700
|
+
return client._request.resolve(cache[cacheID]);
|
701
|
+
}
|
702
|
+
|
703
|
+
if (tries >= client.hosts.length) {
|
704
|
+
if (!opts.fallback || requester === client._request.fallback) {
|
705
|
+
// could not get a response even using the fallback if one was available
|
706
|
+
return client._request.reject(new Error(
|
707
|
+
'Cannot connect to the AlgoliaSearch API.' +
|
708
|
+
' Send an email to support@algolia.com to report and resolve the issue.'
|
709
|
+
));
|
710
|
+
}
|
711
|
+
|
712
|
+
tries = 0;
|
713
|
+
reqOpts.method = opts.fallback.method;
|
714
|
+
reqOpts.url = opts.fallback.url;
|
715
|
+
reqOpts.body = opts.fallback.body;
|
716
|
+
reqOpts.timeout = client.requestTimeout * (tries + 1);
|
717
|
+
client.currentHostIndex = 0;
|
718
|
+
client.forceFallback = true;
|
719
|
+
return doRequest(client._request.fallback, reqOpts);
|
720
|
+
}
|
721
|
+
|
722
|
+
var url = reqOpts.url;
|
723
|
+
|
724
|
+
url += (url.indexOf('?') === -1 ? '?' : '&') + 'X-Algolia-API-Key=' + client.apiKey;
|
725
|
+
url += '&X-Algolia-Application-Id=' + client.applicationID;
|
726
|
+
|
727
|
+
if (client.userToken) {
|
728
|
+
url += '&X-Algolia-UserToken=' + encodeURIComponent(client.userToken);
|
729
|
+
}
|
730
|
+
|
731
|
+
if (client.tagFilters) {
|
732
|
+
url += '&X-Algolia-TagFilters=' + encodeURIComponent(client.tagFilters);
|
733
|
+
}
|
734
|
+
|
735
|
+
for (var i = 0; i < client.extraHeaders.length; ++i) {
|
736
|
+
url += '&' + client.extraHeaders[i].key + '=' + client.extraHeaders[i].value;
|
737
|
+
}
|
738
|
+
|
739
|
+
return requester(client.hosts[client.currentHostIndex] + url, {
|
740
|
+
body: reqOpts.body,
|
741
|
+
method: reqOpts.method,
|
742
|
+
timeout: reqOpts.timeout
|
743
|
+
})
|
744
|
+
.then(function success(httpResponse) {
|
745
|
+
// timeout case, retry immediately
|
746
|
+
if (httpResponse instanceof Error) {
|
747
|
+
return retryRequest();
|
748
|
+
}
|
749
|
+
|
750
|
+
var status =
|
751
|
+
// When in browser mode, using XDR or JSONP
|
752
|
+
// We rely on our own API response `status`, only
|
753
|
+
// provided when an error occurs, we also expect a .message along
|
754
|
+
// Otherwise, it could be a `waitTask` status, that's the only
|
755
|
+
// case where we have a response.status that's not the http statusCode
|
756
|
+
httpResponse && httpResponse.body && httpResponse.body.message && httpResponse.body.status ||
|
757
|
+
|
758
|
+
// this is important to check the request statusCode AFTER the body eventual
|
759
|
+
// statusCode because some implementations (jQuery XDomainRequest transport) may
|
760
|
+
// send statusCode 200 while we had an error
|
761
|
+
httpResponse.statusCode ||
|
762
|
+
|
763
|
+
// When in browser mode, using XDR or JSONP
|
764
|
+
// we default to success when no error (no response.status && response.message)
|
765
|
+
// If there was a JSON.parse() error then body is null and it fails
|
766
|
+
httpResponse && httpResponse.body && 200;
|
767
|
+
|
768
|
+
var ok = status === 200 || status === 201;
|
769
|
+
var retry = !ok && Math.floor(status / 100) !== 4 && Math.floor(status / 100) !== 1;
|
770
|
+
|
771
|
+
if (ok && cache) {
|
772
|
+
cache[cacheID] = httpResponse.body;
|
773
|
+
}
|
774
|
+
|
775
|
+
if (ok) {
|
776
|
+
return httpResponse.body;
|
777
|
+
}
|
778
|
+
|
779
|
+
if (retry) {
|
780
|
+
return retryRequest();
|
781
|
+
}
|
782
|
+
|
783
|
+
var unrecoverableError = new Error(
|
784
|
+
httpResponse.body && httpResponse.body.message || 'Unknown error'
|
785
|
+
);
|
786
|
+
|
787
|
+
return client._request.reject(unrecoverableError);
|
788
|
+
}, tryFallback);
|
789
|
+
|
790
|
+
function retryRequest() {
|
791
|
+
client.currentHostIndex = ++client.currentHostIndex % client.hosts.length;
|
792
|
+
tries += 1;
|
793
|
+
reqOpts.timeout = client.requestTimeout * (tries + 1);
|
794
|
+
return doRequest(requester, reqOpts);
|
795
|
+
}
|
796
|
+
|
797
|
+
function tryFallback() {
|
798
|
+
// if we are switching to fallback right now, set tries to maximum
|
799
|
+
if (!client.forceFallback) {
|
800
|
+
// next time doRequest is called, simulate we tried all hosts
|
801
|
+
tries = client.hosts.length;
|
802
|
+
} else {
|
803
|
+
// we were already using the fallback, but something went wrong (script error)
|
804
|
+
client.currentHostIndex = ++client.currentHostIndex % client.hosts.length;
|
805
|
+
tries += 1;
|
806
|
+
}
|
807
|
+
|
808
|
+
return doRequest(requester, reqOpts);
|
809
|
+
}
|
810
|
+
}
|
811
|
+
|
812
|
+
// we can use a fallback if forced AND fallback parameters are available
|
813
|
+
var useFallback = client.forceFallback && opts.fallback;
|
814
|
+
var requestOptions = useFallback ? opts.fallback : opts;
|
815
|
+
|
816
|
+
var promise = doRequest(
|
817
|
+
useFallback ? client._request.fallback : client._request, {
|
818
|
+
url: requestOptions.url,
|
819
|
+
method: requestOptions.method,
|
820
|
+
body: requestOptions.body,
|
821
|
+
timeout: client.requestTimeout * (tries + 1)
|
822
|
+
}
|
823
|
+
);
|
824
|
+
|
825
|
+
// either we have a callback
|
826
|
+
// either we are using promises
|
827
|
+
if (opts.callback) {
|
828
|
+
promise.then(function okCb(content) {
|
829
|
+
process.nextTick(function() {
|
830
|
+
opts.callback(null, content);
|
831
|
+
});
|
832
|
+
}, function nookCb(err) {
|
833
|
+
process.nextTick(function() {
|
834
|
+
opts.callback(err);
|
835
|
+
});
|
836
|
+
});
|
837
|
+
} else {
|
838
|
+
return promise;
|
839
|
+
}
|
840
|
+
},
|
841
|
+
|
842
|
+
/*
|
843
|
+
* Transform search param object in query string
|
844
|
+
*/
|
845
|
+
_getSearchParams: function(args, params) {
|
846
|
+
if (this._isUndefined(args) || args === null) {
|
847
|
+
return params;
|
848
|
+
}
|
849
|
+
for (var key in args) {
|
850
|
+
if (key !== null && args.hasOwnProperty(key)) {
|
851
|
+
params += params === '' ? '' : '&';
|
852
|
+
params += key + '=' + encodeURIComponent(Object.prototype.toString.call(args[key]) === '[object Array]' ? JSON.stringify(args[key]) : args[key]);
|
853
|
+
}
|
854
|
+
}
|
855
|
+
return params;
|
856
|
+
},
|
857
|
+
_isUndefined: function(obj) {
|
858
|
+
return obj === void 0;
|
859
|
+
}
|
860
|
+
};
|
861
|
+
|
862
|
+
/*
|
863
|
+
* Contains all the functions related to one index
|
864
|
+
* You should use AlgoliaSearch.initIndex(indexName) to retrieve this object
|
865
|
+
*/
|
866
|
+
AlgoliaSearch.prototype.Index.prototype = {
|
867
|
+
/*
|
868
|
+
* Clear all queries in cache
|
869
|
+
*/
|
870
|
+
clearCache: function() {
|
871
|
+
this.cache = {};
|
872
|
+
},
|
873
|
+
/*
|
874
|
+
* Add an object in this index
|
875
|
+
*
|
876
|
+
* @param content contains the javascript object to add inside the index
|
877
|
+
* @param objectID (optional) an objectID you want to attribute to this object
|
878
|
+
* (if the attribute already exist the old object will be overwrite)
|
879
|
+
* @param callback (optional) the result callback with two arguments:
|
880
|
+
* error: null or Error('message')
|
881
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
882
|
+
*/
|
883
|
+
addObject: function(content, objectID, callback) {
|
884
|
+
var indexObj = this;
|
885
|
+
|
886
|
+
if (arguments.length === 1 || typeof objectID === 'function') {
|
887
|
+
callback = objectID;
|
888
|
+
objectID = undefined;
|
889
|
+
}
|
890
|
+
|
891
|
+
return this.as._jsonRequest({
|
892
|
+
method: objectID !== undefined ?
|
893
|
+
'PUT' : // update or create
|
894
|
+
'POST', // create (API generates an objectID)
|
895
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + // create
|
896
|
+
(objectID !== undefined ? '/' + encodeURIComponent(objectID) : ''), // update or create
|
897
|
+
body: content,
|
898
|
+
callback: callback
|
899
|
+
});
|
900
|
+
},
|
901
|
+
/*
|
902
|
+
* Add several objects
|
903
|
+
*
|
904
|
+
* @param objects contains an array of objects to add
|
905
|
+
* @param callback (optional) the result callback with two arguments:
|
906
|
+
* error: null or Error('message')
|
907
|
+
* content: the server answer that updateAt and taskID
|
908
|
+
*/
|
909
|
+
addObjects: function(objects, callback) {
|
910
|
+
var indexObj = this;
|
911
|
+
var postObj = {requests: []};
|
912
|
+
for (var i = 0; i < objects.length; ++i) {
|
913
|
+
var request = { action: 'addObject',
|
914
|
+
body: objects[i] };
|
915
|
+
postObj.requests.push(request);
|
916
|
+
}
|
917
|
+
return this.as._jsonRequest({ method: 'POST',
|
918
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
919
|
+
body: postObj,
|
920
|
+
callback: callback });
|
921
|
+
},
|
922
|
+
/*
|
923
|
+
* Get an object from this index
|
924
|
+
*
|
925
|
+
* @param objectID the unique identifier of the object to retrieve
|
926
|
+
* @param attrs (optional) if set, contains the array of attribute names to retrieve
|
927
|
+
* @param callback (optional) the result callback with two arguments
|
928
|
+
* error: null or Error('message')
|
929
|
+
* content: the object to retrieve or the error message if a failure occured
|
930
|
+
*/
|
931
|
+
getObject: function(objectID, attrs, callback) {
|
932
|
+
var indexObj = this;
|
933
|
+
|
934
|
+
if (arguments.length === 1 || typeof attrs === 'function') {
|
935
|
+
callback = attrs;
|
936
|
+
attrs = undefined;
|
937
|
+
}
|
938
|
+
|
939
|
+
var params = '';
|
940
|
+
if (attrs !== undefined) {
|
941
|
+
params = '?attributes=';
|
942
|
+
for (var i = 0; i < attrs.length; ++i) {
|
943
|
+
if (i !== 0) {
|
944
|
+
params += ',';
|
945
|
+
}
|
946
|
+
params += attrs[i];
|
947
|
+
}
|
948
|
+
}
|
949
|
+
|
950
|
+
return this.as._jsonRequest({
|
951
|
+
method: 'GET',
|
952
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(objectID) + params,
|
953
|
+
callback: callback
|
954
|
+
});
|
955
|
+
},
|
956
|
+
|
957
|
+
/*
|
958
|
+
* Update partially an object (only update attributes passed in argument)
|
959
|
+
*
|
960
|
+
* @param partialObject contains the javascript attributes to override, the
|
961
|
+
* object must contains an objectID attribute
|
962
|
+
* @param callback (optional) the result callback with two arguments:
|
963
|
+
* error: null or Error('message')
|
964
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
965
|
+
*/
|
966
|
+
partialUpdateObject: function(partialObject, callback) {
|
967
|
+
var indexObj = this;
|
968
|
+
return this.as._jsonRequest({ method: 'POST',
|
969
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(partialObject.objectID) + '/partial',
|
970
|
+
body: partialObject,
|
971
|
+
callback: callback });
|
972
|
+
},
|
973
|
+
/*
|
974
|
+
* Partially Override the content of several objects
|
975
|
+
*
|
976
|
+
* @param objects contains an array of objects to update (each object must contains a objectID attribute)
|
977
|
+
* @param callback (optional) the result callback with two arguments:
|
978
|
+
* error: null or Error('message')
|
979
|
+
* content: the server answer that updateAt and taskID
|
980
|
+
*/
|
981
|
+
partialUpdateObjects: function(objects, callback) {
|
982
|
+
var indexObj = this;
|
983
|
+
var postObj = {requests: []};
|
984
|
+
for (var i = 0; i < objects.length; ++i) {
|
985
|
+
var request = { action: 'partialUpdateObject',
|
986
|
+
objectID: objects[i].objectID,
|
987
|
+
body: objects[i] };
|
988
|
+
postObj.requests.push(request);
|
989
|
+
}
|
990
|
+
return this.as._jsonRequest({ method: 'POST',
|
991
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
992
|
+
body: postObj,
|
993
|
+
callback: callback });
|
994
|
+
},
|
995
|
+
/*
|
996
|
+
* Override the content of object
|
997
|
+
*
|
998
|
+
* @param object contains the javascript object to save, the object must contains an objectID attribute
|
999
|
+
* @param callback (optional) the result callback with two arguments:
|
1000
|
+
* error: null or Error('message')
|
1001
|
+
* content: the server answer that updateAt and taskID
|
1002
|
+
*/
|
1003
|
+
saveObject: function(object, callback) {
|
1004
|
+
var indexObj = this;
|
1005
|
+
return this.as._jsonRequest({ method: 'PUT',
|
1006
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(object.objectID),
|
1007
|
+
body: object,
|
1008
|
+
callback: callback });
|
1009
|
+
},
|
1010
|
+
/*
|
1011
|
+
* Override the content of several objects
|
1012
|
+
*
|
1013
|
+
* @param objects contains an array of objects to update (each object must contains a objectID attribute)
|
1014
|
+
* @param callback (optional) the result callback with two arguments:
|
1015
|
+
* error: null or Error('message')
|
1016
|
+
* content: the server answer that updateAt and taskID
|
1017
|
+
*/
|
1018
|
+
saveObjects: function(objects, callback) {
|
1019
|
+
var indexObj = this;
|
1020
|
+
var postObj = {requests: []};
|
1021
|
+
for (var i = 0; i < objects.length; ++i) {
|
1022
|
+
var request = { action: 'updateObject',
|
1023
|
+
objectID: objects[i].objectID,
|
1024
|
+
body: objects[i] };
|
1025
|
+
postObj.requests.push(request);
|
1026
|
+
}
|
1027
|
+
return this.as._jsonRequest({ method: 'POST',
|
1028
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/batch',
|
1029
|
+
body: postObj,
|
1030
|
+
callback: callback });
|
1031
|
+
},
|
1032
|
+
/*
|
1033
|
+
* Delete an object from the index
|
1034
|
+
*
|
1035
|
+
* @param objectID the unique identifier of object to delete
|
1036
|
+
* @param callback (optional) the result callback with two arguments:
|
1037
|
+
* error: null or Error('message')
|
1038
|
+
* content: the server answer that contains 3 elements: createAt, taskId and objectID
|
1039
|
+
*/
|
1040
|
+
deleteObject: function(objectID, callback) {
|
1041
|
+
if (typeof objectID === 'function' || typeof objectID !== 'string' && typeof objectID !== 'number') {
|
1042
|
+
var err = new Error('Cannot delete an object without an objectID');
|
1043
|
+
callback = objectID;
|
1044
|
+
if (typeof callback === 'function') {
|
1045
|
+
return callback(err);
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
return this.as._request.reject(err);
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
var indexObj = this;
|
1052
|
+
return this.as._jsonRequest({ method: 'DELETE',
|
1053
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/' + encodeURIComponent(objectID),
|
1054
|
+
callback: callback });
|
1055
|
+
},
|
1056
|
+
/*
|
1057
|
+
* Search inside the index using XMLHttpRequest request (Using a POST query to
|
1058
|
+
* minimize number of OPTIONS queries: Cross-Origin Resource Sharing).
|
1059
|
+
*
|
1060
|
+
* @param query the full text query
|
1061
|
+
* @param args (optional) if set, contains an object with query parameters:
|
1062
|
+
* - page: (integer) Pagination parameter used to select the page to retrieve.
|
1063
|
+
* Page is zero-based and defaults to 0. Thus, to retrieve the 10th page you need to set page=9
|
1064
|
+
* - hitsPerPage: (integer) Pagination parameter used to select the number of hits per page. Defaults to 20.
|
1065
|
+
* - attributesToRetrieve: a string that contains the list of object attributes you want to retrieve (let you minimize the answer size).
|
1066
|
+
* Attributes are separated with a comma (for example "name,address").
|
1067
|
+
* You can also use an array (for example ["name","address"]).
|
1068
|
+
* By default, all attributes are retrieved. You can also use '*' to retrieve all values when an attributesToRetrieve setting is specified for your index.
|
1069
|
+
* - attributesToHighlight: a string that contains the list of attributes you want to highlight according to the query.
|
1070
|
+
* Attributes are separated by a comma. You can also use an array (for example ["name","address"]).
|
1071
|
+
* If an attribute has no match for the query, the raw value is returned. By default all indexed text attributes are highlighted.
|
1072
|
+
* You can use `*` if you want to highlight all textual attributes. Numerical attributes are not highlighted.
|
1073
|
+
* A matchLevel is returned for each highlighted attribute and can contain:
|
1074
|
+
* - full: if all the query terms were found in the attribute,
|
1075
|
+
* - partial: if only some of the query terms were found,
|
1076
|
+
* - none: if none of the query terms were found.
|
1077
|
+
* - attributesToSnippet: a string that contains the list of attributes to snippet alongside the number of words to return (syntax is `attributeName:nbWords`).
|
1078
|
+
* Attributes are separated by a comma (Example: attributesToSnippet=name:10,content:10).
|
1079
|
+
* You can also use an array (Example: attributesToSnippet: ['name:10','content:10']). By default no snippet is computed.
|
1080
|
+
* - minWordSizefor1Typo: the minimum number of characters in a query word to accept one typo in this word. Defaults to 3.
|
1081
|
+
* - minWordSizefor2Typos: the minimum number of characters in a query word to accept two typos in this word. Defaults to 7.
|
1082
|
+
* - getRankingInfo: if set to 1, the result hits will contain ranking information in _rankingInfo attribute.
|
1083
|
+
* - aroundLatLng: search for entries around a given latitude/longitude (specified as two floats separated by a comma).
|
1084
|
+
* For example aroundLatLng=47.316669,5.016670).
|
1085
|
+
* You can specify the maximum distance in meters with the aroundRadius parameter (in meters) and the precision for ranking with aroundPrecision
|
1086
|
+
* (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).
|
1087
|
+
* At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form {"_geoloc":{"lat":48.853409, "lng":2.348800}})
|
1088
|
+
* - insideBoundingBox: search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng).
|
1089
|
+
* For example insideBoundingBox=47.3165,4.9665,47.3424,5.0201).
|
1090
|
+
* At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form {"_geoloc":{"lat":48.853409, "lng":2.348800}})
|
1091
|
+
* - numericFilters: a string that contains the list of numeric filters you want to apply separated by a comma.
|
1092
|
+
* The syntax of one filter is `attributeName` followed by `operand` followed by `value`. Supported operands are `<`, `<=`, `=`, `>` and `>=`.
|
1093
|
+
* You can have multiple conditions on one attribute like for example numericFilters=price>100,price<1000.
|
1094
|
+
* You can also use an array (for example numericFilters: ["price>100","price<1000"]).
|
1095
|
+
* - tagFilters: filter the query by a set of tags. You can AND tags by separating them by commas.
|
1096
|
+
* To OR tags, you must add parentheses. For example, tags=tag1,(tag2,tag3) means tag1 AND (tag2 OR tag3).
|
1097
|
+
* You can also use an array, for example tagFilters: ["tag1",["tag2","tag3"]] means tag1 AND (tag2 OR tag3).
|
1098
|
+
* At indexing, tags should be added in the _tags** attribute of objects (for example {"_tags":["tag1","tag2"]}).
|
1099
|
+
* - facetFilters: filter the query by a list of facets.
|
1100
|
+
* Facets are separated by commas and each facet is encoded as `attributeName:value`.
|
1101
|
+
* For example: `facetFilters=category:Book,author:John%20Doe`.
|
1102
|
+
* You can also use an array (for example `["category:Book","author:John%20Doe"]`).
|
1103
|
+
* - facets: List of object attributes that you want to use for faceting.
|
1104
|
+
* Comma separated list: `"category,author"` or array `['category','author']`
|
1105
|
+
* Only attributes that have been added in **attributesForFaceting** index setting can be used in this parameter.
|
1106
|
+
* You can also use `*` to perform faceting on all attributes specified in **attributesForFaceting**.
|
1107
|
+
* - queryType: select how the query words are interpreted, it can be one of the following value:
|
1108
|
+
* - prefixAll: all query words are interpreted as prefixes,
|
1109
|
+
* - prefixLast: only the last word is interpreted as a prefix (default behavior),
|
1110
|
+
* - prefixNone: no query word is interpreted as a prefix. This option is not recommended.
|
1111
|
+
* - optionalWords: a string that contains the list of words that should be considered as optional when found in the query.
|
1112
|
+
* Comma separated and array are accepted.
|
1113
|
+
* - distinct: If set to 1, enable the distinct feature (disabled by default) if the attributeForDistinct index setting is set.
|
1114
|
+
* This feature is similar to the SQL "distinct" keyword: when enabled in a query with the distinct=1 parameter,
|
1115
|
+
* all hits containing a duplicate value for the attributeForDistinct attribute are removed from results.
|
1116
|
+
* For example, if the chosen attribute is show_name and several hits have the same value for show_name, then only the best
|
1117
|
+
* one is kept and others are removed.
|
1118
|
+
* - restrictSearchableAttributes: List of attributes you want to use for textual search (must be a subset of the attributesToIndex index setting)
|
1119
|
+
* either comma separated or as an array
|
1120
|
+
* @param callback the result callback with two arguments:
|
1121
|
+
* error: null or Error('message'). If false, the content contains the error.
|
1122
|
+
* content: the server answer that contains the list of results.
|
1123
|
+
*/
|
1124
|
+
search: function(query, args, callback) {
|
1125
|
+
if (arguments.length === 0 || typeof query === 'function') {
|
1126
|
+
// .search(), .search(cb)
|
1127
|
+
callback = query;
|
1128
|
+
query = '';
|
1129
|
+
} else if (arguments.length === 1 || typeof args === 'function') {
|
1130
|
+
// .search(query/args), .search(query, cb)
|
1131
|
+
callback = args;
|
1132
|
+
args = undefined;
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
// .search(args), careful: typeof null === 'object'
|
1136
|
+
if (typeof query === 'object' && query !== null) {
|
1137
|
+
args = query;
|
1138
|
+
query = undefined;
|
1139
|
+
} else if (query === undefined || query === null) { // .search(undefined/null)
|
1140
|
+
query = '';
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
var params = '';
|
1144
|
+
|
1145
|
+
if (query !== undefined) {
|
1146
|
+
params += 'query=' + encodeURIComponent(query);
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
if (args !== undefined) {
|
1150
|
+
params = this.as._getSearchParams(args, params);
|
1151
|
+
}
|
1152
|
+
|
1153
|
+
return this._search(params, callback);
|
1154
|
+
},
|
1155
|
+
|
1156
|
+
/*
|
1157
|
+
* Browse all index content
|
1158
|
+
*
|
1159
|
+
* @param page Pagination parameter used to select the page to retrieve.
|
1160
|
+
* Page is zero-based and defaults to 0. Thus, to retrieve the 10th page you need to set page=9
|
1161
|
+
* @param hitsPerPage: Pagination parameter used to select the number of hits per page. Defaults to 1000.
|
1162
|
+
* @param callback the result callback with two arguments:
|
1163
|
+
* error: null or Error('message'). If false, the content contains the error.
|
1164
|
+
* content: the server answer that contains the list of results.
|
1165
|
+
*/
|
1166
|
+
browse: function(page, hitsPerPage, callback) {
|
1167
|
+
var indexObj = this;
|
1168
|
+
|
1169
|
+
if (arguments.length === 1 || typeof hitsPerPage === 'function') {
|
1170
|
+
callback = hitsPerPage;
|
1171
|
+
hitsPerPage = undefined;
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
var params = '?page=' + page;
|
1175
|
+
if (!this.as._isUndefined(hitsPerPage)) {
|
1176
|
+
params += '&hitsPerPage=' + hitsPerPage;
|
1177
|
+
}
|
1178
|
+
return this.as._jsonRequest({ method: 'GET',
|
1179
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/browse' + params,
|
1180
|
+
callback: callback });
|
1181
|
+
},
|
1182
|
+
|
1183
|
+
/*
|
1184
|
+
* Get a Typeahead.js adapter
|
1185
|
+
* @param searchParams contains an object with query parameters (see search for details)
|
1186
|
+
*/
|
1187
|
+
ttAdapter: function(params) {
|
1188
|
+
var self = this;
|
1189
|
+
return function(query, cb) {
|
1190
|
+
self.search(query, params, function(err, content) {
|
1191
|
+
if (err) {
|
1192
|
+
cb(err);
|
1193
|
+
return;
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
cb(content.hits);
|
1197
|
+
});
|
1198
|
+
};
|
1199
|
+
},
|
1200
|
+
|
1201
|
+
/*
|
1202
|
+
* Wait the publication of a task on the server.
|
1203
|
+
* All server task are asynchronous and you can check with this method that the task is published.
|
1204
|
+
*
|
1205
|
+
* @param taskID the id of the task returned by server
|
1206
|
+
* @param callback the result callback with with two arguments:
|
1207
|
+
* error: null or Error('message')
|
1208
|
+
* content: the server answer that contains the list of results
|
1209
|
+
*/
|
1210
|
+
waitTask: function(taskID, callback) {
|
1211
|
+
// waitTask() must be handled differently from other methods,
|
1212
|
+
// it's a recursive method using a timeout
|
1213
|
+
var indexObj = this;
|
1214
|
+
|
1215
|
+
var promise = this.as._jsonRequest({
|
1216
|
+
method: 'GET',
|
1217
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/task/' + taskID
|
1218
|
+
}).then(function success(content) {
|
1219
|
+
if (content.status !== 'published') {
|
1220
|
+
return new indexObj.as._request.delay(100).then(function() {
|
1221
|
+
return indexObj.waitTask(taskID, callback);
|
1222
|
+
});
|
1223
|
+
}
|
1224
|
+
|
1225
|
+
if (callback) {
|
1226
|
+
process.nextTick(function() {
|
1227
|
+
callback(null, content);
|
1228
|
+
});
|
1229
|
+
} else {
|
1230
|
+
return content;
|
1231
|
+
}
|
1232
|
+
}, function failure(err) {
|
1233
|
+
if (callback) {
|
1234
|
+
process.nextTick(function() {
|
1235
|
+
callback(err);
|
1236
|
+
});
|
1237
|
+
} else {
|
1238
|
+
return err;
|
1239
|
+
}
|
1240
|
+
});
|
1241
|
+
|
1242
|
+
if (!callback) {
|
1243
|
+
return promise;
|
1244
|
+
}
|
1245
|
+
},
|
1246
|
+
|
1247
|
+
/*
|
1248
|
+
* This function deletes the index content. Settings and index specific API keys are kept untouched.
|
1249
|
+
*
|
1250
|
+
* @param callback (optional) the result callback with two arguments
|
1251
|
+
* error: null or Error('message')
|
1252
|
+
* content: the settings object or the error message if a failure occured
|
1253
|
+
*/
|
1254
|
+
clearIndex: function(callback) {
|
1255
|
+
var indexObj = this;
|
1256
|
+
return this.as._jsonRequest({ method: 'POST',
|
1257
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/clear',
|
1258
|
+
callback: callback });
|
1259
|
+
},
|
1260
|
+
/*
|
1261
|
+
* Get settings of this index
|
1262
|
+
*
|
1263
|
+
* @param callback (optional) the result callback with two arguments
|
1264
|
+
* error: null or Error('message')
|
1265
|
+
* content: the settings object or the error message if a failure occured
|
1266
|
+
*/
|
1267
|
+
getSettings: function(callback) {
|
1268
|
+
var indexObj = this;
|
1269
|
+
return this.as._jsonRequest({ method: 'GET',
|
1270
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/settings',
|
1271
|
+
callback: callback });
|
1272
|
+
},
|
1273
|
+
|
1274
|
+
/*
|
1275
|
+
* Set settings for this index
|
1276
|
+
*
|
1277
|
+
* @param settigns the settings object that can contains :
|
1278
|
+
* - minWordSizefor1Typo: (integer) the minimum number of characters to accept one typo (default = 3).
|
1279
|
+
* - minWordSizefor2Typos: (integer) the minimum number of characters to accept two typos (default = 7).
|
1280
|
+
* - hitsPerPage: (integer) the number of hits per page (default = 10).
|
1281
|
+
* - attributesToRetrieve: (array of strings) default list of attributes to retrieve in objects.
|
1282
|
+
* If set to null, all attributes are retrieved.
|
1283
|
+
* - attributesToHighlight: (array of strings) default list of attributes to highlight.
|
1284
|
+
* If set to null, all indexed attributes are highlighted.
|
1285
|
+
* - attributesToSnippet**: (array of strings) default list of attributes to snippet alongside the number of words to return (syntax is attributeName:nbWords).
|
1286
|
+
* By default no snippet is computed. If set to null, no snippet is computed.
|
1287
|
+
* - attributesToIndex: (array of strings) the list of fields you want to index.
|
1288
|
+
* If set to null, all textual and numerical attributes of your objects are indexed, but you should update it to get optimal results.
|
1289
|
+
* This parameter has two important uses:
|
1290
|
+
* - Limit the attributes to index: For example if you store a binary image in base64, you want to store it and be able to
|
1291
|
+
* retrieve it but you don't want to search in the base64 string.
|
1292
|
+
* - Control part of the ranking*: (see the ranking parameter for full explanation) Matches in attributes at the beginning of
|
1293
|
+
* the list will be considered more important than matches in attributes further down the list.
|
1294
|
+
* In one attribute, matching text at the beginning of the attribute will be considered more important than text after, you can disable
|
1295
|
+
* this behavior if you add your attribute inside `unordered(AttributeName)`, for example attributesToIndex: ["title", "unordered(text)"].
|
1296
|
+
* - attributesForFaceting: (array of strings) The list of fields you want to use for faceting.
|
1297
|
+
* 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.
|
1298
|
+
* - attributeForDistinct: (string) The attribute name used for the Distinct feature. This feature is similar to the SQL "distinct" keyword: when enabled
|
1299
|
+
* in query with the distinct=1 parameter, all hits containing a duplicate value for this attribute are removed from results.
|
1300
|
+
* 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.
|
1301
|
+
* - ranking: (array of strings) controls the way results are sorted.
|
1302
|
+
* We have six available criteria:
|
1303
|
+
* - typo: sort according to number of typos,
|
1304
|
+
* - geo: sort according to decreassing distance when performing a geo-location based search,
|
1305
|
+
* - proximity: sort according to the proximity of query words in hits,
|
1306
|
+
* - attribute: sort according to the order of attributes defined by attributesToIndex,
|
1307
|
+
* - exact:
|
1308
|
+
* - if the user query contains one word: sort objects having an attribute that is exactly the query word before others.
|
1309
|
+
* 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
|
1310
|
+
* show starting by the v letter before it.
|
1311
|
+
* - if the user query contains multiple words: sort according to the number of words that matched exactly (and not as a prefix).
|
1312
|
+
* - custom: sort according to a user defined formula set in **customRanking** attribute.
|
1313
|
+
* The standard order is ["typo", "geo", "proximity", "attribute", "exact", "custom"]
|
1314
|
+
* - customRanking: (array of strings) lets you specify part of the ranking.
|
1315
|
+
* The syntax of this condition is an array of strings containing attributes prefixed by asc (ascending order) or desc (descending order) operator.
|
1316
|
+
* For example `"customRanking" => ["desc(population)", "asc(name)"]`
|
1317
|
+
* - queryType: Select how the query words are interpreted, it can be one of the following value:
|
1318
|
+
* - prefixAll: all query words are interpreted as prefixes,
|
1319
|
+
* - prefixLast: only the last word is interpreted as a prefix (default behavior),
|
1320
|
+
* - prefixNone: no query word is interpreted as a prefix. This option is not recommended.
|
1321
|
+
* - highlightPreTag: (string) Specify the string that is inserted before the highlighted parts in the query result (default to "<em>").
|
1322
|
+
* - highlightPostTag: (string) Specify the string that is inserted after the highlighted parts in the query result (default to "</em>").
|
1323
|
+
* - optionalWords: (array of strings) Specify a list of words that should be considered as optional when found in the query.
|
1324
|
+
* @param callback (optional) the result callback with two arguments
|
1325
|
+
* error: null or Error('message')
|
1326
|
+
* content: the server answer or the error message if a failure occured
|
1327
|
+
*/
|
1328
|
+
setSettings: function(settings, callback) {
|
1329
|
+
var indexObj = this;
|
1330
|
+
return this.as._jsonRequest({ method: 'PUT',
|
1331
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/settings',
|
1332
|
+
body: settings,
|
1333
|
+
callback: callback });
|
1334
|
+
},
|
1335
|
+
/*
|
1336
|
+
* List all existing user keys associated to this index
|
1337
|
+
*
|
1338
|
+
* @param callback the result callback with two arguments
|
1339
|
+
* error: null or Error('message')
|
1340
|
+
* content: the server answer with user keys list
|
1341
|
+
*/
|
1342
|
+
listUserKeys: function(callback) {
|
1343
|
+
var indexObj = this;
|
1344
|
+
return this.as._jsonRequest({ method: 'GET',
|
1345
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
1346
|
+
callback: callback });
|
1347
|
+
},
|
1348
|
+
/*
|
1349
|
+
* Get ACL of a user key associated to this index
|
1350
|
+
*
|
1351
|
+
* @param key
|
1352
|
+
* @param callback the result callback with two arguments
|
1353
|
+
* error: null or Error('message')
|
1354
|
+
* content: the server answer with user keys list
|
1355
|
+
*/
|
1356
|
+
getUserKeyACL: function(key, callback) {
|
1357
|
+
var indexObj = this;
|
1358
|
+
return this.as._jsonRequest({ method: 'GET',
|
1359
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys/' + key,
|
1360
|
+
callback: callback });
|
1361
|
+
},
|
1362
|
+
/*
|
1363
|
+
* Delete an existing user key associated to this index
|
1364
|
+
*
|
1365
|
+
* @param key
|
1366
|
+
* @param callback the result callback with two arguments
|
1367
|
+
* error: null or Error('message')
|
1368
|
+
* content: the server answer with user keys list
|
1369
|
+
*/
|
1370
|
+
deleteUserKey: function(key, callback) {
|
1371
|
+
var indexObj = this;
|
1372
|
+
return this.as._jsonRequest({ method: 'DELETE',
|
1373
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys/' + key,
|
1374
|
+
callback: callback });
|
1375
|
+
},
|
1376
|
+
/*
|
1377
|
+
* Add an existing user key associated to this index
|
1378
|
+
*
|
1379
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
1380
|
+
* can contains the following values:
|
1381
|
+
* - search: allow to search (https and http)
|
1382
|
+
* - addObject: allows to add/update an object in the index (https only)
|
1383
|
+
* - deleteObject : allows to delete an existing object (https only)
|
1384
|
+
* - deleteIndex : allows to delete index content (https only)
|
1385
|
+
* - settings : allows to get index settings (https only)
|
1386
|
+
* - editSettings : allows to change index settings (https only)
|
1387
|
+
* @param callback the result callback with two arguments
|
1388
|
+
* error: null or Error('message')
|
1389
|
+
* content: the server answer with user keys list
|
1390
|
+
*/
|
1391
|
+
addUserKey: function(acls, callback) {
|
1392
|
+
var indexObj = this;
|
1393
|
+
var aclsObject = {};
|
1394
|
+
aclsObject.acl = acls;
|
1395
|
+
return this.as._jsonRequest({ method: 'POST',
|
1396
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
1397
|
+
body: aclsObject,
|
1398
|
+
callback: callback });
|
1399
|
+
},
|
1400
|
+
/*
|
1401
|
+
* Add an existing user key associated to this index
|
1402
|
+
*
|
1403
|
+
* @param acls the list of ACL for this key. Defined by an array of strings that
|
1404
|
+
* can contains the following values:
|
1405
|
+
* - search: allow to search (https and http)
|
1406
|
+
* - addObject: allows to add/update an object in the index (https only)
|
1407
|
+
* - deleteObject : allows to delete an existing object (https only)
|
1408
|
+
* - deleteIndex : allows to delete index content (https only)
|
1409
|
+
* - settings : allows to get index settings (https only)
|
1410
|
+
* - editSettings : allows to change index settings (https only)
|
1411
|
+
* @param params.validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
|
1412
|
+
* @param params.maxQueriesPerIPPerHour Specify the maximum number of API calls allowed from an IP address per hour.
|
1413
|
+
* @param params.maxHitsPerQuery Specify the maximum number of hits this API key can retrieve in one call.
|
1414
|
+
* @param callback the result callback with two arguments
|
1415
|
+
* error: null or Error('message')
|
1416
|
+
* content: the server answer with user keys list
|
1417
|
+
*/
|
1418
|
+
addUserKeyWithValidity: function(acls, params, callback) {
|
1419
|
+
var indexObj = this;
|
1420
|
+
var aclsObject = {};
|
1421
|
+
aclsObject.acl = acls;
|
1422
|
+
aclsObject.validity = params.validity;
|
1423
|
+
aclsObject.maxQueriesPerIPPerHour = params.maxQueriesPerIPPerHour;
|
1424
|
+
aclsObject.maxHitsPerQuery = params.maxHitsPerQuery;
|
1425
|
+
return this.as._jsonRequest({ method: 'POST',
|
1426
|
+
url: '/1/indexes/' + encodeURIComponent(indexObj.indexName) + '/keys',
|
1427
|
+
body: aclsObject,
|
1428
|
+
callback: callback });
|
1429
|
+
},
|
1430
|
+
///
|
1431
|
+
/// Internal methods only after this line
|
1432
|
+
///
|
1433
|
+
_search: function(params, callback) {
|
1434
|
+
return this.as._jsonRequest({ cache: this.cache,
|
1435
|
+
method: 'POST',
|
1436
|
+
url: '/1/indexes/' + encodeURIComponent(this.indexName) + '/query',
|
1437
|
+
body: {params: params},
|
1438
|
+
fallback: {
|
1439
|
+
method: 'GET',
|
1440
|
+
url: '/1/indexes/' + encodeURIComponent(this.indexName),
|
1441
|
+
body: {params: params}
|
1442
|
+
},
|
1443
|
+
callback: callback
|
1444
|
+
});
|
1445
|
+
},
|
1446
|
+
|
1447
|
+
// internal attributes
|
1448
|
+
as: null,
|
1449
|
+
indexName: null,
|
1450
|
+
typeAheadArgs: null,
|
1451
|
+
typeAheadValueOption: null
|
1452
|
+
};
|
1453
|
+
|
1454
|
+
// extracted from https://github.com/component/map/blob/master/index.js
|
1455
|
+
// without the crazy toFunction thing
|
1456
|
+
function map(arr, fn){
|
1457
|
+
var ret = [];
|
1458
|
+
for (var i = 0; i < arr.length; ++i) {
|
1459
|
+
ret.push(fn(arr[i], i));
|
1460
|
+
}
|
1461
|
+
return ret;
|
1462
|
+
}
|
1463
|
+
|
1464
|
+
// extracted from https://github.com/coolaj86/knuth-shuffle
|
1465
|
+
// not compatible with browserify
|
1466
|
+
function shuffle(array) {
|
1467
|
+
/*eslint-disable*/
|
1468
|
+
var currentIndex = array.length
|
1469
|
+
, temporaryValue
|
1470
|
+
, randomIndex
|
1471
|
+
;
|
1472
|
+
|
1473
|
+
// While there remain elements to shuffle...
|
1474
|
+
while (0 !== currentIndex) {
|
1475
|
+
|
1476
|
+
// Pick a remaining element...
|
1477
|
+
randomIndex = Math.floor(Math.random() * currentIndex);
|
1478
|
+
currentIndex -= 1;
|
1479
|
+
|
1480
|
+
// And swap it with the current element.
|
1481
|
+
temporaryValue = array[currentIndex];
|
1482
|
+
array[currentIndex] = array[randomIndex];
|
1483
|
+
array[randomIndex] = temporaryValue;
|
1484
|
+
}
|
1485
|
+
|
1486
|
+
return array;
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
}).call(this,require(1))
|
1490
|
+
},{"1":1}],3:[function(require,module,exports){
|
1491
|
+
(function (global){
|
1492
|
+
var createAlgoliasearch = require(5);
|
1493
|
+
var JSONPRequest = require(4);
|
1494
|
+
|
1495
|
+
global.angular.module('algoliasearch', [])
|
1496
|
+
.service('algolia', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {
|
1497
|
+
function request(url, opts) {
|
1498
|
+
return $q(function(resolve, reject) {
|
1499
|
+
var timedOut;
|
1500
|
+
var body = null;
|
1501
|
+
|
1502
|
+
if (opts.body !== undefined) {
|
1503
|
+
body = JSON.stringify(opts.body);
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
var timeout = $q(function(resolveTimeout) {
|
1507
|
+
$timeout(function() {
|
1508
|
+
timedOut = true;
|
1509
|
+
// will cancel the xhr
|
1510
|
+
resolveTimeout('test');
|
1511
|
+
resolve(new Error('Timeout - Could not connect to endpoint ' + url));
|
1512
|
+
}, opts.timeout);
|
1513
|
+
});
|
1514
|
+
|
1515
|
+
$http({
|
1516
|
+
url: url,
|
1517
|
+
method: opts.method,
|
1518
|
+
data: body,
|
1519
|
+
cache: false,
|
1520
|
+
timeout: timeout
|
1521
|
+
}).then(function success(response) {
|
1522
|
+
resolve({
|
1523
|
+
statusCode: response.status,
|
1524
|
+
body: response.data
|
1525
|
+
});
|
1526
|
+
}, function error(response) {
|
1527
|
+
if (timedOut) {
|
1528
|
+
return;
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
// network error
|
1532
|
+
if (response.status === 0) {
|
1533
|
+
reject(new Error('Network error'));
|
1534
|
+
return;
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
resolve({
|
1538
|
+
body: response.data,
|
1539
|
+
statusCode: response.status
|
1540
|
+
});
|
1541
|
+
});
|
1542
|
+
});
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
request.fallback = function(url, opts) {
|
1546
|
+
return $q(function(resolve, reject) {
|
1547
|
+
JSONPRequest(url, opts, function JSONPRequestDone(err, content) {
|
1548
|
+
if (err) {
|
1549
|
+
reject(err);
|
1550
|
+
return;
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
resolve(content);
|
1554
|
+
});
|
1555
|
+
});
|
1556
|
+
};
|
1557
|
+
|
1558
|
+
request.reject = function(val) {
|
1559
|
+
return $q.reject(val);
|
1560
|
+
};
|
1561
|
+
|
1562
|
+
request.resolve = function(val) {
|
1563
|
+
// http://www.bennadel.com/blog/2735-q-when-is-the-missing-q-resolve-method-in-angularjs.htm
|
1564
|
+
return $q.when(val);
|
1565
|
+
};
|
1566
|
+
|
1567
|
+
request.delay = function(ms) {
|
1568
|
+
return $q(function(resolve/*, reject*/) {
|
1569
|
+
$timeout(resolve, ms);
|
1570
|
+
});
|
1571
|
+
};
|
1572
|
+
|
1573
|
+
var algoliasearch = createAlgoliasearch(request);
|
1574
|
+
return {
|
1575
|
+
Client: function(applicationID, apiKey, options) {
|
1576
|
+
return algoliasearch(applicationID, apiKey, options);
|
1577
|
+
}
|
1578
|
+
};
|
1579
|
+
}]);
|
1580
|
+
|
1581
|
+
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
1582
|
+
},{"4":4,"5":5}],4:[function(require,module,exports){
|
1583
|
+
module.exports = JSONPRequest;
|
1584
|
+
|
1585
|
+
var JSONPCounter = 0;
|
1586
|
+
|
1587
|
+
function JSONPRequest(url, opts, cb) {
|
1588
|
+
if (opts.method !== 'GET') {
|
1589
|
+
cb(new Error('Method ' + opts.method + ' ' + url + ' is not supported by JSONP.'));
|
1590
|
+
return;
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
var cbCalled = false;
|
1594
|
+
var timedOut = false;
|
1595
|
+
|
1596
|
+
JSONPCounter += 1;
|
1597
|
+
var head = document.getElementsByTagName('head')[0];
|
1598
|
+
var script = document.createElement('script');
|
1599
|
+
var cbName = 'algoliaJSONP_' + JSONPCounter;
|
1600
|
+
var done = false;
|
1601
|
+
|
1602
|
+
window[cbName] = function(data) {
|
1603
|
+
try {
|
1604
|
+
delete window[cbName];
|
1605
|
+
} catch (e) {
|
1606
|
+
window[cbName] = undefined;
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
if (timedOut) {
|
1610
|
+
return;
|
1611
|
+
}
|
1612
|
+
|
1613
|
+
cbCalled = true;
|
1614
|
+
|
1615
|
+
clean();
|
1616
|
+
|
1617
|
+
cb(null, {
|
1618
|
+
body: data/*,
|
1619
|
+
// We do not send the statusCode, there's no statusCode in JSONP, it will be
|
1620
|
+
// computed using data.status && data.message like with XDR
|
1621
|
+
statusCode*/
|
1622
|
+
});
|
1623
|
+
};
|
1624
|
+
|
1625
|
+
// add callback by hand
|
1626
|
+
url += '&callback=' + cbName;
|
1627
|
+
|
1628
|
+
// add body params by hand
|
1629
|
+
if (opts.body && opts.body.params) {
|
1630
|
+
url += '&' + opts.body.params;
|
1631
|
+
}
|
1632
|
+
|
1633
|
+
var ontimeout = setTimeout(timeout, opts.timeout);
|
1634
|
+
|
1635
|
+
// script onreadystatechange needed only for
|
1636
|
+
// <= IE8
|
1637
|
+
// https://github.com/angular/angular.js/issues/4523
|
1638
|
+
script.onreadystatechange = readystatechange;
|
1639
|
+
script.onload = success;
|
1640
|
+
script.onerror = error;
|
1641
|
+
|
1642
|
+
script.async = true;
|
1643
|
+
script.defer = true;
|
1644
|
+
script.src = url;
|
1645
|
+
head.appendChild(script);
|
1646
|
+
|
1647
|
+
function success() {
|
1648
|
+
if (done || timedOut) {
|
1649
|
+
return;
|
1650
|
+
}
|
1651
|
+
|
1652
|
+
done = true;
|
1653
|
+
|
1654
|
+
// script loaded but did not call the fn => script loading error
|
1655
|
+
if (!cbCalled) {
|
1656
|
+
clean();
|
1657
|
+
cb(new Error('Failed to load JSONP script'));
|
1658
|
+
}
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
function readystatechange() {
|
1662
|
+
if (this.readyState === 'loaded' || this.readyState === 'complete') {
|
1663
|
+
success();
|
1664
|
+
}
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
function clean() {
|
1668
|
+
clearTimeout(ontimeout);
|
1669
|
+
script.onload = null;
|
1670
|
+
script.onreadystatechange = null;
|
1671
|
+
script.onerror = null;
|
1672
|
+
head.removeChild(script);
|
1673
|
+
|
1674
|
+
try {
|
1675
|
+
delete window[cbName];
|
1676
|
+
delete window[cbName + '_loaded'];
|
1677
|
+
} catch (e) {
|
1678
|
+
window[cbName] = null;
|
1679
|
+
window[cbName + '_loaded'] = null;
|
1680
|
+
}
|
1681
|
+
}
|
1682
|
+
|
1683
|
+
function timeout() {
|
1684
|
+
timedOut = true;
|
1685
|
+
clean();
|
1686
|
+
cb(new Error('Timeout - Could not connect to endpoint ' + url));
|
1687
|
+
}
|
1688
|
+
|
1689
|
+
function error() {
|
1690
|
+
if (done || timedOut) {
|
1691
|
+
return;
|
1692
|
+
}
|
1693
|
+
|
1694
|
+
clean();
|
1695
|
+
cb(new Error('Failed to load JSONP script'));
|
1696
|
+
}
|
1697
|
+
}
|
1698
|
+
|
1699
|
+
},{}],5:[function(require,module,exports){
|
1700
|
+
// this file is a `factory of algoliasearch()`
|
1701
|
+
// Given a `request` param, it will provide you an AlgoliaSearch client
|
1702
|
+
// using this particular request
|
1703
|
+
module.exports = createAlgoliasearch;
|
1704
|
+
|
1705
|
+
function createAlgoliasearch(request) {
|
1706
|
+
function algoliasearch(applicationID, apiKey, opts) {
|
1707
|
+
var AlgoliaSearch = require(2);
|
1708
|
+
|
1709
|
+
return new AlgoliaSearch(applicationID, apiKey, opts, request);
|
1710
|
+
}
|
1711
|
+
|
1712
|
+
algoliasearch.version = "3.0.3";
|
1713
|
+
|
1714
|
+
return algoliasearch;
|
1715
|
+
}
|
1716
|
+
|
1717
|
+
},{"2":2}]},{},[3]);
|