diff --git a/source/Ox/js/Array.js b/source/Ox/js/Array.js index 317d620d..74401ed3 100644 --- a/source/Ox/js/Array.js +++ b/source/Ox/js/Array.js @@ -7,6 +7,7 @@ Ox.api Turns an array into a list API (items, options) -> List API items <[o]> An array of objects (key/value stores) options Options object + cache If true, cache results enums Enumerables, for example {size: ['S', 'M', 'L', 'XL']} geo If true, return combined area with totals sort <[o]|[s]> Default sort, for example ['+name', '-age'] @@ -116,12 +117,108 @@ Ox.api Turns an array into a list API Ox.api = function(items, options) { var api = { - enums: options.enums ? parseEnums(options.enums) : {}, - geo: options.geo, - sort: options.sort || [], - sums: options.sums || [], - unique: options.unique || 'id' - }; + cache: options.cache, + enums: options.enums ? parseEnums(options.enums) : {}, + geo: options.geo, + sort: options.sort || [], + sums: options.sums || [], + unique: options.unique || 'id' + }, + fn = function(options, callback) { + var data, + result = {data: {}, status: {code: 200, text: 'ok'}}, + sort = {}; + options = options || {}; + if (options.query) { + // find + options.query.conditions = parseConditions(options.query.conditions); + result.data.items = items.filter(function(item) { + return testQuery(item, options.query); + }); + } else { + result.data.items = Ox.clone(items); + } + if (options.sort && result.data.items.length > 1) { + // sort + options.sort = parseSort(Ox.merge(Ox.clone(options.sort), api.sort)); + options.sort.forEach(function(v) { + var key = v.key; + if (api.enums[key]) { + sort[key] = function(value) { + return api.enums[key].indexOf(value.toLowerCase()); + }; + } /*else if (Ox.isArray(items[0][key])) { + sort[key] = function(value) { + return value.join(', '); + }; + }*/ + }); + result.data.items = Ox.sortBy(result.data.items, options.sort, sort); + } + if (options.positions) { + // return positions + data = {positions: {}}; + options.positions.forEach(function(id) { + data.positions[id] = Ox.getIndex(result.data.items, api.unique, id) + }); + result.data = data; + } else if (!options.keys) { + // return totals + data = {}; + api.sums.forEach(function(key) { + data[key] = Ox.sum(result.data.items.map(function(item) { + return item[key]; + })); + }) + data.items = result.data.items.length; + if (api.geo) { + /* + data.area = Ox.joinAreas(result.data.items.map(function(item) { + return { + sw: {lat: item.south, lng: item.west}, + ne: {lat: item.north, lng: item.east} + }; + })); + data.area = { + south: data.area.sw.lat, + west: data.area.sw.lng, + north: data.area.ne.lat, + east: data.area.ne.lng + }; + */ + data.area = { + south: Ox.MIN_LATITUDE, + west: -180, + north: Ox.MAX_LATITUDE, + east: 180 + } + } + result.data = data; + } else { + // return items + if (!Ox.isEmpty(options.keys)) { + // filter keys + if (options.keys.indexOf(api.unique) == -1) { + options.keys.push(api.unique); + } + 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) { + // apply range + result.data.items = Ox.sub( + result.data.items, options.range[0], options.range[1] + ); + } + } + callback && callback(result); + return result; + }; function parseEnums(enums) { // make enumerable strings lowercase @@ -223,93 +320,7 @@ Ox.api = function(items, options) { return match; } - return function(options, callback) { - var data, - result = {data: {}, status: {code: 200, text: 'ok'}}, - sort = {}; - options = options || {}; - if (options.query) { - // find - options.query.conditions = parseConditions(options.query.conditions); - result.data.items = items.filter(function(item) { - return testQuery(item, options.query); - }); - } else { - result.data.items = Ox.clone(items); - } - if (options.sort && result.data.items.length > 1) { - // sort - options.sort = parseSort(Ox.merge(options.sort, api.sort)); - options.sort.forEach(function(v) { - var key = v.key; - if (api.enums[key]) { - sort[key] = function(value) { - return api.enums[key].indexOf(value.toLowerCase()); - }; - } /*else if (Ox.isArray(items[0][key])) { - sort[key] = function(value) { - return value.join(', '); - }; - }*/ - }); - result.data.items = Ox.sortBy(result.data.items, options.sort, sort); - } - if (options.positions) { - // return positions - data = {positions: {}}; - options.positions.forEach(function(id) { - data.positions[id] = Ox.getIndex(result.data.items, api.unique, id) - }); - result.data = data; - } else if (!options.keys) { - // return totals - data = {}; - api.sums.forEach(function(key) { - data[key] = Ox.sum(result.data.items.map(function(item) { - return item[key]; - })); - }) - data.items = result.data.items.length; - if (api.geo) { - data.area = Ox.joinAreas(result.data.items.map(function(item) { - return { - sw: {lat: item.south, lng: item.west}, - ne: {lat: item.north, lng: item.east} - }; - })); - data.area = { - south: data.area.sw.lat, - west: data.area.sw.lng, - north: data.area.ne.lat, - east: data.area.ne.lng - }; - } - result.data = data; - } else { - // return items - if (!Ox.isEmpty(options.keys)) { - // filter keys - if (options.keys.indexOf(api.unique) == -1) { - options.keys.push(api.unique); - } - 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) { - // apply range - result.data.items = Ox.sub( - result.data.items, options.range[0], options.range[1] - ); - } - } - callback && callback(result); - return result; - }; + return api.cache ? Ox.cache(fn, {async: true}) : fn; };