isomorphic-search
Version:
A configurable search interface.
163 lines (129 loc) • 4.66 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(['exports', './abstraction', './presentation'], factory);
} else if (typeof exports !== "undefined") {
factory(exports, require('./abstraction'), require('./presentation'));
} else {
var mod = {
exports: {}
};
factory(mod.exports, global.abstraction, global.presentation);
global.control = mod.exports;
}
})(this, function (exports, _abstraction, _presentation) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _abstraction2 = _interopRequireDefault(_abstraction);
var _presentation2 = _interopRequireDefault(_presentation);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
/**
* Search agent's control.
*/
var control = {
constructor: function constructor() {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
// Configure.
this.abstraction = Object.assign(_abstraction2.default, options);
this.presentation = _presentation2.default;
// Run.
this.set(data);
// Enable chaining.
return this;
},
engine: function 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;
},
onSearch: function onSearch() {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var search = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var engine = arguments[2];
var results = engine(search);
this.presentation.renderSearchResults(results, this.abstraction);
return results;
},
execute: function execute(abstraction, data, engine) {
var $el = abstraction.$el,
attr = abstraction.attr,
$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;
},
set: function set(data) {
var 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;
},
renderForm: function renderForm(data) {
var 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;
},
renderResults: function renderResults(model, data) {
var _this = this;
var $el = model.$el,
metadata = model.metadata,
template = model.template,
callback = metadata && metadata.result ? metadata.result.callback : false;
// Render results view.
this.presentation.render($el.container, template.results(model), { action: 'append' });
// Get results list.
var resultsList = model.$el.resultsList;
// Render each potential result.
data.forEach(function (datum) {
// Render.
_this.presentation.render(resultsList, template.list(datum, model), { action: 'append' });
// Execute callback on this list item.
if (callback) {
callback(datum);
}
});
}
};
exports.default = control;
});