diff --git a/README.md b/README.md
index cd448547d5..38a1c63847 100644
--- a/README.md
+++ b/README.md
@@ -69,7 +69,10 @@ var search = instantsearch({
appId: appId, // Mandatory
apiKey: apiKey, // Mandatory
indexName: indexName, // Mandatory
- numberLocale: 'fr-FR' // Optional, defaults to 'en-EN'
+ numberLocale: 'fr-FR' // Optional, defaults to 'en-EN',
+ urlSync: { // optionnal, activate url sync if defined
+ useHash: false
+ }
});
// add a widget
@@ -198,6 +201,77 @@ npm run test:watch:browser # chrome
npm run test:watch:browser -- --browsers ChromeCanary # force Chrome Canary
```
+## Instant search configuration
+
+The main configuration of instantsearch.js is done through a configuration object.
+The minimal configuration is made a of three attributes :
+
+```js
+instantsearch({
+ appId: 'my_application_id',
+ apiKey: 'my_search_api_key',
+ indexName: 'my_index_name'
+});
+```
+
+It can also contain other optionnal attributes to enable other features.
+
+### Number locale
+
+For the display of numbers, the locale will be determined by
+the browsers or forced in the configuration :
+
+```js
+instantsearch({
+ appId: 'my_application_id',
+ apiKey: 'my_search_api_key',
+ indexName: 'my_index_name',
+ numberLocale: 'en-US'
+});
+```
+
+### Initial search parameters
+
+At the start of instantsearch, the search configuration is based on the input
+of each widget and the URL. It is also possible to change the defaults of
+the configuration through an object that can contain any parameters understood
+by the Algolia API.
+
+```js
+instantsearch({
+ appId: 'my_application_id',
+ apiKey: 'my_search_api_key',
+ indexName: 'my_index_name',
+ searchParameters: {
+ typoTolerance: 'strict'
+ }
+});
+```
+
+### URL synchronisation
+
+Instantsearch let you synchronize the url with the current search parameters.
+In order to activate this feature, you need to add the urlSync object. It accepts
+3 parameters :
+ - trackedParameters:string[] parameters that will be synchronized in the
+ URL. By default, it will track the query, all the refinable attribute (facets and numeric
+ filters), the index and the page.
+ - useHash:boolean if set to true, the url will be hash based. Otherwise,
+ it'll use the query parameters using the modern history API.
+ - threshold:number time in ms after which a new state is created in the browser
+ history. The default value is 700.
+
+All those parameters are optional and a minimal configuration looks like :
+
+```js
+instantsearch({
+ appId: 'my_application_id',
+ apiKey: 'my_search_api_key',
+ indexName: 'my_index_name',
+ urlSync: {}
+});
+```
+
## Available widgets
[searchBox]: ./widgets-screenshots/search-box.png
@@ -210,7 +284,6 @@ npm run test:watch:browser -- --browsers ChromeCanary # force Chrome Canary
[hierarchicalMenu]: ./widgets-screenshots/hierarchicalMenu.png
[menu]: ./widgets-screenshots/menu.png
[rangeSlider]: ./widgets-screenshots/range-slider.png
-[urlSync]: ./widgets-screenshots/url-sync.gif
### searchBox
@@ -720,45 +793,6 @@ search.addWidget(
);
```
-### urlSync
-
-![Example of urlSync][urlSync]
-
-#### API
-
-```js
-/**
- * Instanciate a url sync widget. This widget let you synchronize the search
- * parameters with the URL. It can operate with legacy API and hash or it can use
- * the modern history API. By default, it will use the modern API, but if you are
- * looking for compatibility with IE8 and IE9, then you should set 'useHash' to
- * true.
- * @class
- * @param {UrlUtil} urlUtils an object containing the function to read, watch the changes
- * and update the URL.
- * @param {object} options may contain the following keys :
- * - threshold:number time in ms after which a new state is created in the browser
- * history. The default value is 700.
- * - trackedParameters:string[] parameters that will be synchronized in the
- * URL. By default, it will track the query, all the refinable attribute (facets and numeric
- * filters), the index and the page.
- * - useHash:boolean if set to true, the url will be hash based. Otherwise,
- * it'll use the query parameters using the modern history API.
- */
-```
-
-#### Usage
-
-```js
-search.addWidget(
- instantsearch.widgets.urlSync({
-/* useHash: true,
- threshold: 600,
- trackedParameters: ['query', 'page', 'attribute:*'] */
- })
-);
-```
-
### hierarchicalMenu
![Example of the hierarchicalMenu widget][hierarchicalMenu]
diff --git a/components/Pagination/Pagination.js b/components/Pagination/Pagination.js
index 9283b73656..2867c607ee 100644
--- a/components/Pagination/Pagination.js
+++ b/components/Pagination/Pagination.js
@@ -18,7 +18,7 @@ class Pagination extends React.Component {
this.props.setCurrentPage(pageNumber);
}
- pageLink({label, ariaLabel, pageNumber, className = null, isDisabled = false, isActive = false}) {
+ pageLink({label, ariaLabel, pageNumber, className = null, isDisabled = false, isActive = false, createURL}) {
var handleClick = this.handleClick.bind(this, pageNumber);
className = cx(bem('item'), className);
@@ -29,6 +29,7 @@ class Pagination extends React.Component {
className = cx(bem('item-page', 'active'), this.props.cssClasses.active, className);
}
+ var url = createURL ? createURL(pageNumber) : '#';
return (
);
}
- previousPageLink(pager) {
+ previousPageLink(pager, createURL) {
var className = cx(bem('item-previous'), this.props.cssClasses.previous);
return this.pageLink({
ariaLabel: 'Previous',
className: className,
isDisabled: pager.isFirstPage(),
label: this.props.labels.previous,
- pageNumber: pager.currentPage - 1
+ pageNumber: pager.currentPage - 1,
+ createURL
});
}
- nextPageLink(pager) {
+ nextPageLink(pager, createURL) {
var className = cx(bem('item-next'), this.props.cssClasses.next);
return this.pageLink({
ariaLabel: 'Next',
className: className,
isDisabled: pager.isLastPage(),
label: this.props.labels.next,
- pageNumber: pager.currentPage + 1
+ pageNumber: pager.currentPage + 1,
+ createURL
});
}
- firstPageLink(pager) {
+ firstPageLink(pager, createURL) {
var className = cx(bem('item-first'), this.props.cssClasses.first);
return this.pageLink({
ariaLabel: 'First',
className: className,
isDisabled: pager.isFirstPage(),
label: this.props.labels.first,
- pageNumber: 0
+ pageNumber: 0,
+ createURL
});
}
- lastPageLink(pager) {
+ lastPageLink(pager, createURL) {
var className = cx(bem('item-last'), this.props.cssClasses.last);
return this.pageLink({
ariaLabel: 'Last',
className: className,
isDisabled: pager.isLastPage(),
label: this.props.labels.last,
- pageNumber: pager.total - 1
+ pageNumber: pager.total - 1,
+ createURL
});
}
- pages(pager) {
+ pages(pager, createURL) {
var pages = [];
var className = cx(bem('item-page'), this.props.cssClasses.item);
@@ -97,7 +103,8 @@ class Pagination extends React.Component {
className: className,
isActive: isActive,
label: pageNumber + 1,
- pageNumber: pageNumber
+ pageNumber: pageNumber,
+ createURL
}));
});
@@ -112,14 +119,15 @@ class Pagination extends React.Component {
});
var cssClassesList = cx(bem(null), this.props.cssClasses.root);
+ var createURL = this.props.createURL;
return (
- {this.props.showFirstLast ? this.firstPageLink(pager) : null}
- {this.previousPageLink(pager)}
- {this.pages(pager)}
- {this.nextPageLink(pager)}
- {this.props.showFirstLast ? this.lastPageLink(pager) : null}
+ {this.props.showFirstLast ? this.firstPageLink(pager, createURL) : null}
+ {this.previousPageLink(pager, createURL)}
+ {this.pages(pager, createURL)}
+ {this.nextPageLink(pager, createURL)}
+ {this.props.showFirstLast ? this.lastPageLink(pager, createURL) : null}
);
}
diff --git a/components/Pagination/PaginationLink.js b/components/Pagination/PaginationLink.js
index e05506b0d9..76df56fa6b 100644
--- a/components/Pagination/PaginationLink.js
+++ b/components/Pagination/PaginationLink.js
@@ -7,7 +7,7 @@ class PaginationLink extends React.Component {
}
render() {
- var {className, label, ariaLabel, handleClick} = this.props;
+ var {className, label, ariaLabel, handleClick, url} = this.props;
return (
@@ -15,7 +15,7 @@ class PaginationLink extends React.Component {
ariaLabel={ariaLabel}
className={className}
dangerouslySetInnerHTML={{__html: label}}
- href="#"
+ href={url}
onClick={handleClick}
>
@@ -33,7 +33,8 @@ PaginationLink.propTypes = {
label: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
- ]).isRequired
+ ]).isRequired,
+ url: React.PropTypes.string
};
module.exports = PaginationLink;
diff --git a/components/RefinementList.js b/components/RefinementList.js
index 60c073ea61..a3f4966229 100644
--- a/components/RefinementList.js
+++ b/components/RefinementList.js
@@ -11,10 +11,12 @@ class RefinementList extends React.Component {
_generateFacetItem(facetValue) {
var hasChildren = facetValue.data && facetValue.data.length > 0;
+ var subList = hasChildren && ;
+ var data = facetValue;
- var subList = hasChildren ?
- :
- null;
+ if (this.props.createURL) {
+ data.url = this.props.createURL(facetValue[this.props.facetNameKey]);
+ }
var templateData = {...facetValue, cssClasses: this.props.cssClasses};
@@ -78,13 +80,15 @@ class RefinementList extends React.Component {
render() {
return (
- {this.props.facetValues.map(this._generateFacetItem, this)}
+ {this.props.facetValues.map(this._generateFacetItem, this)}
);
}
}
RefinementList.propTypes = {
+ Template: React.PropTypes.func,
+ createURL: React.PropTypes.func.isRequired,
cssClasses: React.PropTypes.shape({
item: React.PropTypes.oneOfType([
React.PropTypes.string,
diff --git a/components/Template.js b/components/Template.js
index b02efe3c53..45080671af 100644
--- a/components/Template.js
+++ b/components/Template.js
@@ -1,12 +1,17 @@
var React = require('react');
+var mapValues = require('lodash/object/mapValues');
+var curry = require('lodash/function/curry');
+var hogan = require('hogan.js');
class Template extends React.Component {
render() {
+ var compileOptions = this.props.useCustomCompileOptions[this.props.templateKey] ?
+ this.props.templatesConfig.compileOptions :
+ {};
+
var content = renderTemplate({
template: this.props.templates[this.props.templateKey],
- compileOptions: this.props.useCustomCompileOptions[this.props.templateKey] ?
- this.props.templatesConfig.compileOptions :
- {},
+ compileOptions: compileOptions,
helpers: this.props.templatesConfig.helpers,
data: transformData(this.props.transformData, this.props.templateKey, this.props.data)
});
@@ -76,43 +81,32 @@ function transformData(fn, templateKey, originalData) {
}
function renderTemplate({template, compileOptions, helpers, data}) {
- var hogan = require('hogan.js');
- var forOwn = require('lodash/object/forOwn');
- var content;
+ let isTemplateString = typeof template === 'string';
+ let isTemplateFunction = typeof template === 'function';
- if (typeof template !== 'string' && typeof template !== 'function') {
+ if (!isTemplateString && !isTemplateFunction) {
throw new Error('Template must be `string` or `function`');
+ } else if (isTemplateFunction) {
+ return template(data);
+ } else {
+ let transformedHelpers = transformHelpersToHogan(helpers, compileOptions, data);
+ let preparedData = {...data, helpers: transformedHelpers};
+ return hogan.compile(template, compileOptions).render(preparedData);
}
+}
- if (typeof template === 'function') {
- content = template(data);
- }
-
- if (typeof template === 'string') {
- data = addTemplateHelpersToData(data);
-
- content = hogan.compile(template, compileOptions).render(data);
- }
-
- // We add all our template helper methods to the template as lambdas. Note
- // that lambdas in Mustache are supposed to accept a second argument of
- // `render` to get the rendered value, not the literal `{{value}}`. But
- // this is currently broken (see
- // https://github.com/twitter/hogan.js/issues/222).
- function addTemplateHelpersToData(templateData) {
- templateData.helpers = {};
- forOwn(helpers, (method, name) => {
- templateData.helpers[name] = function() {
- return (text) => {
- var render = (value) => hogan.compile(value, compileOptions).render(this);
- return method.call(this, text, render);
- };
- };
+// We add all our template helper methods to the template as lambdas. Note
+// that lambdas in Mustache are supposed to accept a second argument of
+// `render` to get the rendered value, not the literal `{{value}}`. But
+// this is currently broken (see
+// https://github.com/twitter/hogan.js/issues/222).
+function transformHelpersToHogan(helpers, compileOptions, data) {
+ return mapValues(helpers, (method) => {
+ return curry(function(text) {
+ var render = (value) => hogan.compile(value, compileOptions).render(this);
+ return method.call(data, text, render);
});
- return data;
- }
-
- return content;
+ });
}
module.exports = Template;
diff --git a/example/app.js b/example/app.js
index 5af0c79599..e11fe36922 100644
--- a/example/app.js
+++ b/example/app.js
@@ -4,14 +4,11 @@ var instantsearch = require('../index');
var search = instantsearch({
appId: 'latency',
apiKey: '6be0576ff61c053d5f9a3225e2a90f76',
- indexName: 'instant_search'
-});
-
-search.addWidget(
- instantsearch.widgets.urlSync({
+ indexName: 'instant_search',
+ urlSync: {
useHash: true
- })
-);
+ }
+});
search.addWidget(
instantsearch.widgets.searchBox({
diff --git a/example/templates/and.html b/example/templates/and.html
index 97848b4524..63a74142db 100644
--- a/example/templates/and.html
+++ b/example/templates/and.html
@@ -1,4 +1,4 @@
-
+
{{name}}
{{count}}
diff --git a/example/templates/category.html b/example/templates/category.html
index 802c0cdda4..5915a071d6 100644
--- a/example/templates/category.html
+++ b/example/templates/category.html
@@ -1 +1 @@
-{{name}} {{count}}
+{{name}} {{count}}
diff --git a/index.js b/index.js
index a518f320bb..76658889c1 100644
--- a/index.js
+++ b/index.js
@@ -17,8 +17,7 @@ instantsearch.widgets = {
searchBox: require('./widgets/search-box'),
rangeSlider: require('./widgets/range-slider'),
stats: require('./widgets/stats/stats'),
- toggle: require('./widgets/toggle/toggle'),
- urlSync: require('./widgets/url-sync')
+ toggle: require('./widgets/toggle/toggle')
};
instantsearch.version = require('./lib/version.js');
diff --git a/lib/InstantSearch.js b/lib/InstantSearch.js
index aad05d219b..32f7675142 100644
--- a/lib/InstantSearch.js
+++ b/lib/InstantSearch.js
@@ -7,13 +7,18 @@ var union = require('lodash/array/union');
var EventEmitter = require('events').EventEmitter;
+var urlSyncWidget = require('./url-sync');
+
+function defaultCreateURL() { return '#'; }
+
class InstantSearch extends EventEmitter {
constructor({
appId = null,
apiKey = null,
indexName = null,
numberLocale = 'en-EN',
- searchParameters = {}
+ searchParameters = {},
+ urlSync = null
}) {
super();
if (appId === null || apiKey === null || indexName === null) {
@@ -41,6 +46,7 @@ Usage: instantsearch({
},
compileOptions: {}
};
+ this.urlSync = urlSync;
}
addWidget(widgetDefinition) {
@@ -49,32 +55,22 @@ Usage: instantsearch({
}
start() {
- this.searchParameters = this.widgets.sort(function initLastSort(a, b) {
- // Widgets with the __initLast tag should provide configuration last
- if (a.__initLast === b.__initLast) return 0;
- return a.__initLast ? 1 : -1;
- }).reduce(function(configuration, widgetDefinition) {
- if (!widgetDefinition.getConfiguration) return configuration;
-
- // Update searchParameters with the configuration from the widgets
- var partialConfiguration = widgetDefinition.getConfiguration(configuration);
- return merge(
- {},
- configuration,
- partialConfiguration,
- (a, b) => {
- if (Array.isArray(a)) {
- return union(a, b);
- }
- }
- );
- }, this.searchParameters);
+ if (!this.widgets) throw new Error('No widgets were added to instantsearch.js');
+
+ if (this.urlSync) {
+ let syncWidget = urlSyncWidget(this.urlSync);
+ this.createURL = syncWidget.createURL.bind(syncWidget);
+ this.widgets.push(syncWidget);
+ } else this.createURL = defaultCreateURL;
+
+ this.searchParameters = this.widgets.reduce(enhanceConfiguration, this.searchParameters);
var helper = algoliasearchHelper(
this.client,
this.searchParameters.index || this.indexName,
this.searchParameters
);
+
this.helper = helper;
this._init(helper.state, helper);
@@ -92,7 +88,8 @@ Usage: instantsearch({
templatesConfig: this.templatesConfig,
results,
state,
- helper
+ helper,
+ createURL: this.createURL
});
}, this);
this.emit('render');
@@ -107,4 +104,21 @@ Usage: instantsearch({
}
}
+function enhanceConfiguration(configuration, widgetDefinition) {
+ if (!widgetDefinition.getConfiguration) return configuration;
+
+ // Update searchParameters with the configuration from the widgets
+ var partialConfiguration = widgetDefinition.getConfiguration(configuration);
+ return merge(
+ {},
+ configuration,
+ partialConfiguration,
+ (a, b) => {
+ if (Array.isArray(a)) {
+ return union(a, b);
+ }
+ }
+ );
+}
+
module.exports = InstantSearch;
diff --git a/lib/__tests__/InstantSearch-test.js b/lib/__tests__/InstantSearch-test.js
index ddd1586047..09a9744be6 100644
--- a/lib/__tests__/InstantSearch-test.js
+++ b/lib/__tests__/InstantSearch-test.js
@@ -122,6 +122,7 @@ describe('InstantSearch lifecycle', () => {
expect(widget.render.calledOnce).toBe(true, 'widget.render called once');
expect(widget.render.args[0])
.toEqual([{
+ createURL: search.createURL,
results,
state: helper.state,
helper,
@@ -132,7 +133,7 @@ describe('InstantSearch lifecycle', () => {
});
});
- context('when we have 5 widgets, the third one having __initLast = true', () => {
+ context('when we have 5 widgets', () => {
var widgets;
beforeEach(() => {
@@ -142,8 +143,6 @@ describe('InstantSearch lifecycle', () => {
getConfiguration: sinon.stub().returns({values: [widgetIndex]})
};
- if (widgetIndex === 2) widget.__initLast = true;
-
return widget;
});
widgets.forEach(search.addWidget, search);
@@ -152,7 +151,6 @@ describe('InstantSearch lifecycle', () => {
it('calls widget[x].getConfiguration in the orders the widgets were added', () => {
let order = widgets
- .filter((widget, widgetIndex) => widgetIndex !== 2)
.every((widget, widgetIndex, filteredWidgets) => {
if (widgetIndex === 0) {
return widget.getConfiguration.calledOnce &&
@@ -166,14 +164,8 @@ describe('InstantSearch lifecycle', () => {
expect(order).toBe(true);
});
- it('calls widget[2].getConfiguration before any other widget, because of __initLast', () => {
- let initLastWidget = widgets[2];
- let lastWidget = widgets[widgets.length - 1];
- expect(initLastWidget.getConfiguration.calledAfter(lastWidget.getConfiguration)).toBe(true);
- });
-
it('recursevly merges searchParameters.values array', () => {
- expect(algoliasearchHelper.args[0][2].values).toEqual([-2, -1, 0, 1, 3, 4, 2]);
+ expect(algoliasearchHelper.args[0][2].values).toEqual([-2, -1, 0, 1, 2, 3, 4]);
});
});
diff --git a/widgets/url-sync.js b/lib/url-sync.js
similarity index 84%
rename from widgets/url-sync.js
rename to lib/url-sync.js
index e4c04034c6..bf59a08cd8 100644
--- a/widgets/url-sync.js
+++ b/lib/url-sync.js
@@ -1,4 +1,5 @@
-var AlgoliaSearchHelper = require('algoliasearch-helper').AlgoliaSearchHelper;
+var algoliasearchHelper = require('algoliasearch-helper');
+var AlgoliaSearchHelper = algoliasearchHelper.AlgoliaSearchHelper;
var majorVersionNumber = require('../lib/version.js').split('.')[0];
var isEqual = require('lodash/lang/isEqual');
@@ -33,10 +34,13 @@ var hashUrlUtils = {
window.addEventListener('hashchange', cb);
},
pushState: function(qs) {
- window.location.assign(document.location.search + this.character + qs);
+ window.location.assign(this.createURL(qs));
},
replaceState: function(qs) {
- window.location.replace(document.location.search + this.character + qs);
+ window.location.replace(this.createURL(qs));
+ },
+ createURL: function(qs) {
+ return document.location.search + this.character + qs;
},
readUrl: function() {
return window.location.hash.slice(1);
@@ -53,10 +57,13 @@ var modernUrlUtils = {
window.addEventListener('popstate', cb);
},
pushState: function(qs) {
- window.history.pushState(null, '', this.character + qs + document.location.hash);
+ window.history.pushState(null, '', this.createURL(qs));
},
replaceState: function(qs) {
- window.history.replaceState(null, '', this.character + qs + document.location.hash);
+ window.history.replaceState(null, '', this.createURL(qs));
+ },
+ createURL: function(qs) {
+ return this.character + qs + document.location.hash;
},
readUrl: function() {
return window.location.search.slice(1);
@@ -133,6 +140,16 @@ class URLSync {
this.urlUtils.pushState(qs);
}
}
+
+ createURL(state) {
+ var currentQueryString = this.urlUtils.readUrl();
+ var filteredState = state.filter(this.trackedParameters);
+ var foreignConfig = algoliasearchHelper.url.getUnrecognizedParametersInQueryString(currentQueryString);
+ // Add instantsearch version to reconciliate old url with newer versions
+ foreignConfig.is_v = majorVersionNumber;
+
+ return this.urlUtils.createURL(algoliasearchHelper.url.getQueryStringFromState(filteredState));
+ }
}
/**
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index feab948529..fa745ae73d 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -106,7 +106,7 @@
},
"algoliasearch-helper": {
"version": "2.6.2",
- "from": "algoliasearch-helper@>=2.5.0 <3.0.0",
+ "from": "algoliasearch-helper@>=2.6.2 <3.0.0",
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-2.6.2.tgz",
"dependencies": {
"lodash-compat": {
@@ -767,9 +767,9 @@
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.1.tgz"
},
"core-js": {
- "version": "1.2.1",
+ "version": "1.2.2",
"from": "core-js@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.1.tgz"
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.2.tgz"
},
"debug": {
"version": "2.2.0",
@@ -1016,7 +1016,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "from": "mkdirp@>=0.0.0 <1.0.0",
+ "from": "mkdirp@>=0.5.0 <0.6.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"dependencies": {
"minimist": {
@@ -1117,7 +1117,7 @@
"dependencies": {
"align-text": {
"version": "0.1.3",
- "from": "align-text@>=0.1.0 <0.2.0",
+ "from": "align-text@>=0.1.1 <0.2.0",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.3.tgz",
"dependencies": {
"kind-of": {
@@ -1153,7 +1153,7 @@
"dependencies": {
"align-text": {
"version": "0.1.3",
- "from": "align-text@>=0.1.0 <0.2.0",
+ "from": "align-text@>=0.1.1 <0.2.0",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.3.tgz",
"dependencies": {
"kind-of": {
@@ -1343,7 +1343,7 @@
},
"source-map": {
"version": "0.4.4",
- "from": "source-map@>=0.4.0 <0.5.0",
+ "from": "source-map@>=0.4.1 <0.5.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"dependencies": {
"amdefine": {
@@ -1567,9 +1567,9 @@
"resolved": "https://registry.npmjs.org/babel-plugin-rewire/-/babel-plugin-rewire-0.1.22.tgz"
},
"classnames": {
- "version": "2.1.5",
+ "version": "2.2.0",
"from": "classnames@>=2.1.5 <3.0.0",
- "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.1.5.tgz"
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.0.tgz"
},
"conventional-changelog": {
"version": "0.5.0",
@@ -1808,7 +1808,7 @@
},
"normalize-package-data": {
"version": "2.3.4",
- "from": "normalize-package-data@>=2.3.2 <3.0.0",
+ "from": "normalize-package-data@>=2.3.0 <3.0.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.4.tgz",
"dependencies": {
"is-builtin-module": {
@@ -2510,9 +2510,9 @@
}
},
"concat-stream": {
- "version": "1.5.0",
+ "version": "1.5.1",
"from": "concat-stream@>=1.4.6 <2.0.0",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
@@ -2609,7 +2609,7 @@
},
"es5-ext": {
"version": "0.10.8",
- "from": "es5-ext@>=0.10.6 <0.11.0",
+ "from": "es5-ext@>=0.10.8 <0.11.0",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.8.tgz"
},
"es6-iterator": {
@@ -2691,9 +2691,9 @@
"resolved": "https://registry.npmjs.org/espree/-/espree-2.2.5.tgz"
},
"estraverse": {
- "version": "4.1.0",
+ "version": "4.1.1",
"from": "estraverse@>=4.1.0 <5.0.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.0.tgz"
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz"
},
"estraverse-fb": {
"version": "1.3.1",
@@ -3529,9 +3529,9 @@
"resolved": "https://registry.npmjs.org/eslint-config-algolia/-/eslint-config-algolia-4.1.0.tgz"
},
"eslint-plugin-react": {
- "version": "3.5.1",
+ "version": "3.6.2",
"from": "eslint-plugin-react@>=3.5.1 <4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-3.5.1.tgz"
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-3.6.2.tgz"
},
"events": {
"version": "1.1.0",
@@ -3625,7 +3625,7 @@
"dependencies": {
"loader-utils": {
"version": "0.2.11",
- "from": "loader-utils@>=0.2.0 <0.3.0",
+ "from": "loader-utils@>=0.2.5 <0.3.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.11.tgz",
"dependencies": {
"big.js": {
@@ -4836,9 +4836,9 @@
}
},
"core-js": {
- "version": "1.2.1",
+ "version": "1.2.2",
"from": "core-js@>=1.0.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.1.tgz"
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.2.tgz"
},
"di": {
"version": "0.0.1",
@@ -5717,7 +5717,7 @@
},
"loader-utils": {
"version": "0.2.11",
- "from": "loader-utils@>=0.2.0 <0.3.0",
+ "from": "loader-utils@>=0.2.5 <0.3.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.11.tgz",
"dependencies": {
"big.js": {
@@ -5829,7 +5829,7 @@
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "inherits@>=2.0.1 <2.1.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
@@ -6198,14 +6198,14 @@
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "inherits@>=2.0.0 <2.1.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
},
"xtend": {
"version": "4.0.0",
- "from": "xtend@>=4.0.0 <4.1.0",
+ "from": "xtend@>=4.0.0 <4.1.0-0",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
}
}
@@ -6779,7 +6779,7 @@
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "inherits@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
@@ -6912,7 +6912,7 @@
"dependencies": {
"mkdirp": {
"version": "0.5.1",
- "from": "mkdirp@>=0.0.0 <1.0.0",
+ "from": "mkdirp@>=0.5.1 <0.6.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"dependencies": {
"minimist": {
@@ -7463,16 +7463,16 @@
"from": "builtin-modules@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.0.tgz"
},
- "builtins": {
- "version": "0.0.7",
- "from": "builtins@0.0.7",
- "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz"
- },
"caseless": {
"version": "0.11.0",
"from": "caseless@>=0.11.0 <0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz"
},
+ "builtins": {
+ "version": "0.0.7",
+ "from": "builtins@0.0.7",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz"
+ },
"chalk": {
"version": "1.1.1",
"from": "chalk@1.1.1",
@@ -7627,16 +7627,16 @@
"from": "is-property@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
},
- "is-relative": {
- "version": "0.1.3",
- "from": "is-relative@>=0.1.0 <0.2.0",
- "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz"
- },
"isarray": {
"version": "0.0.1",
"from": "isarray@0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
},
+ "is-relative": {
+ "version": "0.1.3",
+ "from": "is-relative@>=0.1.0 <0.2.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz"
+ },
"isstream": {
"version": "0.1.2",
"from": "isstream@>=0.1.1 <0.2.0",
@@ -7767,16 +7767,16 @@
"from": "lodash.isarray@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz"
},
- "lodash.istypedarray": {
- "version": "3.0.2",
- "from": "lodash.istypedarray@>=3.0.0 <4.0.0",
- "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.2.tgz"
- },
"lodash.keys": {
"version": "3.1.2",
"from": "lodash.keys@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz"
},
+ "lodash.istypedarray": {
+ "version": "3.0.2",
+ "from": "lodash.istypedarray@>=3.0.0 <4.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.2.tgz"
+ },
"lodash.pad": {
"version": "3.1.1",
"from": "lodash.pad@>=3.0.0 <4.0.0",
@@ -7787,16 +7787,16 @@
"from": "lodash.padleft@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.padleft/-/lodash.padleft-3.1.1.tgz"
},
- "lodash.pairs": {
- "version": "3.0.1",
- "from": "lodash.pairs@>=3.0.0 <4.0.0",
- "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz"
- },
"lodash.padright": {
"version": "3.1.1",
"from": "lodash.padright@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.padright/-/lodash.padright-3.1.1.tgz"
},
+ "lodash.pairs": {
+ "version": "3.0.1",
+ "from": "lodash.pairs@>=3.0.0 <4.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz"
+ },
"lodash.repeat": {
"version": "3.0.1",
"from": "lodash.repeat@>=3.0.0 <4.0.0",
@@ -7981,16 +7981,16 @@
"from": "util-deprecate@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.1.tgz"
},
- "util-extend": {
- "version": "1.0.1",
- "from": "util-extend@>=1.0.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.1.tgz"
- },
"validate-npm-package-license": {
"version": "3.0.1",
"from": "validate-npm-package-license@>=3.0.1 <4.0.0",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz"
},
+ "util-extend": {
+ "version": "1.0.1",
+ "from": "util-extend@>=1.0.1 <2.0.0",
+ "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.1.tgz"
+ },
"wcwidth": {
"version": "1.0.0",
"from": "wcwidth@>=1.0.0 <2.0.0",
@@ -8420,7 +8420,7 @@
},
"debug": {
"version": "2.2.0",
- "from": "debug@2.2.0",
+ "from": "debug@>=2.2.0 <2.3.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
@@ -9101,7 +9101,7 @@
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "inherits@>=2.0.0 <2.1.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"ini": {
@@ -9701,19 +9701,19 @@
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.3.2.tgz",
"dependencies": {
"core-js": {
- "version": "1.2.1",
+ "version": "1.2.2",
"from": "core-js@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.1.tgz"
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.2.tgz"
},
"loose-envify": {
- "version": "1.0.0",
+ "version": "1.1.0",
"from": "loose-envify@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.1.0.tgz",
"dependencies": {
"js-tokens": {
- "version": "1.0.1",
+ "version": "1.0.2",
"from": "js-tokens@>=1.0.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.1.tgz"
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.2.tgz"
}
}
},
@@ -9787,7 +9787,7 @@
"dependencies": {
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "inherits@>=2.0.0 <2.1.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
@@ -9811,7 +9811,7 @@
"dependencies": {
"loader-utils": {
"version": "0.2.11",
- "from": "loader-utils@>=0.2.0 <0.3.0",
+ "from": "loader-utils@>=0.2.5 <0.3.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.11.tgz",
"dependencies": {
"big.js": {
@@ -10033,7 +10033,7 @@
},
"xtend": {
"version": "4.0.0",
- "from": "xtend@>=4.0.0 <4.1.0",
+ "from": "xtend@>=4.0.0 <4.1.0-0",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
}
}
@@ -10086,7 +10086,7 @@
"dependencies": {
"loader-utils": {
"version": "0.2.11",
- "from": "loader-utils@>=0.2.0 <0.3.0",
+ "from": "loader-utils@>=0.2.5 <0.3.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.11.tgz",
"dependencies": {
"big.js": {
@@ -10880,9 +10880,9 @@
}
},
"webpack-dev-server": {
- "version": "1.12.0",
+ "version": "1.12.1",
"from": "webpack-dev-server@>=1.12.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.12.0.tgz",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.12.1.tgz",
"dependencies": {
"compression": {
"version": "1.6.0",
@@ -10932,7 +10932,7 @@
},
"debug": {
"version": "2.2.0",
- "from": "debug@2.2.0",
+ "from": "debug@>=2.2.0 <2.3.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
@@ -11276,7 +11276,7 @@
"dependencies": {
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "inherits@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"statuses": {
diff --git a/package.json b/package.json
index d981c00572..610be665d5 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
},
"dependencies": {
"algoliasearch": "^3.8.0",
- "algoliasearch-helper": "^2.5.0",
+ "algoliasearch-helper": "^2.6.2",
"classnames": "^2.1.5",
"events": "^1.1.0",
"hogan.js": "^3.0.2",
diff --git a/widgets/hierarchicalMenu.js b/widgets/hierarchicalMenu.js
index b53a54ec90..e53ad6e27c 100644
--- a/widgets/hierarchicalMenu.js
+++ b/widgets/hierarchicalMenu.js
@@ -8,7 +8,7 @@ var RefinementList = autoHide(headerFooter(require('../components/RefinementList
var defaultTemplates = {
header: '',
- item: '{{name}} {{count}}',
+ item: '{{name}} {{count}}',
footer: ''
};
@@ -66,7 +66,7 @@ function hierarchicalMenu({
separator
}]
}),
- render: function({results, helper, templatesConfig}) {
+ render: function({results, helper, templatesConfig, createURL, state}) {
var facetValues = getFacetValues(results, hierarchicalFacetName, sortBy);
var templateProps = utils.prepareTemplateProps({
@@ -78,6 +78,7 @@ function hierarchicalMenu({
ReactDOM.render(
createURL(state.toggleRefinement(hierarchicalFacetName, facetValue))}
cssClasses={cssClasses}
facetNameKey="path"
facetValues={facetValues}
diff --git a/widgets/menu.js b/widgets/menu.js
index 59eb3666d7..e260f2f71a 100644
--- a/widgets/menu.js
+++ b/widgets/menu.js
@@ -8,7 +8,7 @@ var RefinementList = autoHide(headerFooter(require('../components/RefinementList
var defaultTemplates = {
header: '',
- item: '{{name}} {{count}}',
+ item: '{{name}} {{count}}',
footer: ''
};
@@ -62,7 +62,7 @@ function menu({
attributes: [facetName]
}]
}),
- render: function({results, helper, templatesConfig}) {
+ render: function({results, helper, templatesConfig, state, createURL}) {
var facetValues = getFacetValues(results, hierarchicalFacetName, sortBy, limit);
var templateProps = utils.prepareTemplateProps({
@@ -74,6 +74,7 @@ function menu({
ReactDOM.render(
createURL(state.toggleRefinement(hierarchicalFacetName, facetValue))}
cssClasses={cssClasses}
facetValues={facetValues}
hasResults={facetValues.length > 0}
diff --git a/widgets/pagination/__tests__/pagination-test.js b/widgets/pagination/__tests__/pagination-test.js
index e8fdc7385f..b27d159782 100644
--- a/widgets/pagination/__tests__/pagination-test.js
+++ b/widgets/pagination/__tests__/pagination-test.js
@@ -99,6 +99,7 @@ describe('pagination()', () => {
padding: 3,
setCurrentPage: () => {},
showFirstLast: true,
+ createURL: () => '#',
...extraProps
};
}
diff --git a/widgets/pagination/pagination.js b/widgets/pagination/pagination.js
index 22069bfa26..eb6146da70 100644
--- a/widgets/pagination/pagination.js
+++ b/widgets/pagination/pagination.js
@@ -68,7 +68,7 @@ function pagination({
helper.search();
},
- render: function({results, helper}) {
+ render: function({results, helper, createURL, state}) {
var currentPage = results.page;
var nbPages = results.nbPages;
var nbHits = results.nbHits;
@@ -81,6 +81,7 @@ function pagination({
var Pagination = autoHide(require('../../components/Pagination/Pagination.js'));
ReactDOM.render(
createURL(state.setPage(page))}
cssClasses={cssClasses}
currentPage={currentPage}
hasResults={hasResults}
diff --git a/widgets/refinement-list/refinement-list.js b/widgets/refinement-list/refinement-list.js
index 555849af20..8eb6acadc1 100644
--- a/widgets/refinement-list/refinement-list.js
+++ b/widgets/refinement-list/refinement-list.js
@@ -76,7 +76,7 @@ function refinementList({
return widgetConfiguration;
},
- render: function({results, helper, templatesConfig}) {
+ render: function({results, helper, templatesConfig, state, createURL}) {
var templateProps = utils.prepareTemplateProps({
transformData,
defaultTemplates,
@@ -101,6 +101,7 @@ function refinementList({
ReactDOM.render(
createURL(state.toggleRefinement(facetName, facetValue))}
cssClasses={cssClasses}
facetValues={facetValues}
hasResults={facetValues.length > 0}
diff --git a/widgets/toggle/__tests__/toggle-test.js b/widgets/toggle/__tests__/toggle-test.js
index 652a2030b6..b33723f16b 100644
--- a/widgets/toggle/__tests__/toggle-test.js
+++ b/widgets/toggle/__tests__/toggle-test.js
@@ -91,7 +91,8 @@ describe('toggle()', () => {
cssClasses: {},
hideWhenNoResults: true,
templateProps,
- toggleRefinement: function() {}
+ toggleRefinement: function() {},
+ createURL: () => '#'
};
});
diff --git a/widgets/toggle/toggle.js b/widgets/toggle/toggle.js
index 40d7281c89..eac645e987 100644
--- a/widgets/toggle/toggle.js
+++ b/widgets/toggle/toggle.js
@@ -51,7 +51,7 @@ function toggle({
getConfiguration: () => ({
facets: [facetName]
}),
- render: function({helper, results, templatesConfig}) {
+ render: function({helper, results, templatesConfig, state, createURL}) {
var isRefined = helper.hasRefinements(facetName);
var values = find(results.getFacetValues(facetName), {name: isRefined.toString()});
@@ -70,6 +70,7 @@ function toggle({
ReactDOM.render(
createURL(state.toggleRefinement(facetName, facetValue.isRefined))}
cssClasses={cssClasses}
facetValues={[facetValue]}
hasResults={results.hits.length > 0}