var Iterable; (function($module) { "use strict"; var symbolExists = function() { return window.hasOwnProperty("Symbol") && window.Symbol.hasOwnProperty("iterator"); }, isIterable = function(object) { if (object) { if (symbolExists() && object[window.Symbol.iterator] == Array.prototype[window.Symbol.iterator]) { return true; } else { if (typeof object == "string" || typeof object == "object" && object.hasOwnProperty("length")) { return true; } } } return false; }, setAccessors = function(object) { var length = Object.keys(object).length, accessors = function(length) { return { get: function() { return length; }, set: function() { length = Object.keys(object).length; } }; }; Object.defineProperties(object, { length: accessors(length) }); // if (symbolExists()) { // Object.defineProperties(object, { // // js iterator protocol // [window.Symbol.iterator]: { // value: function() { // var // _iterator = _Iterable.Proxy.new(object); // return { // next: function() { // return { // value: _iterator.next(), // done: !_iterator.hasNext() // }; // } // }; // } // } // }); // } }, parse = function(collection) { var newObject = {}; Object.assign(newObject, collection); setAccessors(newObject); return newObject; }, toIterable = function(collection) { if (!isIterable(collection)) { setAccessors(collection); } }, asIterable = function(collection) { var clone = {}; Object.assign(clone, collection); toIterable(clone); return clone; }, Iterator_ = { new: function(collection) { var keys, amount, i, lastIndex, ConstructorReference = Iterator_.new; if (!(this instanceof ConstructorReference)) { return new ConstructorReference(collection); } collection = asIterable(collection); keys = Object.keys(collection); amount = keys.length; i = -1; lastIndex = amount - 1; this.index = function() { return i; }; // iteration protocols // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols this.next = function() { // sum before to use return collection[keys[++i]]; }; this.hasNext = function() { return i < lastIndex; }; //////////// this.key = function() { return keys[i]; }; this.previous = function() { return collection[keys[--i]]; }; this.nextIndex = function(index) { i = index - 1; }; this.previousIndex = function(index) { i = index + 1; }; this.reset = function() { i = -1; }; this.finalize = function() { i = amount; }; this.finalizeOnReverse = function() { this.reset(); }; this.hasPrev = function() { return i > 0; }; this.each = function(startingIndex, finalIndex, callback) { if (typeof startingIndex == "function" ^ typeof finalIndex == "function") { if (typeof finalIndex == "function") { callback = finalIndex; this.nextIndex(startingIndex); } else { callback = startingIndex; } } else { if (typeof startingIndex == "number") { this.nextIndex(startingIndex); } if (typeof finalIndex == "number") { lastIndex = finalIndex; } } while (this.hasNext()) { callback.call(this, this.next(), this.key()); } }; this.reverseEach = function(startingIndex, callback) { this.finalize(); if (typeof callback != "function" && typeof startingIndex == "function") { callback = startingIndex; } else if (typeof startingIndex != "function") { this.previousIndex(startingIndex); } while (this.hasPrev()) { callback.call(this, this.previous(), this.key()); } }; this.select = function(callback) { var selected = [], iteratorBlock = function(item) { if (callback.call(this, item, this.key())) { selected.push(item); } }; this.each(iteratorBlock); if (selected.length) { return selected; } }; } }; Object.defineProperties($module, { Iterable: { value: {} } }); Object.defineProperties(Iterable, { Proxy: { value: {} } }); Object.defineProperties(Iterable, { symbolExists: { value: function() { return symbolExists(); } }, isIterable: { value: function(object) { return isIterable(object); } }, parse: { value: function(collection) { return parse(collection); } }, toIterable: { value: function(collection) { toIterable(collection); } } }); Object.defineProperties(Iterable.Proxy, { new: { value: function(collection) { var _iterator, ConstructorReference = Iterable.Proxy.new; if (!(this instanceof ConstructorReference)) { return new ConstructorReference(collection); } _iterator = Iterator_.new(collection); // instance methods this.index = function() { return _iterator.index; }; this.key = function() { return _iterator.key(); }; this.next = function() { return _iterator.next(); }; this.previous = function() { return _iterator.previous(); }; this.reset = function() { _iterator.reset(); }; this.finalize = function() { _iterator.finalize(); }; this.finalizeOnReverse = function() { _iterator.finalizeOnReverse(); }; this.hasPrev = function() { return _iterator.hasPrev(); }; this.hasNext = function() { return _iterator.hasNext(); }; this.each = function(startingIndex, finalIndex, callback) { return _iterator.each(startingIndex, finalIndex, callback); }; this.reverseEach = function(startingIndex, callback) { return _iterator.reverseEach(startingIndex, callback); }; this.select = function(callback) { return _iterator.select(callback); }; return this; } } }); })(window);