collection.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. 'use strict';
  2. /**
  3. * An empty collection stub. Use {@link RefsCollection.extend} to extend a
  4. * collection with ref semantics.
  5. *
  6. * @class RefsCollection
  7. */
  8. /**
  9. * Extends a collection with {@link Refs} aware methods
  10. *
  11. * @memberof RefsCollection
  12. * @static
  13. *
  14. * @param {Array<Object>} collection
  15. * @param {Refs} refs instance
  16. * @param {Object} property represented by the collection
  17. * @param {Object} target object the collection is attached to
  18. *
  19. * @return {RefsCollection<Object>} the extended array
  20. */
  21. function extend(collection, refs, property, target) {
  22. var inverseProperty = property.inverse;
  23. /**
  24. * Removes the given element from the array and returns it.
  25. *
  26. * @method RefsCollection#remove
  27. *
  28. * @param {Object} element the element to remove
  29. */
  30. Object.defineProperty(collection, 'remove', {
  31. value: function(element) {
  32. var idx = this.indexOf(element);
  33. if (idx !== -1) {
  34. this.splice(idx, 1);
  35. // unset inverse
  36. refs.unset(element, inverseProperty, target);
  37. }
  38. return element;
  39. }
  40. });
  41. /**
  42. * Returns true if the collection contains the given element
  43. *
  44. * @method RefsCollection#contains
  45. *
  46. * @param {Object} element the element to check for
  47. */
  48. Object.defineProperty(collection, 'contains', {
  49. value: function(element) {
  50. return this.indexOf(element) !== -1;
  51. }
  52. });
  53. /**
  54. * Adds an element to the array, unless it exists already (set semantics).
  55. *
  56. * @method RefsCollection#add
  57. *
  58. * @param {Object} element the element to add
  59. * @param {Number} optional index to add element to
  60. * (possibly moving other elements around)
  61. */
  62. Object.defineProperty(collection, 'add', {
  63. value: function(element, idx) {
  64. var currentIdx = this.indexOf(element);
  65. if (typeof idx === 'undefined') {
  66. if (currentIdx !== -1) {
  67. // element already in collection (!)
  68. return;
  69. }
  70. // add to end of array, as no idx is specified
  71. idx = this.length;
  72. }
  73. // handle already in collection
  74. if (currentIdx !== -1) {
  75. // remove element from currentIdx
  76. this.splice(currentIdx, 1);
  77. }
  78. // add element at idx
  79. this.splice(idx, 0, element);
  80. if (currentIdx === -1) {
  81. // set inverse, unless element was
  82. // in collection already
  83. refs.set(element, inverseProperty, target);
  84. }
  85. }
  86. });
  87. // a simple marker, identifying this element
  88. // as being a refs collection
  89. Object.defineProperty(collection, '__refs_collection', {
  90. value: true
  91. });
  92. return collection;
  93. }
  94. function isExtended(collection) {
  95. return collection.__refs_collection === true;
  96. }
  97. module.exports.extend = extend;
  98. module.exports.isExtended = isExtended;