UNPKG

bugcore

Version:

bugcore is a JavaScript library that provides a foundational architecture for object oriented JS

308 lines (252 loc) 9.88 kB
/* * Copyright (c) 2016 airbug Inc. http://airbug.com * * bugcore may be freely distributed under the MIT license. */ //------------------------------------------------------------------------------- // Annotations //------------------------------------------------------------------------------- //@Export('ObservableCollection') //@Require('AddChange') //@Require('ArgumentBug') //@Require('Class') //@Require('ClearChange') //@Require('Collection') //@Require('IArrayable') //@Require('ICollection') //@Require('IIterable') //@Require('Obj') //@Require('Observable') //@Require('Proxy') //@Require('RemoveChange') //@Require('TypeUtil') //------------------------------------------------------------------------------- // Context //------------------------------------------------------------------------------- require('bugpack').context("*", function(bugpack) { //------------------------------------------------------------------------------- // BugPack //------------------------------------------------------------------------------- var AddChange = bugpack.require('AddChange'); var ArgumentBug = bugpack.require('ArgumentBug'); var Class = bugpack.require('Class'); var ClearChange = bugpack.require('ClearChange'); var Collection = bugpack.require('Collection'); var IArrayable = bugpack.require('IArrayable'); var ICollection = bugpack.require('ICollection'); var IIterable = bugpack.require('IIterable'); var Obj = bugpack.require('Obj'); var Observable = bugpack.require('Observable'); var Proxy = bugpack.require('Proxy'); var RemoveChange = bugpack.require('RemoveChange'); var TypeUtil = bugpack.require('TypeUtil'); //------------------------------------------------------------------------------- // Declare Class //------------------------------------------------------------------------------- /** * @class * @extends {Observable} * @implements {ICollection.<I>} * @template I */ var ObservableCollection = Class.extend(Observable, /** @lends {ObservableCollection.prototype} */{ _name: "ObservableCollection", //------------------------------------------------------------------------------- // Constructor //------------------------------------------------------------------------------- /** * @constructs * @param {(ICollection.<I> | Array.<I>)} items */ _constructor: function(items) { this._super(); //------------------------------------------------------------------------------- // Private Properties //------------------------------------------------------------------------------- /** * @private * @type {Collection.<I>} */ this.observed = this.factoryObserved(items); }, //------------------------------------------------------------------------------- // Getters and Setters //------------------------------------------------------------------------------- /** * @return {Collection.<I>} */ getObserved: function() { return this.observed; }, //------------------------------------------------------------------------------- // IArrayable Implementation //------------------------------------------------------------------------------- /** * @override * @return (Array.<I>) */ toArray: function() { return this.observed.toArray(); }, //------------------------------------------------------------------------------- // ICollection Implementation //------------------------------------------------------------------------------- /** * @param {I} value * @return {boolean} */ add: function(value) { var result = this.observed.add(value); if (result) { this.notifyObservers(new AddChange(value)) } return result; }, /** * @param {(ICollection.<I> | Array.<I>)} items */ addAll: function(items) { if (Class.doesImplement(items, ICollection) || TypeUtil.isArray(items)) { var _this = this; items.forEach(function(value) { _this.add(value); }); } else { throw new ArgumentBug(ArgumentBug.ILLEGAL, "items", items, "parameter must implement ICollection or be an Array"); } }, /** * */ clear: function() { this.observed.clear(); this.notifyObservers(new ClearChange()); }, /** * @param {*} value * @return {boolean} */ contains: function(value) { return this.observed.contains(value); }, /** * @param {(ICollection.<*> | Array.<*>)} items * @return {boolean} */ containsAll: function(items) { return this.observed.contains(items); }, /** * @param {(ICollection.<*> | Array.<*>)} items * @return {boolean} */ containsEqual: function(items) { return this.observed.containsEqual(items); }, /** * @return {number} */ getCount: function() { return this.observed.getCount(); }, /** * @param {*} value * @return {number} */ countValue: function(value) { return this.observed.countValue(value); }, /** * @return {boolean} */ isEmpty: function() { return this.observed.isEmpty(); }, /** * @param {*} value * @return {boolean} */ remove: function(value) { var result = this.observed.remove(value); if (result) { this.notifyObservers(new RemoveChange(value)); } return result; }, /** * @param {(ICollection.<*> | Array.<*>)} items */ removeAll: function(items) { if (Class.doesImplement(items, ICollection) || TypeUtil.isArray(items)) { var _this = this; items.forEach(function(value) { _this.remove(value); }); } else { throw new ArgumentBug(ArgumentBug.ILLEGAL, "items", items, "parameter must implement ICollection or be an Array"); } }, //------------------------------------------------------------------------------- // IIterable Implementation //------------------------------------------------------------------------------- /** * NOTE BRN: If a value is modified in one iteration and then visited at a later time, its value in the loop is * its value at that later time. A value that is deleted before it has been visited will not be visited later. * Values added to the Collection over which iteration is occurring may either be visited or omitted from iteration. * * @param {function(I)} func */ forEach: function(func) { this.observed.forEach(func); }, /** * NOTE BRN: If a value is modified in one iteration and then visited at a later time, its value in the loop is * its value at that later time. A value that is deleted before it has been visited will not be visited later. * Values added to the Collection over which iteration is occurring may either be visited or omitted from iteration. * * @return {IIterator.<I>} */ iterator: function() { return this.observed.iterator(); }, //------------------------------------------------------------------------------- // Obj Methods //------------------------------------------------------------------------------- /** * @param {boolean} deep * @return {ObservableCollection.<I>} */ clone: function(deep) { var cloneCollection = new ObservableCollection(); if (deep) { this.forEach(function(item){ cloneCollection.add(Obj.clone(item, deep)); }); } else { cloneCollection.addAll(this); } return cloneCollection; }, //------------------------------------------------------------------------------- // Protected Methods //------------------------------------------------------------------------------- /** * @protected * @param {(ICollection.<I> | Array.<I>)=} items * @return {Collection.<I>} */ factoryObserved: function(items) { return new Collection(items); } }); //------------------------------------------------------------------------------- // Implement Interfaces //------------------------------------------------------------------------------- Class.implement(ObservableCollection, IArrayable); Class.implement(ObservableCollection, ICollection); Class.implement(ObservableCollection, IIterable); //------------------------------------------------------------------------------- // Exports //------------------------------------------------------------------------------- bugpack.export('ObservableCollection', ObservableCollection); });