diff --git a/source/Ox/js/Array.js b/source/Ox/js/Array.js index 31fcc9cc..3309fcb5 100644 --- a/source/Ox/js/Array.js +++ b/source/Ox/js/Array.js @@ -1,5 +1,175 @@ 'use strict'; +/*@ +Ox.api Turns an array into a list API + (items) -> List API + (items, keys) -> List API + items <[o]> An array of objects + keys <[s]> Array of keys to be included in totals + + > Ox.test.apiResults[0].data + {items: 3, n: 5} + > Ox.test.apiResults[1].data + {items: [{id: 'foo', n: 2}, {id: 'bar', n: 2}, {id: 'baz', n: 1}]} + > Ox.test.apiResults[2].data + {items: [{id: 'bar'}, {id: 'foo'}, {id: 'baz'}]} + > Ox.test.apiResults[3].data + {items: [{id: 'bar', n: 2}]} + > Ox.test.apiResults[4].data + {items: [{id: 'baz', n: 1}, {id: 'foo', n: 2}]} + > Ox.test.apiResults[5].data + {items: [{id: 'baz', n: 1}, {id: 'foo', n: 2}]} + > Ox.test.apiResults[6].data + {items: [{id: 'baz', n: 1}]} +@*/ +Ox.api = function(items, keys) { + keys = keys || []; + function testCondition(item, condition) { + var key = condition.key, + operator = condition.operator.replace('!', ''), + value = condition.value, + not = condition.operator[0] == '!', + itemValue = item[key], + test = { + '=': function(a, b) { + return Ox.isArray(b) ? a >= b[0] && a < b[1] + : Ox.isString(a) ? a.indexOf(b) > -1 + : a === b; + }, + '==': function(a, b) { return a === b; }, + '<': function(a, b) { return a < b; }, + '>': function(a, b) { return a > b; }, + '<=': function(a, b) { return a <= b; }, + '>=': function(a, b) { return a >= b; }, + '^': function(a, b) { return Ox.starts(a, b); }, + '$': function(a, b) { return Ox.ends(a, b); }, + }; + if (Ox.isString(value)) { + value = value.toLowerCase(); + } + if (Ox.isString(itemValue)) { + itemValue = itemValue.toLowerCase(); + } + return test[operator](itemValue, value) == !not; + } + function testQuery(item, query) { + var match = true; + Ox.forEach(query.conditions, function(condition) { + if (condition.conditions) { + match = testQuery(item, condition); + } else { + match = testCondition(item, condition) + } + if ( + (query.operator == '&' && !match) + || (query.operator == '|' && match) + ) { + return false; + } + }); + return match; + } + return function(options) { + var data, + result = {data: {}, status: {code: 200, text: 'ok'}}; + options = options || {}; + if (options.query) { + result.data.items = items.filter(function(item) { + return testQuery(item, options.query); + }); + } else { + result.data.items = Ox.clone(items); + } + if (options.keys) { + if (options.sort) { + result.data.items = Ox.sortBy(result.data.items, options.sort); + } + if (!Ox.isEmpty(options.keys)) { + result.data.items = result.data.items.map(function(item) { + var ret = {}; + options.keys.forEach(function(key) { + ret[key] = item[key]; + }); + return ret; + }); + } + if (options.range) { + result.data.items = Ox.sub( + result.data.items, options.range[0], options.range[1] + ); + } + } else { + data = {items: result.data.items.length}; + keys.forEach(function(key) { + data[key] = Ox.sum(result.data.items.map(function(item) { + return item[key]; + })); + }) + result.data = data; + } + return result; + }; +}; + /*@ Ox.compact Removes null or undefined values > Ox.compact([null,,1,,2,,3]) @@ -151,7 +321,7 @@ Ox.range = function() { var length = by.length, values = {}; by = by.map(function(v) { return { - key: v.replace(/^[\+\-]/g, ''), + key: v.replace(/^[\+\-]/, ''), operator: v[0] == '-' ? '-' : '+' }; });