Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Fix/72 #75

Merged
merged 4 commits into from
May 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 53 additions & 31 deletions src/SearchParameters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,19 @@ var SearchParameters = function( newParameters ) {

/**
* Possible values : prefixAll, prefixLast, prefixNone
* @see https://www.algolia.com/doc#queryType
* @see https://www.algolia.com/doc#queryType
* @member {string}
*/
this.queryType = params.queryType;
/**
* Possible values : true, false, min, strict
* @see https://www.algolia.com/doc#typoTolerance
* @see https://www.algolia.com/doc#typoTolerance
* @member {string}
*/
this.typoTolerance = params.typoTolerance;

/**
* @see https://www.algolia.com/doc#minWordSizefor1Typo
* @see https://www.algolia.com/doc#minWordSizefor1Typo
* @member {number}
*/
this.minWordSizefor1Typo = params.minWordSizefor1Typo;
Expand All @@ -92,108 +92,108 @@ var SearchParameters = function( newParameters ) {
*/
this.minWordSizefor2Typos = params.minWordSizefor2Typos;
/**
* @see https://www.algolia.com/doc#allowTyposOnNumericTokens
* @see https://www.algolia.com/doc#allowTyposOnNumericTokens
* @member {boolean}
*/
this.allowTyposOnNumericTokens = params.allowTyposOnNumericTokens;
/**
* @see https://www.algolia.com/doc#ignorePlurals
* @see https://www.algolia.com/doc#ignorePlurals
* @member {boolean}
*/
this.ignorePlurals = params.ignorePlurals;
/**
* @see https://www.algolia.com/doc#restrictSearchableAttributes
* @see https://www.algolia.com/doc#restrictSearchableAttributes
* @member {string}
*/
this.restrictSearchableAttributes = params.restrictSearchableAttributes;
/**
* @see https://www.algolia.com/doc#advancedSyntax
* @see https://www.algolia.com/doc#advancedSyntax
* @member {boolean}
*/
this.advancedSyntax = params.advancedSyntax;
/**
* @see https://www.algolia.com/doc#analytics
* @see https://www.algolia.com/doc#analytics
* @member {boolean}
*/
this.analytics = params.analytics;
/**
* @see https://www.algolia.com/doc#analyticsTags
* @see https://www.algolia.com/doc#analyticsTags
* @member {string}
*/
this.analyticsTags = params.analyticsTags;
/**
* @see https://www.algolia.com/doc#synonyms
* @see https://www.algolia.com/doc#synonyms
* @member {boolean}
*/
this.synonyms = params.synonyms;
/**
* @see https://www.algolia.com/doc#replaceSynonymsInHighlight
* @see https://www.algolia.com/doc#replaceSynonymsInHighlight
* @member {boolean}
*/
this.replaceSynonymsInHighlight = params.replaceSynonymsInHighlight;
/**
* @see https://www.algolia.com/doc#optionalWords
* @see https://www.algolia.com/doc#optionalWords
* @member {string}
*/
this.optionalWords = params.optionalWords;
/**
* possible values are "lastWords" "firstWords" "allOptionnal" "none" (default)
* @see https://www.algolia.com/doc#removeWordsIfNoResults
* @see https://www.algolia.com/doc#removeWordsIfNoResults
* @member {string}
*/
this.removeWordsIfNoResults = params.removeWordsIfNoResults;
/**
* @see https://www.algolia.com/doc#attributesToRetrieve
* @see https://www.algolia.com/doc#attributesToRetrieve
* @member {string}
*/
this.attributesToRetrieve = params.attributesToRetrieve;
/**
* @see https://www.algolia.com/doc#attributesToHighlight
* @see https://www.algolia.com/doc#attributesToHighlight
* @member {string}
*/
this.attributesToHighlight = params.attributesToHighlight;
/**
* @see https://www.algolia.com/doc#attributesToSnippet
* @see https://www.algolia.com/doc#attributesToSnippet
* @member {string}
*/
this.attributesToSnippet = params.attributesToSnippet;
/**
* @see https://www.algolia.com/doc#getRankingInfo
* @see https://www.algolia.com/doc#getRankingInfo
* @member {integer}
*/
this.getRankingInfo = params.getRankingInfo;
/**
* @see https://www.algolia.com/doc#tagFilters
* @see https://www.algolia.com/doc#tagFilters
* @member {string}
*/
this.tagFilters = params.tagFilters;
/**
* @see https://www.algolia.com/doc#distinct
* @see https://www.algolia.com/doc#distinct
* @member {boolean}
*/
this.distinct = params.distinct;
/**
* @see https://www.algolia.com/doc#aroundLatLng
* @see https://www.algolia.com/doc#aroundLatLng
* @member {string}
*/
this.aroundLatLng = params.aroundLatLng;
/**
* @see https://www.algolia.com/doc#aroundLatLngViaIP
* @see https://www.algolia.com/doc#aroundLatLngViaIP
* @member {boolean}
*/
this.aroundLatLngViaIP = params.aroundLatLngViaIP;
/**
* @see https://www.algolia.com/doc#aroundRadius
* @see https://www.algolia.com/doc#aroundRadius
* @member {number}
*/
this.aroundRadius = params.aroundRadius;
/**
* @see https://www.algolia.com/doc#aroundPrecision
* @see https://www.algolia.com/doc#aroundPrecision
* @member {number}
*/
this.aroundPrecision = params.aroundPrecision;
/**
* @see https://www.algolia.com/doc#insideBoundingBox
* @see https://www.algolia.com/doc#insideBoundingBox
* @member {string}
*/
this.insideBoundingBox = params.insideBoundingBox;
Expand Down Expand Up @@ -336,7 +336,7 @@ SearchParameters.prototype = {
* @param {string} operator applied
* @return {number} value of the refinement
*/
getNumericRefinement : function( attribute, operator ){
getNumericRefinement : function( attribute, operator ) {
return this.numericRefinements[ attribute ] && this.numericRefinements[ attribute ][ operator ];
},
/**
Expand Down Expand Up @@ -365,9 +365,16 @@ SearchParameters.prototype = {
* @return {SearchParameters}
*/
addFacetRefinement : function addFacetRefinement( facet, value ) {
if( this.isRefined( facet, value ) ) {
return this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it return a this.mutateMe(noop) instead ? So the return of addFacetRefinement is consistenly a new object ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case isRefined( facet, value ) returns true, it would mean that there would be no changes, so might as well avoid creating a new instance (there are thousands of case we create useless new objects, true :D, it's just continuous improvement here)

}

return this.mutateMe( function( m ) {
m.page = 0;
m.facetsRefinements[ facet ] = value;
if( !m.facetsRefinements[ facet ] ) {
m.facetsRefinements[ facet ] = [];
}
m.facetsRefinements[ facet ].push( value );
} );
},
/**
Expand Down Expand Up @@ -403,15 +410,29 @@ SearchParameters.prototype = {
} );
},
/**
* Remove a refinement set on facet.
* Remove a refinement set on facet. If a value is provided, it will clear the
* refinement for the given value, otherwise it will clear all the refinement
* values for the facetted attribute.
* @method
* @param {string} facet
* @param {string} value
* @return {SearchParameters}
*/
removeFacetRefinement : function removeFacetRefinement( facet ) {
removeFacetRefinement : function removeFacetRefinement( facet, value ) {
return this.mutateMe( function( m ) {
m.page = 0;
m._clearFacetRefinements( facet );
if( value ) {
var idx = m.facetsRefinements[ facet ].indexOf( value );
if( idx > -1 ) {
m.facetsRefinements[ facet ].splice( idx, 1 );
if( m.facetsRefinements[ facet ].length === 0 ) {
delete m.facetsRefinements[ facet ];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to delete the array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually we remove the key from the object so when iterating with a for in we don't need to check for the content.

}
}
}
else {
m._clearFacetRefinements( facet );
}
} );
},
/**
Expand Down Expand Up @@ -519,7 +540,7 @@ SearchParameters.prototype = {
*/
toggleFacetRefinement : function toggleFacetRefinement( facet, value ) {
if( this.isFacetRefined( facet, value ) ) {
return this.removeFacetRefinement( facet );
return this.removeFacetRefinement( facet, value );
}
else {
return this.addFacetRefinement( facet, value );
Expand Down Expand Up @@ -563,7 +584,8 @@ SearchParameters.prototype = {
* @return {boolean}
*/
isFacetRefined : function isFacetRefined( facet, value ) {
return this.facetsRefinements[ facet ] === value;
return this.facetsRefinements[ facet ] &&
this.facetsRefinements[ facet ].indexOf( value ) !== -1;
},
/**
* Returns true if the couple (facet, value) is excluded
Expand Down
2 changes: 1 addition & 1 deletion src/SearchResults/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ var SearchResults = function( state, algoliaResponse ) {
forEach( result.facets, function( facetResults, dfacet ) {
var position = disjunctiveFacetsIndices[ dfacet ];

var dataFromMainRequest = mainSubResponse.facets[ dfacet ];
var dataFromMainRequest = ( mainSubResponse.facets && mainSubResponse.facets[ dfacet ] ) || {};
this.disjunctiveFacets[ position ] = {
name : dfacet,
data : extend( {}, facetResults, dataFromMainRequest )
Expand Down
6 changes: 4 additions & 2 deletions src/algoliasearch.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,10 @@ AlgoliaSearchHelper.prototype._hasDisjunctiveRefinements = function( facet ) {
AlgoliaSearchHelper.prototype._getFacetFilters = function( facet ) {
var facetFilters = [];

forEach( this.state.facetsRefinements, function( facetValue, facetName ) {
facetFilters.push( facetName + ":" + facetValue );
forEach( this.state.facetsRefinements, function( facetValues, facetName ) {
forEach( facetValues, function( facetValue ) {
facetFilters.push( facetName + ":" + facetValue );
} );
} );

forEach( this.state.facetsExcludes, function( facetValues, facetName ) {
Expand Down
1 change: 0 additions & 1 deletion test/spec/SearchParameters.getRefinedDisjunctiveFacets.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use strict";

var test = require( "tape" );
//var _ = require( "lodash" );
var SearchParameters = require( "../../src/SearchParameters" );
Expand Down
9 changes: 4 additions & 5 deletions test/spec/helper.clears.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use strict";

var test = require( "tape" ),
algoliasearchHelper = require( "../../index" ),
isUndefined = require( "lodash/lang/isUndefined" );
Expand All @@ -25,7 +24,7 @@ var init = function init() {
test( "Check that the state objects match how we test them", function( t ) {
var helper = init();

t.deepEqual( helper.state.facetsRefinements, { "facet1" : "0", "facet2" : "0" } );
t.deepEqual( helper.state.facetsRefinements, { "facet1" : [ "0" ], "facet2" : [ "0" ] } );
t.deepEqual( helper.state.disjunctiveFacetsRefinements, { "disjunctiveFacet1" : [ "0" ], "disjunctiveFacet2" : [ "0" ] } );
t.deepEqual( helper.state.facetsExcludes, { "excluded1" : [ "0" ], "excluded2" : [ "0" ] } );
t.deepEqual( helper.state.numericRefinements, { "numeric1" : { ">=" : "0", "<" : "10" }, "numeric2" : { ">=" : 0, "<" : 10 } } );
Expand All @@ -37,7 +36,7 @@ test( "Clear with a name should work on every type and not remove others than ta
var helper = init();

helper.clearRefinements( "facet1" );
t.deepEqual( helper.state.facetsRefinements, { "facet2" : "0" } );
t.deepEqual( helper.state.facetsRefinements, { "facet2" : [ "0" ] } );

helper.clearRefinements( "disjunctiveFacet1" );
t.deepEqual( helper.state.disjunctiveFacetsRefinements, { "disjunctiveFacet2" : [ "0" ] } );
Expand All @@ -57,7 +56,7 @@ test( "Clearing the same field from multiple elements should remove it everywher

helper.addNumericRefinement( "facet1", ">=", "10" ).toggleExclude( "facet1", "value" );

t.equal( helper.state.facetsRefinements.facet1, "0" );
t.deepEqual( helper.state.facetsRefinements.facet1, [ "0" ] );
t.deepEqual( helper.state.numericRefinements.facet1, { ">=" : "10" } );
t.deepEqual( helper.state.facetsExcludes.facet1, [ "value" ] );

Expand All @@ -72,7 +71,7 @@ test( "Clearing the same field from multiple elements should remove it everywher
test( "Clearing twice the same attribute should be not problem", function( t ) {
var helper = init();

t.equal( helper.state.facetsRefinements.facet1, "0" );
t.deepEqual( helper.state.facetsRefinements.facet1, [ "0" ] );
helper.clearRefinements( "facet1" );
t.assert( isUndefined( helper.state.facetsRefinements.facet1 ) );
t.doesNotThrow( function() {
Expand Down
1 change: 1 addition & 0 deletions test/spec/helper.constructor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
var test = require("tape");
var _ = require( "lodash" );
var sinon = require("sinon");
Expand Down
7 changes: 3 additions & 4 deletions test/spec/refinements.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ test( "Adding refinments should add an entry to the refinments attribute", funct
var facetValue = "42";

t.ok( _.isEmpty( helper.state.facetsRefinements ), "should be empty at first" );
helper.addRefine( facetName, "42" );
t.ok( _.size( helper.state.facetsRefinements ) === 1 &&
helper.state.facetsRefinements.facet1 === facetValue,
"when adding a refinment, should have one" );
helper.addRefine( facetName, facetValue );
t.ok( _.size( helper.state.facetsRefinements ) === 1, "when adding a refinment, should have one" );
t.deepEqual( helper.state.facetsRefinements.facet1, [ facetValue ] );
helper.addRefine( facetName, facetValue );
t.ok( _.size( helper.state.facetsRefinements ) === 1, "when adding the same, should still be one" );
helper.removeRefine( facetName, facetValue );
Expand Down
1 change: 0 additions & 1 deletion test/spec/search.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use strict";

var test = require("tape");
var sinon = require("sinon");
var algoliaSearch = require( "algoliasearch" );
Expand Down