diff --git a/source/Ox.Image/Ox.Image.js b/source/Ox.Image/Ox.Image.js index b8b391bd..c6d02cab 100644 --- a/source/Ox.Image/Ox.Image.js +++ b/source/Ox.Image/Ox.Image.js @@ -147,7 +147,7 @@ Ox.load.Image = function(options, callback) { val = Ox.hsl([rgba[0], rgba[1], rgba[2]])[i]; rgb = i == 0 ? Ox.rgb([val, 1, 0.5]) - : Ox.map(Ox.range(3), function(v) { + : Ox.range(3).map(function() { return parseInt(val * 255); }); return Ox.merge(rgb, rgba[3]); @@ -343,9 +343,9 @@ Ox.load.Image = function(options, callback) { : Ox.isNumber(arguments[2]) ? arguments[2] : 0, b = 0, bin, // Array of bits per byte to be modified (0 is LSB) - bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(bit) { - return mode & 1 << bit ? bit : null; - }), + bits = mode < 1 ? [-mode] : Ox.filter(Ox.range(8), function(i) { + return mode & 1 << i; + }; cap = getCapacity(bits.length), len; // Compress the string str = Ox[deflate ? 'encodeDeflate' : 'encodeUTF8'](str); @@ -359,7 +359,7 @@ Ox.load.Image = function(options, callback) { str = str.substr(0, Math.ceil(cap)); // Create an array of bit values bin = Ox.flatten(Ox.map(str, function(chr) { - return Ox.map(Ox.range(8), function(i) { + return Ox.range(8).map(function(i) { return chr.charCodeAt(0) >> 7 - i & 1; }); })); @@ -414,8 +414,8 @@ Ox.load.Image = function(options, callback) { : Ox.isNumber(arguments[1]) ? arguments[1] : 0, bin = '', // Array of bits per byte to be modified (0 is LSB) - bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(b) { - return mode & 1 << b ? b : null; + bits = mode < 1 ? [-mode] : Ox.range(8).filter(function(i) { + return mode & 1 << i; }), done = 0, len = 4, str = ''; that.forEach(function(rgba, xy, index) { diff --git a/source/Ox.UI/js/Core/Ox.URL.js b/source/Ox.UI/js/Core/Ox.URL.js index a62e9a94..cead8619 100644 --- a/source/Ox.UI/js/Core/Ox.URL.js +++ b/source/Ox.UI/js/Core/Ox.URL.js @@ -262,9 +262,7 @@ Ox.URL = function(options) { parts.push(constructFind(state.find)); } } - return '/' + Ox.map(parts, function(part) { - return part || null; - }).join('/'); + return '/' + Ox.filter(parts).join('/'); } function constructValue(str, key) { diff --git a/source/Ox.UI/js/Form/Ox.ArrayInput.js b/source/Ox.UI/js/Form/Ox.ArrayInput.js index 58f1c333..db510bb8 100644 --- a/source/Ox.UI/js/Form/Ox.ArrayInput.js +++ b/source/Ox.UI/js/Form/Ox.ArrayInput.js @@ -116,8 +116,9 @@ Ox.ArrayInput = function(options, self) { function getValue() { return Ox.map(self.$input, function($input) { - var value = $input.value(); - return value === '' ? null : value; + return $input.value(); + }).filter(function(value) { + return value !== ''; }); }; diff --git a/source/Ox.UI/js/Form/Ox.Input.js b/source/Ox.UI/js/Form/Ox.Input.js index 5132908c..fdd203af 100644 --- a/source/Ox.UI/js/Form/Ox.Input.js +++ b/source/Ox.UI/js/Form/Ox.Input.js @@ -357,8 +357,6 @@ Ox.Input = function(options, self) { } newLength = newValue.length; - //Ox.Log('Form', 'selectEnd', selectEnd) - if (self.options.autocompleteReplace) { value = self.options.value; self.options.value = newValue; @@ -374,27 +372,32 @@ Ox.Input = function(options, self) { } if (self.options.autocompleteSelect) { - value = (self.options.autocompleteReplace ? value : self.options.value).toLowerCase(); + value = ( + self.options.autocompleteReplace + ? value : self.options.value + ).toLowerCase(); if (values.length) { self.oldCursor = cursor(); self.oldValue = self.options.value; self.$autocompleteMenu.options({ - items: Ox.map(values, function(v, i) { - var ret = null; + items: Ox.filter(values, function(v, i) { + var ret = false; if ( !self.options.autocompleteSelectMax || i < self.options.autocompleteSelectMax ) { - if (value == v.toLowerCase()) { + if (v.toLowerCase() === value) { selected = i; } - ret = { - id: v.toLowerCase().replace(/ /g, '_'), // fixme: need function to do lowercase, underscores etc? - title: self.options.autocompleteSelectHighlight ? - Ox.highlight(v, value, 'OxHighlight') : v - }; + ret = true; } return ret; + }).map(function(v) { + return { + id: v.toLowerCase().replace(/ /g, '_'), // fixme: need function to do lowercase, underscores etc? + title: self.options.autocompleteSelectHighlight ? + Ox.highlight(v, value, 'OxHighlight') : v + }; }) }); if (!self.selectEventBound) { @@ -403,7 +406,6 @@ Ox.Input = function(options, self) { }); self.selectEventBound = true; } - Ox.Log('AUTO', 'show menu') self.$autocompleteMenu.options({ selected: selected }).showMenu(); diff --git a/source/Ox.UI/js/Form/Ox.OptionGroup.js b/source/Ox.UI/js/Form/Ox.OptionGroup.js index aadc9fe4..71ed2fa0 100644 --- a/source/Ox.UI/js/Form/Ox.OptionGroup.js +++ b/source/Ox.UI/js/Form/Ox.OptionGroup.js @@ -45,8 +45,8 @@ Ox.OptionGroup = function(items, min, max, property) { @*/ // FIXME: isn't value more useful in all cases? this[property] = function() { - return Ox.map(items, function(item, i) { - return item[property] ? i : null; + return Ox.indicesOf(items, function(item) { + return item[property]; }); }; diff --git a/source/Ox.UI/js/Form/Ox.SelectInput.js b/source/Ox.UI/js/Form/Ox.SelectInput.js index 83b127c4..ac5334f9 100644 --- a/source/Ox.UI/js/Form/Ox.SelectInput.js +++ b/source/Ox.UI/js/Form/Ox.SelectInput.js @@ -67,8 +67,10 @@ Ox.SelectInput = function(options, self) { return value[value[0] == self.other ? 1 : 0] }, split: function(value) { - return Ox.map(self.options.items, function(item, i) { - return i < item.length - 1 ? item.id : null; + return Ox.filter(self.options.items, function(item, i) { + return i < item.length - 1; + }).map(function(item) { + return item.id; }).indexOf(value) > -1 ? [value, ''] : [self.other, value]; }, width: self.options.width @@ -89,8 +91,10 @@ Ox.SelectInput = function(options, self) { function setValue(isOther) { if ( (!self.options.value && isOther !== true) - || Ox.map(self.options.items, function(item) { - return item.id != self.other ? item.id : null; + || Ox.filter(self.options.items, function(item) { + return item.id != self.other; + }).map(function(item) { + return item.id; }).indexOf(self.options.value) > -1 ) { self.$select.options({ diff --git a/source/Ox.UI/js/List/Ox.Chart.js b/source/Ox.UI/js/List/Ox.Chart.js index 627e45b5..7ec2116a 100644 --- a/source/Ox.UI/js/List/Ox.Chart.js +++ b/source/Ox.UI/js/List/Ox.Chart.js @@ -154,8 +154,8 @@ Ox.Chart = function(options, self) { }); while (Ox.sum(widths) != totalWidth) { max = Ox.max(widths); - maxKeys = Ox.map(Object.keys(widths), function(key) { - return widths[key] == max ? key : null; + maxKeys = Object.keys(widths).filter(function(key) { + return widths[key] == max; }); widths[maxKeys[0]] += Ox.sum(widths) < totalWidth ? 1 : -1; } diff --git a/source/Ox.UI/js/List/Ox.IconItem.js b/source/Ox.UI/js/List/Ox.IconItem.js index 550a5be6..6a1c8f90 100644 --- a/source/Ox.UI/js/List/Ox.IconItem.js +++ b/source/Ox.UI/js/List/Ox.IconItem.js @@ -160,16 +160,13 @@ Ox.IconItem = function(options, self) { text = Ox.isArray(text) ? text.join(', ') : text; var lines = Ox.wordwrap(text, maxLength, '\n', true, false).split('\n'); return Ox.highlightHTML( - Ox.map(lines, function(line, i) { - if (i < maxLines - 1) { - return line; - } else if (i == maxLines - 1) { - return lines.length == maxLines ? line : Ox.truncate(lines.map(function(line, i) { - return i < maxLines - 1 ? null : line; - }).join(' '), maxLength, '...', 'center'); - } else { - return null; - } + lines.slice(0, maxLines).map(function(line, i) { + return i < maxLines - 1 || lines.length == maxLines + ? line + : Ox.truncate( + lines.slice(maxLines).join(' '), + maxLength, '...', 'center' + ); }).join('
'), self.options.find, 'OxHighlight', ['br'] ).replace(/ (<.*?>)?/g, ' $1'); diff --git a/source/Ox.UI/js/List/Ox.TextList.js b/source/Ox.UI/js/List/Ox.TextList.js index b361424b..255ea032 100644 --- a/source/Ox.UI/js/List/Ox.TextList.js +++ b/source/Ox.UI/js/List/Ox.TextList.js @@ -183,8 +183,10 @@ Ox.TextList = function(options, self) { max: -1, min: 1, type: 'image', - value: Ox.map(self.options.columns, function(column) { - return column.visible ? column.id : null; + value: Ox.filter(self.options.columns, function(column) { + return column.visible; + }).map(function(column) { + return column.id; }) }) .bindEvent('change', changeColumns) diff --git a/source/Ox.UI/js/List/Ox.TreeList.js b/source/Ox.UI/js/List/Ox.TreeList.js index ba062394..48b2a1d6 100644 --- a/source/Ox.UI/js/List/Ox.TreeList.js +++ b/source/Ox.UI/js/List/Ox.TreeList.js @@ -160,7 +160,7 @@ Ox.TreeList = function(options, self) { if (type == 'array' || type == 'object') { ret.title += Ox.toTitleCase(type) + ' [' + Ox.len(value) + ']'; - ret.items = Ox.map(Ox.sort(Ox.keys(value)), function(k) { + ret.items = Ox.sort(Ox.keys(value).map(function(k) { return parseData(k, value[k]); }); } else { diff --git a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js index 27c2c8f6..382b76dc 100644 --- a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js +++ b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js @@ -328,7 +328,7 @@ Ox.AnnotationFolder = function(options, self) { } function getAnnotations() { - return Ox.map(self.options.items, function(item) { + return Ox.filter(self.options.items, function(item) { return self.editing && item.id == self.options.selected || ( ( self.options.range == 'all' || ( @@ -344,7 +344,7 @@ Ox.AnnotationFolder = function(options, self) { self.options.users == 'all' || self.options.users.indexOf(item.user) > -1 ) - ) ? item : null; + ); }); } diff --git a/source/Ox.UI/js/Video/Ox.VideoEditor.js b/source/Ox.UI/js/Video/Ox.VideoEditor.js index 99748379..fcbaa857 100644 --- a/source/Ox.UI/js/Video/Ox.VideoEditor.js +++ b/source/Ox.UI/js/Video/Ox.VideoEditor.js @@ -425,11 +425,11 @@ Ox.VideoEditor = function(options, self) { {key: 'G', action: 'Go to Next Result'}, {key: Ox.UI.symbols['return'], action: 'Edit/Submit'}, {key: Ox.UI.symbols.escape, action: 'Cancel/Deselect'} - ], Ox.map(self.options.layers, function(layer, i) { + ], Ox.filter(self.options.layers.map(function(layer, i) { return layer.editable ? {key: i + 1, action: 'Add ' + layer.item} : null; - })).forEach(function(shortcut) { + }))).forEach(function(shortcut) { self.$keyboardShortcuts.append( $('
').css({display: 'table-row'}) .append( diff --git a/source/Ox.UI/js/Video/Ox.VideoPlayer.js b/source/Ox.UI/js/Video/Ox.VideoPlayer.js index dafe5927..236d5dfa 100644 --- a/source/Ox.UI/js/Video/Ox.VideoPlayer.js +++ b/source/Ox.UI/js/Video/Ox.VideoPlayer.js @@ -1175,14 +1175,27 @@ Ox.VideoPlayer = function(options, self) { var results = []; if (query.length) { query = query.toLowerCase(); - results = Ox.map(self.options.annotations, function(annotation) { + results = Ox.filter(self.options.annotations, function(annotation) { return Ox.decodeHTML(Ox.stripTags( annotation.text.toLowerCase() - )).indexOf(query) > -1 ? { + )).indexOf(query) > -1; + }).map(function(annotation) { + return { id: annotation.id, 'in': annotation['in'], out: annotation.out - } : null; + }; + }) + results = Ox.filter(self.options.annotations, function(annotation) { + return Ox.decodeHTML(Ox.stripTags( + annotation.text.toLowerCase() + )).indexOf(query) > -1; + }).map(function(annotation) { + return { + id: annotation.id, + 'in': annotation['in'], + out: annotation.out + }; }); } //Ox.print('FIND RESULTS:', results); diff --git a/source/Ox.UI/js/Window/Ox.Dialog.js b/source/Ox.UI/js/Window/Ox.Dialog.js index e650d154..a0ec5150 100644 --- a/source/Ox.UI/js/Window/Ox.Dialog.js +++ b/source/Ox.UI/js/Window/Ox.Dialog.js @@ -496,9 +496,7 @@ Ox.Dialog = function(options, self) { function setButtons() { var buttonsLeft, buttonsRight, - index = Ox.map(self.options.buttons, function(v, i) { - return Ox.isEmpty(v) ? i : null; - })[0]; + index = Ox.indexOf(self.options.buttons, Ox.isEmpty); if (index) { buttonsLeft = Ox.sub(self.options.buttons, 0, index); buttonsRight = Ox.sub(self.options.buttons, index + 1); diff --git a/source/Ox/js/Collection.js b/source/Ox/js/Collection.js index c7ba9dac..5c3f3265 100644 --- a/source/Ox/js/Collection.js +++ b/source/Ox/js/Collection.js @@ -111,6 +111,7 @@ Ox.filter Filters a collection by a given condition @*/ Ox.filter = function(col, fn, that) { var ret, type = Ox.typeOf(col); + fn = fn || Ox.identity; if (type == 'object') { ret = {}; Ox.forEach(col, function(val, key) { @@ -303,6 +304,16 @@ Ox.indexOf = function(col, fn) { return index == col.length ? -1 : index; }; +// FIXME: use this instead of `Ox.filter(Ox.map())` when it's just about getting +// the original indices +Ox.indicesOf = function(col, fn) { + return Ox.map(col, function(val, i) { + return fn(val) ? i : null; + }).filter(function(index) { + return index !== null; + }); +}; + /*@ Ox.isEmpty Tests if a value is an empty array, object or string (value) -> True if the value is an empty array, object or string @@ -460,8 +471,7 @@ Ox.makeObject = function(arr) { /*@ Ox.map Transforms the values of an array, object or string Unlike [].map(), Ox.map() works for arrays, - objects and strings. Returning null from the iterator - function will remove the element from the collection. + objects and strings. > Ox.map([0, 0, 0], function(v, i) { return v == i; }) [true, false, false] > Ox.map({a: 'a', b: 'a', c: 'a'}, function(v, k) { return v == k; }) @@ -474,21 +484,19 @@ Ox.map Transforms the values of an array, object or string # > Ox.map([,], function(v, i) { return i; }) # [0] @*/ - -// FIXME: it would sometimes be nice to have Ox.map(3, function(i) {...}) -// instead of Ox.range(3).map(function(i) {...}) - -Ox.map = function(obj, fn) { - // fixme: return null to filter out may be a bit esoteric - var isObject = Ox.isObject(obj), - ret = isObject ? {} : []; - Ox.forEach(obj, function(val, key) { - // FIXME: is there any reason for this strange assignment? - var map; - if ((map = fn(val, key)) !== null) { - ret[isObject ? key : ret.length] = map; +Ox.map = function(col, fn, that) { + var type = Ox.typeOf(col), ret; + if (type == 'object') { + ret = {}; + Ox.forEach(col, function(val, key) { + ret[key] = fn.call(that, val, key, col); + }); + } else { + ret = Ox.toArray(col).map(fn); + if (type == 'string') { + ret = ret.join(''); } - }); + } return ret; }; diff --git a/source/Ox/js/Date.js b/source/Ox/js/Date.js index 70c246c0..82cbae68 100644 --- a/source/Ox/js/Date.js +++ b/source/Ox/js/Date.js @@ -25,9 +25,9 @@ Ox.getDateInWeek = function(date, weekday, utc) { date = Ox.makeDate(date); var sourceWeekday = Ox.getISODay(date, utc), targetWeekday = Ox.isNumber(weekday) ? weekday - : Ox.map(Ox.WEEKDAYS, function(v, i) { - return v.substr(0, 3) == weekday.substr(0, 3) ? i + 1 : null; - })[0]; + : Ox.indexOf(Ox.WEEKDAYS, function(v) { + return v.substr(0, 3) == weekday.substr(0, 3); + }) + 1; return Ox.setDate(date, Ox.getDate(date, utc) - sourceWeekday + targetWeekday, utc); } @@ -71,9 +71,9 @@ Ox.getDaysInMonth Get the number of days in a given month Ox.getDaysInMonth = function(year, month) { year = Ox.makeYear(year); month = Ox.isNumber(month) ? month - : Ox.map(Ox.MONTHS, function(v, i) { - return v.substr(0, 3) == month.substr(0, 3) ? i + 1 : null; - })[0]; + : Ox.getIndexOf(Ox.MONTHS, function(v) { + return v.substr(0, 3) == month.substr(0, 3); + }) + 1; return new Date(year, month, 0).getDate(); } diff --git a/source/Ox/js/Encoding.js b/source/Ox/js/Encoding.js index 859e3216..55e7a4ef 100644 --- a/source/Ox/js/Encoding.js +++ b/source/Ox/js/Encoding.js @@ -279,8 +279,9 @@ Ox.encodeHTML = function(str) { return Ox.map(str.toString(), function(v) { var code = v.charCodeAt(0); - return code < 128 ? (v in Ox.HTML_ENTITIES ? Ox.HTML_ENTITIES[v] : v) : - '&#x' + Ox.pad(code.toString(16).toUpperCase(), 4) + ';'; + return code < 128 + ? (v in Ox.HTML_ENTITIES ? Ox.HTML_ENTITIES[v] : v) + : '&#x' + Ox.pad(code.toString(16).toUpperCase(), 4) + ';'; }).join(''); }; diff --git a/source/Ox/js/Format.js b/source/Ox/js/Format.js index e5a20dc7..fb18dfa8 100644 --- a/source/Ox/js/Format.js +++ b/source/Ox/js/Format.js @@ -366,9 +366,9 @@ Ox.formatDateRangeDuration = function(start, end, utc) { } } }); - return Ox.map(values, function(value, i) { - return value ? value + ' ' + keys[i] + (value > 1 ? 's' : '') : null; - }).join(' '); + return Ox.filter(Ox.map(values, function(value, i) { + return value ? value + ' ' + keys[i] + (value > 1 ? 's' : '') : ''; + })).join(' '); }; /*@ @@ -450,7 +450,7 @@ Ox.formatDuration = function(/*sec, dec, format*/) { str.shift(); pad.shift(); } - return Ox.map(val, function(v, i) { + return Ox.filter(Ox.map(val, function(v, i) { var ret; if (!format) { ret = Ox.pad(v, pad[i]); @@ -458,10 +458,10 @@ Ox.formatDuration = function(/*sec, dec, format*/) { ret = v + (format == 'long' ? ' ' : '') + str[i] + (format == 'long' && v != 1 ? 's' : ''); } else { - ret = null; + ret = ''; } return ret; - }).join(!format ? ':' : ' '); + })).join(!format ? ':' : ' '); }; /*@ diff --git a/source/Ox/js/Geo.js b/source/Ox/js/Geo.js index ed95ed40..1c9e6b60 100644 --- a/source/Ox/js/Geo.js +++ b/source/Ox/js/Geo.js @@ -356,11 +356,11 @@ ne: {lat: 90, lng: ret.sw.lng} }]; function containsGaps(area) { - return Ox.map(gaps, function(gap, i) { + return Ox.getIndices(gaps, function(gap) { return Ox.containsArea({ sw: {lat: -90, lng: area.sw.lng}, ne: {lat: 90, lng: area.ne.lng} - }, gap) ? i : null; + }, gap); }); } function intersectsWithGaps(area) { diff --git a/source/Ox/js/JavaScript.js b/source/Ox/js/JavaScript.js index 2b4f1999..2af839a5 100644 --- a/source/Ox/js/JavaScript.js +++ b/source/Ox/js/JavaScript.js @@ -42,7 +42,7 @@ Ox.doc Generates documentation for annotated JavaScript Ox.doc = (function() { // fixme: dont require the trailing '@' var re = { - item: /^(.+?) <(.+?)> (.+)$/, + item: /^(.+?) <(.+?)>(.*?)$/, multiline: /^\/\*\@.*?\n([\w\W]+)\n.*?\@\*\/$/, script: /\n(\s*