'use strict'; /** * An empty collection stub. Use {@link RefsCollection.extend} to extend a * collection with ref semantics. * * @class RefsCollection */ /** * Extends a collection with {@link Refs} aware methods * * @memberof RefsCollection * @static * * @param {Array} collection * @param {Refs} refs instance * @param {Object} property represented by the collection * @param {Object} target object the collection is attached to * * @return {RefsCollection} the extended array */ function extend(collection, refs, property, target) { var inverseProperty = property.inverse; /** * Removes the given element from the array and returns it. * * @method RefsCollection#remove * * @param {Object} element the element to remove */ Object.defineProperty(collection, 'remove', { value: function(element) { var idx = this.indexOf(element); if (idx !== -1) { this.splice(idx, 1); // unset inverse refs.unset(element, inverseProperty, target); } return element; } }); /** * Returns true if the collection contains the given element * * @method RefsCollection#contains * * @param {Object} element the element to check for */ Object.defineProperty(collection, 'contains', { value: function(element) { return this.indexOf(element) !== -1; } }); /** * Adds an element to the array, unless it exists already (set semantics). * * @method RefsCollection#add * * @param {Object} element the element to add * @param {Number} optional index to add element to * (possibly moving other elements around) */ Object.defineProperty(collection, 'add', { value: function(element, idx) { var currentIdx = this.indexOf(element); if (typeof idx === 'undefined') { if (currentIdx !== -1) { // element already in collection (!) return; } // add to end of array, as no idx is specified idx = this.length; } // handle already in collection if (currentIdx !== -1) { // remove element from currentIdx this.splice(currentIdx, 1); } // add element at idx this.splice(idx, 0, element); if (currentIdx === -1) { // set inverse, unless element was // in collection already refs.set(element, inverseProperty, target); } } }); // a simple marker, identifying this element // as being a refs collection Object.defineProperty(collection, '__refs_collection', { value: true }); return collection; } function isExtended(collection) { return collection.__refs_collection === true; } module.exports.extend = extend; module.exports.isExtended = isExtended;