UNPKG

isomorphic-search

Version:
155 lines (128 loc) 4.12 kB
/** * Client-side */ let presentation = { // Inserts element into DOM at proper index. insertAt($container, action, index, content) { let siblings = $container.children(); if (siblings.length) { return siblings.eq(index).after(content); } return $container[action](content); }, // Sets given template on view. render($container, content, {action='append', index=false}) { if (!index && index !== 0) { $container[action](content); } else { this.insertAt($container, content, {action, index}); } return }, /** * Renders search results to the view. * * @param {array} results * @param {object} abstraction * @return {array} results */ renderSearchResults(results, abstraction) { // Reset view. abstraction.$el.noResults.remove(); // Get elements. let {$el, el, attr, identifier, template} = abstraction, hiddenClass = attr.hidden, $results = $el.results, $resultsList = $el.resultsList, $li = $el.result, li = el.result; // Empty view before rendering results only. $li.addClass(hiddenClass); if (!results || !results.length) { $resultsList.prepend(template.noResults(abstraction)); return results; } results.forEach((result) => { // Display matching search result. $results. find(`${li}[data-${identifier}="${result[identifier]}"]`). removeClass(hiddenClass); }); return results; }, search: { // Cancel search. cancel: (event, {attr, $el, icon, metadata}) => { let cancelClass = icon.cancel, hiddenClass = attr.hidden, iconClasses = `${cancelClass} ${icon.search}`, {input} = metadata, search = $el.input.val(); // Reset value of search field. $el.input.val(''); // Remove no results view. $el.noResults.remove(); // Hide results from view. $el.results.addClass(hiddenClass); // Reveal individual results so they'll be exposed with container. $el.result.removeClass(hiddenClass); // Toggle from cancel button to search button. $el.container.find(`.${cancelClass}`).toggleClass(iconClasses); // Execute callback. if (input && input.cancel && input.cancel.callback) { input.cancel.callback(event, search); } }, // Update input. // @TODO Review change method. change: (event, abstraction, data, engine, searchCallback) => { const {input} = abstraction.metadata; // Execute search. let search = searchCallback(abstraction, data, engine); // Execute callback on change. if (input && input.change && input.change.callback) { input.change.callback(event, search); } }, // Focus on input. focus: (event, abstraction) => { let {$el, attr, icon, template, metadata} = abstraction, {input} = metadata, hiddenClass = attr.hidden, search = $el.input.val(); // Replace the search icon with the cancel icon. $el.submit.removeClass(icon.search).addClass(icon.cancel); // Display all potential results. $el.results.removeClass(hiddenClass); // Execute callback. if (input && input.focus && input.focus.callback) { input.focus.callback(event, search); } return true; } }, // Set events on view. bind(abstraction, data, engine, onChangeCallback) { let {attr, $el, icon} = abstraction; // Set events on search input. $el.input. off(). on('focus', (event) => { this.search.focus(event, abstraction); }). on('keyup, paste, input', (event) => { this.search.change(event, abstraction, data, engine, onChangeCallback); }); $el.menu. off(). // Set events on search icon. on('click', `.${icon.search}`, (event) => { this.search.focus(event, abstraction); }). // Set events on cancel icon. on('click', `.${icon.cancel}`, (event) => { this.search.cancel(event, abstraction); }); } }; export default presentation;