UNPKG

addsearch-search-ui

Version:

JavaScript library to develop Search UIs for the web

138 lines (110 loc) 4.08 kB
import './facets.scss'; import handlebars from 'handlebars'; import { FACETS_TEMPLATE } from './templates'; import { toggleFacetFilter } from '../../actions/filters'; import { search } from '../../actions/search'; import { observeStoreByKey } from '../../store'; import { validateContainer } from '../../util/dom'; import {createFilterObject} from "../filters/filterstateobserver"; export default class Facets { constructor(client, reduxStore, conf, baseFilters) { this.client = client; this.reduxStore = reduxStore; this.conf = conf; function _isEmpty(obj) { return !obj ? true : Object.keys(obj).length === 0; } var IGNORE_RENDERING_ON_REQUEST_BY = [ 'component.loadMore', 'component.pagination', 'component.sortby' ]; if (validateContainer(conf.containerId)) { observeStoreByKey(this.reduxStore, 'search', (search) => { var activeFacets = this.reduxStore.getState().filters.activeFacets; if (search.loading || IGNORE_RENDERING_ON_REQUEST_BY.indexOf(search.callBy) > -1) { return; } if (_isEmpty(activeFacets[this.conf.field]) || !this.conf.advancedSticky) { this.render(search); } else { var filterObjectCustom = createFilterObject( this.reduxStore.getState().filters, baseFilters, this.conf.field); if (search.callBy !== this.conf.field) { client.fetchCustomApi(this.conf.field, filterObjectCustom, res => { this.render(res, true); }) } } }); } } setFilter(value) { // Dispatch facet and refresh search this.reduxStore.dispatch(toggleFacetFilter(this.conf.field, value, true)); } render(search, isStickyFacetsRenderer) { if (search.loading) { return; } const facetField = this.conf.field; const results = isStickyFacetsRenderer ? search : search.results; // Facets in search results let facets = []; if (results && results.facets && results.facets[facetField]) { facets = results.facets[facetField]; } // Read active facets from redux state const activeFacets = this.getActiveFacets(facetField); // Sticky facets (i.e. not updating if keyword is unchanged) if (this.conf.sticky === true && !this.conf.advancedSticky) { // Keyword has changed, facets are not saved yet, or no selected facets. Show new incoming facets if (this.keyword !== search.keyword || !this.stickyFacets || activeFacets.length === 0) { this.keyword = search.keyword; this.stickyFacets = facets; } // Keyword not changed. Show old facets else { facets = this.stickyFacets; } } // Possible filtering function to remove unwanted facets if (this.conf.facetsFilter) { facets = this.conf.facetsFilter(facets); } // Render const data = { conf: this.conf, facets: facets }; // Compile HTML and inject to element if changed const html = handlebars.compile(this.conf.template || FACETS_TEMPLATE)(data); if (this.renderedHtml === html && activeFacets === this.renderedActiveFacets) { return; } this.renderedActiveFacets = activeFacets; const container = document.getElementById(this.conf.containerId); container.innerHTML = html; this.renderedHtml = html; // Attach events const options = container.getElementsByTagName('input'); for (let i=0; i<options.length; i++) { let checkbox = options[i]; checkbox.checked = activeFacets.indexOf(checkbox.value) !== -1; checkbox.onchange = (e) => { this.setFilter(e.target.value, e.target.checked); }; } } getActiveFacets(facetField) { // Read active facets from redux state let activeFacets = []; const activeFacetState = this.reduxStore.getState().filters.activeFacets; if (activeFacetState[facetField]) { for (let value in activeFacetState[facetField]) { activeFacets.push(value); } } return activeFacets; } }