From 565dc6ad35d0ce8a5cfb6bc38613c7f133caad2b Mon Sep 17 00:00:00 2001 From: rolux Date: Fri, 25 May 2012 09:44:48 +0200 Subject: [PATCH] rename vars; move Ox.find, Ox.getIndexById, Ox.getObjectById, Ox.makeArray and Ox.toArray to Array.js; make Ox.find accept a third argument ('leading') and return a single array; improve IE patch for Ox.toArray --- source/Ox/js/Array.js | 203 +++++++++++++++++++++++++++++++----------- 1 file changed, 151 insertions(+), 52 deletions(-) diff --git a/source/Ox/js/Array.js b/source/Ox/js/Array.js index 47d29768..aead3812 100644 --- a/source/Ox/js/Array.js +++ b/source/Ox/js/Array.js @@ -317,7 +317,7 @@ Ox.api = function(items, options) { (query.operator == '&' && !match) || (query.operator == '|' && match) ) { - Ox.Break()(); + Ox.Break(); } }); return match; @@ -329,42 +329,108 @@ Ox.api = function(items, options) { /*@ Ox.compact Removes null or undefined values - (arr) -> Array + (array) -> Array > Ox.compact([null,,1,,2,,3]) [1, 2, 3] @*/ -Ox.compact = function(arr) { - return arr.filter(function(val) { - return !Ox.isNull(val) && !Ox.isUndefined(val); +Ox.compact = function(array) { + return array.filter(function(value) { + return !Ox.isNull(value) && !Ox.isUndefined(value); }); }; +/*@ +Ox.find Returns array elements that match a string + Returns an array of case-insensitive matches: exact match first, then + leading matches, then other matches + > Ox.find(['Bar', 'Barfoo', 'Foo', 'Foobar'], 'foo') + ['Foo', 'Foobar', 'Barfoo'] + > Ox.find(['Bar', 'Barfoo', 'Foo', 'Foobar'], 'foo', true) + ['Foo', 'Foobar'] +@*/ +Ox.find = function(array, string, leading) { + var ret = [[], []]; + string = string.toLowerCase(); + array.forEach(function(value) { + var lowerCase = value.toLowerCase(), + index = lowerCase.indexOf(string); + index > -1 && ret[index == 0 ? 0 : 1][ + lowerCase == string ? 'unshift' : 'push' + ](value); + }) + return leading ? ret[0] : ret[0].concat(ret[1]); +}; + /*@ Ox.flatten Flattens an array (arr) -> Array > Ox.flatten([1, [2, [3], 2], 1]) [1, 2, 3, 2, 1] @*/ -Ox.flatten = function(arr) { +Ox.flatten = function(array) { var ret = []; - arr.forEach(function(val) { - if (Ox.isArray(val)) { - Ox.flatten(val).forEach(function(val) { - ret.push(val); + array.forEach(function(value) { + if (Ox.isArray(value)) { + Ox.flatten(value).forEach(function(value) { + ret.push(value); }); } else { - ret.push(val); + ret.push(value); } }); return ret; }; +/*@ +Ox.getIndexById Returns the first array index of an object with a given id + > Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar') + 1 + > Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz') + -1 +@*/ +Ox.getIndexById = function(array, id) { + return Ox.indexOf(array, function(obj) { + return obj.id === id; + }); +}; + +/*@ +Ox.getObjectById Returns the first object in an array with a given id + > Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar') + {id: "bar", str: "Bar"} + > Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz') + null +@*/ +Ox.getObjectById = function(array, id) { + var index = Ox.getIndexById(array, id); + return index > -1 ? array[index] : null; +}; + /* Ox.indexOf = function(arr) { // indexOf for primitives, test for function, deep equal for others }; */ +/*@ +Ox.makeArray Wraps any non-array in an array. + > Ox.makeArray('foo') + ['foo'] + > Ox.makeArray(['foo']) + ['foo'] +@*/ +Ox.makeArray = function(value) { + var ret, type = Ox.typeOf(value); + if (type == 'arguments') { + ret = Ox.toArray(value); + } else if (type == 'array') { + ret = value; + } else { + ret = [value]; + } + return ret; +}; + /*@ Ox.range Python-style range (stop) -> <[n]> range @@ -391,11 +457,11 @@ Ox.range Python-style range [-1, -1.5] @*/ Ox.range = function() { - var arr = []; - Ox.loop.apply(null, Ox.toArray(arguments).concat(function(i) { - arr.push(i); + var array = []; + Ox.loop.apply(null, Ox.toArray(arguments).concat(function(index) { + array.push(index); })); - return arr; + return array; }; (function() { @@ -439,7 +505,7 @@ Ox.range = function() { len = article.length; sort[val] = sort[val].slice(len + 1) + ', ' + sort[val].slice(0, len); - Ox.Break()(); + Ox.Break(); } }); } else { @@ -451,10 +517,10 @@ Ox.range = function() { /*@ Ox.sort Sorts an array, handling articles and digits, ignoring capitalization - (arr) -> Sorted array - (arr, fn) -> Sorted array - arr Array - fn Optional map function that returns the value for the array element + (array) -> Sorted array + (array, map) -> Sorted array + array Array + map Optional map function that returns the value for the array element > Ox.sort(['"z"', '10', '9', 'B', 'a']) ['9', '10', 'a', 'B', '"z"'] > Ox.sort([{id: 0, name: '80 Days'}, {id: 1, name: '8 Women'}], function(v) {return v.name}) @@ -464,15 +530,15 @@ Ox.range = function() { > Ox.sort(['Man', 'A Plan', 'The Canal']) ['The Canal', 'Man', 'A Plan'] @*/ - Ox.sort = function(arr, fn) { - var sort = getSortValues(fn ? arr.map(fn) : arr); - return arr.sort(function(a, b) { - a = fn ? fn(a) : a; - b = fn ? fn(b) : b; + Ox.sort = function(array, map) { + var values = getSortValues(map ? array.map(map) : array); + return array.sort(function(a, b) { + a = map ? map(a) : a; + b = map ? map(b) : b; var ret = 0; - if (sort[a] < sort[b]) { + if (values[a] < values[b]) { ret = -1; - } else if (sort[a] > sort[b]) { + } else if (values[a] > values[b]) { ret = 1; } return ret; @@ -481,33 +547,33 @@ Ox.range = function() { /*@ Ox.sortBy Sorts an array of objects by given properties - (arr, by) -> Sorted array - arr <[o]> Array of objects + (array, by[, map]) -> Sorted array + array <[o]> Array of objects by <[s]> Array of object keys (asc: 'foo' or '+foo', desc: '-foo') - fn Optional functions, per key, that return the sort value + map Optional map functions, per key, that return the sort value > Ox.sortBy([{x: 1, y: 1}, {x: 1, y: 2}, {x: 2, y: 2}], ['+x', '-y']) [{x: 1, y: 2}, {x: 1, y: 1}, {x: 2, y: 2}] > Ox.sortBy([{id: 0, name: '80 Days'}, {id: 1, name: '8 Women'}], ['name']) [{id: 1, name: '8 Women'}, {id: 0, name: '80 Days'}] @*/ - Ox.sortBy = function(arr, by, fn) { + Ox.sortBy = function(array, by, map) { var values = {}; by = Ox.makeArray(by); - fn = fn || {}; - by = by.map(function(v) { - return Ox.isString(v) ? { - key: v.replace(/^[\+\-]/, ''), - operator: v[0] == '-' ? '-' : '+' - } : v; + map = map || {}; + by = by.map(function(value) { + return Ox.isString(value) ? { + key: value.replace(/^[\+\-]/, ''), + operator: value[0] == '-' ? '-' : '+' + } : value; }); - by.map(function(v) { - return v.key; + by.map(function(value) { + return value.key; }).forEach(function(key) { - values[key] = getSortValues(arr.map(function(v) { - return v[key]; - }), fn[key]); + values[key] = getSortValues(array.map(function(value) { + return value[key]; + }), map[key]); }); - return arr.sort(function(a, b) { + return array.sort(function(a, b) { var aValue, bValue, index = 0, key, ret = 0; while (ret == 0 && index < by.length) { key = by[index].key; @@ -529,16 +595,49 @@ Ox.range = function() { }()); +/*@ +Ox.toArray Takes an array-like object and returns a true array + (value) -> True array + value <*> Array-like object + > (function() { return Ox.toArray(arguments); }('foo', 'bar')) + ['foo', 'bar'] + > Ox.toArray('foo') + ['f', 'o', 'o'] + > Ox.toArray({0: 'f', 1: 'o', 2: 'o', length: 3}) + ['f', 'o', 'o'] +@*/ +Ox.toArray = function(collection) { + return Ox.slice(collection); +}; +try { + Array.prototype.slice.call(document.getElementsByTagName('head')); +} catch (error) { + // Handle MSIE NodeLists + Ox.toArray = function(collection) { + var i, length, ret = []; + try { + ret = Ox.slice(collection); + } catch (error) { + length = collection.length; + for (i = 0; i < length; i++) { + ret[i] = collection[i]; + } + } + return ret; + }; +} + /*@ Ox.unique Returns an array without duplicate values + (array) -> Array > Ox.unique([1, 2, 3, 2, 1]) [1, 2, 3] > Ox.unique([NaN, NaN]) [] @*/ -Ox.unique = function(arr) { - return Ox.filter(arr, function(val, i) { - return arr.indexOf(val) == i; +Ox.unique = function(array) { + return Ox.filter(array, function(value, index) { + return array.indexOf(value) == index; }); }; @@ -551,12 +650,12 @@ Ox.zip Zips an array of arrays @*/ Ox.zip = function() { var args = arguments.length == 1 ? arguments[0] : Ox.toArray(arguments), - arr = []; - args[0].forEach(function(v, i) { - arr[i] = []; - args.forEach(function(v) { - arr[i].push(v[i]); + array = []; + args[0].forEach(function(value, index) { + array[index] = []; + args.forEach(function(value) { + array[index].push(value[index]); }); }); - return arr; + return array; };