UNPKG

addsearch-search-ui

Version:

JavaScript library to develop Search UIs for the web

118 lines (94 loc) 3.44 kB
import './sortby.scss'; import handlebars from 'handlebars'; import { SORTBY_TYPE } from './index'; import { SORTBY_RADIOGROUP_TEMPLATE, SORTBY_SELECT_TEMPLATE} from './templates'; import { sortBy } from '../../actions/sortby'; import { search } from '../../actions/search'; import { setPage } from '../../actions/pagination'; import { observeStoreByKey } from '../../store'; import { validateContainer } from '../../util/dom'; export default class SortBy { constructor(client, reduxStore, conf) { this.client = client; this.conf = conf; this.reduxStore = reduxStore; 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')); } render(sortbyState) { const { field, order } = sortbyState; // Template let template = null; if (this.conf.template) { template = this.conf.template; } else if (this.conf.type === SORTBY_TYPE.RADIO_GROUP) { template = SORTBY_RADIOGROUP_TEMPLATE; } else { template = SORTBY_SELECT_TEMPLATE; } // Data let data = Object.assign({}, this.conf); data.options.forEach(option => { if (option.sortBy === field && option.order === order) { option.active = true; } else { option.active = false; } }); // Compile HTML and inject to element if changed const html = handlebars.compile(template)(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; } } } } } }