diff --git a/dev/app.js b/dev/app.js
index 04c834c0d6..5bc556d963 100644
--- a/dev/app.js
+++ b/dev/app.js
@@ -277,6 +277,8 @@ search.addWidget(
templates: {
header: 'Price'
},
+ min: 100,
+ max: 500,
step: 10,
tooltips: {
format: function(formattedValue) {
diff --git a/src/widgets/range-slider/__tests__/range-slider-test.js b/src/widgets/range-slider/__tests__/range-slider-test.js
index dedcaa2a91..902986c48e 100644
--- a/src/widgets/range-slider/__tests__/range-slider-test.js
+++ b/src/widgets/range-slider/__tests__/range-slider-test.js
@@ -48,7 +48,6 @@ describe('rangeSlider()', () => {
rangeSlider.__Rewire__('headerFooterHOC', headerFooter);
container = document.createElement('div');
- widget = rangeSlider({container, attributeName: 'aNumAttr', cssClasses: {root: ['root', 'cx']}});
helper = new AlgoliasearchHelper(
{search: function() {}},
@@ -58,12 +57,90 @@ describe('rangeSlider()', () => {
sinon.spy(helper, 'addNumericRefinement');
sinon.spy(helper, 'clearRefinements');
sinon.spy(helper, 'search');
- widget.init({helper});
+ });
+
+ context('min option', () => {
+ it('refines when no previous configuration', () => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', min: 100});
+ expect(widget.getConfiguration()).toEqual({
+ disjunctiveFacets: ['aNumAttr'],
+ numericRefinements: {aNumAttr: {'>=': [100]}}
+ });
+ });
+
+ it('does not refine when previous configuration', () => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', min: 100});
+ expect(widget.getConfiguration({numericRefinements: {aNumAttr: {}}})).toEqual({
+ disjunctiveFacets: ['aNumAttr']
+ });
+ });
+
+ it('works along with max option', () => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', min: 100, max: 200});
+ expect(widget.getConfiguration()).toEqual({
+ disjunctiveFacets: ['aNumAttr'],
+ numericRefinements: {aNumAttr: {'>=': [100], '<=': [200]}}
+ });
+ });
+
+ it('sets the right ranges', () => {
+ results = {};
+ widget = rangeSlider({container, attributeName: 'aNumAttr', min: 100, max: 200});
+ helper.setState(widget.getConfiguration());
+ widget.init({helper});
+ widget.render({results, helper});
+ let props = {
+ cssClasses: {
+ root: 'ais-range-slider',
+ header: 'ais-range-slider--header',
+ body: 'ais-range-slider--body',
+ footer: 'ais-range-slider--footer'
+ },
+ collapsible: false,
+ onChange: () => {},
+ pips: true,
+ range: {max: 200, min: 100},
+ shouldAutoHideContainer: false,
+ start: [100, 200],
+ step: 1,
+ templateProps: {
+ templates: {footer: '', header: ''},
+ templatesConfig: undefined,
+ transformData: undefined,
+ useCustomCompileOptions: {footer: false, header: false}
+ },
+ tooltips: true
+ };
+
+ expect(ReactDOM.render.calledOnce).toBe(true, 'ReactDOM.render called once');
+ expect(autoHideContainer.calledOnce).toBe(true, 'autoHideContainer called once');
+ expect(headerFooter.calledOnce).toBe(true, 'headerFooter called once');
+ expect(ReactDOM.render.firstCall.args[0]).toEqualJSX();
+ });
+ });
+
+ context('max option', () => {
+ it('refines when no previous configuration', () => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', max: 100});
+ expect(widget.getConfiguration()).toEqual({
+ disjunctiveFacets: ['aNumAttr'],
+ numericRefinements: {aNumAttr: {'<=': [100]}}
+ });
+ });
+
+ it('does not refine when previous configuration', () => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', max: 100});
+ expect(widget.getConfiguration({numericRefinements: {aNumAttr: {}}})).toEqual({
+ disjunctiveFacets: ['aNumAttr']
+ });
+ });
});
context('without result', () => {
beforeEach(() => {
results = {};
+ widget = rangeSlider({container, attributeName: 'aNumAttr', cssClasses: {root: ['root', 'cx']}});
+ widget.init({helper});
});
it('calls ReactDOM.render(, container)', () => {
@@ -101,6 +178,8 @@ describe('rangeSlider()', () => {
context('when rangestats min === stats max', () => {
beforeEach(() => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', cssClasses: {root: ['root', 'cx']}});
+ widget.init({helper});
results = {
disjunctiveFacets: [{
name: 'aNumAttr',
@@ -150,6 +229,8 @@ describe('rangeSlider()', () => {
context('with results', () => {
beforeEach(() => {
+ widget = rangeSlider({container, attributeName: 'aNumAttr', cssClasses: {root: ['root', 'cx']}});
+ widget.init({helper});
results = {
disjunctiveFacets: [{
name: 'aNumAttr',
diff --git a/src/widgets/range-slider/range-slider.js b/src/widgets/range-slider/range-slider.js
index c81b8dd9b9..5fd498f7bf 100644
--- a/src/widgets/range-slider/range-slider.js
+++ b/src/widgets/range-slider/range-slider.js
@@ -38,6 +38,8 @@ let defaultTemplates = {
* @param {string|string[]} [options.cssClasses.footer] CSS class to add to the footer element
* @param {object|boolean} [options.collapsible=false] Hide the widget body and footer when clicking on header
* @param {boolean} [options.collapsible.collapsed] Initial collapsed state of a collapsible widget
+ * @param {number} [options.min] Minimal slider value, default to automatically computed from the result set
+ * @param {number} [options.max] Maximal slider value, defaults to automatically computed from the result set
* @return {Object}
*/
const usage = `Usage:
@@ -50,7 +52,9 @@ rangeSlider({
[ step=1 ],
[ pips=true ],
[ autoHideContainer=true ],
- [ collapsible=false ]
+ [ collapsible=false ],
+ [ min ],
+ [ max ]
});
`;
function rangeSlider({
@@ -62,7 +66,9 @@ function rangeSlider({
cssClasses: userCssClasses = {},
step = 1,
pips = true,
- autoHideContainer = true
+ autoHideContainer = true,
+ min: userMin,
+ max: userMax
} = {}) {
if (!container || !attributeName) {
throw new Error(usage);
@@ -82,9 +88,31 @@ function rangeSlider({
};
return {
- getConfiguration: () => ({
- disjunctiveFacets: [attributeName]
- }),
+ getConfiguration: (originalConf) => {
+ const conf = {
+ disjunctiveFacets: [attributeName]
+ };
+
+ if (
+ (userMin !== undefined || userMax !== undefined)
+ &&
+ (!originalConf ||
+ originalConf.numericRefinements &&
+ originalConf.numericRefinements[attributeName] === undefined)
+ ) {
+ conf.numericRefinements = {[attributeName]: {}};
+
+ if (userMin !== undefined) {
+ conf.numericRefinements[attributeName]['>='] = [userMin];
+ }
+
+ if (userMax !== undefined) {
+ conf.numericRefinements[attributeName]['<='] = [userMax];
+ }
+ }
+
+ return conf;
+ },
_getCurrentRefinement(helper) {
let min = helper.state.getNumericRefinement(attributeName, '>=');
let max = helper.state.getNumericRefinement(attributeName, '<=');
@@ -125,16 +153,27 @@ function rangeSlider({
},
render({results, helper}) {
let facet = find(results.disjunctiveFacets, {name: attributeName});
- let stats = facet !== undefined ? facet.stats : undefined;
- let currentRefinement = this._getCurrentRefinement(helper);
+ let stats;
+
+ if (userMin !== undefined || userMax !== undefined) {
+ stats = {};
+
+ if (userMin !== undefined) {
+ stats.min = userMin;
+ }
- if (stats === undefined) {
- stats = {
+ if (userMax !== undefined) {
+ stats.max = userMax;
+ }
+ } else {
+ stats = facet !== undefined && facet.stats !== undefined ? facet.stats : {
min: null,
max: null
};
}
+ let currentRefinement = this._getCurrentRefinement(helper);
+
if (tooltips.format !== undefined) {
tooltips = [{to: tooltips.format}, {to: tooltips.format}];
}