{"version":3,"file":"static/js/426.3ac027f3.chunk.js","mappings":"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","sources":["../node_modules/@algolia/events/events.js","../node_modules/algoliasearch-helper/index.js","../node_modules/algoliasearch-helper/src/DerivedHelper/index.js","../node_modules/algoliasearch-helper/src/RecommendParameters/index.js","../node_modules/algoliasearch-helper/src/RecommendResults/index.js","../node_modules/algoliasearch-helper/src/SearchParameters/RefinementList.js","../node_modules/algoliasearch-helper/src/SearchParameters/index.js","../node_modules/algoliasearch-helper/src/SearchResults/generate-hierarchical-tree.js","../node_modules/algoliasearch-helper/src/SearchResults/index.js","../node_modules/algoliasearch-helper/src/algoliasearch.helper.js","../node_modules/algoliasearch-helper/src/functions/compact.js","../node_modules/algoliasearch-helper/src/functions/defaultsPure.js","../node_modules/algoliasearch-helper/src/functions/escapeFacetValue.js","../node_modules/algoliasearch-helper/src/functions/find.js","../node_modules/algoliasearch-helper/src/functions/findIndex.js","../node_modules/algoliasearch-helper/src/functions/flat.js","../node_modules/algoliasearch-helper/src/functions/formatSort.js","../node_modules/algoliasearch-helper/src/functions/inherits.js","../node_modules/algoliasearch-helper/src/functions/intersection.js","../node_modules/algoliasearch-helper/src/functions/merge.js","../node_modules/algoliasearch-helper/src/functions/objectHasKeys.js","../node_modules/algoliasearch-helper/src/functions/omit.js","../node_modules/algoliasearch-helper/src/functions/orderBy.js","../node_modules/algoliasearch-helper/src/functions/valToNumber.js","../node_modules/algoliasearch-helper/src/requestBuilder.js","../node_modules/algoliasearch-helper/src/utils/isValidUserToken.js","../node_modules/algoliasearch-helper/src/utils/sortAndMergeRecommendations.js","../node_modules/algoliasearch-helper/src/version.js"],"sourcesContent":["// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nfunction EventEmitter() {\n this._events = this._events || {};\n this._maxListeners = this._maxListeners || undefined;\n}\nmodule.exports = EventEmitter;\n\n// Backwards-compat with node 0.10.x\n// EventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nEventEmitter.defaultMaxListeners = 10;\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function(n) {\n if (!isNumber(n) || n < 0 || isNaN(n))\n throw TypeError('n must be a positive number');\n this._maxListeners = n;\n return this;\n};\n\nEventEmitter.prototype.emit = function(type) {\n var er, handler, len, args, i, listeners;\n\n if (!this._events)\n this._events = {};\n\n // If there is no 'error' event listener then throw.\n if (type === 'error') {\n if (!this._events.error ||\n (isObject(this._events.error) && !this._events.error.length)) {\n er = arguments[1];\n if (er instanceof Error) {\n throw er; // Unhandled 'error' event\n } else {\n // At least give some kind of context to the user\n var err = new Error('Uncaught, unspecified \"error\" event. (' + er + ')');\n err.context = er;\n throw err;\n }\n }\n }\n\n handler = this._events[type];\n\n if (isUndefined(handler))\n return false;\n\n if (isFunction(handler)) {\n switch (arguments.length) {\n // fast cases\n case 1:\n handler.call(this);\n break;\n case 2:\n handler.call(this, arguments[1]);\n break;\n case 3:\n handler.call(this, arguments[1], arguments[2]);\n break;\n // slower\n default:\n args = Array.prototype.slice.call(arguments, 1);\n handler.apply(this, args);\n }\n } else if (isObject(handler)) {\n args = Array.prototype.slice.call(arguments, 1);\n listeners = handler.slice();\n len = listeners.length;\n for (i = 0; i < len; i++)\n listeners[i].apply(this, args);\n }\n\n return true;\n};\n\nEventEmitter.prototype.addListener = function(type, listener) {\n var m;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events)\n this._events = {};\n\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (this._events.newListener)\n this.emit('newListener', type,\n isFunction(listener.listener) ?\n listener.listener : listener);\n\n if (!this._events[type])\n // Optimize the case of one listener. Don't need the extra array object.\n this._events[type] = listener;\n else if (isObject(this._events[type]))\n // If we've already got an array, just append.\n this._events[type].push(listener);\n else\n // Adding the second element, need to change to array.\n this._events[type] = [this._events[type], listener];\n\n // Check for listener leak\n if (isObject(this._events[type]) && !this._events[type].warned) {\n if (!isUndefined(this._maxListeners)) {\n m = this._maxListeners;\n } else {\n m = EventEmitter.defaultMaxListeners;\n }\n\n if (m && m > 0 && this._events[type].length > m) {\n this._events[type].warned = true;\n console.error('(node) warning: possible EventEmitter memory ' +\n 'leak detected. %d listeners added. ' +\n 'Use emitter.setMaxListeners() to increase limit.',\n this._events[type].length);\n if (typeof console.trace === 'function') {\n // not supported in IE 10\n console.trace();\n }\n }\n }\n\n return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n var fired = false;\n\n function g() {\n this.removeListener(type, g);\n\n if (!fired) {\n fired = true;\n listener.apply(this, arguments);\n }\n }\n\n g.listener = listener;\n this.on(type, g);\n\n return this;\n};\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener = function(type, listener) {\n var list, position, length, i;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events || !this._events[type])\n return this;\n\n list = this._events[type];\n length = list.length;\n position = -1;\n\n if (list === listener ||\n (isFunction(list.listener) && list.listener === listener)) {\n delete this._events[type];\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n\n } else if (isObject(list)) {\n for (i = length; i-- > 0;) {\n if (list[i] === listener ||\n (list[i].listener && list[i].listener === listener)) {\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (list.length === 1) {\n list.length = 0;\n delete this._events[type];\n } else {\n list.splice(position, 1);\n }\n\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n }\n\n return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n var key, listeners;\n\n if (!this._events)\n return this;\n\n // not listening for removeListener, no need to emit\n if (!this._events.removeListener) {\n if (arguments.length === 0)\n this._events = {};\n else if (this._events[type])\n delete this._events[type];\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n for (key in this._events) {\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = {};\n return this;\n }\n\n listeners = this._events[type];\n\n if (isFunction(listeners)) {\n this.removeListener(type, listeners);\n } else if (listeners) {\n // LIFO order\n while (listeners.length)\n this.removeListener(type, listeners[listeners.length - 1]);\n }\n delete this._events[type];\n\n return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n var ret;\n if (!this._events || !this._events[type])\n ret = [];\n else if (isFunction(this._events[type]))\n ret = [this._events[type]];\n else\n ret = this._events[type].slice();\n return ret;\n};\n\nEventEmitter.prototype.listenerCount = function(type) {\n if (this._events) {\n var evlistener = this._events[type];\n\n if (isFunction(evlistener))\n return 1;\n else if (evlistener)\n return evlistener.length;\n }\n return 0;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n return emitter.listenerCount(type);\n};\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\n","'use strict';\n\nvar AlgoliaSearchHelper = require('./src/algoliasearch.helper');\nvar RecommendParameters = require('./src/RecommendParameters');\nvar RecommendResults = require('./src/RecommendResults');\nvar SearchParameters = require('./src/SearchParameters');\nvar SearchResults = require('./src/SearchResults');\n\n/**\n * The algoliasearchHelper module is the function that will let its\n * contains everything needed to use the Algoliasearch\n * Helper. It is a also a function that instanciate the helper.\n * To use the helper, you also need the Algolia JS client v3.\n * @example\n * //using the UMD build\n * var client = algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76');\n * var helper = algoliasearchHelper(client, 'bestbuy', {\n * facets: ['shipping'],\n * disjunctiveFacets: ['category']\n * });\n * helper.on('result', function(event) {\n * console.log(event.results);\n * });\n * helper\n * .toggleFacetRefinement('category', 'Movies & TV Shows')\n * .toggleFacetRefinement('shipping', 'Free shipping')\n * .search();\n * @example\n * // The helper is an event emitter using the node API\n * helper.on('result', updateTheResults);\n * helper.once('result', updateTheResults);\n * helper.removeListener('result', updateTheResults);\n * helper.removeAllListeners('result');\n * @module algoliasearchHelper\n * @param {AlgoliaSearch} client an AlgoliaSearch client\n * @param {string} index the name of the index to query\n * @param {SearchParameters|object} opts an object defining the initial config of the search. It doesn't have to be a {SearchParameters}, just an object containing the properties you need from it.\n * @param {SearchResultsOptions|object} searchResultsOptions an object defining the options to use when creating the search results.\n * @return {AlgoliaSearchHelper} The helper instance\n */\nfunction algoliasearchHelper(client, index, opts, searchResultsOptions) {\n return new AlgoliaSearchHelper(client, index, opts, searchResultsOptions);\n}\n\n/**\n * The version currently used\n * @member module:algoliasearchHelper.version\n * @type {number}\n */\nalgoliasearchHelper.version = require('./src/version');\n\n/**\n * Constructor for the Helper.\n * @member module:algoliasearchHelper.AlgoliaSearchHelper\n * @type {AlgoliaSearchHelper}\n */\nalgoliasearchHelper.AlgoliaSearchHelper = AlgoliaSearchHelper;\n\n/**\n * Constructor for the object containing all the parameters of the search.\n * @member module:algoliasearchHelper.SearchParameters\n * @type {SearchParameters}\n */\nalgoliasearchHelper.SearchParameters = SearchParameters;\n\n/**\n * Constructor for the object containing all the parameters for Recommend.\n * @member module:algoliasearchHelper.RecommendParameters\n * @type {RecommendParameters}\n */\nalgoliasearchHelper.RecommendParameters = RecommendParameters;\n\n/**\n * Constructor for the object containing the results of the search.\n * @member module:algoliasearchHelper.SearchResults\n * @type {SearchResults}\n */\nalgoliasearchHelper.SearchResults = SearchResults;\n\n/**\n * Constructor for the object containing the results for Recommend.\n * @member module:algoliasearchHelper.RecommendResults\n * @type {RecommendResults}\n */\nalgoliasearchHelper.RecommendResults = RecommendResults;\n\nmodule.exports = algoliasearchHelper;\n","'use strict';\n\nvar EventEmitter = require('@algolia/events');\n\nvar inherits = require('../functions/inherits');\n\n/**\n * A DerivedHelper is a way to create sub requests to\n * Algolia from a main helper.\n * @class\n * @classdesc The DerivedHelper provides an event based interface for search callbacks:\n * - search: when a search is triggered using the `search()` method.\n * - result: when the response is retrieved from Algolia and is processed.\n * This event contains a {@link SearchResults} object and the\n * {@link SearchParameters} corresponding to this answer.\n * @param {AlgoliaSearchHelper} mainHelper the main helper\n * @param {function} fn the function to create the derived state for search\n * @param {function} recommendFn the function to create the derived state for recommendations\n */\nfunction DerivedHelper(mainHelper, fn, recommendFn) {\n this.main = mainHelper;\n this.fn = fn;\n this.recommendFn = recommendFn;\n this.lastResults = null;\n this.lastRecommendResults = null;\n}\n\ninherits(DerivedHelper, EventEmitter);\n\n/**\n * Detach this helper from the main helper\n * @return {undefined}\n * @throws Error if the derived helper is already detached\n */\nDerivedHelper.prototype.detach = function () {\n this.removeAllListeners();\n this.main.detachDerivedHelper(this);\n};\n\nDerivedHelper.prototype.getModifiedState = function (parameters) {\n return this.fn(parameters);\n};\n\nDerivedHelper.prototype.getModifiedRecommendState = function (parameters) {\n return this.recommendFn(parameters);\n};\n\nmodule.exports = DerivedHelper;\n","'use strict';\n\n/**\n * RecommendParameters is the data structure that contains all the information\n * usable for getting recommendations from the Algolia API. It doesn't do the\n * search itself, nor does it contains logic about the parameters.\n * It is an immutable object, therefore it has been created in a way that each\n * changes does not change the object itself but returns a copy with the\n * modification.\n * This object should probably not be instantiated outside of the helper. It\n * will be provided when needed.\n * @constructor\n * @classdesc contains all the parameters for recommendations\n * @param {RecommendParametersOptions} opts the options to create the object\n */\nfunction RecommendParameters(opts) {\n opts = opts || {};\n this.params = opts.params || [];\n}\n\nRecommendParameters.prototype = {\n constructor: RecommendParameters,\n\n addParams: function (params) {\n var newParams = this.params.slice();\n\n newParams.push(params);\n\n return new RecommendParameters({ params: newParams });\n },\n\n removeParams: function (id) {\n return new RecommendParameters({\n params: this.params.filter(function (param) {\n return param.$$id !== id;\n }),\n });\n },\n\n addFrequentlyBoughtTogether: function (params) {\n return this.addParams(\n Object.assign({}, params, { model: 'bought-together' })\n );\n },\n\n addRelatedProducts: function (params) {\n return this.addParams(\n Object.assign({}, params, { model: 'related-products' })\n );\n },\n\n addTrendingItems: function (params) {\n return this.addParams(\n Object.assign({}, params, { model: 'trending-items' })\n );\n },\n\n addTrendingFacets: function (params) {\n return this.addParams(\n Object.assign({}, params, { model: 'trending-facets' })\n );\n },\n\n addLookingSimilar: function (params) {\n return this.addParams(\n Object.assign({}, params, { model: 'looking-similar' })\n );\n },\n\n _buildQueries: function (indexName, cache) {\n return this.params\n .filter(function (params) {\n return cache[params.$$id] === undefined;\n })\n .map(function (params) {\n var query = Object.assign({}, params, {\n indexName: indexName,\n // @TODO: remove this if it ever gets handled by the API\n threshold: params.threshold || 0,\n });\n delete query.$$id;\n\n return query;\n });\n },\n};\n\nmodule.exports = RecommendParameters;\n","'use strict';\n\n/**\n * Constructor for SearchResults\n * @class\n * @classdesc SearchResults contains the results of a query to Algolia using the\n * {@link AlgoliaSearchHelper}.\n * @param {RecommendParameters} state state that led to the response\n * @param {Record<string,RecommendResultItem>} results the results from algolia client\n **/\nfunction RecommendResults(state, results) {\n this._state = state;\n this._rawResults = {};\n\n // eslint-disable-next-line consistent-this\n var self = this;\n\n state.params.forEach(function (param) {\n var id = param.$$id;\n self[id] = results[id];\n self._rawResults[id] = results[id];\n });\n}\n\nRecommendResults.prototype = {\n constructor: RecommendResults,\n};\n\nmodule.exports = RecommendResults;\n","'use strict';\n\n/**\n * Functions to manipulate refinement lists\n *\n * The RefinementList is not formally defined through a prototype but is based\n * on a specific structure.\n *\n * @module SearchParameters.refinementList\n *\n * @typedef {string[]} SearchParameters.refinementList.Refinements\n * @typedef {Object.<string, SearchParameters.refinementList.Refinements>} SearchParameters.refinementList.RefinementList\n */\n\nvar defaultsPure = require('../functions/defaultsPure');\nvar objectHasKeys = require('../functions/objectHasKeys');\nvar omit = require('../functions/omit');\n\nvar lib = {\n /**\n * Adds a refinement to a RefinementList\n * @param {RefinementList} refinementList the initial list\n * @param {string} attribute the attribute to refine\n * @param {string} value the value of the refinement, if the value is not a string it will be converted\n * @return {RefinementList} a new and updated refinement list\n */\n addRefinement: function addRefinement(refinementList, attribute, value) {\n if (lib.isRefined(refinementList, attribute, value)) {\n return refinementList;\n }\n\n var valueAsString = '' + value;\n\n var facetRefinement = !refinementList[attribute]\n ? [valueAsString]\n : refinementList[attribute].concat(valueAsString);\n\n var mod = {};\n\n mod[attribute] = facetRefinement;\n\n return defaultsPure({}, mod, refinementList);\n },\n /**\n * Removes refinement(s) for an attribute:\n * - if the value is specified removes the refinement for the value on the attribute\n * - if no value is specified removes all the refinements for this attribute\n * @param {RefinementList} refinementList the initial list\n * @param {string} attribute the attribute to refine\n * @param {string} [value] the value of the refinement\n * @return {RefinementList} a new and updated refinement lst\n */\n removeRefinement: function removeRefinement(\n refinementList,\n attribute,\n value\n ) {\n if (value === undefined) {\n // we use the \"filter\" form of clearRefinement, since it leaves empty values as-is\n // the form with a string will remove the attribute completely\n return lib.clearRefinement(refinementList, function (v, f) {\n return attribute === f;\n });\n }\n\n var valueAsString = '' + value;\n\n return lib.clearRefinement(refinementList, function (v, f) {\n return attribute === f && valueAsString === v;\n });\n },\n /**\n * Toggles the refinement value for an attribute.\n * @param {RefinementList} refinementList the initial list\n * @param {string} attribute the attribute to refine\n * @param {string} value the value of the refinement\n * @return {RefinementList} a new and updated list\n */\n toggleRefinement: function toggleRefinement(\n refinementList,\n attribute,\n value\n ) {\n if (value === undefined)\n throw new Error('toggleRefinement should be used with a value');\n\n if (lib.isRefined(refinementList, attribute, value)) {\n return lib.removeRefinement(refinementList, attribute, value);\n }\n\n return lib.addRefinement(refinementList, attribute, value);\n },\n /**\n * Clear all or parts of a RefinementList. Depending on the arguments, three\n * kinds of behavior can happen:\n * - if no attribute is provided: clears the whole list\n * - if an attribute is provided as a string: clears the list for the specific attribute\n * - if an attribute is provided as a function: discards the elements for which the function returns true\n * @param {RefinementList} refinementList the initial list\n * @param {string} [attribute] the attribute or function to discard\n * @param {string} [refinementType] optional parameter to give more context to the attribute function\n * @return {RefinementList} a new and updated refinement list\n */\n clearRefinement: function clearRefinement(\n refinementList,\n attribute,\n refinementType\n ) {\n if (attribute === undefined) {\n // return the same object if the list is already empty\n // this is mainly for tests, as it doesn't have much impact on performance\n if (!objectHasKeys(refinementList)) {\n return refinementList;\n }\n return {};\n } else if (typeof attribute === 'string') {\n return omit(refinementList, [attribute]);\n } else if (typeof attribute === 'function') {\n var hasChanged = false;\n\n var newRefinementList = Object.keys(refinementList).reduce(function (\n memo,\n key\n ) {\n var values = refinementList[key] || [];\n var facetList = values.filter(function (value) {\n return !attribute(value, key, refinementType);\n });\n\n if (facetList.length !== values.length) {\n hasChanged = true;\n }\n\n memo[key] = facetList;\n\n return memo;\n },\n {});\n\n if (hasChanged) return newRefinementList;\n return refinementList;\n }\n\n // We return nothing if the attribute is not undefined, a string or a function,\n // as it is not a valid value for a refinement\n return undefined;\n },\n /**\n * Test if the refinement value is used for the attribute. If no refinement value\n * is provided, test if the refinementList contains any refinement for the\n * given attribute.\n * @param {RefinementList} refinementList the list of refinement\n * @param {string} attribute name of the attribute\n * @param {string} [refinementValue] value of the filter/refinement\n * @return {boolean} true if the attribute is refined, false otherwise\n */\n isRefined: function isRefined(refinementList, attribute, refinementValue) {\n var containsRefinements =\n Boolean(refinementList[attribute]) &&\n refinementList[attribute].length > 0;\n\n if (refinementValue === undefined || !containsRefinements) {\n return containsRefinements;\n }\n\n var refinementValueAsString = '' + refinementValue;\n\n return refinementList[attribute].indexOf(refinementValueAsString) !== -1;\n },\n};\n\nmodule.exports = lib;\n","'use strict';\n\nvar defaultsPure = require('../functions/defaultsPure');\nvar find = require('../functions/find');\nvar intersection = require('../functions/intersection');\nvar merge = require('../functions/merge');\nvar objectHasKeys = require('../functions/objectHasKeys');\nvar omit = require('../functions/omit');\nvar valToNumber = require('../functions/valToNumber');\nvar isValidUserToken = require('../utils/isValidUserToken');\n\nvar RefinementList = require('./RefinementList');\n\n/**\n * isEqual, but only for numeric refinement values, possible values:\n * - 5\n * - [5]\n * - [[5]]\n * - [[5,5],[4]]\n * @param {any} a numeric refinement value\n * @param {any} b numeric refinement value\n * @return {boolean} true if the values are equal\n */\nfunction isEqualNumericRefinement(a, b) {\n if (Array.isArray(a) && Array.isArray(b)) {\n return (\n a.length === b.length &&\n a.every(function (el, i) {\n return isEqualNumericRefinement(b[i], el);\n })\n );\n }\n return a === b;\n}\n\n/**\n * like _.find but using deep equality to be able to use it\n * to find arrays.\n * @private\n * @param {any[]} array array to search into (elements are base or array of base)\n * @param {any} searchedValue the value we're looking for (base or array of base)\n * @return {any} the searched value or undefined\n */\nfunction findArray(array, searchedValue) {\n return find(array, function (currentValue) {\n return isEqualNumericRefinement(currentValue, searchedValue);\n });\n}\n\n/**\n * The facet list is the structure used to store the list of values used to\n * filter a single attribute.\n * @typedef {string[]} SearchParameters.FacetList\n */\n\n/**\n * Structure to store numeric filters with the operator as the key. The supported operators\n * are `=`, `>`, `<`, `>=`, `<=` and `!=`.\n * @typedef {Object.<string, Array.<number|number[]>>} SearchParameters.OperatorList\n */\n\n/**\n * SearchParameters is the data structure that contains all the information\n * usable for making a search to Algolia API. It doesn't do the search itself,\n * nor does it contains logic about the parameters.\n * It is an immutable object, therefore it has been created in a way that each\n * changes does not change the object itself but returns a copy with the\n * modification.\n * This object should probably not be instantiated outside of the helper. It will\n * be provided when needed. This object is documented for reference as you'll\n * get it from events generated by the {@link AlgoliaSearchHelper}.\n * If need be, instantiate the Helper from the factory function {@link SearchParameters.make}\n * @constructor\n * @classdesc contains all the parameters of a search\n * @param {object|SearchParameters} newParameters existing parameters or partial object\n * for the properties of a new SearchParameters\n * @see SearchParameters.make\n * @example <caption>SearchParameters of the first query in\n * <a href=\"http://demos.algolia.com/instant-search-demo/\">the instant search demo</a></caption>\n{\n \"query\": \"\",\n \"disjunctiveFacets\": [\n \"customerReviewCount\",\n \"category\",\n \"salePrice_range\",\n \"manufacturer\"\n ],\n \"maxValuesPerFacet\": 30,\n \"page\": 0,\n \"hitsPerPage\": 10,\n \"facets\": [\n \"type\",\n \"shipping\"\n ]\n}\n */\nfunction SearchParameters(newParameters) {\n var params = newParameters\n ? SearchParameters._parseNumbers(newParameters)\n : {};\n\n if (params.userToken !== undefined && !isValidUserToken(params.userToken)) {\n // eslint-disable-next-line no-console\n console.warn(\n '[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\\n - Format: [a-zA-Z0-9_-]{1,64}'\n );\n }\n /**\n * This attribute contains the list of all the conjunctive facets\n * used. This list will be added to requested facets in the\n * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.\n * @member {string[]}\n */\n this.facets = params.facets || [];\n /**\n * This attribute contains the list of all the disjunctive facets\n * used. This list will be added to requested facets in the\n * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.\n * @member {string[]}\n */\n this.disjunctiveFacets = params.disjunctiveFacets || [];\n /**\n * This attribute contains the list of all the hierarchical facets\n * used. This list will be added to requested facets in the\n * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.\n * Hierarchical facets are a sub type of disjunctive facets that\n * let you filter faceted attributes hierarchically.\n * @member {string[]|object[]}\n */\n this.hierarchicalFacets = params.hierarchicalFacets || [];\n\n // Refinements\n /**\n * This attribute contains all the filters that need to be\n * applied on the conjunctive facets. Each facet must be properly\n * defined in the `facets` attribute.\n *\n * The key is the name of the facet, and the `FacetList` contains all\n * filters selected for the associated facet name.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `facetFilters` attribute.\n * @member {Object.<string, SearchParameters.FacetList>}\n */\n this.facetsRefinements = params.facetsRefinements || {};\n /**\n * This attribute contains all the filters that need to be\n * excluded from the conjunctive facets. Each facet must be properly\n * defined in the `facets` attribute.\n *\n * The key is the name of the facet, and the `FacetList` contains all\n * filters excluded for the associated facet name.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `facetFilters` attribute.\n * @member {Object.<string, SearchParameters.FacetList>}\n */\n this.facetsExcludes = params.facetsExcludes || {};\n /**\n * This attribute contains all the filters that need to be\n * applied on the disjunctive facets. Each facet must be properly\n * defined in the `disjunctiveFacets` attribute.\n *\n * The key is the name of the facet, and the `FacetList` contains all\n * filters selected for the associated facet name.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `facetFilters` attribute.\n * @member {Object.<string, SearchParameters.FacetList>}\n */\n this.disjunctiveFacetsRefinements = params.disjunctiveFacetsRefinements || {};\n /**\n * This attribute contains all the filters that need to be\n * applied on the numeric attributes.\n *\n * The key is the name of the attribute, and the value is the\n * filters to apply to this attribute.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `numericFilters` attribute.\n * @member {Object.<string, SearchParameters.OperatorList>}\n */\n this.numericRefinements = params.numericRefinements || {};\n /**\n * This attribute contains all the tags used to refine the query.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `tagFilters` attribute.\n * @member {string[]}\n */\n this.tagRefinements = params.tagRefinements || [];\n /**\n * This attribute contains all the filters that need to be\n * applied on the hierarchical facets. Each facet must be properly\n * defined in the `hierarchicalFacets` attribute.\n *\n * The key is the name of the facet, and the `FacetList` contains all\n * filters selected for the associated facet name. The FacetList values\n * are structured as a string that contain the values for each level\n * separated by the configured separator.\n *\n * When querying algolia, the values stored in this attribute will\n * be translated into the `facetFilters` attribute.\n * @member {Object.<string, SearchParameters.FacetList>}\n */\n this.hierarchicalFacetsRefinements =\n params.hierarchicalFacetsRefinements || {};\n\n // eslint-disable-next-line consistent-this\n var self = this;\n Object.keys(params).forEach(function (paramName) {\n var isKeyKnown = SearchParameters.PARAMETERS.indexOf(paramName) !== -1;\n var isValueDefined = params[paramName] !== undefined;\n\n if (!isKeyKnown && isValueDefined) {\n self[paramName] = params[paramName];\n }\n });\n}\n\n/**\n * List all the properties in SearchParameters and therefore all the known Algolia properties\n * This doesn't contain any beta/hidden features.\n * @private\n */\nSearchParameters.PARAMETERS = Object.keys(new SearchParameters());\n\n/**\n * @private\n * @param {object} partialState full or part of a state\n * @return {object} a new object with the number keys as number\n */\nSearchParameters._parseNumbers = function (partialState) {\n // Do not parse numbers again in SearchParameters, they ought to be parsed already\n if (partialState instanceof SearchParameters) return partialState;\n\n var numbers = {};\n\n var numberKeys = [\n 'aroundPrecision',\n 'aroundRadius',\n 'getRankingInfo',\n 'minWordSizefor2Typos',\n 'minWordSizefor1Typo',\n 'page',\n 'maxValuesPerFacet',\n 'distinct',\n 'minimumAroundRadius',\n 'hitsPerPage',\n 'minProximity',\n ];\n\n numberKeys.forEach(function (k) {\n var value = partialState[k];\n if (typeof value === 'string') {\n var parsedValue = parseFloat(value);\n // global isNaN is ok to use here, value is only number or NaN\n numbers[k] = isNaN(parsedValue) ? value : parsedValue;\n }\n });\n\n // there's two formats of insideBoundingBox, we need to parse\n // the one which is an array of float geo rectangles\n if (Array.isArray(partialState.insideBoundingBox)) {\n numbers.insideBoundingBox = partialState.insideBoundingBox.map(function (\n geoRect\n ) {\n if (Array.isArray(geoRect)) {\n return geoRect.map(function (value) {\n return parseFloat(value);\n });\n }\n return geoRect;\n });\n }\n\n if (partialState.numericRefinements) {\n var numericRefinements = {};\n Object.keys(partialState.numericRefinements).forEach(function (attribute) {\n var operators = partialState.numericRefinements[attribute] || {};\n numericRefinements[attribute] = {};\n Object.keys(operators).forEach(function (operator) {\n var values = operators[operator];\n var parsedValues = values.map(function (v) {\n if (Array.isArray(v)) {\n return v.map(function (vPrime) {\n if (typeof vPrime === 'string') {\n return parseFloat(vPrime);\n }\n return vPrime;\n });\n } else if (typeof v === 'string') {\n return parseFloat(v);\n }\n return v;\n });\n numericRefinements[attribute][operator] = parsedValues;\n });\n });\n numbers.numericRefinements = numericRefinements;\n }\n\n return merge(partialState, numbers);\n};\n\n/**\n * Factory for SearchParameters\n * @param {object|SearchParameters} newParameters existing parameters or partial\n * object for the properties of a new SearchParameters\n * @return {SearchParameters} frozen instance of SearchParameters\n */\nSearchParameters.make = function makeSearchParameters(newParameters) {\n var instance = new SearchParameters(newParameters);\n\n var hierarchicalFacets = newParameters.hierarchicalFacets || [];\n hierarchicalFacets.forEach(function (facet) {\n if (facet.rootPath) {\n var currentRefinement = instance.getHierarchicalRefinement(facet.name);\n\n if (\n currentRefinement.length > 0 &&\n currentRefinement[0].indexOf(facet.rootPath) !== 0\n ) {\n instance = instance.clearRefinements(facet.name);\n }\n\n // get it again in case it has been cleared\n currentRefinement = instance.getHierarchicalRefinement(facet.name);\n if (currentRefinement.length === 0) {\n instance = instance.toggleHierarchicalFacetRefinement(\n facet.name,\n facet.rootPath\n );\n }\n }\n });\n\n return instance;\n};\n\n/**\n * Validates the new parameters based on the previous state\n * @param {SearchParameters} currentState the current state\n * @param {object|SearchParameters} parameters the new parameters to set\n * @return {Error|null} Error if the modification is invalid, null otherwise\n */\nSearchParameters.validate = function (currentState, parameters) {\n var params = parameters || {};\n\n if (\n currentState.tagFilters &&\n params.tagRefinements &&\n params.tagRefinements.length > 0\n ) {\n return new Error(\n '[Tags] Cannot switch from the managed tag API to the advanced API. It is probably ' +\n 'an error, if it is really what you want, you should first clear the tags with clearTags method.'\n );\n }\n\n if (currentState.tagRefinements.length > 0 && params.tagFilters) {\n return new Error(\n '[Tags] Cannot switch from the advanced tag API to the managed API. It is probably ' +\n 'an error, if it is not, you should first clear the tags with clearTags method.'\n );\n }\n\n if (\n currentState.numericFilters &&\n params.numericRefinements &&\n objectHasKeys(params.numericRefinements)\n ) {\n return new Error(\n \"[Numeric filters] Can't switch from the advanced to the managed API. It\" +\n ' is probably an error, if this is really what you want, you have to first' +\n ' clear the numeric filters.'\n );\n }\n\n if (objectHasKeys(currentState.numericRefinements) && params.numericFilters) {\n return new Error(\n \"[Numeric filters] Can't switch from the managed API to the advanced. It\" +\n ' is probably an error, if this is really what you want, you have to first' +\n ' clear the numeric filters.'\n );\n }\n\n return null;\n};\n\nSearchParameters.prototype = {\n constructor: SearchParameters,\n\n /**\n * Remove all refinements (disjunctive + conjunctive + excludes + numeric filters)\n * @method\n * @param {undefined|string|SearchParameters.clearCallback} [attribute] optional string or function\n * - If not given, means to clear all the filters.\n * - If `string`, means to clear all refinements for the `attribute` named filter.\n * - If `function`, means to clear all the refinements that return truthy values.\n * @return {SearchParameters} new instance with filters cleared\n */\n clearRefinements: function clearRefinements(attribute) {\n var patch = {\n numericRefinements: this._clearNumericRefinements(attribute),\n facetsRefinements: RefinementList.clearRefinement(\n this.facetsRefinements,\n attribute,\n 'conjunctiveFacet'\n ),\n facetsExcludes: RefinementList.clearRefinement(\n this.facetsExcludes,\n attribute,\n 'exclude'\n ),\n disjunctiveFacetsRefinements: RefinementList.clearRefinement(\n this.disjunctiveFacetsRefinements,\n attribute,\n 'disjunctiveFacet'\n ),\n hierarchicalFacetsRefinements: RefinementList.clearRefinement(\n this.hierarchicalFacetsRefinements,\n attribute,\n 'hierarchicalFacet'\n ),\n };\n if (\n patch.numericRefinements === this.numericRefinements &&\n patch.facetsRefinements === this.facetsRefinements &&\n patch.facetsExcludes === this.facetsExcludes &&\n patch.disjunctiveFacetsRefinements ===\n this.disjunctiveFacetsRefinements &&\n patch.hierarchicalFacetsRefinements === this.hierarchicalFacetsRefinements\n ) {\n return this;\n }\n return this.setQueryParameters(patch);\n },\n /**\n * Remove all the refined tags from the SearchParameters\n * @method\n * @return {SearchParameters} new instance with tags cleared\n */\n clearTags: function clearTags() {\n if (this.tagFilters === undefined && this.tagRefinements.length === 0)\n return this;\n\n return this.setQueryParameters({\n tagFilters: undefined,\n tagRefinements: [],\n });\n },\n /**\n * Set the index.\n * @method\n * @param {string} index the index name\n * @return {SearchParameters} new instance\n */\n setIndex: function setIndex(index) {\n if (index === this.index) return this;\n\n return this.setQueryParameters({\n index: index,\n });\n },\n /**\n * Query setter\n * @method\n * @param {string} newQuery value for the new query\n * @return {SearchParameters} new instance\n */\n setQuery: function setQuery(newQuery) {\n if (newQuery === this.query) return this;\n\n return this.setQueryParameters({\n query: newQuery,\n });\n },\n /**\n * Page setter\n * @method\n * @param {number} newPage new page number\n * @return {SearchParameters} new instance\n */\n setPage: function setPage(newPage) {\n if (newPage === this.page) return this;\n\n return this.setQueryParameters({\n page: newPage,\n });\n },\n /**\n * Facets setter\n * The facets are the simple facets, used for conjunctive (and) faceting.\n * @method\n * @param {string[]} facets all the attributes of the algolia records used for conjunctive faceting\n * @return {SearchParameters} new instance\n */\n setFacets: function setFacets(facets) {\n return this.setQueryParameters({\n facets: facets,\n });\n },\n /**\n * Disjunctive facets setter\n * Change the list of disjunctive (or) facets the helper chan handle.\n * @method\n * @param {string[]} facets all the attributes of the algolia records used for disjunctive faceting\n * @return {SearchParameters} new instance\n */\n setDisjunctiveFacets: function setDisjunctiveFacets(facets) {\n return this.setQueryParameters({\n disjunctiveFacets: facets,\n });\n },\n /**\n * HitsPerPage setter\n * Hits per page represents the number of hits retrieved for this query\n * @method\n * @param {number} n number of hits retrieved per page of results\n * @return {SearchParameters} new instance\n */\n setHitsPerPage: function setHitsPerPage(n) {\n if (this.hitsPerPage === n) return this;\n\n return this.setQueryParameters({\n hitsPerPage: n,\n });\n },\n /**\n * typoTolerance setter\n * Set the value of typoTolerance\n * @method\n * @param {string} typoTolerance new value of typoTolerance (\"true\", \"false\", \"min\" or \"strict\")\n * @return {SearchParameters} new instance\n */\n setTypoTolerance: function setTypoTolerance(typoTolerance) {\n if (this.typoTolerance === typoTolerance) return this;\n\n return this.setQueryParameters({\n typoTolerance: typoTolerance,\n });\n },\n /**\n * Add a numeric filter for a given attribute\n * When value is an array, they are combined with OR\n * When value is a single value, it will combined with AND\n * @method\n * @param {string} attribute attribute to set the filter on\n * @param {string} operator operator of the filter (possible values: =, >, >=, <, <=, !=)\n * @param {number | number[]} value value of the filter\n * @return {SearchParameters} new instance\n * @example\n * // for price = 50 or 40\n * state.addNumericRefinement('price', '=', [50, 40]);\n * @example\n * // for size = 38 and 40\n * state.addNumericRefinement('size', '=', 38);\n * state.addNumericRefinement('size', '=', 40);\n */\n addNumericRefinement: function (attribute, operator, value) {\n var val = valToNumber(value);\n\n if (this.isNumericRefined(attribute, operator, val)) return this;\n\n var mod = merge({}, this.numericRefinements);\n\n mod[attribute] = merge({}, mod[attribute]);\n\n if (mod[attribute][operator]) {\n // Array copy\n mod[attribute][operator] = mod[attribute][operator].slice();\n // Add the element. Concat can't be used here because value can be an array.\n mod[attribute][operator].push(val);\n } else {\n mod[attribute][operator] = [val];\n }\n\n return this.setQueryParameters({\n numericRefinements: mod,\n });\n },\n /**\n * Get the list of conjunctive refinements for a single facet\n * @param {string} facetName name of the attribute used for faceting\n * @return {string[]} list of refinements\n */\n getConjunctiveRefinements: function (facetName) {\n if (!this.isConjunctiveFacet(facetName)) {\n return [];\n }\n return this.facetsRefinements[facetName] || [];\n },\n /**\n * Get the list of disjunctive refinements for a single facet\n * @param {string} facetName name of the attribute used for faceting\n * @return {string[]} list of refinements\n */\n getDisjunctiveRefinements: function (facetName) {\n if (!this.isDisjunctiveFacet(facetName)) {\n return [];\n }\n return this.disjunctiveFacetsRefinements[facetName] || [];\n },\n /**\n * Get the list of hierarchical refinements for a single facet\n * @param {string} facetName name of the attribute used for faceting\n * @return {string[]} list of refinements\n */\n getHierarchicalRefinement: function (facetName) {\n // we send an array but we currently do not support multiple\n // hierarchicalRefinements for a hierarchicalFacet\n return this.hierarchicalFacetsRefinements[facetName] || [];\n },\n /**\n * Get the list of exclude refinements for a single facet\n * @param {string} facetName name of the attribute used for faceting\n * @return {string[]} list of refinements\n */\n getExcludeRefinements: function (facetName) {\n if (!this.isConjunctiveFacet(facetName)) {\n return [];\n }\n return this.facetsExcludes[facetName] || [];\n },\n\n /**\n * Remove all the numeric filter for a given (attribute, operator)\n * @method\n * @param {string} attribute attribute to set the filter on\n * @param {string} [operator] operator of the filter (possible values: =, >, >=, <, <=, !=)\n * @param {number} [number] the value to be removed\n * @return {SearchParameters} new instance\n */\n removeNumericRefinement: function (attribute, operator, number) {\n var paramValue = number;\n if (paramValue !== undefined) {\n if (!this.isNumericRefined(attribute, operator, paramValue)) {\n return this;\n }\n return this.setQueryParameters({\n numericRefinements: this._clearNumericRefinements(function (\n value,\n key\n ) {\n return (\n key === attribute &&\n value.op === operator &&\n isEqualNumericRefinement(value.val, valToNumber(paramValue))\n );\n }),\n });\n } else if (operator !== undefined) {\n if (!this.isNumericRefined(attribute, operator)) return this;\n return this.setQueryParameters({\n numericRefinements: this._clearNumericRefinements(function (\n value,\n key\n ) {\n return key === attribute && value.op === operator;\n }),\n });\n }\n\n if (!this.isNumericRefined(attribute)) return this;\n return this.setQueryParameters({\n numericRefinements: this._clearNumericRefinements(function (value, key) {\n return key === attribute;\n }),\n });\n },\n /**\n * Get the list of numeric refinements for a single facet\n * @param {string} facetName name of the attribute used for faceting\n * @return {SearchParameters.OperatorList} list of refinements\n */\n getNumericRefinements: function (facetName) {\n return this.numericRefinements[facetName] || {};\n },\n /**\n * Return the current refinement for the (attribute, operator)\n * @param {string} attribute attribute in the record\n * @param {string} operator operator applied on the refined values\n * @return {Array.<number|number[]>} refined values\n */\n getNumericRefinement: function (attribute, operator) {\n return (\n this.numericRefinements[attribute] &&\n this.numericRefinements[attribute][operator]\n );\n },\n /**\n * Clear numeric filters.\n * @method\n * @private\n * @param {string|SearchParameters.clearCallback} [attribute] optional string or function\n * - If not given, means to clear all the filters.\n * - If `string`, means to clear all refinements for the `attribute` named filter.\n * - If `function`, means to clear all the refinements that return truthy values.\n * @return {Object.<string, OperatorList>} new numeric refinements\n */\n _clearNumericRefinements: function _clearNumericRefinements(attribute) {\n if (attribute === undefined) {\n if (!objectHasKeys(this.numericRefinements)) {\n return this.numericRefinements;\n }\n return {};\n } else if (typeof attribute === 'string') {\n return omit(this.numericRefinements, [attribute]);\n } else if (typeof attribute === 'function') {\n var hasChanged = false;\n var numericRefinements = this.numericRefinements;\n var newNumericRefinements = Object.keys(numericRefinements).reduce(\n function (memo, key) {\n var operators = numericRefinements[key];\n var operatorList = {};\n\n operators = operators || {};\n Object.keys(operators).forEach(function (operator) {\n var values = operators[operator] || [];\n var outValues = [];\n values.forEach(function (value) {\n var predicateResult = attribute(\n { val: value, op: operator },\n key,\n 'numeric'\n );\n if (!predicateResult) outValues.push(value);\n });\n if (outValues.length !== values.length) {\n hasChanged = true;\n }\n operatorList[operator] = outValues;\n });\n\n memo[key] = operatorList;\n\n return memo;\n },\n {}\n );\n\n if (hasChanged) return newNumericRefinements;\n return this.numericRefinements;\n }\n\n // We return nothing if the attribute is not undefined, a string or a function,\n // as it is not a valid value for a refinement\n return undefined;\n },\n /**\n * Add a facet to the facets attribute of the helper configuration, if it\n * isn't already present.\n * @method\n * @param {string} facet facet name to add\n * @return {SearchParameters} new instance\n */\n addFacet: function addFacet(facet) {\n if (this.isConjunctiveFacet(facet)) {\n return this;\n }\n\n return this.setQueryParameters({\n facets: this.facets.concat([facet]),\n });\n },\n /**\n * Add a disjunctive facet to the disjunctiveFacets attribute of the helper\n * configuration, if it isn't already present.\n * @method\n * @param {string} facet disjunctive facet name to add\n * @return {SearchParameters} new instance\n */\n addDisjunctiveFacet: function addDisjunctiveFacet(facet) {\n if (this.isDisjunctiveFacet(facet)) {\n return this;\n }\n\n return this.setQueryParameters({\n disjunctiveFacets: this.disjunctiveFacets.concat([facet]),\n });\n },\n /**\n * Add a hierarchical facet to the hierarchicalFacets attribute of the helper\n * configuration.\n * @method\n * @param {object} hierarchicalFacet hierarchical facet to add\n * @return {SearchParameters} new instance\n * @throws will throw an error if a hierarchical facet with the same name was already declared\n */\n addHierarchicalFacet: function addHierarchicalFacet(hierarchicalFacet) {\n if (this.isHierarchicalFacet(hierarchicalFacet.name)) {\n throw new Error(\n 'Cannot declare two hierarchical facets with the same name: `' +\n hierarchicalFacet.name +\n '`'\n );\n }\n\n return this.setQueryParameters({\n hierarchicalFacets: this.hierarchicalFacets.concat([hierarchicalFacet]),\n });\n },\n /**\n * Add a refinement on a \"normal\" facet\n * @method\n * @param {string} facet attribute to apply the faceting on\n * @param {string} value value of the attribute (will be converted to string)\n * @return {SearchParameters} new instance\n */\n addFacetRefinement: function addFacetRefinement(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n if (RefinementList.isRefined(this.facetsRefinements, facet, value))\n return this;\n\n return this.setQueryParameters({\n facetsRefinements: RefinementList.addRefinement(\n this.facetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * Exclude a value from a \"normal\" facet\n * @method\n * @param {string} facet attribute to apply the exclusion on\n * @param {string} value value of the attribute (will be converted to string)\n * @return {SearchParameters} new instance\n */\n addExcludeRefinement: function addExcludeRefinement(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n if (RefinementList.isRefined(this.facetsExcludes, facet, value))\n return this;\n\n return this.setQueryParameters({\n facetsExcludes: RefinementList.addRefinement(\n this.facetsExcludes,\n facet,\n value\n ),\n });\n },\n /**\n * Adds a refinement on a disjunctive facet.\n * @method\n * @param {string} facet attribute to apply the faceting on\n * @param {string} value value of the attribute (will be converted to string)\n * @return {SearchParameters} new instance\n */\n addDisjunctiveFacetRefinement: function addDisjunctiveFacetRefinement(\n facet,\n value\n ) {\n if (!this.isDisjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the disjunctiveFacets attribute of the helper configuration'\n );\n }\n\n if (\n RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)\n )\n return this;\n\n return this.setQueryParameters({\n disjunctiveFacetsRefinements: RefinementList.addRefinement(\n this.disjunctiveFacetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * addTagRefinement adds a tag to the list used to filter the results\n * @param {string} tag tag to be added\n * @return {SearchParameters} new instance\n */\n addTagRefinement: function addTagRefinement(tag) {\n if (this.isTagRefined(tag)) return this;\n\n var modification = {\n tagRefinements: this.tagRefinements.concat(tag),\n };\n\n return this.setQueryParameters(modification);\n },\n /**\n * Remove a facet from the facets attribute of the helper configuration, if it\n * is present.\n * @method\n * @param {string} facet facet name to remove\n * @return {SearchParameters} new instance\n */\n removeFacet: function removeFacet(facet) {\n if (!this.isConjunctiveFacet(facet)) {\n return this;\n }\n\n return this.clearRefinements(facet).setQueryParameters({\n facets: this.facets.filter(function (f) {\n return f !== facet;\n }),\n });\n },\n /**\n * Remove a disjunctive facet from the disjunctiveFacets attribute of the\n * helper configuration, if it is present.\n * @method\n * @param {string} facet disjunctive facet name to remove\n * @return {SearchParameters} new instance\n */\n removeDisjunctiveFacet: function removeDisjunctiveFacet(facet) {\n if (!this.isDisjunctiveFacet(facet)) {\n return this;\n }\n\n return this.clearRefinements(facet).setQueryParameters({\n disjunctiveFacets: this.disjunctiveFacets.filter(function (f) {\n return f !== facet;\n }),\n });\n },\n /**\n * Remove a hierarchical facet from the hierarchicalFacets attribute of the\n * helper configuration, if it is present.\n * @method\n * @param {string} facet hierarchical facet name to remove\n * @return {SearchParameters} new instance\n */\n removeHierarchicalFacet: function removeHierarchicalFacet(facet) {\n if (!this.isHierarchicalFacet(facet)) {\n return this;\n }\n\n return this.clearRefinements(facet).setQueryParameters({\n hierarchicalFacets: this.hierarchicalFacets.filter(function (f) {\n return f.name !== facet;\n }),\n });\n },\n /**\n * Remove a refinement set on facet. If a value is provided, it will clear the\n * refinement for the given value, otherwise it will clear all the refinement\n * values for the faceted attribute.\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {string} [value] value used to filter\n * @return {SearchParameters} new instance\n */\n removeFacetRefinement: function removeFacetRefinement(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n if (!RefinementList.isRefined(this.facetsRefinements, facet, value))\n return this;\n\n return this.setQueryParameters({\n facetsRefinements: RefinementList.removeRefinement(\n this.facetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * Remove a negative refinement on a facet\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {string} value value used to filter\n * @return {SearchParameters} new instance\n */\n removeExcludeRefinement: function removeExcludeRefinement(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n if (!RefinementList.isRefined(this.facetsExcludes, facet, value))\n return this;\n\n return this.setQueryParameters({\n facetsExcludes: RefinementList.removeRefinement(\n this.facetsExcludes,\n facet,\n value\n ),\n });\n },\n /**\n * Remove a refinement on a disjunctive facet\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {string} value value used to filter\n * @return {SearchParameters} new instance\n */\n removeDisjunctiveFacetRefinement: function removeDisjunctiveFacetRefinement(\n facet,\n value\n ) {\n if (!this.isDisjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the disjunctiveFacets attribute of the helper configuration'\n );\n }\n if (\n !RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)\n )\n return this;\n\n return this.setQueryParameters({\n disjunctiveFacetsRefinements: RefinementList.removeRefinement(\n this.disjunctiveFacetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * Remove a tag from the list of tag refinements\n * @method\n * @param {string} tag the tag to remove\n * @return {SearchParameters} new instance\n */\n removeTagRefinement: function removeTagRefinement(tag) {\n if (!this.isTagRefined(tag)) return this;\n\n var modification = {\n tagRefinements: this.tagRefinements.filter(function (t) {\n return t !== tag;\n }),\n };\n\n return this.setQueryParameters(modification);\n },\n /**\n * Generic toggle refinement method to use with facet, disjunctive facets\n * and hierarchical facets\n * @param {string} facet the facet to refine\n * @param {string} value the associated value\n * @return {SearchParameters} new instance\n * @throws will throw an error if the facet is not declared in the settings of the helper\n * @deprecated since version 2.19.0, see {@link SearchParameters#toggleFacetRefinement}\n */\n toggleRefinement: function toggleRefinement(facet, value) {\n return this.toggleFacetRefinement(facet, value);\n },\n /**\n * Generic toggle refinement method to use with facet, disjunctive facets\n * and hierarchical facets\n * @param {string} facet the facet to refine\n * @param {string} value the associated value\n * @return {SearchParameters} new instance\n * @throws will throw an error if the facet is not declared in the settings of the helper\n */\n toggleFacetRefinement: function toggleFacetRefinement(facet, value) {\n if (this.isHierarchicalFacet(facet)) {\n return this.toggleHierarchicalFacetRefinement(facet, value);\n } else if (this.isConjunctiveFacet(facet)) {\n return this.toggleConjunctiveFacetRefinement(facet, value);\n } else if (this.isDisjunctiveFacet(facet)) {\n return this.toggleDisjunctiveFacetRefinement(facet, value);\n }\n\n throw new Error(\n 'Cannot refine the undeclared facet ' +\n facet +\n '; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets'\n );\n },\n /**\n * Switch the refinement applied over a facet/value\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {SearchParameters} new instance\n */\n toggleConjunctiveFacetRefinement: function toggleConjunctiveFacetRefinement(\n facet,\n value\n ) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n\n return this.setQueryParameters({\n facetsRefinements: RefinementList.toggleRefinement(\n this.facetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * Switch the refinement applied over a facet/value\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {SearchParameters} new instance\n */\n toggleExcludeFacetRefinement: function toggleExcludeFacetRefinement(\n facet,\n value\n ) {\n if (!this.isConjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the facets attribute of the helper configuration'\n );\n }\n\n return this.setQueryParameters({\n facetsExcludes: RefinementList.toggleRefinement(\n this.facetsExcludes,\n facet,\n value\n ),\n });\n },\n /**\n * Switch the refinement applied over a facet/value\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {SearchParameters} new instance\n */\n toggleDisjunctiveFacetRefinement: function toggleDisjunctiveFacetRefinement(\n facet,\n value\n ) {\n if (!this.isDisjunctiveFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the disjunctiveFacets attribute of the helper configuration'\n );\n }\n\n return this.setQueryParameters({\n disjunctiveFacetsRefinements: RefinementList.toggleRefinement(\n this.disjunctiveFacetsRefinements,\n facet,\n value\n ),\n });\n },\n /**\n * Switch the refinement applied over a facet/value\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {SearchParameters} new instance\n */\n toggleHierarchicalFacetRefinement: function toggleHierarchicalFacetRefinement(\n facet,\n value\n ) {\n if (!this.isHierarchicalFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the hierarchicalFacets attribute of the helper configuration'\n );\n }\n\n var separator = this._getHierarchicalFacetSeparator(\n this.getHierarchicalFacetByName(facet)\n );\n\n var mod = {};\n\n var upOneOrMultipleLevel =\n this.hierarchicalFacetsRefinements[facet] !== undefined &&\n this.hierarchicalFacetsRefinements[facet].length > 0 &&\n // remove current refinement:\n // refinement was 'beer > IPA', call is toggleRefine('beer > IPA'), refinement should be `beer`\n (this.hierarchicalFacetsRefinements[facet][0] === value ||\n // remove a parent refinement of the current refinement:\n // - refinement was 'beer > IPA > Flying dog'\n // - call is toggleRefine('beer > IPA')\n // - refinement should be `beer`\n this.hierarchicalFacetsRefinements[facet][0].indexOf(\n value + separator\n ) === 0);\n\n if (upOneOrMultipleLevel) {\n if (value.indexOf(separator) === -1) {\n // go back to root level\n mod[facet] = [];\n } else {\n mod[facet] = [value.slice(0, value.lastIndexOf(separator))];\n }\n } else {\n mod[facet] = [value];\n }\n\n return this.setQueryParameters({\n hierarchicalFacetsRefinements: defaultsPure(\n {},\n mod,\n this.hierarchicalFacetsRefinements\n ),\n });\n },\n\n /**\n * Adds a refinement on a hierarchical facet.\n * @param {string} facet the facet name\n * @param {string} path the hierarchical facet path\n * @return {SearchParameter} the new state\n * @throws Error if the facet is not defined or if the facet is refined\n */\n addHierarchicalFacetRefinement: function (facet, path) {\n if (this.isHierarchicalFacetRefined(facet)) {\n throw new Error(facet + ' is already refined.');\n }\n if (!this.isHierarchicalFacet(facet)) {\n throw new Error(\n facet +\n ' is not defined in the hierarchicalFacets attribute of the helper configuration.'\n );\n }\n var mod = {};\n mod[facet] = [path];\n return this.setQueryParameters({\n hierarchicalFacetsRefinements: defaultsPure(\n {},\n mod,\n this.hierarchicalFacetsRefinements\n ),\n });\n },\n\n /**\n * Removes the refinement set on a hierarchical facet.\n * @param {string} facet the facet name\n * @return {SearchParameter} the new state\n * @throws Error if the facet is not defined or if the facet is not refined\n */\n removeHierarchicalFacetRefinement: function (facet) {\n if (!this.isHierarchicalFacetRefined(facet)) {\n return this;\n }\n var mod = {};\n mod[facet] = [];\n return this.setQueryParameters({\n hierarchicalFacetsRefinements: defaultsPure(\n {},\n mod,\n this.hierarchicalFacetsRefinements\n ),\n });\n },\n /**\n * Switch the tag refinement\n * @method\n * @param {string} tag the tag to remove or add\n * @return {SearchParameters} new instance\n */\n toggleTagRefinement: function toggleTagRefinement(tag) {\n if (this.isTagRefined(tag)) {\n return this.removeTagRefinement(tag);\n }\n\n return this.addTagRefinement(tag);\n },\n /**\n * Test if the facet name is from one of the disjunctive facets\n * @method\n * @param {string} facet facet name to test\n * @return {boolean} true if facet is a disjunctive facet\n */\n isDisjunctiveFacet: function (facet) {\n return this.disjunctiveFacets.indexOf(facet) > -1;\n },\n /**\n * Test if the facet name is from one of the hierarchical facets\n * @method\n * @param {string} facetName facet name to test\n * @return {boolean} true if facetName is a hierarchical facet\n */\n isHierarchicalFacet: function (facetName) {\n return this.getHierarchicalFacetByName(facetName) !== undefined;\n },\n /**\n * Test if the facet name is from one of the conjunctive/normal facets\n * @method\n * @param {string} facet facet name to test\n * @return {boolean} true if facet is a conjunctive facet\n */\n isConjunctiveFacet: function (facet) {\n return this.facets.indexOf(facet) > -1;\n },\n /**\n * Returns true if the facet is refined, either for a specific value or in\n * general.\n * @method\n * @param {string} facet name of the attribute for used for faceting\n * @param {string} value, optional value. If passed will test that this value\n * is filtering the given facet.\n * @return {boolean} returns true if refined\n */\n isFacetRefined: function isFacetRefined(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n return false;\n }\n return RefinementList.isRefined(this.facetsRefinements, facet, value);\n },\n /**\n * Returns true if the facet contains exclusions or if a specific value is\n * excluded.\n *\n * @method\n * @param {string} facet name of the attribute for used for faceting\n * @param {string} [value] optional value. If passed will test that this value\n * is filtering the given facet.\n * @return {boolean} returns true if refined\n */\n isExcludeRefined: function isExcludeRefined(facet, value) {\n if (!this.isConjunctiveFacet(facet)) {\n return false;\n }\n return RefinementList.isRefined(this.facetsExcludes, facet, value);\n },\n /**\n * Returns true if the facet contains a refinement, or if a value passed is a\n * refinement for the facet.\n * @method\n * @param {string} facet name of the attribute for used for faceting\n * @param {string} value optional, will test if the value is used for refinement\n * if there is one, otherwise will test if the facet contains any refinement\n * @return {boolean} true if the facet is refined\n */\n isDisjunctiveFacetRefined: function isDisjunctiveFacetRefined(facet, value) {\n if (!this.isDisjunctiveFacet(facet)) {\n return false;\n }\n return RefinementList.isRefined(\n this.disjunctiveFacetsRefinements,\n facet,\n value\n );\n },\n /**\n * Returns true if the facet contains a refinement, or if a value passed is a\n * refinement for the facet.\n * @method\n * @param {string} facet name of the attribute for used for faceting\n * @param {string} value optional, will test if the value is used for refinement\n * if there is one, otherwise will test if the facet contains any refinement\n * @return {boolean} true if the facet is refined\n */\n isHierarchicalFacetRefined: function isHierarchicalFacetRefined(\n facet,\n value\n ) {\n if (!this.isHierarchicalFacet(facet)) {\n return false;\n }\n\n var refinements = this.getHierarchicalRefinement(facet);\n\n if (!value) {\n return refinements.length > 0;\n }\n\n return refinements.indexOf(value) !== -1;\n },\n /**\n * Test if the triple (attribute, operator, value) is already refined.\n * If only the attribute and the operator are provided, it tests if the\n * contains any refinement value.\n * @method\n * @param {string} attribute attribute for which the refinement is applied\n * @param {string} [operator] operator of the refinement\n * @param {string} [value] value of the refinement\n * @return {boolean} true if it is refined\n */\n isNumericRefined: function isNumericRefined(attribute, operator, value) {\n if (value === undefined && operator === undefined) {\n return Boolean(this.numericRefinements[attribute]);\n }\n\n var isOperatorDefined =\n this.numericRefinements[attribute] &&\n this.numericRefinements[attribute][operator] !== undefined;\n\n if (value === undefined || !isOperatorDefined) {\n return isOperatorDefined;\n }\n\n var parsedValue = valToNumber(value);\n var isAttributeValueDefined =\n findArray(this.numericRefinements[attribute][operator], parsedValue) !==\n undefined;\n\n return isOperatorDefined && isAttributeValueDefined;\n },\n /**\n * Returns true if the tag refined, false otherwise\n * @method\n * @param {string} tag the tag to check\n * @return {boolean} true if tag is refined\n */\n isTagRefined: function isTagRefined(tag) {\n return this.tagRefinements.indexOf(tag) !== -1;\n },\n /**\n * Returns the list of all disjunctive facets refined\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {string[]} returns the list of refinements\n */\n getRefinedDisjunctiveFacets: function getRefinedDisjunctiveFacets() {\n // eslint-disable-next-line consistent-this\n var self = this;\n\n // attributes used for numeric filter can also be disjunctive\n var disjunctiveNumericRefinedFacets = intersection(\n Object.keys(this.numericRefinements).filter(function (facet) {\n return Object.keys(self.numericRefinements[facet]).length > 0;\n }),\n this.disjunctiveFacets\n );\n\n return Object.keys(this.disjunctiveFacetsRefinements)\n .filter(function (facet) {\n return self.disjunctiveFacetsRefinements[facet].length > 0;\n })\n .concat(disjunctiveNumericRefinedFacets)\n .concat(this.getRefinedHierarchicalFacets())\n .sort();\n },\n /**\n * Returns the list of all disjunctive facets refined\n * @method\n * @param {string} facet name of the attribute used for faceting\n * @param {value} value value used for filtering\n * @return {string[]} returns the list of refinements\n */\n getRefinedHierarchicalFacets: function getRefinedHierarchicalFacets() {\n // eslint-disable-next-line consistent-this\n var self = this;\n return intersection(\n // enforce the order between the two arrays,\n // so that refinement name index === hierarchical facet index\n this.hierarchicalFacets.map(function (facet) {\n return facet.name;\n }),\n Object.keys(this.hierarchicalFacetsRefinements).filter(function (facet) {\n return self.hierarchicalFacetsRefinements[facet].length > 0;\n })\n ).sort();\n },\n /**\n * Returned the list of all disjunctive facets not refined\n * @method\n * @return {string[]} returns the list of facets that are not refined\n */\n getUnrefinedDisjunctiveFacets: function () {\n var refinedFacets = this.getRefinedDisjunctiveFacets();\n\n return this.disjunctiveFacets.filter(function (f) {\n return refinedFacets.indexOf(f) === -1;\n });\n },\n\n managedParameters: [\n 'index',\n\n 'facets',\n 'disjunctiveFacets',\n 'facetsRefinements',\n 'hierarchicalFacets',\n 'facetsExcludes',\n\n 'disjunctiveFacetsRefinements',\n 'numericRefinements',\n 'tagRefinements',\n 'hierarchicalFacetsRefinements',\n ],\n\n getQueryParams: function getQueryParams() {\n var managedParameters = this.managedParameters;\n\n var queryParams = {};\n\n // eslint-disable-next-line consistent-this\n var self = this;\n Object.keys(this).forEach(function (paramName) {\n var paramValue = self[paramName];\n if (\n managedParameters.indexOf(paramName) === -1 &&\n paramValue !== undefined\n ) {\n queryParams[paramName] = paramValue;\n }\n });\n\n return queryParams;\n },\n /**\n * Let the user set a specific value for a given parameter. Will return the\n * same instance if the parameter is invalid or if the value is the same as the\n * previous one.\n * @method\n * @param {string} parameter the parameter name\n * @param {any} value the value to be set, must be compliant with the definition\n * of the attribute on the object\n * @return {SearchParameters} the updated state\n */\n setQueryParameter: function setParameter(parameter, value) {\n if (this[parameter] === value) return this;\n\n var modification = {};\n\n modification[parameter] = value;\n\n return this.setQueryParameters(modification);\n },\n /**\n * Let the user set any of the parameters with a plain object.\n * @method\n * @param {object} params all the keys and the values to be updated\n * @return {SearchParameters} a new updated instance\n */\n setQueryParameters: function setQueryParameters(params) {\n if (!params) return this;\n\n var error = SearchParameters.validate(this, params);\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line consistent-this\n var self = this;\n var nextWithNumbers = SearchParameters._parseNumbers(params);\n var previousPlainObject = Object.keys(this).reduce(function (acc, key) {\n acc[key] = self[key];\n return acc;\n }, {});\n\n var nextPlainObject = Object.keys(nextWithNumbers).reduce(function (\n previous,\n key\n ) {\n var isPreviousValueDefined = previous[key] !== undefined;\n var isNextValueDefined = nextWithNumbers[key] !== undefined;\n\n if (isPreviousValueDefined && !isNextValueDefined) {\n return omit(previous, [key]);\n }\n\n if (isNextValueDefined) {\n previous[key] = nextWithNumbers[key];\n }\n\n return previous;\n },\n previousPlainObject);\n\n return new this.constructor(nextPlainObject);\n },\n\n /**\n * Returns a new instance with the page reset. Two scenarios possible:\n * the page is omitted -> return the given instance\n * the page is set -> return a new instance with a page of 0\n * @return {SearchParameters} a new updated instance\n */\n resetPage: function () {\n if (this.page === undefined) {\n return this;\n }\n\n return this.setPage(0);\n },\n\n /**\n * Helper function to get the hierarchicalFacet separator or the default one (`>`)\n * @param {object} hierarchicalFacet the hierarchicalFacet object\n * @return {string} returns the hierarchicalFacet.separator or `>` as default\n */\n _getHierarchicalFacetSortBy: function (hierarchicalFacet) {\n return hierarchicalFacet.sortBy || ['isRefined:desc', 'name:asc'];\n },\n\n /**\n * Helper function to get the hierarchicalFacet separator or the default one (`>`)\n * @private\n * @param {object} hierarchicalFacet the hierarchicalFacet object\n * @return {string} returns the hierarchicalFacet.separator or `>` as default\n */\n _getHierarchicalFacetSeparator: function (hierarchicalFacet) {\n return hierarchicalFacet.separator || ' > ';\n },\n\n /**\n * Helper function to get the hierarchicalFacet prefix path or null\n * @private\n * @param {object} hierarchicalFacet the hierarchicalFacet object\n * @return {string} returns the hierarchicalFacet.rootPath or null as default\n */\n _getHierarchicalRootPath: function (hierarchicalFacet) {\n return hierarchicalFacet.rootPath || null;\n },\n\n /**\n * Helper function to check if we show the parent level of the hierarchicalFacet\n * @private\n * @param {object} hierarchicalFacet the hierarchicalFacet object\n * @return {string} returns the hierarchicalFacet.showParentLevel or true as default\n */\n _getHierarchicalShowParentLevel: function (hierarchicalFacet) {\n if (typeof hierarchicalFacet.showParentLevel === 'boolean') {\n return hierarchicalFacet.showParentLevel;\n }\n return true;\n },\n\n /**\n * Helper function to get the hierarchicalFacet by it's name\n * @param {string} hierarchicalFacetName the hierarchicalFacet name\n * @return {object} a hierarchicalFacet\n */\n getHierarchicalFacetByName: function (hierarchicalFacetName) {\n return find(this.hierarchicalFacets, function (f) {\n return f.name === hierarchicalFacetName;\n });\n },\n\n /**\n * Get the current breadcrumb for a hierarchical facet, as an array\n * @param {string} facetName Hierarchical facet name\n * @return {array.<string>} the path as an array of string\n */\n getHierarchicalFacetBreadcrumb: function (facetName) {\n if (!this.isHierarchicalFacet(facetName)) {\n return [];\n }\n\n var refinement = this.getHierarchicalRefinement(facetName)[0];\n if (!refinement) return [];\n\n var separator = this._getHierarchicalFacetSeparator(\n this.getHierarchicalFacetByName(facetName)\n );\n var path = refinement.split(separator);\n return path.map(function (part) {\n return part.trim();\n });\n },\n\n toString: function () {\n return JSON.stringify(this, null, 2);\n },\n};\n\n/**\n * Callback used for clearRefinement method\n * @callback SearchParameters.clearCallback\n * @param {OperatorList|FacetList} value the value of the filter\n * @param {string} key the current attribute name\n * @param {string} type `numeric`, `disjunctiveFacet`, `conjunctiveFacet`, `hierarchicalFacet` or `exclude`\n * depending on the type of facet\n * @return {boolean} `true` if the element should be removed. `false` otherwise.\n */\nmodule.exports = SearchParameters;\n","'use strict';\n\nmodule.exports = generateTrees;\n\nvar fv = require('../functions/escapeFacetValue');\nvar find = require('../functions/find');\nvar prepareHierarchicalFacetSortBy = require('../functions/formatSort');\nvar orderBy = require('../functions/orderBy');\nvar escapeFacetValue = fv.escapeFacetValue;\nvar unescapeFacetValue = fv.unescapeFacetValue;\n\nfunction generateTrees(state) {\n return function generate(hierarchicalFacetResult, hierarchicalFacetIndex) {\n var hierarchicalFacet = state.hierarchicalFacets[hierarchicalFacetIndex];\n var hierarchicalFacetRefinement =\n (state.hierarchicalFacetsRefinements[hierarchicalFacet.name] &&\n state.hierarchicalFacetsRefinements[hierarchicalFacet.name][0]) ||\n '';\n var hierarchicalSeparator =\n state._getHierarchicalFacetSeparator(hierarchicalFacet);\n var hierarchicalRootPath =\n state._getHierarchicalRootPath(hierarchicalFacet);\n var hierarchicalShowParentLevel =\n state._getHierarchicalShowParentLevel(hierarchicalFacet);\n var sortBy = prepareHierarchicalFacetSortBy(\n state._getHierarchicalFacetSortBy(hierarchicalFacet)\n );\n\n var rootExhaustive = hierarchicalFacetResult.every(function (facetResult) {\n return facetResult.exhaustive;\n });\n\n var generateTreeFn = generateHierarchicalTree(\n sortBy,\n hierarchicalSeparator,\n hierarchicalRootPath,\n hierarchicalShowParentLevel,\n hierarchicalFacetRefinement\n );\n\n var results = hierarchicalFacetResult;\n\n if (hierarchicalRootPath) {\n results = hierarchicalFacetResult.slice(\n hierarchicalRootPath.split(hierarchicalSeparator).length\n );\n }\n\n return results.reduce(generateTreeFn, {\n name: state.hierarchicalFacets[hierarchicalFacetIndex].name,\n count: null, // root level, no count\n isRefined: true, // root level, always refined\n path: null, // root level, no path\n escapedValue: null,\n exhaustive: rootExhaustive,\n data: null,\n });\n };\n}\n\nfunction generateHierarchicalTree(\n sortBy,\n hierarchicalSeparator,\n hierarchicalRootPath,\n hierarchicalShowParentLevel,\n currentRefinement\n) {\n return function generateTree(\n hierarchicalTree,\n hierarchicalFacetResult,\n currentHierarchicalLevel\n ) {\n var parent = hierarchicalTree;\n\n if (currentHierarchicalLevel > 0) {\n var level = 0;\n\n parent = hierarchicalTree;\n\n while (level < currentHierarchicalLevel) {\n /**\n * @type {object[]]} hierarchical data\n */\n var data = parent && Array.isArray(parent.data) ? parent.data : [];\n parent = find(data, function (subtree) {\n return subtree.isRefined;\n });\n level++;\n }\n }\n\n // we found a refined parent, let's add current level data under it\n if (parent) {\n // filter values in case an object has multiple categories:\n // {\n // categories: {\n // level0: ['beers', 'bières'],\n // level1: ['beers > IPA', 'bières > Belges']\n // }\n // }\n //\n // If parent refinement is `beers`, then we do not want to have `bières > Belges`\n // showing up\n\n var picked = Object.keys(hierarchicalFacetResult.data)\n .map(function (facetValue) {\n return [facetValue, hierarchicalFacetResult.data[facetValue]];\n })\n .filter(function (tuple) {\n var facetValue = tuple[0];\n return onlyMatchingTree(\n facetValue,\n parent.path || hierarchicalRootPath,\n currentRefinement,\n hierarchicalSeparator,\n hierarchicalRootPath,\n hierarchicalShowParentLevel\n );\n });\n\n parent.data = orderBy(\n picked.map(function (tuple) {\n var facetValue = tuple[0];\n var facetCount = tuple[1];\n\n return format(\n facetCount,\n facetValue,\n hierarchicalSeparator,\n unescapeFacetValue(currentRefinement),\n hierarchicalFacetResult.exhaustive\n );\n }),\n sortBy[0],\n sortBy[1]\n );\n }\n\n return hierarchicalTree;\n };\n}\n\n// eslint-disable-next-line max-params\nfunction onlyMatchingTree(\n facetValue,\n parentPath,\n currentRefinement,\n hierarchicalSeparator,\n hierarchicalRootPath,\n hierarchicalShowParentLevel\n) {\n // we want the facetValue is a child of hierarchicalRootPath\n if (\n hierarchicalRootPath &&\n (facetValue.indexOf(hierarchicalRootPath) !== 0 ||\n hierarchicalRootPath === facetValue)\n ) {\n return false;\n }\n\n // we always want root levels (only when there is no prefix path)\n return (\n (!hierarchicalRootPath &&\n facetValue.indexOf(hierarchicalSeparator) === -1) ||\n // if there is a rootPath, being root level mean 1 level under rootPath\n (hierarchicalRootPath &&\n facetValue.split(hierarchicalSeparator).length -\n hierarchicalRootPath.split(hierarchicalSeparator).length ===\n 1) ||\n // if current refinement is a root level and current facetValue is a root level,\n // keep the facetValue\n (facetValue.indexOf(hierarchicalSeparator) === -1 &&\n currentRefinement.indexOf(hierarchicalSeparator) === -1) ||\n // currentRefinement is a child of the facet value\n currentRefinement.indexOf(facetValue) === 0 ||\n // facetValue is a child of the current parent, add it\n (facetValue.indexOf(parentPath + hierarchicalSeparator) === 0 &&\n (hierarchicalShowParentLevel ||\n facetValue.indexOf(currentRefinement) === 0))\n );\n}\n\nfunction format(\n facetCount,\n facetValue,\n hierarchicalSeparator,\n currentRefinement,\n exhaustive\n) {\n var parts = facetValue.split(hierarchicalSeparator);\n return {\n name: parts[parts.length - 1].trim(),\n path: facetValue,\n escapedValue: escapeFacetValue(facetValue),\n count: facetCount,\n isRefined:\n currentRefinement === facetValue ||\n currentRefinement.indexOf(facetValue + hierarchicalSeparator) === 0,\n exhaustive: exhaustive,\n data: null,\n };\n}\n","'use strict';\n\nvar compact = require('../functions/compact');\nvar defaultsPure = require('../functions/defaultsPure');\nvar fv = require('../functions/escapeFacetValue');\nvar find = require('../functions/find');\nvar findIndex = require('../functions/findIndex');\nvar formatSort = require('../functions/formatSort');\nvar merge = require('../functions/merge');\nvar orderBy = require('../functions/orderBy');\nvar escapeFacetValue = fv.escapeFacetValue;\nvar unescapeFacetValue = fv.unescapeFacetValue;\n\nvar generateHierarchicalTree = require('./generate-hierarchical-tree');\n\n/**\n * @typedef SearchResults.Facet\n * @type {object}\n * @property {string} name name of the attribute in the record\n * @property {object} data the faceting data: value, number of entries\n * @property {object} stats undefined unless facet_stats is retrieved from algolia\n */\n\n/**\n * @typedef SearchResults.HierarchicalFacet\n * @type {object}\n * @property {string} name name of the current value given the hierarchical level, trimmed.\n * If root node, you get the facet name\n * @property {number} count number of objects matching this hierarchical value\n * @property {string} path the current hierarchical value full path\n * @property {boolean} isRefined `true` if the current value was refined, `false` otherwise\n * @property {HierarchicalFacet[]} data sub values for the current level\n */\n\n/**\n * @typedef SearchResults.FacetValue\n * @type {object}\n * @property {string} name the facet value itself\n * @property {number} count times this facet appears in the results\n * @property {boolean} isRefined is the facet currently selected\n * @property {boolean} isExcluded is the facet currently excluded (only for conjunctive facets)\n */\n\n/**\n * @typedef Refinement\n * @type {object}\n * @property {string} type the type of filter used:\n * `numeric`, `facet`, `exclude`, `disjunctive`, `hierarchical`\n * @property {string} attributeName name of the attribute used for filtering\n * @property {string} name the value of the filter\n * @property {number} numericValue the value as a number. Only for numeric filters.\n * @property {string} operator the operator used. Only for numeric filters.\n * @property {number} count the number of computed hits for this filter. Only on facets.\n * @property {boolean} exhaustive if the count is exhaustive\n */\n\n/**\n * Turn an array of attributes in an object of attributes with their position in the array as value\n * @param {string[]} attributes the list of attributes in the record\n * @return {object} the list of attributes indexed by attribute name\n */\nfunction getIndices(attributes) {\n var indices = {};\n\n attributes.forEach(function (val, idx) {\n indices[val] = idx;\n });\n\n return indices;\n}\n\nfunction assignFacetStats(dest, facetStats, key) {\n if (facetStats && facetStats[key]) {\n dest.stats = facetStats[key];\n }\n}\n\n/**\n * @typedef {Object} HierarchicalFacet\n * @property {string} name\n * @property {string[]} attributes\n */\n\n/**\n * @param {HierarchicalFacet[]} hierarchicalFacets All hierarchical facets\n * @param {string} hierarchicalAttributeName The name of the hierarchical attribute\n * @return {HierarchicalFacet} The hierarchical facet matching the attribute name\n */\nfunction findMatchingHierarchicalFacetFromAttributeName(\n hierarchicalFacets,\n hierarchicalAttributeName\n) {\n return find(\n hierarchicalFacets,\n function facetKeyMatchesAttribute(hierarchicalFacet) {\n var facetNames = hierarchicalFacet.attributes || [];\n return facetNames.indexOf(hierarchicalAttributeName) > -1;\n }\n );\n}\n\n/**\n * Constructor for SearchResults\n * @class\n * @classdesc SearchResults contains the results of a query to Algolia using the\n * {@link AlgoliaSearchHelper}.\n * @param {SearchParameters} state state that led to the response\n * @param {array.<object>} results the results from algolia client\n * @param {object} options options to control results content\n * @example <caption>SearchResults of the first query in\n * <a href=\"http://demos.algolia.com/instant-search-demo\">the instant search demo</a></caption>\n{\n \"hitsPerPage\": 10,\n \"processingTimeMS\": 2,\n \"facets\": [\n {\n \"name\": \"type\",\n \"data\": {\n \"HardGood\": 6627,\n \"BlackTie\": 550,\n \"Music\": 665,\n \"Software\": 131,\n \"Game\": 456,\n \"Movie\": 1571\n },\n \"exhaustive\": false\n },\n {\n \"exhaustive\": false,\n \"data\": {\n \"Free shipping\": 5507\n },\n \"name\": \"shipping\"\n }\n ],\n \"hits\": [\n {\n \"thumbnailImage\": \"http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_54x108_s.gif\",\n \"_highlightResult\": {\n \"shortDescription\": {\n \"matchLevel\": \"none\",\n \"value\": \"Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection\",\n \"matchedWords\": []\n },\n \"category\": {\n \"matchLevel\": \"none\",\n \"value\": \"Computer Security Software\",\n \"matchedWords\": []\n },\n \"manufacturer\": {\n \"matchedWords\": [],\n \"value\": \"Webroot\",\n \"matchLevel\": \"none\"\n },\n \"name\": {\n \"value\": \"Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows\",\n \"matchedWords\": [],\n \"matchLevel\": \"none\"\n }\n },\n \"image\": \"http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_105x210_sc.jpg\",\n \"shipping\": \"Free shipping\",\n \"bestSellingRank\": 4,\n \"shortDescription\": \"Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection\",\n \"url\": \"http://www.bestbuy.com/site/webroot-secureanywhere-internet-security-3-devi…d=1219060687969&skuId=1688832&cmp=RMX&ky=2d3GfEmNIzjA0vkzveHdZEBgpPCyMnLTJ\",\n \"name\": \"Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows\",\n \"category\": \"Computer Security Software\",\n \"salePrice_range\": \"1 - 50\",\n \"objectID\": \"1688832\",\n \"type\": \"Software\",\n \"customerReviewCount\": 5980,\n \"salePrice\": 49.99,\n \"manufacturer\": \"Webroot\"\n },\n ....\n ],\n \"nbHits\": 10000,\n \"disjunctiveFacets\": [\n {\n \"exhaustive\": false,\n \"data\": {\n \"5\": 183,\n \"12\": 112,\n \"7\": 149,\n ...\n },\n \"name\": \"customerReviewCount\",\n \"stats\": {\n \"max\": 7461,\n \"avg\": 157.939,\n \"min\": 1\n }\n },\n {\n \"data\": {\n \"Printer Ink\": 142,\n \"Wireless Speakers\": 60,\n \"Point & Shoot Cameras\": 48,\n ...\n },\n \"name\": \"category\",\n \"exhaustive\": false\n },\n {\n \"exhaustive\": false,\n \"data\": {\n \"> 5000\": 2,\n \"1 - 50\": 6524,\n \"501 - 2000\": 566,\n \"201 - 500\": 1501,\n \"101 - 200\": 1360,\n \"2001 - 5000\": 47\n },\n \"name\": \"salePrice_range\"\n },\n {\n \"data\": {\n \"Dynex™\": 202,\n \"Insignia™\": 230,\n \"PNY\": 72,\n ...\n },\n \"name\": \"manufacturer\",\n \"exhaustive\": false\n }\n ],\n \"query\": \"\",\n \"nbPages\": 100,\n \"page\": 0,\n \"index\": \"bestbuy\"\n}\n **/\nfunction SearchResults(state, results, options) {\n var mainSubResponse = results[0] || {};\n\n this._rawResults = results;\n\n // eslint-disable-next-line consistent-this\n var self = this;\n\n // https://www.algolia.com/doc/api-reference/api-methods/search/#response\n Object.keys(mainSubResponse).forEach(function (key) {\n self[key] = mainSubResponse[key];\n });\n\n // Make every key of the result options reachable from the instance\n var opts = merge(\n {\n persistHierarchicalRootCount: false,\n },\n options\n );\n Object.keys(opts).forEach(function (key) {\n self[key] = opts[key];\n });\n\n /**\n * query used to generate the results\n * @name query\n * @member {string}\n * @memberof SearchResults\n * @instance\n */\n /**\n * The query as parsed by the engine given all the rules.\n * @name parsedQuery\n * @member {string}\n * @memberof SearchResults\n * @instance\n */\n /**\n * all the records that match the search parameters. Each record is\n * augmented with a new attribute `_highlightResult`\n * which is an object keyed by attribute and with the following properties:\n * - `value` : the value of the facet highlighted (html)\n * - `matchLevel`: `full`, `partial` or `none`, depending on how the query terms match\n * @name hits\n * @member {object[]}\n * @memberof SearchResults\n * @instance\n */\n /**\n * index where the results come from\n * @name index\n * @member {string}\n * @memberof SearchResults\n * @instance\n */\n /**\n * number of hits per page requested\n * @name hitsPerPage\n * @member {number}\n * @memberof SearchResults\n * @instance\n */\n /**\n * total number of hits of this query on the index\n * @name nbHits\n * @member {number}\n * @memberof SearchResults\n * @instance\n */\n /**\n * total number of pages with respect to the number of hits per page and the total number of hits\n * @name nbPages\n * @member {number}\n * @memberof SearchResults\n * @instance\n */\n /**\n * current page\n * @name page\n * @member {number}\n * @memberof SearchResults\n * @instance\n */\n /**\n * The position if the position was guessed by IP.\n * @name aroundLatLng\n * @member {string}\n * @memberof SearchResults\n * @instance\n * @example \"48.8637,2.3615\",\n */\n /**\n * The radius computed by Algolia.\n * @name automaticRadius\n * @member {string}\n * @memberof SearchResults\n * @instance\n * @example \"126792922\",\n */\n /**\n * String identifying the server used to serve this request.\n *\n * getRankingInfo needs to be set to `true` for this to be returned\n *\n * @name serverUsed\n * @member {string}\n * @memberof SearchResults\n * @instance\n * @example \"c7-use-2.algolia.net\",\n */\n /**\n * Boolean that indicates if the computation of the counts did time out.\n * @deprecated\n * @name timeoutCounts\n * @member {boolean}\n * @memberof SearchResults\n * @instance\n */\n /**\n * Boolean that indicates if the computation of the hits did time out.\n * @deprecated\n * @name timeoutHits\n * @member {boolean}\n * @memberof SearchResults\n * @instance\n */\n /**\n * True if the counts of the facets is exhaustive\n * @name exhaustiveFacetsCount\n * @member {boolean}\n * @memberof SearchResults\n * @instance\n */\n /**\n * True if the number of hits is exhaustive\n * @name exhaustiveNbHits\n * @member {boolean}\n * @memberof SearchResults\n * @instance\n */\n /**\n * Contains the userData if they are set by a [query rule](https://www.algolia.com/doc/guides/query-rules/query-rules-overview/).\n * @name userData\n * @member {object[]}\n * @memberof SearchResults\n * @instance\n */\n /**\n * queryID is the unique identifier of the query used to generate the current search results.\n * This value is only available if the `clickAnalytics` search parameter is set to `true`.\n * @name queryID\n * @member {string}\n * @memberof SearchResults\n * @instance\n */\n\n /**\n * sum of the processing time of all the queries\n * @name processingTimeMS\n * @member {number}\n * @memberof SearchResults\n * @instance\n */\n this.processingTimeMS = results.reduce(function (sum, result) {\n return result.processingTimeMS === undefined\n ? sum\n : sum + result.processingTimeMS;\n }, 0);\n\n /**\n * disjunctive facets results\n * @member {SearchResults.Facet[]}\n */\n this.disjunctiveFacets = [];\n /**\n * disjunctive facets results\n * @member {SearchResults.HierarchicalFacet[]}\n */\n this.hierarchicalFacets = state.hierarchicalFacets.map(\n function initFutureTree() {\n return [];\n }\n );\n /**\n * other facets results\n * @member {SearchResults.Facet[]}\n */\n this.facets = [];\n\n var disjunctiveFacets = state.getRefinedDisjunctiveFacets();\n\n var facetsIndices = getIndices(state.facets);\n var disjunctiveFacetsIndices = getIndices(state.disjunctiveFacets);\n var nextDisjunctiveResult = 1;\n\n // Since we send request only for disjunctive facets that have been refined,\n // we get the facets information from the first, general, response.\n\n var mainFacets = mainSubResponse.facets || {};\n\n Object.keys(mainFacets).forEach(function (facetKey) {\n var facetValueObject = mainFacets[facetKey];\n\n var hierarchicalFacet = findMatchingHierarchicalFacetFromAttributeName(\n state.hierarchicalFacets,\n facetKey\n );\n\n if (hierarchicalFacet) {\n // Place the hierarchicalFacet data at the correct index depending on\n // the attributes order that was defined at the helper initialization\n var facetIndex = hierarchicalFacet.attributes.indexOf(facetKey);\n var idxAttributeName = findIndex(state.hierarchicalFacets, function (f) {\n return f.name === hierarchicalFacet.name;\n });\n self.hierarchicalFacets[idxAttributeName][facetIndex] = {\n attribute: facetKey,\n data: facetValueObject,\n exhaustive: mainSubResponse.exhaustiveFacetsCount,\n };\n } else {\n var isFacetDisjunctive = state.disjunctiveFacets.indexOf(facetKey) !== -1;\n var isFacetConjunctive = state.facets.indexOf(facetKey) !== -1;\n var position;\n\n if (isFacetDisjunctive) {\n position = disjunctiveFacetsIndices[facetKey];\n self.disjunctiveFacets[position] = {\n name: facetKey,\n data: facetValueObject,\n exhaustive: mainSubResponse.exhaustiveFacetsCount,\n };\n assignFacetStats(\n self.disjunctiveFacets[position],\n mainSubResponse.facets_stats,\n facetKey\n );\n }\n if (isFacetConjunctive) {\n position = facetsIndices[facetKey];\n self.facets[position] = {\n name: facetKey,\n data: facetValueObject,\n exhaustive: mainSubResponse.exhaustiveFacetsCount,\n };\n assignFacetStats(\n self.facets[position],\n mainSubResponse.facets_stats,\n facetKey\n );\n }\n }\n });\n\n // Make sure we do not keep holes within the hierarchical facets\n this.hierarchicalFacets = compact(this.hierarchicalFacets);\n\n // aggregate the refined disjunctive facets\n disjunctiveFacets.forEach(function (disjunctiveFacet) {\n var result = results[nextDisjunctiveResult];\n var facets = result && result.facets ? result.facets : {};\n var hierarchicalFacet = state.getHierarchicalFacetByName(disjunctiveFacet);\n\n // There should be only item in facets.\n Object.keys(facets).forEach(function (dfacet) {\n var facetResults = facets[dfacet];\n\n var position;\n\n if (hierarchicalFacet) {\n position = findIndex(state.hierarchicalFacets, function (f) {\n return f.name === hierarchicalFacet.name;\n });\n var attributeIndex = findIndex(\n self.hierarchicalFacets[position],\n function (f) {\n return f.attribute === dfacet;\n }\n );\n\n // previous refinements and no results so not able to find it\n if (attributeIndex === -1) {\n return;\n }\n\n self.hierarchicalFacets[position][attributeIndex].data = merge(\n {},\n self.hierarchicalFacets[position][attributeIndex].data,\n facetResults\n );\n } else {\n position = disjunctiveFacetsIndices[dfacet];\n\n var dataFromMainRequest =\n (mainSubResponse.facets && mainSubResponse.facets[dfacet]) || {};\n\n self.disjunctiveFacets[position] = {\n name: dfacet,\n data: defaultsPure({}, facetResults, dataFromMainRequest),\n exhaustive: result.exhaustiveFacetsCount,\n };\n assignFacetStats(\n self.disjunctiveFacets[position],\n result.facets_stats,\n dfacet\n );\n\n if (state.disjunctiveFacetsRefinements[dfacet]) {\n state.disjunctiveFacetsRefinements[dfacet].forEach(function (\n refinementValue\n ) {\n // add the disjunctive refinements if it is no more retrieved\n if (\n !self.disjunctiveFacets[position].data[refinementValue] &&\n state.disjunctiveFacetsRefinements[dfacet].indexOf(\n unescapeFacetValue(refinementValue)\n ) > -1\n ) {\n self.disjunctiveFacets[position].data[refinementValue] = 0;\n }\n });\n }\n }\n });\n nextDisjunctiveResult++;\n });\n\n // if we have some parent level values for hierarchical facets, merge them\n state.getRefinedHierarchicalFacets().forEach(function (refinedFacet) {\n var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet);\n var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);\n\n var currentRefinement = state.getHierarchicalRefinement(refinedFacet);\n // if we are already at a root refinement (or no refinement at all), there is no\n // root level values request\n if (\n currentRefinement.length === 0 ||\n currentRefinement[0].split(separator).length < 2\n ) {\n return;\n }\n\n results.slice(nextDisjunctiveResult).forEach(function (result) {\n var facets = result && result.facets ? result.facets : {};\n\n Object.keys(facets).forEach(function (dfacet) {\n var facetResults = facets[dfacet];\n var position = findIndex(state.hierarchicalFacets, function (f) {\n return f.name === hierarchicalFacet.name;\n });\n var attributeIndex = findIndex(\n self.hierarchicalFacets[position],\n function (f) {\n return f.attribute === dfacet;\n }\n );\n\n // previous refinements and no results so not able to find it\n if (attributeIndex === -1) {\n return;\n }\n\n // when we always get root levels, if the hits refinement is `beers > IPA` (count: 5),\n // then the disjunctive values will be `beers` (count: 100),\n // but we do not want to display\n // | beers (100)\n // > IPA (5)\n // We want\n // | beers (5)\n // > IPA (5)\n // @MAJOR: remove this legacy behaviour in next major version\n var defaultData = {};\n\n if (\n currentRefinement.length > 0 &&\n !self.persistHierarchicalRootCount\n ) {\n var root = currentRefinement[0].split(separator)[0];\n defaultData[root] =\n self.hierarchicalFacets[position][attributeIndex].data[root];\n }\n\n self.hierarchicalFacets[position][attributeIndex].data = defaultsPure(\n defaultData,\n facetResults,\n self.hierarchicalFacets[position][attributeIndex].data\n );\n });\n\n nextDisjunctiveResult++;\n });\n });\n\n // add the excludes\n Object.keys(state.facetsExcludes).forEach(function (facetName) {\n var excludes = state.facetsExcludes[facetName];\n var position = facetsIndices[facetName];\n\n self.facets[position] = {\n name: facetName,\n data: mainFacets[facetName],\n exhaustive: mainSubResponse.exhaustiveFacetsCount,\n };\n excludes.forEach(function (facetValue) {\n self.facets[position] = self.facets[position] || { name: facetName };\n self.facets[position].data = self.facets[position].data || {};\n self.facets[position].data[facetValue] = 0;\n });\n });\n\n /**\n * @type {Array}\n */\n this.hierarchicalFacets = this.hierarchicalFacets.map(\n generateHierarchicalTree(state)\n );\n\n /**\n * @type {Array}\n */\n this.facets = compact(this.facets);\n /**\n * @type {Array}\n */\n this.disjunctiveFacets = compact(this.disjunctiveFacets);\n\n this._state = state;\n}\n\n/**\n * Get a facet object with its name\n * @deprecated\n * @param {string} name name of the faceted attribute\n * @return {SearchResults.Facet} the facet object\n */\nSearchResults.prototype.getFacetByName = function (name) {\n function predicate(facet) {\n return facet.name === name;\n }\n\n return (\n find(this.facets, predicate) ||\n find(this.disjunctiveFacets, predicate) ||\n find(this.hierarchicalFacets, predicate)\n );\n};\n\n/**\n * Get the facet values of a specified attribute from a SearchResults object.\n * @private\n * @param {SearchResults} results the search results to search in\n * @param {string} attribute name of the faceted attribute to search for\n * @return {array|object} facet values. For the hierarchical facets it is an object.\n */\nfunction extractNormalizedFacetValues(results, attribute) {\n function predicate(facet) {\n return facet.name === attribute;\n }\n\n if (results._state.isConjunctiveFacet(attribute)) {\n var facet = find(results.facets, predicate);\n if (!facet) return [];\n\n return Object.keys(facet.data).map(function (name) {\n var value = escapeFacetValue(name);\n return {\n name: name,\n escapedValue: value,\n count: facet.data[name],\n isRefined: results._state.isFacetRefined(attribute, value),\n isExcluded: results._state.isExcludeRefined(attribute, name),\n };\n });\n } else if (results._state.isDisjunctiveFacet(attribute)) {\n var disjunctiveFacet = find(results.disjunctiveFacets, predicate);\n if (!disjunctiveFacet) return [];\n\n return Object.keys(disjunctiveFacet.data).map(function (name) {\n var value = escapeFacetValue(name);\n return {\n name: name,\n escapedValue: value,\n count: disjunctiveFacet.data[name],\n isRefined: results._state.isDisjunctiveFacetRefined(attribute, value),\n };\n });\n } else if (results._state.isHierarchicalFacet(attribute)) {\n var hierarchicalFacetValues = find(results.hierarchicalFacets, predicate);\n if (!hierarchicalFacetValues) return hierarchicalFacetValues;\n\n var hierarchicalFacet =\n results._state.getHierarchicalFacetByName(attribute);\n var separator =\n results._state._getHierarchicalFacetSeparator(hierarchicalFacet);\n var currentRefinement = unescapeFacetValue(\n results._state.getHierarchicalRefinement(attribute)[0] || ''\n );\n\n if (currentRefinement.indexOf(hierarchicalFacet.rootPath) === 0) {\n currentRefinement = currentRefinement.replace(\n hierarchicalFacet.rootPath + separator,\n ''\n );\n }\n\n var currentRefinementSplit = currentRefinement.split(separator);\n currentRefinementSplit.unshift(attribute);\n\n setIsRefined(hierarchicalFacetValues, currentRefinementSplit, 0);\n\n return hierarchicalFacetValues;\n }\n\n return undefined;\n}\n\n/**\n * Set the isRefined of a hierarchical facet result based on the current state.\n * @param {SearchResults.HierarchicalFacet} item Hierarchical facet to fix\n * @param {string[]} currentRefinement array of parts of the current hierarchical refinement\n * @param {number} depth recursion depth in the currentRefinement\n * @return {undefined} function mutates the item\n */\nfunction setIsRefined(item, currentRefinement, depth) {\n item.isRefined =\n item.name === (currentRefinement[depth] && currentRefinement[depth].trim());\n if (item.data) {\n item.data.forEach(function (child) {\n setIsRefined(child, currentRefinement, depth + 1);\n });\n }\n}\n\n/**\n * Sort nodes of a hierarchical or disjunctive facet results\n * @private\n * @param {function} sortFn sort function to apply\n * @param {HierarchicalFacet|Array} node node upon which we want to apply the sort\n * @param {string[]} names attribute names\n * @param {number} [level=0] current index in the names array\n * @return {HierarchicalFacet|Array} sorted node\n */\nfunction recSort(sortFn, node, names, level) {\n level = level || 0;\n\n if (Array.isArray(node)) {\n return sortFn(node, names[level]);\n }\n\n if (!node.data || node.data.length === 0) {\n return node;\n }\n\n var children = node.data.map(function (childNode) {\n return recSort(sortFn, childNode, names, level + 1);\n });\n var sortedChildren = sortFn(children, names[level]);\n var newNode = defaultsPure({ data: sortedChildren }, node);\n return newNode;\n}\n\nSearchResults.DEFAULT_SORT = ['isRefined:desc', 'count:desc', 'name:asc'];\n\nfunction vanillaSortFn(order, data) {\n return data.sort(order);\n}\n\n/**\n * @typedef FacetOrdering\n * @type {Object}\n * @property {string[]} [order]\n * @property {'count' | 'alpha' | 'hidden'} [sortRemainingBy]\n */\n\n/**\n * Sorts facet arrays via their facet ordering\n * @param {Array} facetValues the values\n * @param {FacetOrdering} facetOrdering the ordering\n * @returns {Array} the sorted facet values\n */\nfunction sortViaFacetOrdering(facetValues, facetOrdering) {\n var orderedFacets = [];\n var remainingFacets = [];\n var hide = facetOrdering.hide || [];\n var order = facetOrdering.order || [];\n\n /**\n * an object with the keys being the values in order, the values their index:\n * ['one', 'two'] -> { one: 0, two: 1 }\n */\n var reverseOrder = order.reduce(function (acc, name, i) {\n acc[name] = i;\n return acc;\n }, {});\n\n facetValues.forEach(function (item) {\n // hierarchical facets get sorted using their raw name\n var name = item.path || item.name;\n var hidden = hide.indexOf(name) > -1;\n if (!hidden && reverseOrder[name] !== undefined) {\n orderedFacets[reverseOrder[name]] = item;\n } else if (!hidden) {\n remainingFacets.push(item);\n }\n });\n\n orderedFacets = orderedFacets.filter(function (facet) {\n return facet;\n });\n\n var sortRemainingBy = facetOrdering.sortRemainingBy;\n var ordering;\n if (sortRemainingBy === 'hidden') {\n return orderedFacets;\n } else if (sortRemainingBy === 'alpha') {\n ordering = [\n ['path', 'name'],\n ['asc', 'asc'],\n ];\n } else {\n ordering = [['count'], ['desc']];\n }\n\n return orderedFacets.concat(\n orderBy(remainingFacets, ordering[0], ordering[1])\n );\n}\n\n/**\n * @param {SearchResults} results the search results class\n * @param {string} attribute the attribute to retrieve ordering of\n * @returns {FacetOrdering | undefined} the facet ordering\n */\nfunction getFacetOrdering(results, attribute) {\n return (\n results.renderingContent &&\n results.renderingContent.facetOrdering &&\n results.renderingContent.facetOrdering.values &&\n results.renderingContent.facetOrdering.values[attribute]\n );\n}\n\n/**\n * Get a the list of values for a given facet attribute. Those values are sorted\n * refinement first, descending count (bigger value on top), and name ascending\n * (alphabetical order). The sort formula can overridden using either string based\n * predicates or a function.\n *\n * This method will return all the values returned by the Algolia engine plus all\n * the values already refined. This means that it can happen that the\n * `maxValuesPerFacet` [configuration](https://www.algolia.com/doc/rest-api/search#param-maxValuesPerFacet)\n * might not be respected if you have facet values that are already refined.\n * @param {string} attribute attribute name\n * @param {object} opts configuration options.\n * @param {boolean} [opts.facetOrdering]\n * Force the use of facetOrdering from the result if a sortBy is present. If\n * sortBy isn't present, facetOrdering will be used automatically.\n * @param {Array.<string> | function} opts.sortBy\n * When using strings, it consists of\n * the name of the [FacetValue](#SearchResults.FacetValue) or the\n * [HierarchicalFacet](#SearchResults.HierarchicalFacet) attributes with the\n * order (`asc` or `desc`). For example to order the value by count, the\n * argument would be `['count:asc']`.\n *\n * If only the attribute name is specified, the ordering defaults to the one\n * specified in the default value for this attribute.\n *\n * When not specified, the order is\n * ascending. This parameter can also be a function which takes two facet\n * values and should return a number, 0 if equal, 1 if the first argument is\n * bigger or -1 otherwise.\n *\n * The default value for this attribute `['isRefined:desc', 'count:desc', 'name:asc']`\n * @return {FacetValue[]|HierarchicalFacet|undefined} depending on the type of facet of\n * the attribute requested (hierarchical, disjunctive or conjunctive)\n * @example\n * helper.on('result', function(event){\n * //get values ordered only by name ascending using the string predicate\n * event.results.getFacetValues('city', {sortBy: ['name:asc']});\n * //get values ordered only by count ascending using a function\n * event.results.getFacetValues('city', {\n * // this is equivalent to ['count:asc']\n * sortBy: function(a, b) {\n * if (a.count === b.count) return 0;\n * if (a.count > b.count) return 1;\n * if (b.count > a.count) return -1;\n * }\n * });\n * });\n */\nSearchResults.prototype.getFacetValues = function (attribute, opts) {\n var facetValues = extractNormalizedFacetValues(this, attribute);\n if (!facetValues) {\n return undefined;\n }\n\n var options = defaultsPure({}, opts, {\n sortBy: SearchResults.DEFAULT_SORT,\n // if no sortBy is given, attempt to sort based on facetOrdering\n // if it is given, we still allow to sort via facet ordering first\n facetOrdering: !(opts && opts.sortBy),\n });\n\n // eslint-disable-next-line consistent-this\n var results = this;\n var attributes;\n if (Array.isArray(facetValues)) {\n attributes = [attribute];\n } else {\n var config = results._state.getHierarchicalFacetByName(facetValues.name);\n attributes = config.attributes;\n }\n\n return recSort(\n function (data, facetName) {\n if (options.facetOrdering) {\n var facetOrdering = getFacetOrdering(results, facetName);\n if (facetOrdering) {\n return sortViaFacetOrdering(data, facetOrdering);\n }\n }\n\n if (Array.isArray(options.sortBy)) {\n var order = formatSort(options.sortBy, SearchResults.DEFAULT_SORT);\n return orderBy(data, order[0], order[1]);\n } else if (typeof options.sortBy === 'function') {\n return vanillaSortFn(options.sortBy, data);\n }\n throw new Error(\n 'options.sortBy is optional but if defined it must be ' +\n 'either an array of string (predicates) or a sorting function'\n );\n },\n facetValues,\n attributes\n );\n};\n\n/**\n * Returns the facet stats if attribute is defined and the facet contains some.\n * Otherwise returns undefined.\n * @param {string} attribute name of the faceted attribute\n * @return {object} The stats of the facet\n */\nSearchResults.prototype.getFacetStats = function (attribute) {\n if (this._state.isConjunctiveFacet(attribute)) {\n return getFacetStatsIfAvailable(this.facets, attribute);\n } else if (this._state.isDisjunctiveFacet(attribute)) {\n return getFacetStatsIfAvailable(this.disjunctiveFacets, attribute);\n }\n\n return undefined;\n};\n\n/**\n * @typedef {Object} FacetListItem\n * @property {string} name\n */\n\n/**\n * @param {FacetListItem[]} facetList (has more items, but enough for here)\n * @param {string} facetName The attribute to look for\n * @return {object|undefined} The stats of the facet\n */\nfunction getFacetStatsIfAvailable(facetList, facetName) {\n var data = find(facetList, function (facet) {\n return facet.name === facetName;\n });\n return data && data.stats;\n}\n\n/**\n * Returns all refinements for all filters + tags. It also provides\n * additional information: count and exhaustiveness for each filter.\n *\n * See the [refinement type](#Refinement) for an exhaustive view of the available\n * data.\n *\n * Note that for a numeric refinement, results are grouped per operator, this\n * means that it will return responses for operators which are empty.\n *\n * @return {Array.<Refinement>} all the refinements\n */\nSearchResults.prototype.getRefinements = function () {\n var state = this._state;\n // eslint-disable-next-line consistent-this\n var results = this;\n var res = [];\n\n Object.keys(state.facetsRefinements).forEach(function (attributeName) {\n state.facetsRefinements[attributeName].forEach(function (name) {\n res.push(\n getRefinement(state, 'facet', attributeName, name, results.facets)\n );\n });\n });\n\n Object.keys(state.facetsExcludes).forEach(function (attributeName) {\n state.facetsExcludes[attributeName].forEach(function (name) {\n res.push(\n getRefinement(state, 'exclude', attributeName, name, results.facets)\n );\n });\n });\n\n Object.keys(state.disjunctiveFacetsRefinements).forEach(function (\n attributeName\n ) {\n state.disjunctiveFacetsRefinements[attributeName].forEach(function (name) {\n res.push(\n getRefinement(\n state,\n 'disjunctive',\n attributeName,\n name,\n results.disjunctiveFacets\n )\n );\n });\n });\n\n Object.keys(state.hierarchicalFacetsRefinements).forEach(function (\n attributeName\n ) {\n state.hierarchicalFacetsRefinements[attributeName].forEach(function (name) {\n res.push(\n getHierarchicalRefinement(\n state,\n attributeName,\n name,\n results.hierarchicalFacets\n )\n );\n });\n });\n\n Object.keys(state.numericRefinements).forEach(function (attributeName) {\n var operators = state.numericRefinements[attributeName];\n Object.keys(operators).forEach(function (operator) {\n operators[operator].forEach(function (value) {\n res.push({\n type: 'numeric',\n attributeName: attributeName,\n name: value,\n numericValue: value,\n operator: operator,\n });\n });\n });\n });\n\n state.tagRefinements.forEach(function (name) {\n res.push({ type: 'tag', attributeName: '_tags', name: name });\n });\n\n return res;\n};\n\n/**\n * @typedef {Object} Facet\n * @property {string} name\n * @property {Object} data\n * @property {boolean} exhaustive\n */\n\n/**\n * @param {SearchParameters} state the current state\n * @param {string} type the type of the refinement\n * @param {string} attributeName The attribute of the facet\n * @param {*} name The name of the facet\n * @param {Facet[]} resultsFacets facets from the results\n * @return {Refinement} the refinement\n */\nfunction getRefinement(state, type, attributeName, name, resultsFacets) {\n var facet = find(resultsFacets, function (f) {\n return f.name === attributeName;\n });\n var count = facet && facet.data && facet.data[name] ? facet.data[name] : 0;\n var exhaustive = (facet && facet.exhaustive) || false;\n\n return {\n type: type,\n attributeName: attributeName,\n name: name,\n count: count,\n exhaustive: exhaustive,\n };\n}\n\n/**\n * @param {SearchParameters} state the current state\n * @param {string} attributeName the attribute of the hierarchical facet\n * @param {string} name the name of the facet\n * @param {Facet[]} resultsFacets facets from the results\n * @return {HierarchicalFacet} the hierarchical facet\n */\nfunction getHierarchicalRefinement(state, attributeName, name, resultsFacets) {\n var facetDeclaration = state.getHierarchicalFacetByName(attributeName);\n var separator = state._getHierarchicalFacetSeparator(facetDeclaration);\n var split = name.split(separator);\n var rootFacet = find(resultsFacets, function (facet) {\n return facet.name === attributeName;\n });\n\n var facet = split.reduce(function (intermediateFacet, part) {\n var newFacet =\n intermediateFacet &&\n find(intermediateFacet.data, function (f) {\n return f.name === part;\n });\n return newFacet !== undefined ? newFacet : intermediateFacet;\n }, rootFacet);\n\n var count = (facet && facet.count) || 0;\n var exhaustive = (facet && facet.exhaustive) || false;\n var path = (facet && facet.path) || '';\n\n return {\n type: 'hierarchical',\n attributeName: attributeName,\n name: path,\n count: count,\n exhaustive: exhaustive,\n };\n}\n\nmodule.exports = SearchResults;\n","'use strict';\n\nvar EventEmitter = require('@algolia/events');\n\nvar DerivedHelper = require('./DerivedHelper');\nvar escapeFacetValue = require('./functions/escapeFacetValue').escapeFacetValue;\nvar inherits = require('./functions/inherits');\nvar merge = require('./functions/merge');\nvar objectHasKeys = require('./functions/objectHasKeys');\nvar omit = require('./functions/omit');\nvar RecommendParameters = require('./RecommendParameters');\nvar RecommendResults = require('./RecommendResults');\nvar requestBuilder = require('./requestBuilder');\nvar SearchParameters = require('./SearchParameters');\nvar SearchResults = require('./SearchResults');\nvar sortAndMergeRecommendations = require('./utils/sortAndMergeRecommendations');\nvar version = require('./version');\n\n/**\n * Event triggered when a parameter is set or updated\n * @event AlgoliaSearchHelper#event:change\n * @property {object} event\n * @property {SearchParameters} event.state the current parameters with the latest changes applied\n * @property {SearchResults} event.results the previous results received from Algolia. `null` before the first request\n * @example\n * helper.on('change', function(event) {\n * console.log('The parameters have changed');\n * });\n */\n\n/**\n * Event triggered when a main search is sent to Algolia\n * @event AlgoliaSearchHelper#event:search\n * @property {object} event\n * @property {SearchParameters} event.state the parameters used for this search\n * @property {SearchResults} event.results the results from the previous search. `null` if it is the first search.\n * @example\n * helper.on('search', function(event) {\n * console.log('Search sent');\n * });\n */\n\n/**\n * Event triggered when a search using `searchForFacetValues` is sent to Algolia\n * @event AlgoliaSearchHelper#event:searchForFacetValues\n * @property {object} event\n * @property {SearchParameters} event.state the parameters used for this search it is the first search.\n * @property {string} event.facet the facet searched into\n * @property {string} event.query the query used to search in the facets\n * @example\n * helper.on('searchForFacetValues', function(event) {\n * console.log('searchForFacetValues sent');\n * });\n */\n\n/**\n * Event triggered when a search using `searchOnce` is sent to Algolia\n * @event AlgoliaSearchHelper#event:searchOnce\n * @property {object} event\n * @property {SearchParameters} event.state the parameters used for this search it is the first search.\n * @example\n * helper.on('searchOnce', function(event) {\n * console.log('searchOnce sent');\n * });\n */\n\n/**\n * Event triggered when the results are retrieved from Algolia\n * @event AlgoliaSearchHelper#event:result\n * @property {object} event\n * @property {SearchResults} event.results the results received from Algolia\n * @property {SearchParameters} event.state the parameters used to query Algolia. Those might be different from the one in the helper instance (for example if the network is unreliable).\n * @example\n * helper.on('result', function(event) {\n * console.log('Search results received');\n * });\n */\n\n/**\n * Event triggered when Algolia sends back an error. For example, if an unknown parameter is\n * used, the error can be caught using this event.\n * @event AlgoliaSearchHelper#event:error\n * @property {object} event\n * @property {Error} event.error the error returned by the Algolia.\n * @example\n * helper.on('error', function(event) {\n * console.log('Houston we got a problem.');\n * });\n */\n\n/**\n * Event triggered when the queue of queries have been depleted (with any result or outdated queries)\n * @event AlgoliaSearchHelper#event:searchQueueEmpty\n * @example\n * helper.on('searchQueueEmpty', function() {\n * console.log('No more search pending');\n * // This is received before the result event if we're not expecting new results\n * });\n *\n * helper.search();\n */\n\n/**\n * Initialize a new AlgoliaSearchHelper\n * @class\n * @classdesc The AlgoliaSearchHelper is a class that ease the management of the\n * search. It provides an event based interface for search callbacks:\n * - change: when the internal search state is changed.\n * This event contains a {@link SearchParameters} object and the\n * {@link SearchResults} of the last result if any.\n * - search: when a search is triggered using the `search()` method.\n * - result: when the response is retrieved from Algolia and is processed.\n * This event contains a {@link SearchResults} object and the\n * {@link SearchParameters} corresponding to this answer.\n * - error: when the response is an error. This event contains the error returned by the server.\n * @param {AlgoliaSearch} client an AlgoliaSearch client\n * @param {string} index the index name to query\n * @param {SearchParameters | object} options an object defining the initial\n * config of the search. It doesn't have to be a {SearchParameters},\n * just an object containing the properties you need from it.\n * @param {SearchResultsOptions|object} searchResultsOptions an object defining the options to use when creating the search results.\n */\nfunction AlgoliaSearchHelper(client, index, options, searchResultsOptions) {\n if (typeof client.addAlgoliaAgent === 'function') {\n client.addAlgoliaAgent('JS Helper (' + version + ')');\n }\n\n this.setClient(client);\n var opts = options || {};\n opts.index = index;\n this.state = SearchParameters.make(opts);\n this.recommendState = new RecommendParameters({\n params: opts.recommendState,\n });\n this.lastResults = null;\n this.lastRecommendResults = null;\n this._queryId = 0;\n this._recommendQueryId = 0;\n this._lastQueryIdReceived = -1;\n this._lastRecommendQueryIdReceived = -1;\n this.derivedHelpers = [];\n this._currentNbQueries = 0;\n this._currentNbRecommendQueries = 0;\n this._searchResultsOptions = searchResultsOptions;\n this._recommendCache = {};\n}\n\ninherits(AlgoliaSearchHelper, EventEmitter);\n\n/**\n * Start the search with the parameters set in the state. When the\n * method is called, it triggers a `search` event. The results will\n * be available through the `result` event. If an error occurs, an\n * `error` will be fired instead.\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires search\n * @fires result\n * @fires error\n * @chainable\n */\nAlgoliaSearchHelper.prototype.search = function () {\n this._search({ onlyWithDerivedHelpers: false });\n return this;\n};\n\nAlgoliaSearchHelper.prototype.searchOnlyWithDerivedHelpers = function () {\n this._search({ onlyWithDerivedHelpers: true });\n return this;\n};\n\n/**\n * Sends the recommendation queries set in the state. When the method is\n * called, it triggers a `fetch` event. The results will be available through\n * the `result` event. If an error occurs, an `error` will be fired instead.\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires fetch\n * @fires result\n * @fires error\n * @chainable\n */\nAlgoliaSearchHelper.prototype.recommend = function () {\n this._recommend();\n return this;\n};\n\n/**\n * Gets the search query parameters that would be sent to the Algolia Client\n * for the hits\n * @return {object} Query Parameters\n */\nAlgoliaSearchHelper.prototype.getQuery = function () {\n var state = this.state;\n return requestBuilder._getHitsSearchParams(state);\n};\n\n/**\n * Start a search using a modified version of the current state. This method does\n * not trigger the helper lifecycle and does not modify the state kept internally\n * by the helper. This second aspect means that the next search call will be the\n * same as a search call before calling searchOnce.\n * @param {object} options can contain all the parameters that can be set to SearchParameters\n * plus the index\n * @param {function} [cb] optional callback executed when the response from the\n * server is back.\n * @return {promise|undefined} if a callback is passed the method returns undefined\n * otherwise it returns a promise containing an object with two keys :\n * - content with a SearchResults\n * - state with the state used for the query as a SearchParameters\n * @example\n * // Changing the number of records returned per page to 1\n * // This example uses the callback API\n * var state = helper.searchOnce({hitsPerPage: 1},\n * function(error, content, state) {\n * // if an error occurred it will be passed in error, otherwise its value is null\n * // content contains the results formatted as a SearchResults\n * // state is the instance of SearchParameters used for this search\n * });\n * @example\n * // Changing the number of records returned per page to 1\n * // This example uses the promise API\n * var state1 = helper.searchOnce({hitsPerPage: 1})\n * .then(promiseHandler);\n *\n * function promiseHandler(res) {\n * // res contains\n * // {\n * // content : SearchResults\n * // state : SearchParameters (the one used for this specific search)\n * // }\n * }\n */\nAlgoliaSearchHelper.prototype.searchOnce = function (options, cb) {\n var tempState = !options\n ? this.state\n : this.state.setQueryParameters(options);\n var queries = requestBuilder._getQueries(tempState.index, tempState);\n // eslint-disable-next-line consistent-this\n var self = this;\n\n this._currentNbQueries++;\n\n this.emit('searchOnce', {\n state: tempState,\n });\n\n if (cb) {\n this.client\n .search(queries)\n .then(function (content) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) {\n self.emit('searchQueueEmpty');\n }\n\n cb(null, new SearchResults(tempState, content.results), tempState);\n })\n .catch(function (err) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) {\n self.emit('searchQueueEmpty');\n }\n\n cb(err, null, tempState);\n });\n\n return undefined;\n }\n\n return this.client.search(queries).then(\n function (content) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');\n return {\n content: new SearchResults(tempState, content.results),\n state: tempState,\n _originalResponse: content,\n };\n },\n function (e) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');\n throw e;\n }\n );\n};\n\n/**\n * Start the search for answers with the parameters set in the state.\n * This method returns a promise.\n * @param {Object} options - the options for answers API call\n * @param {string[]} options.attributesForPrediction - Attributes to use for predictions. If empty, `searchableAttributes` is used instead.\n * @param {string[]} options.queryLanguages - The languages in the query. Currently only supports ['en'].\n * @param {number} options.nbHits - Maximum number of answers to retrieve from the Answers Engine. Cannot be greater than 1000.\n *\n * @return {promise} the answer results\n * @deprecated answers is deprecated and will be replaced with new initiatives\n */\nAlgoliaSearchHelper.prototype.findAnswers = function (options) {\n // eslint-disable-next-line no-console\n console.warn('[algoliasearch-helper] answers is no longer supported');\n var state = this.state;\n var derivedHelper = this.derivedHelpers[0];\n if (!derivedHelper) {\n return Promise.resolve([]);\n }\n var derivedState = derivedHelper.getModifiedState(state);\n var data = merge(\n {\n attributesForPrediction: options.attributesForPrediction,\n nbHits: options.nbHits,\n },\n {\n params: omit(requestBuilder._getHitsSearchParams(derivedState), [\n 'attributesToSnippet',\n 'hitsPerPage',\n 'restrictSearchableAttributes',\n 'snippetEllipsisText',\n ]),\n }\n );\n\n var errorMessage =\n 'search for answers was called, but this client does not have a function client.initIndex(index).findAnswers';\n if (typeof this.client.initIndex !== 'function') {\n throw new Error(errorMessage);\n }\n var index = this.client.initIndex(derivedState.index);\n if (typeof index.findAnswers !== 'function') {\n throw new Error(errorMessage);\n }\n return index.findAnswers(derivedState.query, options.queryLanguages, data);\n};\n\n/**\n * Structure of each result when using\n * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues)\n * @typedef FacetSearchHit\n * @type {object}\n * @property {string} value the facet value\n * @property {string} highlighted the facet value highlighted with the query string\n * @property {number} count number of occurrence of this facet value\n * @property {boolean} isRefined true if the value is already refined\n */\n\n/**\n * Structure of the data resolved by the\n * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues)\n * promise.\n * @typedef FacetSearchResult\n * @type {object}\n * @property {FacetSearchHit} facetHits the results for this search for facet values\n * @property {number} processingTimeMS time taken by the query inside the engine\n */\n\n/**\n * Search for facet values based on an query and the name of a faceted attribute. This\n * triggers a search and will return a promise. On top of using the query, it also sends\n * the parameters from the state so that the search is narrowed down to only the possible values.\n *\n * See the description of [FacetSearchResult](reference.html#FacetSearchResult)\n * @param {string} facet the name of the faceted attribute\n * @param {string} query the string query for the search\n * @param {number} [maxFacetHits] the maximum number values returned. Should be > 0 and <= 100\n * @param {object} [userState] the set of custom parameters to use on top of the current state. Setting a property to `undefined` removes\n * it in the generated query.\n * @return {promise.<FacetSearchResult>} the results of the search\n */\nAlgoliaSearchHelper.prototype.searchForFacetValues = function (\n facet,\n query,\n maxFacetHits,\n userState\n) {\n var clientHasSFFV = typeof this.client.searchForFacetValues === 'function';\n var clientHasInitIndex = typeof this.client.initIndex === 'function';\n if (\n !clientHasSFFV &&\n !clientHasInitIndex &&\n typeof this.client.search !== 'function'\n ) {\n throw new Error(\n 'search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues'\n );\n }\n\n var state = this.state.setQueryParameters(userState || {});\n var isDisjunctive = state.isDisjunctiveFacet(facet);\n var algoliaQuery = requestBuilder.getSearchForFacetQuery(\n facet,\n query,\n maxFacetHits,\n state\n );\n\n this._currentNbQueries++;\n // eslint-disable-next-line consistent-this\n var self = this;\n var searchForFacetValuesPromise;\n // newer algoliasearch ^3.27.1 - ~4.0.0\n if (clientHasSFFV) {\n searchForFacetValuesPromise = this.client.searchForFacetValues([\n { indexName: state.index, params: algoliaQuery },\n ]);\n // algoliasearch < 3.27.1\n } else if (clientHasInitIndex) {\n searchForFacetValuesPromise = this.client\n .initIndex(state.index)\n .searchForFacetValues(algoliaQuery);\n // algoliasearch ~5.0.0\n } else {\n // @MAJOR only use client.search\n delete algoliaQuery.facetName;\n searchForFacetValuesPromise = this.client\n .search([\n {\n type: 'facet',\n facet: facet,\n indexName: state.index,\n params: algoliaQuery,\n },\n ])\n .then(function processResponse(response) {\n return response.results[0];\n });\n }\n\n this.emit('searchForFacetValues', {\n state: state,\n facet: facet,\n query: query,\n });\n\n return searchForFacetValuesPromise.then(\n function addIsRefined(content) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');\n\n content = Array.isArray(content) ? content[0] : content;\n\n content.facetHits.forEach(function (f) {\n f.escapedValue = escapeFacetValue(f.value);\n f.isRefined = isDisjunctive\n ? state.isDisjunctiveFacetRefined(facet, f.escapedValue)\n : state.isFacetRefined(facet, f.escapedValue);\n });\n\n return content;\n },\n function (e) {\n self._currentNbQueries--;\n if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');\n throw e;\n }\n );\n};\n\n/**\n * Sets the text query used for the search.\n *\n * This method resets the current page to 0.\n * @param {string} q the user query\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.setQuery = function (q) {\n this._change({\n state: this.state.resetPage().setQuery(q),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Remove all the types of refinements except tags. A string can be provided to remove\n * only the refinements of a specific attribute. For more advanced use case, you can\n * provide a function instead. This function should follow the\n * [clearCallback definition](#SearchParameters.clearCallback).\n *\n * This method resets the current page to 0.\n * @param {string} [name] optional name of the facet / attribute on which we want to remove all refinements\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n * @example\n * // Removing all the refinements\n * helper.clearRefinements().search();\n * @example\n * // Removing all the filters on a the category attribute.\n * helper.clearRefinements('category').search();\n * @example\n * // Removing only the exclude filters on the category facet.\n * helper.clearRefinements(function(value, attribute, type) {\n * return type === 'exclude' && attribute === 'category';\n * }).search();\n */\nAlgoliaSearchHelper.prototype.clearRefinements = function (name) {\n this._change({\n state: this.state.resetPage().clearRefinements(name),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Remove all the tag filters.\n *\n * This method resets the current page to 0.\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.clearTags = function () {\n this._change({\n state: this.state.resetPage().clearTags(),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Adds a disjunctive filter to a faceted attribute with the `value` provided. If the\n * filter is already set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value (will be converted to string)\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addDisjunctiveFacetRefinement = function (\n facet,\n value\n) {\n this._change({\n state: this.state.resetPage().addDisjunctiveFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addDisjunctiveFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.addDisjunctiveRefine = function () {\n return this.addDisjunctiveFacetRefinement.apply(this, arguments);\n};\n\n/**\n * Adds a refinement on a hierarchical facet. It will throw\n * an exception if the facet is not defined or if the facet\n * is already refined.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet name\n * @param {string} path the hierarchical facet path\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @throws Error if the facet is not defined or if the facet is refined\n * @chainable\n * @fires change\n */\nAlgoliaSearchHelper.prototype.addHierarchicalFacetRefinement = function (\n facet,\n path\n) {\n this._change({\n state: this.state.resetPage().addHierarchicalFacetRefinement(facet, path),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Adds a an numeric filter to an attribute with the `operator` and `value` provided. If the\n * filter is already set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} attribute the attribute on which the numeric filter applies\n * @param {string} operator the operator of the filter\n * @param {number} value the value of the filter\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addNumericRefinement = function (\n attribute,\n operator,\n value\n) {\n this._change({\n state: this.state\n .resetPage()\n .addNumericRefinement(attribute, operator, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Adds a filter to a faceted attribute with the `value` provided. If the\n * filter is already set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value (will be converted to string)\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addFacetRefinement = function (facet, value) {\n this._change({\n state: this.state.resetPage().addFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.addRefine = function () {\n return this.addFacetRefinement.apply(this, arguments);\n};\n\n/**\n * Adds a an exclusion filter to a faceted attribute with the `value` provided. If the\n * filter is already set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value (will be converted to string)\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addFacetExclusion = function (facet, value) {\n this._change({\n state: this.state.resetPage().addExcludeRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetExclusion}\n */\nAlgoliaSearchHelper.prototype.addExclude = function () {\n return this.addFacetExclusion.apply(this, arguments);\n};\n\n/**\n * Adds a tag filter with the `tag` provided. If the\n * filter is already set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} tag the tag to add to the filter\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addTag = function (tag) {\n this._change({\n state: this.state.resetPage().addTagRefinement(tag),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Adds a \"frequently bought together\" recommendation query.\n *\n * @param {FrequentlyBoughtTogetherQuery} params the parameters for the recommendation\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addFrequentlyBoughtTogether = function (params) {\n this._recommendChange({\n state: this.recommendState.addFrequentlyBoughtTogether(params),\n });\n\n return this;\n};\n\n/**\n * Adds a \"related products\" recommendation query.\n *\n * @param {RelatedProductsQuery} params the parameters for the recommendation\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addRelatedProducts = function (params) {\n this._recommendChange({\n state: this.recommendState.addRelatedProducts(params),\n });\n\n return this;\n};\n\n/**\n * Adds a \"trending items\" recommendation query.\n *\n * @param {TrendingItemsQuery} params the parameters for the recommendation\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addTrendingItems = function (params) {\n this._recommendChange({\n state: this.recommendState.addTrendingItems(params),\n });\n\n return this;\n};\n\n/**\n * Adds a \"trending facets\" recommendation query.\n *\n * @param {TrendingFacetsQuery} params the parameters for the recommendation\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addTrendingFacets = function (params) {\n this._recommendChange({\n state: this.recommendState.addTrendingFacets(params),\n });\n\n return this;\n};\n\n/**\n * Adds a \"looking similar\" recommendation query.\n *\n * @param {LookingSimilarQuery} params the parameters for the recommendation\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.addLookingSimilar = function (params) {\n this._recommendChange({\n state: this.recommendState.addLookingSimilar(params),\n });\n\n return this;\n};\n\n/**\n * Removes an numeric filter to an attribute with the `operator` and `value` provided. If the\n * filter is not set, it doesn't change the filters.\n *\n * Some parameters are optional, triggering different behavior:\n * - if the value is not provided, then all the numeric value will be removed for the\n * specified attribute/operator couple.\n * - if the operator is not provided either, then all the numeric filter on this attribute\n * will be removed.\n *\n * This method resets the current page to 0.\n * @param {string} attribute the attribute on which the numeric filter applies\n * @param {string} [operator] the operator of the filter\n * @param {number} [value] the value of the filter\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeNumericRefinement = function (\n attribute,\n operator,\n value\n) {\n this._change({\n state: this.state\n .resetPage()\n .removeNumericRefinement(attribute, operator, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Removes a disjunctive filter to a faceted attribute with the `value` provided. If the\n * filter is not set, it doesn't change the filters.\n *\n * If the value is omitted, then this method will remove all the filters for the\n * attribute.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} [value] the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeDisjunctiveFacetRefinement = function (\n facet,\n value\n) {\n this._change({\n state: this.state\n .resetPage()\n .removeDisjunctiveFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeDisjunctiveFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.removeDisjunctiveRefine = function () {\n return this.removeDisjunctiveFacetRefinement.apply(this, arguments);\n};\n\n/**\n * Removes the refinement set on a hierarchical facet.\n * @param {string} facet the facet name\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @throws Error if the facet is not defined or if the facet is not refined\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeHierarchicalFacetRefinement = function (\n facet\n) {\n this._change({\n state: this.state.resetPage().removeHierarchicalFacetRefinement(facet),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Removes a filter to a faceted attribute with the `value` provided. If the\n * filter is not set, it doesn't change the filters.\n *\n * If the value is omitted, then this method will remove all the filters for the\n * attribute.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} [value] the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeFacetRefinement = function (facet, value) {\n this._change({\n state: this.state.resetPage().removeFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.removeRefine = function () {\n return this.removeFacetRefinement.apply(this, arguments);\n};\n\n/**\n * Removes an exclusion filter to a faceted attribute with the `value` provided. If the\n * filter is not set, it doesn't change the filters.\n *\n * If the value is omitted, then this method will remove all the filters for the\n * attribute.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} [value] the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeFacetExclusion = function (facet, value) {\n this._change({\n state: this.state.resetPage().removeExcludeRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetExclusion}\n */\nAlgoliaSearchHelper.prototype.removeExclude = function () {\n return this.removeFacetExclusion.apply(this, arguments);\n};\n\n/**\n * Removes a tag filter with the `tag` provided. If the\n * filter is not set, it doesn't change the filters.\n *\n * This method resets the current page to 0.\n * @param {string} tag tag to remove from the filter\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeTag = function (tag) {\n this._change({\n state: this.state.resetPage().removeTagRefinement(tag),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Removes a \"frequently bought together\" recommendation query.\n *\n * @param {number} id identifier of the recommendation widget\n * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeFrequentlyBoughtTogether = function (id) {\n this._recommendChange({\n state: this.recommendState.removeParams(id),\n });\n\n return this;\n};\n\n/**\n * Removes a \"related products\" recommendation query.\n *\n * @param {number} id identifier of the recommendation widget\n * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeRelatedProducts = function (id) {\n this._recommendChange({\n state: this.recommendState.removeParams(id),\n });\n\n return this;\n};\n\n/**\n * Removes a \"trending items\" recommendation query.\n *\n * @param {number} id identifier of the recommendation widget\n * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeTrendingItems = function (id) {\n this._recommendChange({\n state: this.recommendState.removeParams(id),\n });\n\n return this;\n};\n\n/**\n * Removes a \"trending facets\" recommendation query.\n *\n * @param {number} id identifier of the recommendation widget\n * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeTrendingFacets = function (id) {\n this._recommendChange({\n state: this.recommendState.removeParams(id),\n });\n\n return this;\n};\n\n/**\n * Removes a \"looking similar\" recommendation query.\n *\n * @param {number} id identifier of the recommendation widget\n * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.removeLookingSimilar = function (id) {\n this._recommendChange({\n state: this.recommendState.removeParams(id),\n });\n\n return this;\n};\n\n/**\n * Adds or removes an exclusion filter to a faceted attribute with the `value` provided. If\n * the value is set then it removes it, otherwise it adds the filter.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.toggleFacetExclusion = function (facet, value) {\n this._change({\n state: this.state.resetPage().toggleExcludeFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetExclusion}\n */\nAlgoliaSearchHelper.prototype.toggleExclude = function () {\n return this.toggleFacetExclusion.apply(this, arguments);\n};\n\n/**\n * Adds or removes a filter to a faceted attribute with the `value` provided. If\n * the value is set then it removes it, otherwise it adds the filter.\n *\n * This method can be used for conjunctive, disjunctive and hierarchical filters.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @throws Error will throw an error if the facet is not declared in the settings of the helper\n * @fires change\n * @chainable\n * @deprecated since version 2.19.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.toggleRefinement = function (facet, value) {\n return this.toggleFacetRefinement(facet, value);\n};\n\n/**\n * Adds or removes a filter to a faceted attribute with the `value` provided. If\n * the value is set then it removes it, otherwise it adds the filter.\n *\n * This method can be used for conjunctive, disjunctive and hierarchical filters.\n *\n * This method resets the current page to 0.\n * @param {string} facet the facet to refine\n * @param {string} value the associated value\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @throws Error will throw an error if the facet is not declared in the settings of the helper\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.toggleFacetRefinement = function (facet, value) {\n this._change({\n state: this.state.resetPage().toggleFacetRefinement(facet, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement}\n */\nAlgoliaSearchHelper.prototype.toggleRefine = function () {\n return this.toggleFacetRefinement.apply(this, arguments);\n};\n\n/**\n * Adds or removes a tag filter with the `value` provided. If\n * the value is set then it removes it, otherwise it adds the filter.\n *\n * This method resets the current page to 0.\n * @param {string} tag tag to remove or add\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.toggleTag = function (tag) {\n this._change({\n state: this.state.resetPage().toggleTagRefinement(tag),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Increments the page number by one.\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n * @example\n * helper.setPage(0).nextPage().getPage();\n * // returns 1\n */\nAlgoliaSearchHelper.prototype.nextPage = function () {\n var page = this.state.page || 0;\n return this.setPage(page + 1);\n};\n\n/**\n * Decrements the page number by one.\n * @fires change\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @chainable\n * @example\n * helper.setPage(1).previousPage().getPage();\n * // returns 0\n */\nAlgoliaSearchHelper.prototype.previousPage = function () {\n var page = this.state.page || 0;\n return this.setPage(page - 1);\n};\n\n/**\n * @private\n * @param {number} page The page number\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @chainable\n * @fires change\n */\nfunction setCurrentPage(page) {\n if (page < 0) throw new Error('Page requested below 0.');\n\n this._change({\n state: this.state.setPage(page),\n isPageReset: false,\n });\n\n return this;\n}\n\n/**\n * Change the current page\n * @deprecated\n * @param {number} page The page number\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.setCurrentPage = setCurrentPage;\n\n/**\n * Updates the current page.\n * @function\n * @param {number} page The page number\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.setPage = setCurrentPage;\n\n/**\n * Updates the name of the index that will be targeted by the query.\n *\n * This method resets the current page to 0.\n * @param {string} name the index name\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.setIndex = function (name) {\n this._change({\n state: this.state.resetPage().setIndex(name),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Update a parameter of the search. This method reset the page\n *\n * The complete list of parameters is available on the\n * [Algolia website](https://www.algolia.com/doc/rest#query-an-index).\n * The most commonly used parameters have their own [shortcuts](#query-parameters-shortcuts)\n * or benefit from higher-level APIs (all the kind of filters and facets have their own API)\n *\n * This method resets the current page to 0.\n * @param {string} parameter name of the parameter to update\n * @param {any} value new value of the parameter\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n * @example\n * helper.setQueryParameter('hitsPerPage', 20).search();\n */\nAlgoliaSearchHelper.prototype.setQueryParameter = function (parameter, value) {\n this._change({\n state: this.state.resetPage().setQueryParameter(parameter, value),\n isPageReset: true,\n });\n\n return this;\n};\n\n/**\n * Set the whole state (warning: will erase previous state)\n * @param {SearchParameters} newState the whole new state\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @fires change\n * @chainable\n */\nAlgoliaSearchHelper.prototype.setState = function (newState) {\n this._change({\n state: SearchParameters.make(newState),\n isPageReset: false,\n });\n\n return this;\n};\n\n/**\n * Override the current state without triggering a change event.\n * Do not use this method unless you know what you are doing. (see the example\n * for a legit use case)\n * @param {SearchParameters} newState the whole new state\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n * @example\n * helper.on('change', function(state){\n * // In this function you might want to find a way to store the state in the url/history\n * updateYourURL(state)\n * })\n * window.onpopstate = function(event){\n * // This is naive though as you should check if the state is really defined etc.\n * helper.overrideStateWithoutTriggeringChangeEvent(event.state).search()\n * }\n * @chainable\n */\nAlgoliaSearchHelper.prototype.overrideStateWithoutTriggeringChangeEvent =\n function (newState) {\n this.state = new SearchParameters(newState);\n return this;\n };\n\n/**\n * Check if an attribute has any numeric, conjunctive, disjunctive or hierarchical filters.\n * @param {string} attribute the name of the attribute\n * @return {boolean} true if the attribute is filtered by at least one value\n * @example\n * // hasRefinements works with numeric, conjunctive, disjunctive and hierarchical filters\n * helper.hasRefinements('price'); // false\n * helper.addNumericRefinement('price', '>', 100);\n * helper.hasRefinements('price'); // true\n *\n * helper.hasRefinements('color'); // false\n * helper.addFacetRefinement('color', 'blue');\n * helper.hasRefinements('color'); // true\n *\n * helper.hasRefinements('material'); // false\n * helper.addDisjunctiveFacetRefinement('material', 'plastic');\n * helper.hasRefinements('material'); // true\n *\n * helper.hasRefinements('categories'); // false\n * helper.toggleFacetRefinement('categories', 'kitchen > knife');\n * helper.hasRefinements('categories'); // true\n *\n */\nAlgoliaSearchHelper.prototype.hasRefinements = function (attribute) {\n if (objectHasKeys(this.state.getNumericRefinements(attribute))) {\n return true;\n } else if (this.state.isConjunctiveFacet(attribute)) {\n return this.state.isFacetRefined(attribute);\n } else if (this.state.isDisjunctiveFacet(attribute)) {\n return this.state.isDisjunctiveFacetRefined(attribute);\n } else if (this.state.isHierarchicalFacet(attribute)) {\n return this.state.isHierarchicalFacetRefined(attribute);\n }\n\n // there's currently no way to know that the user did call `addNumericRefinement` at some point\n // thus we cannot distinguish if there once was a numeric refinement that was cleared\n // so we will return false in every other situations to be consistent\n // while what we should do here is throw because we did not find the attribute in any type\n // of refinement\n return false;\n};\n\n/**\n * Check if a value is excluded for a specific faceted attribute. If the value\n * is omitted then the function checks if there is any excluding refinements.\n *\n * @param {string} facet name of the attribute for used for faceting\n * @param {string} [value] optional value. If passed will test that this value\n * is filtering the given facet.\n * @return {boolean} true if refined\n * @example\n * helper.isExcludeRefined('color'); // false\n * helper.isExcludeRefined('color', 'blue') // false\n * helper.isExcludeRefined('color', 'red') // false\n *\n * helper.addFacetExclusion('color', 'red');\n *\n * helper.isExcludeRefined('color'); // true\n * helper.isExcludeRefined('color', 'blue') // false\n * helper.isExcludeRefined('color', 'red') // true\n */\nAlgoliaSearchHelper.prototype.isExcluded = function (facet, value) {\n return this.state.isExcludeRefined(facet, value);\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasRefinements}\n */\nAlgoliaSearchHelper.prototype.isDisjunctiveRefined = function (facet, value) {\n return this.state.isDisjunctiveFacetRefined(facet, value);\n};\n\n/**\n * Check if the string is a currently filtering tag.\n * @param {string} tag tag to check\n * @return {boolean} true if the tag is currently refined\n */\nAlgoliaSearchHelper.prototype.hasTag = function (tag) {\n return this.state.isTagRefined(tag);\n};\n\n// eslint-disable-next-line valid-jsdoc\n/**\n * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasTag}\n */\nAlgoliaSearchHelper.prototype.isTagRefined = function () {\n return this.hasTagRefinements.apply(this, arguments);\n};\n\n/**\n * Get the name of the currently used index.\n * @return {string} name of the index\n * @example\n * helper.setIndex('highestPrice_products').getIndex();\n * // returns 'highestPrice_products'\n */\nAlgoliaSearchHelper.prototype.getIndex = function () {\n return this.state.index;\n};\n\nfunction getCurrentPage() {\n return this.state.page;\n}\n\n/**\n * Get the currently selected page\n * @deprecated\n * @return {number} the current page\n */\nAlgoliaSearchHelper.prototype.getCurrentPage = getCurrentPage;\n/**\n * Get the currently selected page\n * @function\n * @return {number} the current page\n */\nAlgoliaSearchHelper.prototype.getPage = getCurrentPage;\n\n/**\n * Get all the tags currently set to filters the results.\n *\n * @return {string[]} The list of tags currently set.\n */\nAlgoliaSearchHelper.prototype.getTags = function () {\n return this.state.tagRefinements;\n};\n\n/**\n * Get the list of refinements for a given attribute. This method works with\n * conjunctive, disjunctive, excluding and numerical filters.\n *\n * See also SearchResults#getRefinements\n *\n * @param {string} facetName attribute name used for faceting\n * @return {Array.<FacetRefinement|NumericRefinement>} All Refinement are objects that contain a value, and\n * a type. Numeric also contains an operator.\n * @example\n * helper.addNumericRefinement('price', '>', 100);\n * helper.getRefinements('price');\n * // [\n * // {\n * // \"value\": [\n * // 100\n * // ],\n * // \"operator\": \">\",\n * // \"type\": \"numeric\"\n * // }\n * // ]\n * @example\n * helper.addFacetRefinement('color', 'blue');\n * helper.addFacetExclusion('color', 'red');\n * helper.getRefinements('color');\n * // [\n * // {\n * // \"value\": \"blue\",\n * // \"type\": \"conjunctive\"\n * // },\n * // {\n * // \"value\": \"red\",\n * // \"type\": \"exclude\"\n * // }\n * // ]\n * @example\n * helper.addDisjunctiveFacetRefinement('material', 'plastic');\n * // [\n * // {\n * // \"value\": \"plastic\",\n * // \"type\": \"disjunctive\"\n * // }\n * // ]\n */\nAlgoliaSearchHelper.prototype.getRefinements = function (facetName) {\n var refinements = [];\n\n if (this.state.isConjunctiveFacet(facetName)) {\n var conjRefinements = this.state.getConjunctiveRefinements(facetName);\n\n conjRefinements.forEach(function (r) {\n refinements.push({\n value: r,\n type: 'conjunctive',\n });\n });\n\n var excludeRefinements = this.state.getExcludeRefinements(facetName);\n\n excludeRefinements.forEach(function (r) {\n refinements.push({\n value: r,\n type: 'exclude',\n });\n });\n } else if (this.state.isDisjunctiveFacet(facetName)) {\n var disjunctiveRefinements =\n this.state.getDisjunctiveRefinements(facetName);\n\n disjunctiveRefinements.forEach(function (r) {\n refinements.push({\n value: r,\n type: 'disjunctive',\n });\n });\n }\n\n var numericRefinements = this.state.getNumericRefinements(facetName);\n\n Object.keys(numericRefinements).forEach(function (operator) {\n var value = numericRefinements[operator];\n\n refinements.push({\n value: value,\n operator: operator,\n type: 'numeric',\n });\n });\n\n return refinements;\n};\n\n/**\n * Return the current refinement for the (attribute, operator)\n * @param {string} attribute attribute in the record\n * @param {string} operator operator applied on the refined values\n * @return {Array.<number|number[]>} refined values\n */\nAlgoliaSearchHelper.prototype.getNumericRefinement = function (\n attribute,\n operator\n) {\n return this.state.getNumericRefinement(attribute, operator);\n};\n\n/**\n * Get the current breadcrumb for a hierarchical facet, as an array\n * @param {string} facetName Hierarchical facet name\n * @return {array.<string>} the path as an array of string\n */\nAlgoliaSearchHelper.prototype.getHierarchicalFacetBreadcrumb = function (\n facetName\n) {\n return this.state.getHierarchicalFacetBreadcrumb(facetName);\n};\n\n// /////////// PRIVATE\n\n/**\n * Perform the underlying queries\n * @private\n * @param {object} options options for the query\n * @param {boolean} [options.onlyWithDerivedHelpers=false] if true, only the derived helpers will be queried\n * @return {undefined} does not return anything\n * @fires search\n * @fires result\n * @fires error\n */\nAlgoliaSearchHelper.prototype._search = function (options) {\n var state = this.state;\n var states = [];\n var mainQueries = [];\n\n if (!options.onlyWithDerivedHelpers) {\n mainQueries = requestBuilder._getQueries(state.index, state);\n\n states.push({\n state: state,\n queriesCount: mainQueries.length,\n helper: this,\n });\n\n this.emit('search', {\n state: state,\n results: this.lastResults,\n });\n }\n\n var derivedQueries = this.derivedHelpers.map(function (derivedHelper) {\n var derivedState = derivedHelper.getModifiedState(state);\n var derivedStateQueries = derivedState.index\n ? requestBuilder._getQueries(derivedState.index, derivedState)\n : [];\n\n states.push({\n state: derivedState,\n queriesCount: derivedStateQueries.length,\n helper: derivedHelper,\n });\n\n derivedHelper.emit('search', {\n state: derivedState,\n results: derivedHelper.lastResults,\n });\n\n return derivedStateQueries;\n });\n\n var queries = Array.prototype.concat.apply(mainQueries, derivedQueries);\n\n var queryId = this._queryId++;\n this._currentNbQueries++;\n\n if (!queries.length) {\n return Promise.resolve({ results: [] }).then(\n this._dispatchAlgoliaResponse.bind(this, states, queryId)\n );\n }\n\n try {\n this.client\n .search(queries)\n .then(this._dispatchAlgoliaResponse.bind(this, states, queryId))\n .catch(this._dispatchAlgoliaError.bind(this, queryId));\n } catch (error) {\n // If we reach this part, we're in an internal error state\n this.emit('error', {\n error: error,\n });\n }\n\n return undefined;\n};\n\nAlgoliaSearchHelper.prototype._recommend = function () {\n var searchState = this.state;\n var recommendState = this.recommendState;\n var index = this.getIndex();\n var states = [{ state: recommendState, index: index, helper: this }];\n var ids = recommendState.params.map(function (param) {\n return param.$$id;\n });\n\n this.emit('fetch', {\n recommend: {\n state: recommendState,\n results: this.lastRecommendResults,\n },\n });\n\n var cache = this._recommendCache;\n\n var derivedQueries = this.derivedHelpers.map(function (derivedHelper) {\n var derivedIndex = derivedHelper.getModifiedState(searchState).index;\n if (!derivedIndex) {\n return [];\n }\n\n // Contrary to what is done when deriving the search state, we don't want to\n // provide the current recommend state to the derived helper, as it would\n // inherit unwanted queries. We instead provide an empty recommend state.\n var derivedState = derivedHelper.getModifiedRecommendState(\n new RecommendParameters()\n );\n states.push({\n state: derivedState,\n index: derivedIndex,\n helper: derivedHelper,\n });\n\n ids = Array.prototype.concat.apply(\n ids,\n derivedState.params.map(function (param) {\n return param.$$id;\n })\n );\n\n derivedHelper.emit('fetch', {\n recommend: {\n state: derivedState,\n results: derivedHelper.lastRecommendResults,\n },\n });\n\n return derivedState._buildQueries(derivedIndex, cache);\n });\n\n var queries = Array.prototype.concat.apply(\n this.recommendState._buildQueries(index, cache),\n derivedQueries\n );\n\n if (queries.length === 0) {\n return;\n }\n\n if (\n queries.length > 0 &&\n typeof this.client.getRecommendations === 'undefined'\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n 'Please update algoliasearch/lite to the latest version in order to use recommend widgets.'\n );\n return;\n }\n\n var queryId = this._recommendQueryId++;\n this._currentNbRecommendQueries++;\n\n try {\n this.client\n .getRecommendations(queries)\n .then(this._dispatchRecommendResponse.bind(this, queryId, states, ids))\n .catch(this._dispatchRecommendError.bind(this, queryId));\n } catch (error) {\n // If we reach this part, we're in an internal error state\n this.emit('error', {\n error: error,\n });\n }\n\n return;\n};\n\n/**\n * Transform the responses as sent by the server and transform them into a user\n * usable object that merge the results of all the batch requests. It will dispatch\n * over the different helper + derived helpers (when there are some).\n * @private\n * @param {array.<{SearchParameters, AlgoliaQueries, AlgoliaSearchHelper}>} states state used to generate the request\n * @param {number} queryId id of the current request\n * @param {object} content content of the response\n * @return {undefined}\n */\nAlgoliaSearchHelper.prototype._dispatchAlgoliaResponse = function (\n states,\n queryId,\n content\n) {\n // eslint-disable-next-line consistent-this\n var self = this;\n\n // @TODO remove the number of outdated queries discarded instead of just one\n\n if (queryId < this._lastQueryIdReceived) {\n // Outdated answer\n return;\n }\n\n this._currentNbQueries -= queryId - this._lastQueryIdReceived;\n this._lastQueryIdReceived = queryId;\n\n if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');\n\n var results = content.results.slice();\n\n states.forEach(function (s) {\n var state = s.state;\n var queriesCount = s.queriesCount;\n var helper = s.helper;\n var specificResults = results.splice(0, queriesCount);\n\n if (!state.index) {\n helper.emit('result', {\n results: null,\n state: state,\n });\n return;\n }\n\n helper.lastResults = new SearchResults(\n state,\n specificResults,\n self._searchResultsOptions\n );\n\n helper.emit('result', {\n results: helper.lastResults,\n state: state,\n });\n });\n};\n\nAlgoliaSearchHelper.prototype._dispatchRecommendResponse = function (\n queryId,\n states,\n ids,\n content\n) {\n // @TODO remove the number of outdated queries discarded instead of just one\n\n if (queryId < this._lastRecommendQueryIdReceived) {\n // Outdated answer\n return;\n }\n\n this._currentNbRecommendQueries -=\n queryId - this._lastRecommendQueryIdReceived;\n this._lastRecommendQueryIdReceived = queryId;\n\n if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');\n\n var cache = this._recommendCache;\n\n var idsMap = {};\n ids\n .filter(function (id) {\n return cache[id] === undefined;\n })\n .forEach(function (id, index) {\n if (!idsMap[id]) idsMap[id] = [];\n\n idsMap[id].push(index);\n });\n\n Object.keys(idsMap).forEach(function (id) {\n var indices = idsMap[id];\n var firstResult = content.results[indices[0]];\n if (indices.length === 1) {\n cache[id] = firstResult;\n return;\n }\n cache[id] = Object.assign({}, firstResult, {\n hits: sortAndMergeRecommendations(\n indices.map(function (idx) {\n return content.results[idx].hits;\n })\n ),\n });\n });\n\n var results = {};\n ids.forEach(function (id) {\n results[id] = cache[id];\n });\n\n states.forEach(function (s) {\n var state = s.state;\n var helper = s.helper;\n\n if (!s.index) {\n // eslint-disable-next-line no-warning-comments\n // TODO: emit \"result\" event when events for Recommend are implemented\n helper.emit('recommend:result', {\n results: null,\n state: state,\n });\n return;\n }\n\n helper.lastRecommendResults = new RecommendResults(state, results);\n\n // eslint-disable-next-line no-warning-comments\n // TODO: emit \"result\" event when events for Recommend are implemented\n helper.emit('recommend:result', {\n recommend: {\n results: helper.lastRecommendResults,\n state: state,\n },\n });\n });\n};\n\nAlgoliaSearchHelper.prototype._dispatchAlgoliaError = function (\n queryId,\n error\n) {\n if (queryId < this._lastQueryIdReceived) {\n // Outdated answer\n return;\n }\n\n this._currentNbQueries -= queryId - this._lastQueryIdReceived;\n this._lastQueryIdReceived = queryId;\n\n this.emit('error', {\n error: error,\n });\n\n if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');\n};\n\nAlgoliaSearchHelper.prototype._dispatchRecommendError = function (\n queryId,\n error\n) {\n if (queryId < this._lastRecommendQueryIdReceived) {\n // Outdated answer\n return;\n }\n\n this._currentNbRecommendQueries -=\n queryId - this._lastRecommendQueryIdReceived;\n this._lastRecommendQueryIdReceived = queryId;\n\n this.emit('error', {\n error: error,\n });\n\n if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');\n};\n\nAlgoliaSearchHelper.prototype.containsRefinement = function (\n query,\n facetFilters,\n numericFilters,\n tagFilters\n) {\n return (\n query ||\n facetFilters.length !== 0 ||\n numericFilters.length !== 0 ||\n tagFilters.length !== 0\n );\n};\n\n/**\n * Test if there are some disjunctive refinements on the facet\n * @private\n * @param {string} facet the attribute to test\n * @return {boolean} true if there are refinements on this attribute\n */\nAlgoliaSearchHelper.prototype._hasDisjunctiveRefinements = function (facet) {\n return (\n this.state.disjunctiveRefinements[facet] &&\n this.state.disjunctiveRefinements[facet].length > 0\n );\n};\n\nAlgoliaSearchHelper.prototype._change = function (event) {\n var state = event.state;\n var isPageReset = event.isPageReset;\n\n if (state !== this.state) {\n this.state = state;\n\n this.emit('change', {\n state: this.state,\n results: this.lastResults,\n isPageReset: isPageReset,\n });\n }\n};\n\nAlgoliaSearchHelper.prototype._recommendChange = function (event) {\n var state = event.state;\n\n if (state !== this.recommendState) {\n this.recommendState = state;\n\n // eslint-disable-next-line no-warning-comments\n // TODO: emit \"change\" event when events for Recommend are implemented\n this.emit('recommend:change', {\n search: {\n results: this.lastResults,\n state: this.state,\n },\n recommend: {\n results: this.lastRecommendResults,\n state: this.recommendState,\n },\n });\n }\n};\n\n/**\n * Clears the cache of the underlying Algolia client.\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n */\nAlgoliaSearchHelper.prototype.clearCache = function () {\n if (this.client.clearCache) this.client.clearCache();\n return this;\n};\n\n/**\n * Updates the internal client instance. If the reference of the clients\n * are equal then no update is actually done.\n * @param {AlgoliaSearch} newClient an AlgoliaSearch client\n * @return {AlgoliaSearchHelper} Method is chainable, it returns itself\n */\nAlgoliaSearchHelper.prototype.setClient = function (newClient) {\n if (this.client === newClient) return this;\n\n if (typeof newClient.addAlgoliaAgent === 'function') {\n newClient.addAlgoliaAgent('JS Helper (' + version + ')');\n }\n this.client = newClient;\n\n return this;\n};\n\n/**\n * Gets the instance of the currently used client.\n * @return {AlgoliaSearch} the currently used client\n */\nAlgoliaSearchHelper.prototype.getClient = function () {\n return this.client;\n};\n\n/**\n * Creates an derived instance of the Helper. A derived helper\n * is a way to request other indices synchronised with the lifecycle\n * of the main Helper. This mechanism uses the multiqueries feature\n * of Algolia to aggregate all the requests in a single network call.\n *\n * This method takes a function that is used to create a new SearchParameter\n * that will be used to create requests to Algolia. Those new requests\n * are created just before the `search` event. The signature of the function\n * is `SearchParameters -> SearchParameters`.\n *\n * This method returns a new DerivedHelper which is an EventEmitter\n * that fires the same `search`, `result` and `error` events. Those\n * events, however, will receive data specific to this DerivedHelper\n * and the SearchParameters that is returned by the call of the\n * parameter function.\n * @param {function} fn SearchParameters -> SearchParameters\n * @param {function} recommendFn RecommendParameters -> RecommendParameters\n * @return {DerivedHelper} a new DerivedHelper\n */\nAlgoliaSearchHelper.prototype.derive = function (fn, recommendFn) {\n var derivedHelper = new DerivedHelper(this, fn, recommendFn);\n this.derivedHelpers.push(derivedHelper);\n return derivedHelper;\n};\n\n/**\n * This method detaches a derived Helper from the main one. Prefer using the one from the\n * derived helper itself, to remove the event listeners too.\n * @private\n * @param {DerivedHelper} derivedHelper the derived helper to detach\n * @return {undefined} nothing is returned\n * @throws Error\n */\nAlgoliaSearchHelper.prototype.detachDerivedHelper = function (derivedHelper) {\n var pos = this.derivedHelpers.indexOf(derivedHelper);\n if (pos === -1) throw new Error('Derived helper already detached');\n this.derivedHelpers.splice(pos, 1);\n};\n\n/**\n * This method returns true if there is currently at least one on-going search.\n * @return {boolean} true if there is a search pending\n */\nAlgoliaSearchHelper.prototype.hasPendingRequests = function () {\n return this._currentNbQueries > 0;\n};\n\n/**\n * @typedef AlgoliaSearchHelper.NumericRefinement\n * @type {object}\n * @property {number[]} value the numbers that are used for filtering this attribute with\n * the operator specified.\n * @property {string} operator the faceting data: value, number of entries\n * @property {string} type will be 'numeric'\n */\n\n/**\n * @typedef AlgoliaSearchHelper.FacetRefinement\n * @type {object}\n * @property {string} value the string use to filter the attribute\n * @property {string} type the type of filter: 'conjunctive', 'disjunctive', 'exclude'\n */\n\nmodule.exports = AlgoliaSearchHelper;\n","'use strict';\n\nmodule.exports = function compact(array) {\n if (!Array.isArray(array)) {\n return [];\n }\n\n return array.filter(Boolean);\n};\n","'use strict';\n\n// NOTE: this behaves like lodash/defaults, but doesn't mutate the target\n// it also preserve keys order\nmodule.exports = function defaultsPure() {\n var sources = Array.prototype.slice.call(arguments);\n\n return sources.reduceRight(function (acc, source) {\n Object.keys(Object(source)).forEach(function (key) {\n if (source[key] === undefined) {\n return;\n }\n if (acc[key] !== undefined) {\n // remove if already added, so that we can add it in correct order\n delete acc[key];\n }\n acc[key] = source[key];\n });\n return acc;\n }, {});\n};\n","'use strict';\n\n/**\n * Replaces a leading - with \\-\n * @private\n * @param {any} value the facet value to replace\n * @returns {any} the escaped facet value or the value if it was not a string\n */\nfunction escapeFacetValue(value) {\n if (typeof value !== 'string') return value;\n\n return String(value).replace(/^-/, '\\\\-');\n}\n\n/**\n * Replaces a leading \\- with -\n * @private\n * @param {any} value the escaped facet value\n * @returns {any} the unescaped facet value or the value if it was not a string\n */\nfunction unescapeFacetValue(value) {\n if (typeof value !== 'string') return value;\n\n return value.replace(/^\\\\-/, '-');\n}\n\nmodule.exports = {\n escapeFacetValue: escapeFacetValue,\n unescapeFacetValue: unescapeFacetValue,\n};\n","'use strict';\n\n// @MAJOR can be replaced by native Array#find when we change support\nmodule.exports = function find(array, comparator) {\n if (!Array.isArray(array)) {\n return undefined;\n }\n\n for (var i = 0; i < array.length; i++) {\n if (comparator(array[i])) {\n return array[i];\n }\n }\n\n return undefined;\n};\n","'use strict';\n\n// @MAJOR can be replaced by native Array#findIndex when we change support\nmodule.exports = function find(array, comparator) {\n if (!Array.isArray(array)) {\n return -1;\n }\n\n for (var i = 0; i < array.length; i++) {\n if (comparator(array[i])) {\n return i;\n }\n }\n return -1;\n};\n","// @MAJOR: remove this function and use Array.prototype.flat\nmodule.exports = function flat(arr) {\n return arr.reduce(function (acc, val) {\n return acc.concat(val);\n }, []);\n};\n","'use strict';\n\nvar find = require('./find');\n\n/**\n * Transform sort format from user friendly notation to lodash format\n * @param {string[]} sortBy array of predicate of the form \"attribute:order\"\n * @param {string[]} [defaults] array of predicate of the form \"attribute:order\"\n * @return {array.<string[]>} array containing 2 elements : attributes, orders\n */\nmodule.exports = function formatSort(sortBy, defaults) {\n var defaultInstructions = (defaults || []).map(function (sort) {\n return sort.split(':');\n });\n\n return sortBy.reduce(\n function preparePredicate(out, sort) {\n var sortInstruction = sort.split(':');\n\n var matchingDefault = find(\n defaultInstructions,\n function (defaultInstruction) {\n return defaultInstruction[0] === sortInstruction[0];\n }\n );\n\n if (sortInstruction.length > 1 || !matchingDefault) {\n out[0].push(sortInstruction[0]);\n out[1].push(sortInstruction[1]);\n return out;\n }\n\n out[0].push(matchingDefault[0]);\n out[1].push(matchingDefault[1]);\n return out;\n },\n [[], []]\n );\n};\n","'use strict';\n\nfunction inherits(ctor, superCtor) {\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true,\n },\n });\n}\n\nmodule.exports = inherits;\n","'use strict';\n\nfunction intersection(arr1, arr2) {\n return arr1.filter(function (value, index) {\n return (\n arr2.indexOf(value) > -1 &&\n arr1.indexOf(value) === index /* skips duplicates */\n );\n });\n}\n\nmodule.exports = intersection;\n","'use strict';\n\nfunction clone(value) {\n if (typeof value === 'object' && value !== null) {\n return _merge(Array.isArray(value) ? [] : {}, value);\n }\n return value;\n}\n\nfunction isObjectOrArrayOrFunction(value) {\n return (\n typeof value === 'function' ||\n Array.isArray(value) ||\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\nfunction _merge(target, source) {\n if (target === source) {\n return target;\n }\n\n // eslint-disable-next-line no-restricted-syntax\n for (var key in source) {\n if (\n !Object.prototype.hasOwnProperty.call(source, key) ||\n key === '__proto__' ||\n key === 'constructor'\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n var sourceVal = source[key];\n var targetVal = target[key];\n\n if (typeof targetVal !== 'undefined' && typeof sourceVal === 'undefined') {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n if (\n isObjectOrArrayOrFunction(targetVal) &&\n isObjectOrArrayOrFunction(sourceVal)\n ) {\n target[key] = _merge(targetVal, sourceVal);\n } else {\n target[key] = clone(sourceVal);\n }\n }\n return target;\n}\n\n/**\n * This method is like Object.assign, but recursively merges own and inherited\n * enumerable keyed properties of source objects into the destination object.\n *\n * NOTE: this behaves like lodash/merge, but:\n * - does mutate functions if they are a source\n * - treats non-plain objects as plain\n * - does not work for circular objects\n * - treats sparse arrays as sparse\n * - does not convert Array-like objects (Arguments, NodeLists, etc.) to arrays\n *\n * @param {Object} target The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n */\nfunction merge(target) {\n if (!isObjectOrArrayOrFunction(target)) {\n target = {};\n }\n\n for (var i = 1, l = arguments.length; i < l; i++) {\n var source = arguments[i];\n\n if (isObjectOrArrayOrFunction(source)) {\n _merge(target, source);\n }\n }\n return target;\n}\n\nmodule.exports = merge;\n","'use strict';\n\nfunction objectHasKeys(obj) {\n return obj && Object.keys(obj).length > 0;\n}\n\nmodule.exports = objectHasKeys;\n","'use strict';\n\n// https://github.com/babel/babel/blob/3aaafae053fa75febb3aa45d45b6f00646e30ba4/packages/babel-helpers/src/helpers.js#L604-L620\nfunction _objectWithoutPropertiesLoose(source, excluded) {\n if (source === null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key;\n var i;\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n // eslint-disable-next-line no-continue\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n return target;\n}\n\nmodule.exports = _objectWithoutPropertiesLoose;\n","'use strict';\n\nfunction compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined;\n var valIsNull = value === null;\n\n var othIsDefined = other !== undefined;\n var othIsNull = other === null;\n\n if (\n (!othIsNull && value > other) ||\n (valIsNull && othIsDefined) ||\n !valIsDefined\n ) {\n return 1;\n }\n if (\n (!valIsNull && value < other) ||\n (othIsNull && valIsDefined) ||\n !othIsDefined\n ) {\n return -1;\n }\n }\n return 0;\n}\n\n/**\n * @param {Array<object>} collection object with keys in attributes\n * @param {Array<string>} iteratees attributes\n * @param {Array<string>} orders asc | desc\n * @return {Array<object>} sorted collection\n */\nfunction orderBy(collection, iteratees, orders) {\n if (!Array.isArray(collection)) {\n return [];\n }\n\n if (!Array.isArray(orders)) {\n orders = [];\n }\n\n var result = collection.map(function (value, index) {\n return {\n criteria: iteratees.map(function (iteratee) {\n return value[iteratee];\n }),\n index: index,\n value: value,\n };\n });\n\n result.sort(function comparer(object, other) {\n var index = -1;\n\n while (++index < object.criteria.length) {\n var res = compareAscending(object.criteria[index], other.criteria[index]);\n if (res) {\n if (index >= orders.length) {\n return res;\n }\n if (orders[index] === 'desc') {\n return -res;\n }\n return res;\n }\n }\n\n // This ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n });\n\n return result.map(function (res) {\n return res.value;\n });\n}\n\nmodule.exports = orderBy;\n","'use strict';\n\nfunction valToNumber(v) {\n if (typeof v === 'number') {\n return v;\n } else if (typeof v === 'string') {\n return parseFloat(v);\n } else if (Array.isArray(v)) {\n return v.map(valToNumber);\n }\n\n throw new Error(\n 'The value should be a number, a parsable string or an array of those.'\n );\n}\n\nmodule.exports = valToNumber;\n","'use strict';\n\nvar merge = require('./functions/merge');\n\nfunction sortObject(obj) {\n return Object.keys(obj)\n .sort()\n .reduce(function (acc, curr) {\n acc[curr] = obj[curr];\n return acc;\n }, {});\n}\n\nvar requestBuilder = {\n /**\n * Get all the queries to send to the client, those queries can used directly\n * with the Algolia client.\n * @private\n * @param {string} index The name of the index\n * @param {SearchParameters} state The state from which to get the queries\n * @return {object[]} The queries\n */\n _getQueries: function getQueries(index, state) {\n var queries = [];\n\n // One query for the hits\n queries.push({\n indexName: index,\n params: requestBuilder._getHitsSearchParams(state),\n });\n\n // One for each disjunctive facets\n state.getRefinedDisjunctiveFacets().forEach(function (refinedFacet) {\n queries.push({\n indexName: index,\n params: requestBuilder._getDisjunctiveFacetSearchParams(\n state,\n refinedFacet\n ),\n });\n });\n\n // More to get the parent levels of the hierarchical facets when refined\n state.getRefinedHierarchicalFacets().forEach(function (refinedFacet) {\n var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet);\n var currentRefinement = state.getHierarchicalRefinement(refinedFacet);\n var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);\n\n // If we are deeper than level 0 (starting from `beer > IPA`)\n // we want to get all parent values\n if (\n currentRefinement.length > 0 &&\n currentRefinement[0].split(separator).length > 1\n ) {\n // We generate a map of the filters we will use for our facet values queries\n var filtersMap = currentRefinement[0]\n .split(separator)\n .slice(0, -1)\n .reduce(function createFiltersMap(map, segment, level) {\n return map.concat({\n attribute: hierarchicalFacet.attributes[level],\n value:\n level === 0\n ? segment\n : [map[map.length - 1].value, segment].join(separator),\n });\n }, []);\n\n filtersMap.forEach(function (filter, level) {\n var params = requestBuilder._getDisjunctiveFacetSearchParams(\n state,\n filter.attribute,\n level === 0\n );\n\n // Keep facet filters unrelated to current hierarchical attributes\n function hasHierarchicalFacetFilter(value) {\n return hierarchicalFacet.attributes.some(function (attribute) {\n return attribute === value.split(':')[0];\n });\n }\n\n var filteredFacetFilters = (params.facetFilters || []).reduce(\n function (acc, facetFilter) {\n if (Array.isArray(facetFilter)) {\n var filtered = facetFilter.filter(function (filterValue) {\n return !hasHierarchicalFacetFilter(filterValue);\n });\n\n if (filtered.length > 0) {\n acc.push(filtered);\n }\n }\n\n if (\n typeof facetFilter === 'string' &&\n !hasHierarchicalFacetFilter(facetFilter)\n ) {\n acc.push(facetFilter);\n }\n\n return acc;\n },\n []\n );\n\n var parent = filtersMap[level - 1];\n if (level > 0) {\n params.facetFilters = filteredFacetFilters.concat(\n parent.attribute + ':' + parent.value\n );\n } else {\n params.facetFilters =\n filteredFacetFilters.length > 0\n ? filteredFacetFilters\n : undefined;\n }\n\n queries.push({ indexName: index, params: params });\n });\n }\n });\n\n return queries;\n },\n\n /**\n * Build search parameters used to fetch hits\n * @private\n * @param {SearchParameters} state The state from which to get the queries\n * @return {object.<string, any>} The search parameters for hits\n */\n _getHitsSearchParams: function (state) {\n var facets = state.facets\n .concat(state.disjunctiveFacets)\n .concat(requestBuilder._getHitsHierarchicalFacetsAttributes(state))\n .sort();\n\n var facetFilters = requestBuilder._getFacetFilters(state);\n var numericFilters = requestBuilder._getNumericFilters(state);\n var tagFilters = requestBuilder._getTagFilters(state);\n var additionalParams = {};\n\n if (facets.length > 0) {\n additionalParams.facets = facets.indexOf('*') > -1 ? ['*'] : facets;\n }\n\n if (tagFilters.length > 0) {\n additionalParams.tagFilters = tagFilters;\n }\n\n if (facetFilters.length > 0) {\n additionalParams.facetFilters = facetFilters;\n }\n\n if (numericFilters.length > 0) {\n additionalParams.numericFilters = numericFilters;\n }\n\n return sortObject(merge({}, state.getQueryParams(), additionalParams));\n },\n\n /**\n * Build search parameters used to fetch a disjunctive facet\n * @private\n * @param {SearchParameters} state The state from which to get the queries\n * @param {string} facet the associated facet name\n * @param {boolean} hierarchicalRootLevel ?? FIXME\n * @return {object} The search parameters for a disjunctive facet\n */\n _getDisjunctiveFacetSearchParams: function (\n state,\n facet,\n hierarchicalRootLevel\n ) {\n var facetFilters = requestBuilder._getFacetFilters(\n state,\n facet,\n hierarchicalRootLevel\n );\n var numericFilters = requestBuilder._getNumericFilters(state, facet);\n var tagFilters = requestBuilder._getTagFilters(state);\n var additionalParams = {\n hitsPerPage: 0,\n page: 0,\n analytics: false,\n clickAnalytics: false,\n };\n\n if (tagFilters.length > 0) {\n additionalParams.tagFilters = tagFilters;\n }\n\n var hierarchicalFacet = state.getHierarchicalFacetByName(facet);\n\n if (hierarchicalFacet) {\n additionalParams.facets =\n requestBuilder._getDisjunctiveHierarchicalFacetAttribute(\n state,\n hierarchicalFacet,\n hierarchicalRootLevel\n );\n } else {\n additionalParams.facets = facet;\n }\n\n if (numericFilters.length > 0) {\n additionalParams.numericFilters = numericFilters;\n }\n\n if (facetFilters.length > 0) {\n additionalParams.facetFilters = facetFilters;\n }\n\n return sortObject(merge({}, state.getQueryParams(), additionalParams));\n },\n\n /**\n * Return the numeric filters in an algolia request fashion\n * @private\n * @param {SearchParameters} state the state from which to get the filters\n * @param {string} [facetName] the name of the attribute for which the filters should be excluded\n * @return {string[]} the numeric filters in the algolia format\n */\n _getNumericFilters: function (state, facetName) {\n if (state.numericFilters) {\n return state.numericFilters;\n }\n\n var numericFilters = [];\n\n Object.keys(state.numericRefinements).forEach(function (attribute) {\n var operators = state.numericRefinements[attribute] || {};\n Object.keys(operators).forEach(function (operator) {\n var values = operators[operator] || [];\n if (facetName !== attribute) {\n values.forEach(function (value) {\n if (Array.isArray(value)) {\n var vs = value.map(function (v) {\n return attribute + operator + v;\n });\n numericFilters.push(vs);\n } else {\n numericFilters.push(attribute + operator + value);\n }\n });\n }\n });\n });\n\n return numericFilters;\n },\n\n /**\n * Return the tags filters depending on which format is used, either tagFilters or tagRefinements\n * @private\n * @param {SearchParameters} state the state from which to get the filters\n * @return {string} Tag filters in a single string\n */\n _getTagFilters: function (state) {\n if (state.tagFilters) {\n return state.tagFilters;\n }\n\n return state.tagRefinements.join(',');\n },\n\n /**\n * Build facetFilters parameter based on current refinements. The array returned\n * contains strings representing the facet filters in the algolia format.\n * @private\n * @param {SearchParameters} state The state from which to get the queries\n * @param {string} [facet] if set, the current disjunctive facet\n * @param {boolean} [hierarchicalRootLevel] ?? FIXME\n * @return {array.<string>} The facet filters in the algolia format\n */\n _getFacetFilters: function (state, facet, hierarchicalRootLevel) {\n var facetFilters = [];\n\n var facetsRefinements = state.facetsRefinements || {};\n Object.keys(facetsRefinements)\n .sort()\n .forEach(function (facetName) {\n var facetValues = facetsRefinements[facetName] || [];\n facetValues\n .slice()\n .sort()\n .forEach(function (facetValue) {\n facetFilters.push(facetName + ':' + facetValue);\n });\n });\n\n var facetsExcludes = state.facetsExcludes || {};\n Object.keys(facetsExcludes)\n .sort()\n .forEach(function (facetName) {\n var facetValues = facetsExcludes[facetName] || [];\n facetValues.sort().forEach(function (facetValue) {\n facetFilters.push(facetName + ':-' + facetValue);\n });\n });\n\n var disjunctiveFacetsRefinements = state.disjunctiveFacetsRefinements || {};\n Object.keys(disjunctiveFacetsRefinements)\n .sort()\n .forEach(function (facetName) {\n var facetValues = disjunctiveFacetsRefinements[facetName] || [];\n if (facetName === facet || !facetValues || facetValues.length === 0) {\n return;\n }\n var orFilters = [];\n\n facetValues\n .slice()\n .sort()\n .forEach(function (facetValue) {\n orFilters.push(facetName + ':' + facetValue);\n });\n\n facetFilters.push(orFilters);\n });\n\n var hierarchicalFacetsRefinements =\n state.hierarchicalFacetsRefinements || {};\n Object.keys(hierarchicalFacetsRefinements)\n .sort()\n .forEach(function (facetName) {\n var facetValues = hierarchicalFacetsRefinements[facetName] || [];\n var facetValue = facetValues[0];\n\n if (facetValue === undefined) {\n return;\n }\n\n var hierarchicalFacet = state.getHierarchicalFacetByName(facetName);\n var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);\n var rootPath = state._getHierarchicalRootPath(hierarchicalFacet);\n var attributeToRefine;\n var attributesIndex;\n\n // we ask for parent facet values only when the `facet` is the current hierarchical facet\n if (facet === facetName) {\n // if we are at the root level already, no need to ask for facet values, we get them from\n // the hits query\n if (\n facetValue.indexOf(separator) === -1 ||\n (!rootPath && hierarchicalRootLevel === true) ||\n (rootPath &&\n rootPath.split(separator).length ===\n facetValue.split(separator).length)\n ) {\n return;\n }\n\n if (!rootPath) {\n attributesIndex = facetValue.split(separator).length - 2;\n facetValue = facetValue.slice(0, facetValue.lastIndexOf(separator));\n } else {\n attributesIndex = rootPath.split(separator).length - 1;\n facetValue = rootPath;\n }\n\n attributeToRefine = hierarchicalFacet.attributes[attributesIndex];\n } else {\n attributesIndex = facetValue.split(separator).length - 1;\n\n attributeToRefine = hierarchicalFacet.attributes[attributesIndex];\n }\n\n if (attributeToRefine) {\n facetFilters.push([attributeToRefine + ':' + facetValue]);\n }\n });\n\n return facetFilters;\n },\n\n _getHitsHierarchicalFacetsAttributes: function (state) {\n var out = [];\n\n return state.hierarchicalFacets.reduce(\n // ask for as much levels as there's hierarchical refinements\n function getHitsAttributesForHierarchicalFacet(\n allAttributes,\n hierarchicalFacet\n ) {\n var hierarchicalRefinement = state.getHierarchicalRefinement(\n hierarchicalFacet.name\n )[0];\n\n // if no refinement, ask for root level\n if (!hierarchicalRefinement) {\n allAttributes.push(hierarchicalFacet.attributes[0]);\n return allAttributes;\n }\n\n var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);\n var level = hierarchicalRefinement.split(separator).length;\n var newAttributes = hierarchicalFacet.attributes.slice(0, level + 1);\n\n return allAttributes.concat(newAttributes);\n },\n out\n );\n },\n\n _getDisjunctiveHierarchicalFacetAttribute: function (\n state,\n hierarchicalFacet,\n rootLevel\n ) {\n var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);\n if (rootLevel === true) {\n var rootPath = state._getHierarchicalRootPath(hierarchicalFacet);\n var attributeIndex = 0;\n\n if (rootPath) {\n attributeIndex = rootPath.split(separator).length;\n }\n return [hierarchicalFacet.attributes[attributeIndex]];\n }\n\n var hierarchicalRefinement =\n state.getHierarchicalRefinement(hierarchicalFacet.name)[0] || '';\n // if refinement is 'beers > IPA > Flying dog',\n // then we want `facets: ['beers > IPA']` as disjunctive facet (parent level values)\n\n var parentLevel = hierarchicalRefinement.split(separator).length - 1;\n return hierarchicalFacet.attributes.slice(0, parentLevel + 1);\n },\n\n getSearchForFacetQuery: function (facetName, query, maxFacetHits, state) {\n var stateForSearchForFacetValues = state.isDisjunctiveFacet(facetName)\n ? state.clearRefinements(facetName)\n : state;\n var searchForFacetSearchParameters = {\n facetQuery: query,\n facetName: facetName,\n };\n if (typeof maxFacetHits === 'number') {\n searchForFacetSearchParameters.maxFacetHits = maxFacetHits;\n }\n return sortObject(\n merge(\n {},\n requestBuilder._getHitsSearchParams(stateForSearchForFacetValues),\n searchForFacetSearchParameters\n )\n );\n },\n};\n\nmodule.exports = requestBuilder;\n","'use strict';\n\nmodule.exports = function isValidUserToken(userToken) {\n if (userToken === null) {\n return false;\n }\n return /^[a-zA-Z0-9_-]{1,64}$/.test(userToken);\n};\n","'use strict';\n\nvar find = require('../functions/find');\nvar flat = require('../functions/flat');\n\nfunction getAverageIndices(indexTracker, nrOfObjs) {\n var avgIndices = [];\n\n Object.keys(indexTracker).forEach(function (key) {\n if (indexTracker[key].count < 2) {\n indexTracker[key].indexSum += 100;\n }\n avgIndices.push({\n objectID: key,\n avgOfIndices: indexTracker[key].indexSum / nrOfObjs,\n });\n });\n\n return avgIndices.sort(function (a, b) {\n return a.avgOfIndices > b.avgOfIndices ? 1 : -1;\n });\n}\n\nfunction sortAndMergeRecommendations(results) {\n var indexTracker = {};\n\n results.forEach(function (hits) {\n hits.forEach(function (hit, index) {\n if (!indexTracker[hit.objectID]) {\n indexTracker[hit.objectID] = { indexSum: index, count: 1 };\n } else {\n indexTracker[hit.objectID] = {\n indexSum: indexTracker[hit.objectID].indexSum + index,\n count: indexTracker[hit.objectID].count + 1,\n };\n }\n });\n });\n\n var sortedAverageIndices = getAverageIndices(indexTracker, results.length);\n\n var finalOrder = sortedAverageIndices.reduce(function (\n orderedHits,\n avgIndexRef\n ) {\n var result = find(flat(results), function (hit) {\n return hit.objectID === avgIndexRef.objectID;\n });\n return result ? orderedHits.concat(result) : orderedHits;\n },\n []);\n\n return finalOrder;\n}\n\nmodule.exports = sortAndMergeRecommendations;\n","'use strict';\n\nmodule.exports = '3.22.2';\n"],"names":["EventEmitter","this","_events","_maxListeners","undefined","isFunction","arg","isObject","isUndefined","module","exports","prototype","defaultMaxListeners","setMaxListeners","n","isNaN","TypeError","emit","type","er","handler","len","args","i","listeners","error","length","arguments","Error","err","context","call","Array","slice","apply","addListener","listener","m","newListener","push","warned","console","trace","on","once","fired","g","removeListener","list","position","splice","removeAllListeners","key","listenerCount","evlistener","emitter","AlgoliaSearchHelper","require","RecommendParameters","RecommendResults","SearchParameters","SearchResults","algoliasearchHelper","client","index","opts","searchResultsOptions","version","DerivedHelper","mainHelper","fn","recommendFn","main","lastResults","lastRecommendResults","inherits","detach","detachDerivedHelper","getModifiedState","parameters","getModifiedRecommendState","params","constructor","addParams","newParams","removeParams","id","filter","param","$$id","addFrequentlyBoughtTogether","Object","assign","model","addRelatedProducts","addTrendingItems","addTrendingFacets","addLookingSimilar","_buildQueries","indexName","cache","map","query","threshold","state","results","_state","_rawResults","self","forEach","defaultsPure","objectHasKeys","omit","lib","addRefinement","refinementList","attribute","value","isRefined","valueAsString","facetRefinement","concat","mod","removeRefinement","clearRefinement","v","f","toggleRefinement","refinementType","hasChanged","newRefinementList","keys","reduce","memo","values","facetList","refinementValue","containsRefinements","Boolean","refinementValueAsString","indexOf","find","intersection","merge","valToNumber","isValidUserToken","RefinementList","isEqualNumericRefinement","a","b","isArray","every","el","newParameters","_parseNumbers","userToken","warn","facets","disjunctiveFacets","hierarchicalFacets","facetsRefinements","facetsExcludes","disjunctiveFacetsRefinements","numericRefinements","tagRefinements","hierarchicalFacetsRefinements","paramName","isKeyKnown","PARAMETERS","isValueDefined","partialState","numbers","k","parsedValue","parseFloat","insideBoundingBox","geoRect","operators","operator","parsedValues","vPrime","make","instance","facet","rootPath","currentRefinement","getHierarchicalRefinement","name","clearRefinements","toggleHierarchicalFacetRefinement","validate","currentState","tagFilters","numericFilters","patch","_clearNumericRefinements","setQueryParameters","clearTags","setIndex","setQuery","newQuery","setPage","newPage","page","setFacets","setDisjunctiveFacets","setHitsPerPage","hitsPerPage","setTypoTolerance","typoTolerance","addNumericRefinement","val","isNumericRefined","getConjunctiveRefinements","facetName","isConjunctiveFacet","getDisjunctiveRefinements","isDisjunctiveFacet","getExcludeRefinements","removeNumericRefinement","number","paramValue","op","getNumericRefinements","getNumericRefinement","newNumericRefinements","operatorList","outValues","addFacet","addDisjunctiveFacet","addHierarchicalFacet","hierarchicalFacet","isHierarchicalFacet","addFacetRefinement","addExcludeRefinement","addDisjunctiveFacetRefinement","addTagRefinement","tag","isTagRefined","modification","removeFacet","removeDisjunctiveFacet","removeHierarchicalFacet","removeFacetRefinement","removeExcludeRefinement","removeDisjunctiveFacetRefinement","removeTagRefinement","t","toggleFacetRefinement","toggleConjunctiveFacetRefinement","toggleDisjunctiveFacetRefinement","toggleExcludeFacetRefinement","separator","_getHierarchicalFacetSeparator","getHierarchicalFacetByName","lastIndexOf","addHierarchicalFacetRefinement","path","isHierarchicalFacetRefined","removeHierarchicalFacetRefinement","toggleTagRefinement","isFacetRefined","isExcludeRefined","isDisjunctiveFacetRefined","refinements","isOperatorDefined","array","searchedValue","isAttributeValueDefined","currentValue","getRefinedDisjunctiveFacets","disjunctiveNumericRefinedFacets","getRefinedHierarchicalFacets","sort","getUnrefinedDisjunctiveFacets","refinedFacets","managedParameters","getQueryParams","queryParams","setQueryParameter","parameter","nextWithNumbers","previousPlainObject","acc","nextPlainObject","previous","isPreviousValueDefined","isNextValueDefined","resetPage","_getHierarchicalFacetSortBy","sortBy","_getHierarchicalRootPath","_getHierarchicalShowParentLevel","showParentLevel","hierarchicalFacetName","getHierarchicalFacetBreadcrumb","refinement","split","part","trim","toString","JSON","stringify","hierarchicalFacetResult","hierarchicalFacetIndex","hierarchicalFacetRefinement","hierarchicalSeparator","hierarchicalRootPath","hierarchicalShowParentLevel","prepareHierarchicalFacetSortBy","rootExhaustive","facetResult","exhaustive","generateTreeFn","hierarchicalTree","currentHierarchicalLevel","parent","level","data","subtree","picked","facetValue","tuple","parentPath","onlyMatchingTree","orderBy","facetCount","parts","escapedValue","escapeFacetValue","count","format","unescapeFacetValue","generateHierarchicalTree","fv","compact","findIndex","formatSort","getIndices","attributes","indices","idx","assignFacetStats","dest","facetStats","stats","options","mainSubResponse","persistHierarchicalRootCount","processingTimeMS","sum","result","facetsIndices","disjunctiveFacetsIndices","nextDisjunctiveResult","mainFacets","facetKey","hierarchicalAttributeName","facetValueObject","facetIndex","idxAttributeName","exhaustiveFacetsCount","isFacetDisjunctive","isFacetConjunctive","facets_stats","disjunctiveFacet","dfacet","facetResults","attributeIndex","dataFromMainRequest","refinedFacet","defaultData","root","excludes","extractNormalizedFacetValues","predicate","isExcluded","hierarchicalFacetValues","replace","currentRefinementSplit","unshift","setIsRefined","item","depth","child","recSort","sortFn","node","names","children","childNode","sortedChildren","getFacetStatsIfAvailable","getRefinement","attributeName","resultsFacets","getFacetByName","DEFAULT_SORT","getFacetValues","facetValues","facetOrdering","renderingContent","getFacetOrdering","orderedFacets","remainingFacets","hide","reverseOrder","order","hidden","ordering","sortRemainingBy","sortViaFacetOrdering","vanillaSortFn","getFacetStats","getRefinements","res","facetDeclaration","rootFacet","intermediateFacet","newFacet","numericValue","requestBuilder","sortAndMergeRecommendations","addAlgoliaAgent","setClient","recommendState","_queryId","_recommendQueryId","_lastQueryIdReceived","_lastRecommendQueryIdReceived","derivedHelpers","_currentNbQueries","_currentNbRecommendQueries","_searchResultsOptions","_recommendCache","setCurrentPage","_change","isPageReset","getCurrentPage","search","_search","onlyWithDerivedHelpers","searchOnlyWithDerivedHelpers","recommend","_recommend","getQuery","_getHitsSearchParams","searchOnce","cb","tempState","queries","_getQueries","then","content","_originalResponse","e","catch","findAnswers","derivedHelper","Promise","resolve","derivedState","attributesForPrediction","nbHits","errorMessage","initIndex","queryLanguages","searchForFacetValues","maxFacetHits","userState","clientHasSFFV","clientHasInitIndex","isDisjunctive","algoliaQuery","getSearchForFacetQuery","searchForFacetValuesPromise","response","facetHits","q","addDisjunctiveRefine","addRefine","addFacetExclusion","addExclude","addTag","_recommendChange","removeDisjunctiveRefine","removeRefine","removeFacetExclusion","removeExclude","removeTag","removeFrequentlyBoughtTogether","removeRelatedProducts","removeTrendingItems","removeTrendingFacets","removeLookingSimilar","toggleFacetExclusion","toggleExclude","toggleRefine","toggleTag","nextPage","previousPage","setState","newState","overrideStateWithoutTriggeringChangeEvent","hasRefinements","isDisjunctiveRefined","hasTag","hasTagRefinements","getIndex","getPage","getTags","r","states","mainQueries","queriesCount","helper","derivedQueries","derivedStateQueries","queryId","_dispatchAlgoliaResponse","bind","_dispatchAlgoliaError","searchState","ids","derivedIndex","getRecommendations","_dispatchRecommendResponse","_dispatchRecommendError","s","specificResults","idsMap","firstResult","hits","containsRefinement","facetFilters","_hasDisjunctiveRefinements","disjunctiveRefinements","event","clearCache","newClient","getClient","derive","pos","hasPendingRequests","sources","reduceRight","source","String","comparator","arr","defaults","defaultInstructions","out","sortInstruction","matchingDefault","defaultInstruction","ctor","superCtor","create","enumerable","writable","configurable","arr1","arr2","isObjectOrArrayOrFunction","_merge","target","hasOwnProperty","sourceVal","targetVal","l","obj","excluded","sourceKeys","compareAscending","other","valIsDefined","valIsNull","othIsDefined","othIsNull","collection","iteratees","orders","criteria","iteratee","object","sortObject","curr","_getDisjunctiveFacetSearchParams","filtersMap","segment","join","hasHierarchicalFacetFilter","some","filteredFacetFilters","facetFilter","filtered","filterValue","_getHitsHierarchicalFacetsAttributes","_getFacetFilters","_getNumericFilters","_getTagFilters","additionalParams","hierarchicalRootLevel","analytics","clickAnalytics","_getDisjunctiveHierarchicalFacetAttribute","vs","orFilters","attributeToRefine","attributesIndex","allAttributes","hierarchicalRefinement","newAttributes","rootLevel","parentLevel","stateForSearchForFacetValues","searchForFacetSearchParameters","facetQuery","test","flat","indexTracker","hit","objectID","indexSum","sortedAverageIndices","nrOfObjs","avgIndices","avgOfIndices","getAverageIndices","orderedHits","avgIndexRef"],"sourceRoot":""}