coveo-search-ui
Version:
Coveo JavaScript Search Framework
130 lines (103 loc) • 4.28 kB
text/typescript
import { isFunction } from 'underscore';
import { QueryStateModel, QueryEvents, Component } from '../Core';
import { ComponentsTypes } from './ComponentsTypes';
import { $$ } from './Dom';
import { InitializationEvents } from '../events/InitializationEvents';
export interface IDependsOnCompatibleFacetOptions {
id?: string;
dependsOn?: string;
dependsOnCondition?: IDependentFacetCondition;
}
export interface IDependsOnCompatibleFacet extends Component {
options: IDependsOnCompatibleFacetOptions;
}
export interface IDependentFacet {
reset: () => void;
ref: IDependsOnCompatibleFacet;
}
export interface IDependentFacetCondition {
(facet: IDependsOnCompatibleFacet): boolean;
}
export class DependsOnManager {
private parentFacetRef: IDependsOnCompatibleFacet;
constructor(private facet: IDependentFacet) {
$$(this.facet.ref.searchInterface.element).on(QueryEvents.buildingQuery, () => this.handleBuildingQuery());
if (this.getDependsOn(this.facet.ref)) {
this.facet.ref.bind.onRootElement(InitializationEvents.afterComponentsInitialization, () => this.setupDependentFacet());
}
}
private setupDependentFacet() {
$$(this.facet.ref.element).addClass('coveo-hidden-dependant-facet');
this.parentFacetRef = this.getParentFacet(this.facet.ref);
if (this.parentFacetRef) {
$$(this.facet.ref.root).on('state:change', () => this.resetIfConditionUnfullfiled());
}
}
private resetIfConditionUnfullfiled() {
const condition = this.getDependsOnCondition(this.facet.ref);
if (!condition(this.parentFacetRef)) {
this.facet.reset();
}
}
private getId(component: IDependsOnCompatibleFacet) {
const id = component.options.id;
return id ? `${id}` : null;
}
private getDependsOn(component: IDependsOnCompatibleFacet) {
const dependsOn = component.options.dependsOn;
return dependsOn ? `${dependsOn}` : null;
}
private getDependsOnCondition(component: IDependsOnCompatibleFacet): IDependentFacetCondition {
const conditionOption = component.options.dependsOnCondition;
return conditionOption && isFunction(conditionOption)
? conditionOption
: () => this.parentHasSelectedValues(component) && this.parentIsEnabled(component);
}
private parentHasSelectedValues(component: IDependsOnCompatibleFacet) {
const parent = this.getParentFacet(component);
return parent && this.valuesExistForFacetWithId(this.getId(parent));
}
private parentIsEnabled(component: IDependsOnCompatibleFacet) {
const parent = this.getParentFacet(component);
return parent && !parent.disabled;
}
private valuesExistForFacetWithId(facetId: string) {
const values = this.facet.ref.queryStateModel.get(QueryStateModel.getFacetId(facetId));
return !!values && !!values.length;
}
private get allFacetsInInterface() {
return ComponentsTypes.getAllFacetsFromSearchInterface(this.facet.ref.searchInterface) as IDependsOnCompatibleFacet[];
}
private getParentFacet(component: IDependsOnCompatibleFacet) {
const parent = this.allFacetsInInterface.filter(
potentialParentFacet => this.getId(potentialParentFacet) === this.getDependsOn(component)
);
if (!parent.length) {
component.logger.warn('DependsOn reference does not exist', this.getDependsOn(this.facet.ref));
return null;
}
return parent[0];
}
private get dependentFacets() {
return this.allFacetsInInterface.filter(
potentialDependentFacet => this.getId(this.facet.ref) === this.getDependsOn(potentialDependentFacet)
);
}
private handleBuildingQuery() {
this.dependentFacets.forEach(dependentFacet => {
const condition = this.getDependsOnCondition(dependentFacet);
if (condition(this.facet.ref)) {
$$(dependentFacet.element).removeClass('coveo-hidden-dependant-facet');
return dependentFacet.enable();
}
dependentFacet.disable();
$$(dependentFacet.element).addClass('coveo-hidden-dependant-facet');
});
}
public get hasDependentFacets() {
return !!this.dependentFacets.length;
}
public get dependentFacetsHaveSelectedValues() {
return this.dependentFacets.some(dependentFacet => this.valuesExistForFacetWithId(this.getId(dependentFacet)));
}
}