UNPKG

addsearch-search-ui

Version:

JavaScript library to develop Search UIs for the web

132 lines (108 loc) 4.17 kB
import './sortby.scss'; import handlebars from 'handlebars'; import { SORTBY_TYPE } from './index'; import { sortBy } from '../../actions/sortby'; import { search } from '../../actions/search'; import { setPage } from '../../actions/pagination'; import { observeStoreByKey } from '../../store'; import { validateContainer } from '../../util/dom'; import PRECOMPILED_SORTBY_RADIOGROUP_TEMPLATE from './precompile-templates/sortby_radiogroup.handlebars'; import PRECOMPILED_SORTBY_SELECT_TEMPLATE from './precompile-templates/sortby_select.handlebars'; export default class SortBy { constructor(client, reduxStore, conf) { this.client = client; this.conf = conf; this.reduxStore = reduxStore; this.conf.options.forEach((option) => { option.sortBy = typeof option.sortBy === 'string' ? option.sortBy.split(',') : option.sortBy; option.order = typeof option.order === 'string' ? option.order.split(',') : option.order; }); if (validateContainer(conf.containerId)) { observeStoreByKey(this.reduxStore, 'sortby', (state) => this.render(state)); } } onChangeSelect(select) { const selectedOption = select.options[select.selectedIndex]; const field = selectedOption.getAttribute('data-field'); const order = selectedOption.getAttribute('data-order'); this.dispatchAndRefresh(field, order); } onChangeRadio(e) { const fields = e.target.getAttribute('data-field'); const orders = e.target.getAttribute('data-order'); this.dispatchAndRefresh(fields, orders); } dispatchAndRefresh(stringFields, stringOrders) { const fields = stringFields.split(','); const orders = stringOrders.split(','); // Dispatch sortby this.reduxStore.dispatch(sortBy(this.client, fields, orders, this.reduxStore)); // Reset paging this.reduxStore.dispatch(setPage(this.client, 1, null, this.reduxStore)); // Refresh search const keyword = this.reduxStore.getState().keyword.value; this.reduxStore.dispatch(search(this.client, keyword, null, null, null, this.reduxStore, null, 'component.sortby')); } arraysMatch(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } return arr1.every((element, index) => element === arr2[index]); } render(sortbyState) { const { field, order } = sortbyState; // Template let templateDefault = null; if (this.conf.type === SORTBY_TYPE.RADIO_GROUP) { templateDefault = PRECOMPILED_SORTBY_RADIOGROUP_TEMPLATE; } else { templateDefault = PRECOMPILED_SORTBY_SELECT_TEMPLATE; } // Data let data = Object.assign({}, this.conf); data.options.forEach(option => { if (this.arraysMatch(option.sortBy, field) && this.arraysMatch(option.order, order)) { option.active = true; } else { option.active = false; } }); // Compile HTML and inject to element if changed let html; if (this.conf.precompiledTemplate) { html = this.conf.precompiledTemplate(data); } else if (this.conf.template) { html = handlebars.compile(this.conf.template)(data); } else { html = templateDefault(data); } if (this.renderedHtml === html) { return; } const container = document.getElementById(this.conf.containerId); container.innerHTML = html; this.renderedHtml = html; // Attach listeners if (this.conf.type === SORTBY_TYPE.RADIO_GROUP) { const radioButtons = container.querySelectorAll('input'); for (let i=0; i<radioButtons.length; i++) { radioButtons[i].onclick = (e) => this.onChangeRadio(e); } } else { container.querySelector('select').onchange = (e) => this.onChangeSelect(e.target); // Pre-selected option if (sortbyState) { const options = container.getElementsByTagName('option'); for (let i=0; i<options.length; i++) { if (options[i].getAttribute('data-field') === field && options[i].getAttribute('data-order') === order) { container.querySelector('select').value = options[i].text; break; } } } } } }