UNPKG

isomorphic-search

Version:
149 lines (117 loc) 3.68 kB
/** * Search agent's control. */ import abstraction from './abstraction'; import presentation from './presentation'; let control = { // Runs module with the given configurations. constructor(data=[], options={}) { // Configure. this.abstraction = Object.assign(abstraction, options); this.presentation = presentation; // Run. this.set(data); // Enable chaining. return this; }, // Instantiate & configure search engine. engine(engine, data, options) { // Notify if search engine has not been set. if (!engine) { return this.abstraction.notify(this.abstraction.messages.engine); } // Instantiate. if (typeof engine === 'function') { engine = new engine(data, options); } // Get search method. if (engine.search && typeof engine.search === 'function') { engine = engine.search.bind(engine); } // Save instantiated engine to abstraction. this.abstraction.search = engine; return engine; }, // Executes search and shows results. onSearch(data=[], search='', engine) { let results = engine(search); this.presentation.renderSearchResults(results, this.abstraction); return results; }, /** * Sends user's search to server. * * @param {string} input An element selector for the search input. * @return {string} The user's entry into the search input. */ execute(abstraction, data, engine) { let {$el, attr} = abstraction, $input = $el.input, search = $input.val(), hiddenClass = attr.hidden, eachResult = $el.result; // Handle empty search value. if (!search) { // Show all possible results. eachResult.removeClass(hiddenClass); return search; } // Initiate search for user input. this.onSearch(data, search, engine); return search; }, /** * Sets search form and its events on the view. * * @return {array} An array of searchable objects. */ set(data) { const model = this.abstraction, valid = model.validate(data); if (valid !== true) { return this.abstraction.notify(valid); } // Render form and bind events to it. this.renderForm(data); // Render results. this.renderResults(model, data); return data; }, // Sets search form on view, and sets events in anticipation of a search. renderForm(data) { const model = this.abstraction, $parent = model.$el.parent, form = model.template.form, engine = this.engine(model.engine, data, model.options), metadata = model.metadata, callback = metadata && metadata.form && metadata.form.callback ? metadata.form.callback : this.execute.bind(this); // Render form. this.presentation.render($parent, form(model), {action: 'prepend'}); // Bind events to view. this.presentation.bind(model, data, engine, callback); return true; }, // Render results. renderResults(model, data) { let {$el, metadata, template} = model, callback = metadata && metadata.result ? metadata.result.callback : false; // Render results view. this.presentation.render( $el.container, template.results(model), {action: 'append'}); // Get results list. let resultsList = model.$el.resultsList; // Render each potential result. data.forEach((datum) => { // Render. this.presentation.render( resultsList, template.list(datum, model), {action: 'append'}); // Execute callback on this list item. if (callback) { callback(datum); } }); } } export default control;