coveo-search-ui
Version:
Coveo JavaScript Search Framework
228 lines (195 loc) • 7.25 kB
text/typescript
import { Assert } from '../../misc/Assert';
import { Utils } from '../../utils/Utils';
import { IGroupByResult } from '../../rest/GroupByResult';
import { FacetValue } from './FacetValue';
import * as _ from 'underscore';
import { FacetValuesOrder } from './FacetValuesOrder';
export interface ISortFacetValuesOptions {
facetValuesOrder: FacetValuesOrder;
numberOfValues: number;
}
export class FacetValues {
private values: FacetValue[];
constructor(groupByResult?: IGroupByResult) {
if (Utils.exists(groupByResult)) {
this.values = _.map(groupByResult.values, groupByValue => FacetValue.createFromGroupByValue(groupByValue));
} else {
this.values = [];
}
}
add(facetValue: FacetValue) {
Assert.exists(facetValue);
Assert.check(!this.contains(facetValue.value));
this.values.push(facetValue);
}
remove(value: string) {
Assert.isNonEmptyString(value);
value = value;
this.values = _.filter(this.values, (elem: FacetValue) => elem.value != value);
}
size(): number {
return this.values.length;
}
isEmpty(): boolean {
return this.values.length == 0;
}
at(index: number): FacetValue {
Assert.isLargerOrEqualsThan(0, index);
Assert.isSmallerThan(this.values.length, index);
return this.values[index];
}
get(value: string): FacetValue {
return _.find(this.values, (elem: FacetValue) => elem.value.toLowerCase() == value.toLowerCase());
}
contains(value: string): boolean {
return Utils.exists(this.get(value));
}
getAll(): FacetValue[] {
return this.values;
}
getSelected(): FacetValue[] {
return _.filter(this.values, (value: FacetValue) => value.selected);
}
getExcluded(): FacetValue[] {
return _.filter(this.values, (value: FacetValue) => value.excluded);
}
hasSelectedOrExcludedValues(): boolean {
return this.getSelected().length != 0 || this.getExcluded().length != 0;
}
hasSelectedAndExcludedValues(): boolean {
return this.getSelected().length != 0 && this.getExcluded().length != 0;
}
hasOnlyExcludedValues(): boolean {
return this.getSelected().length == 0 && this.getExcluded().length != 0;
}
hasOnlySelectedValues(): boolean {
return this.getSelected().length != 0 && this.getExcluded().length == 0;
}
reset() {
_.each(this.values, (elem: FacetValue) => elem.reset());
}
importActiveValuesFromOtherList(other: FacetValues) {
Assert.exists(other);
_.each(other.getSelected(), (otherValue: FacetValue) => {
var myValue = this.get(otherValue.value);
if (Utils.exists(myValue)) {
myValue.selected = true;
} else {
this.values.push(otherValue.cloneWithZeroOccurrences());
}
});
_.each(other.getExcluded(), (otherValue: FacetValue) => {
var myValue = this.get(otherValue.value);
if (Utils.exists(myValue)) {
myValue.excluded = true;
} else if (otherValue.occurrences != 0) {
var occurrences = otherValue.occurrences;
var clone = otherValue.cloneWithZeroOccurrences();
clone.occurrences = occurrences;
this.values.push(clone);
} else {
this.values.push(otherValue.cloneWithZeroOccurrences());
}
});
}
updateCountsFromNewValues(newValues: FacetValues) {
Assert.exists(newValues);
this.values = _.map(this.values, (myValue: FacetValue) => {
var newValue = newValues.get(myValue.value);
if (Utils.exists(newValue)) {
myValue.updateCountsFromNewValue(newValue);
return myValue;
} else if (myValue.occurrences == null) {
return myValue.cloneWithZeroOccurrences();
}
return myValue;
});
}
updateDeltaWithFilteredFacetValues(filtered: FacetValues, isMultiValueField: boolean) {
Assert.exists(filtered);
_.each(this.values, (unfilteredValue: FacetValue) => {
var filteredValue = filtered.get(unfilteredValue.value);
unfilteredValue.waitingForDelta = false;
if (Utils.exists(filteredValue)) {
if (unfilteredValue.occurrences - filteredValue.occurrences > 0) {
// When there are only exclusion in the facet, there should be no "delta"
// The number of value for each facet will be what is selected, no addition.
if (this.hasOnlyExcludedValues()) {
unfilteredValue.delta = null;
unfilteredValue.occurrences = filteredValue.occurrences;
} else {
unfilteredValue.delta = unfilteredValue.occurrences - filteredValue.occurrences;
}
} else {
unfilteredValue.delta = null;
}
} else if (!unfilteredValue.selected && !unfilteredValue.excluded) {
if (isMultiValueField && filtered.values.length == 0) {
unfilteredValue.delta = null;
unfilteredValue.occurrences = 0;
} else {
unfilteredValue.delta = unfilteredValue.occurrences;
}
}
});
}
mergeWithUnfilteredFacetValues(unfiltered: FacetValues) {
Assert.exists(unfiltered);
var values: FacetValue[] = [];
_.each(unfiltered.values, (unfilteredValue: FacetValue) => {
var filteredValue = this.get(unfilteredValue.value);
if (Utils.exists(filteredValue)) {
if (filteredValue.occurrences == unfilteredValue.occurrences) {
values.push(filteredValue);
} else {
values.push(unfilteredValue.cloneWithDelta(unfilteredValue.occurrences, unfilteredValue.occurrences - filteredValue.occurrences));
}
} else {
values.push(unfilteredValue.cloneWithDelta(unfilteredValue.occurrences, unfilteredValue.occurrences));
}
});
var index = 0;
_.each(this.values, (value: FacetValue) => {
var unfilteredValue = unfiltered.get(value.value);
if (!Utils.exists(unfilteredValue)) {
if (value.selected || value.excluded) {
values.splice(index, 0, value);
index++;
}
} else {
for (var i = 0; i < values.length; i++) {
if (values[i].value == value.value) {
index = i + 1;
break;
}
}
}
});
this.values = values;
}
sort(options: ISortFacetValuesOptions) {
const { facetValuesOrder, numberOfValues } = options;
this.values = facetValuesOrder.reorderValuesIfUsingAlphabeticalSort(this.values);
this.sortValuesDependingOnStatus(numberOfValues);
this.values = facetValuesOrder.reorderValuesIfUsingCustomSort(this.values);
}
sortValuesDependingOnStatus(numOfDisplayedValues: number) {
this.values = _.sortBy(this.values, (value: FacetValue) => {
if (value.selected) {
return 1;
} else if (value.excluded) {
return 3;
} else {
return 2;
}
});
this.ensureExcludedValuesAreDisplayed(numOfDisplayedValues);
}
private ensureExcludedValuesAreDisplayed(numOfDisplayedValues: number) {
if (numOfDisplayedValues != null && numOfDisplayedValues < this.values.length) {
var nbExclude = this.getExcluded().length;
var excludedValues = this.values.splice(this.values.length - nbExclude, nbExclude);
this.values.splice(numOfDisplayedValues - nbExclude, 0, ...excludedValues);
}
}
}