todomvc
Version:
> Helping you select an MV\* framework
101 lines (79 loc) • 2.92 kB
JavaScript
/** MIT License (c) copyright B Cavalier & J Hann */
(function (define) {
define(function (require) {
var when;
when = require('when');
/**
* Returns a view of the supplied collection adapter, such that the view
* appears to contain transformed items, and delegates to the supplied
* adapter. If an inverse transform is supplied, either via the
* inverse param, or via transform.inverse, it will be used when items
* are added or removed
* @param adapter {Object} the adapter for which to create a transformed view
* @param transform {Function} the transform to apply to items. It may return
* a promise
* @param [inverse] {Function} inverse transform, can be provided explicitly
* if transform doesn't have an inverse property (transform.inverse). It may
* return a promise
*/
function transformCollection(adapter, transform, inverse) {
if(!transform) throw new Error('No transform supplied');
inverse = inverse || transform.inverse;
return {
comparator: adapter.comparator,
identifier: adapter.identifier,
forEach: function(lambda) {
var inflight;
// Ensure that these happen sequentially, even when
// the transform function is async
function transformedLambda(item) {
inflight = when(inflight, function() {
return when(transform(item), lambda);
});
return inflight;
}
return when(adapter.forEach(transformedLambda), function() {
return inflight;
});
},
add: makeTransformedAndPromiseAware(adapter, 'add', inverse),
remove: makeTransformedAndPromiseAware(adapter, 'remove', inverse),
update: makeTransformedAndPromiseAware(adapter, 'update', inverse),
clear: function() {
// return the original clear result since it may be a promise
return adapter.clear();
},
getOptions: function() {
return adapter.getOptions();
}
}
}
return transformCollection;
/**
* Creates a promise-aware version of the adapter method that supports
* transform functions that may return a promise
* @param adapter {Object} original adapter
* @param method {String} name of adapter method to make promise-aware
* @param transform {Function} transform function to apply to items
* before passing them to the original adapter method
* @return {Function} if transform is provided, returns a new function
* that applies the (possibly async) supplied transform and invokes
* the original adapter method with the transform result. If transform
* is falsey, a no-op function will be returned
*/
function makeTransformedAndPromiseAware(adapter, method, transform) {
return transform
? function(item) {
return when(transform(item), function(transformed) {
return adapter[method](transformed);
})
}
: noop;
}
function noop() {}
});
}(
typeof define == 'function'
? define
: function (factory) { module.exports = factory(require); }
));