/** * @class Enumerable * @desc A port of the Ruby enumerable API for Actionscript 2.0 * @author abc * @version 0.1 * @see http://prototypejs.org/api/enumerable (identical usage examples as prototype) * Thanks to Sam for porting to JS and making this port a walk in the park. * Published under an MIT License. See http://www.zimoutliner.com/license.html */ class Enumerable extends Array { private function _each(iterator:Function) { for (var i = 0, length = this.length; i < length; i++) { iterator(this[i]); } } public function each(iterator:Function) { var index = 0; try { this._each(function(value) { iterator(value, index++); }); } catch(e) { if(e.message != 'break') throw e; } return this; } public function all(iterator:Function):Boolean { var result = true; this.each(function(value, index) { result = (result && (iterator(value,index) || value === true)); if (!result) throw new Error('break'); }); return result; } public function any(iterator:Function):Boolean { var result = false; this.each(function(value, index) { result = ((iterator(value, index) || value === true)); if (result) throw new Error('break'); }); return result; } public function collect(iterator:Function) { var results = new Enumerable(); this.each(function(value, index) { results.push(iterator(value, index) || value); }); return results; } public function map(iterator:Function) { return this.collect(iterator); } public function detect(iterator:Function) { var result = null; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw new Error('break'); } }); return result; } public function find(iterator:Function) { return this.detect(iterator); } public function findAll(iterator:Function):Enumerable { var results = new Enumerable(); this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; } function select(iterator:Function):Enumerable { return this.findAll(iterator); } function inject(accumulator, iterator) { this.each(function(value, index) { accumulator = iterator(accumulator, value, index); }); return accumulator; } function include(value):Boolean { var found = false; this.each(function(object) { if (value == object) { found = true; throw new Error('break'); } }); return found; } function member(value):Boolean { return this.include(value); } function reject(iterator:Function):Enumerable { var results = new Enumerable(); this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; } function max(iterator:Function) { var result=null; this.each(function(value, index) { value = (iterator(value, index) || value); if (result == undefined || value >= result) result = value; }); return result; } function min(iterator:Function) { var result=null; this.each(function(value, index) { value = (iterator(value, index) || value); if (result == undefined || value < result) result = value; }); return result; } /** * @desc Returns the sorted enumerable. Does not manipulate the original enumerable. */ function sortBy(iterator:Function):Enumerable { return this.map(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); } function pluck(property:String):Enumerable { var results = new Enumerable(); this.each(function(value, index) { results.push(value[property]); }); return results; } function filter(iterator:Function):Enumerable { return this.reject(iterator); } function size():Number { return this.length; } }