/** @module collection */ /** * в разработке */ kit.PluginManager.register('Collection', function(module, exports, require, global) { var support = require('support'); var valueEx = support.valueEx; function filter(value, key, arr) { return !support.empty(value); } function getSimilarInstance(type) { if(type === 'object') { return new Collection({}); } return new Collection([]); } function setLastIndex(key){ var n = Number(key); if (support.arr.isKey(key) && n > this.__lastIndex) { this.__lastIndex = n; } return this.__lastIndex; } function actualParams() { var index; this.length = this.__keys.length; this.__lastIndex = 0; for(index in this.__keys) { setLastIndex.call(this, this.__keys[index]); } } /** * @class Collection * @memberOf kit */ var Collection = function (data = []) { this.data = data; if(Array.isArray(data)) { this.__type = 'array'; } else if(typeof data === 'object') { this.__type = 'object'; if(data.hasOwnProperty('length') && !Object.keys(data).includes('length')) { this.__type = 'arrayObject'; } } else { this.__type = 'array'; this.data = [data]; console.warn('collection: not support data' + typeof data); } var key; this.__lastIndex = 0; this.length = 0; this.__keys = []; this.__values = []; for(key in this.data) { if(!this.data.hasOwnProperty(key)) continue; setLastIndex.call(this, key); this.length = this.__keys.push(support.arr.isKey(key)?Number(key):(''+key)); this.__values.push(this.data[key]); } }; Collection.prototype.all = function () { if(this.__type === 'array' || this.__type === 'arrayObject') { return this.toArray(); } return this.toObject(); }; Collection.prototype.toArray = function () { var index, arr = []; for(index in this.__keys) { arr.push(this.__values[index]); } return arr; }; Collection.prototype.toObject = function () { var index, ob = {}; for(index in this.__keys) { ob[this.__keys[index]] = this.__values[index]; } return ob; }; Collection.prototype.serialize = function () { return JSON.stringify(this.all()); }; Collection.prototype.has = function (key) { return this.data.hasOwnProperty(key) && this.__keys.includes(support.arr.isKey(key)?Number(key):(''+key)); }; Collection.prototype.indexKey = function (key) { return this.__keys.indexOf(key); }; /** * @param key * @param value * @return {kit.Collection} */ Collection.prototype.set = Collection.prototype.put = function (key, value) { var index = -1; if(this.has(key)) { this.data[key] = this.__values[index = this.indexKey(key)] = value; return this; } this.length = this.__keys.push(support.arr.isKey(key)?Number(key):(''+key)); this.data[key] = this.__values[this.length-1] = value; setLastIndex.call(this, key); return this; }; /** * @param value * @return {kit.Collection} */ Collection.prototype.push = function (value) { this.set(this.__lastIndex + 1, value); return this; }; Collection.prototype.get = function (key, defValue = undefined) { if(this.has(key)) { return this.data[key]; } return defValue; }; Collection.prototype.count = function () { return this.__keys.length; }; Collection.prototype.isEmpty = function () { return this.count() === 0; }; /** * @param callback * @return {kit.Collection} */ Collection.prototype.map = function (callback) { var res = getSimilarInstance(this.__type); for (var key of Object.keys(this.data)) { res.put(key, valueEx(callback, this.data[key], key, this.data)); } return res; }; /** * @param callback * @return {kit.Collection} */ Collection.prototype.each = function (callback = true) { var BreakException = {}, keys, i, key; try { keys = Object.keys(this.data); if(keys.length) for (i = 0; i < keys.length; i++) { key = keys[i]; if(valueEx(callback, this.data[key], key, this.data) === false) { throw BreakException; } } } catch (e) { if (e !== BreakException) throw e; } return this; }; /** * @param callback * @return {kit.Collection} */ Collection.prototype.eachReverse = function (callback = true) { var BreakException = {}, i; try { if(this.__keys.length) for (i = this.__keys.length - 1; i >= 0; i--) { if(valueEx(callback, this.__values[i], this.__keys[i], this.data) === false) { throw BreakException; } } } catch (e) { if (e !== BreakException) throw e; } return this; }; /** * @param callback * @return {kit.Collection} */ Collection.prototype.filter = function (callback = filter) { var res = getSimilarInstance(this.__type); this.each(function (value, key, arr) { if(valueEx(callback, value, key, arr)) { res.put(key, value); } }); return res; }; Collection.prototype.every = function (callback) { var res = true; this.each(function (value, key, arr) { res = res && !!valueEx(callback, value, key, arr); }); return res; }; Collection.prototype.first = function (callback = true) { var res = undefined; this.each(function (value, key, arr) { if(valueEx(callback, value, key, arr)) { res = value; return false; } }); return res; }; Collection.prototype.firstKey = function (callback = true) { var res = undefined; this.each(function (value, key, arr) { if(valueEx(callback, value, key, arr)) { res = key; return false; } }); return res; }; Collection.prototype.last = function (callback = true) { var res = undefined; this.eachReverse(function (value, key, arr) { if(valueEx(callback, value, key, arr)) { res = value; return false; } }); return res; }; Collection.prototype.lastKey = function (callback = true) { var res = undefined; this.eachReverse(function (value, key, arr) { if(valueEx(callback, value, key, arr)) { res = key; return false; } }); return res; }; /** * Method removes an item from the collection by its key * @param key * @return {kit.Collection} */ Collection.prototype.forget = function (key) { key = valueEx(key); if(!this.has(key)) { return this; } var index = this.indexKey(key); this.__keys.splice(index, 1); this.__values.splice(index, 1); actualParams.call(this); delete this.data[key]; return this; }; /** * Method removes and returns an item from the collection by its key * @param key * @param defValue * @return {kit.Collection} */ Collection.prototype.pull = function (key, defValue = undefined) { key = valueEx(key); if(!this.has(key)) { return defValue; } var index = this.indexKey(key); var value = this.__values[index]; this.__keys.splice(index, 1); this.__values.splice(index, 1); actualParams.call(this); delete this.data[key]; return value; }; /** * Method removes and returns the last item from the collection */ Collection.prototype.pop = function(){ var index = this.length - 1; if(index < 0) { return undefined; } var key = this.__keys[index]; var value = this.__values[index]; this.__keys.splice(index, 1); this.__values.splice(index, 1); actualParams.call(this); delete this.data[key]; return value; }; /** * Method removes and returns the first item from the collection */ Collection.prototype.shift = function(){ var index = 0; if(this.length <= 0) { return undefined; } var key = this.__keys[index]; var value = this.__values[index]; this.__keys.splice(index, 1); this.__values.splice(index, 1); actualParams.call(this); delete this.data[key]; return value; }; /** * @return {kit.Collection} */ Collection.prototype.keys = function () { return new Collection(Object.keys(this.data)); }; /** * @return {kit.Collection} */ Collection.prototype.dump = function () { console.log('Collection', this.data); return this; }; /** * @return {kit.Collection} */ Collection.prototype.dd = function () { this.dump(); debugger; return this; }; return module.exports = Collection; });