Version 3.18.1
Show:

File: collection/js/arraylist.js

  1. /**
  2. * Collection utilities beyond what is provided in the YUI core
  3. * @module collection
  4. * @submodule arraylist
  5. */
  6. var YArray = Y.Array,
  7. YArray_each = YArray.each,
  8. ArrayListProto;
  9. /**
  10. * Generic ArrayList class for managing lists of items and iterating operations
  11. * over them. The targeted use for this class is for augmentation onto a
  12. * class that is responsible for managing multiple instances of another class
  13. * (e.g. NodeList for Nodes). The recommended use is to augment your class with
  14. * ArrayList, then use ArrayList.addMethod to mirror the API of the constituent
  15. * items on the list's API.
  16. *
  17. * The default implementation creates immutable lists, but mutability can be
  18. * provided via the arraylist-add submodule or by implementing mutation methods
  19. * directly on the augmented class's prototype.
  20. *
  21. * @class ArrayList
  22. * @constructor
  23. * @param items { Array } array of items this list will be responsible for
  24. */
  25. function ArrayList( items ) {
  26. if ( items !== undefined ) {
  27. this._items = Y.Lang.isArray( items ) ? items : YArray( items );
  28. } else {
  29. // ||= to support lazy initialization from augment
  30. this._items = this._items || [];
  31. }
  32. }
  33. ArrayListProto = {
  34. /**
  35. * Get an item by index from the list. Override this method if managing a
  36. * list of objects that have a different public representation (e.g. Node
  37. * instances vs DOM nodes). The iteration methods that accept a user
  38. * function will use this method for access list items for operation.
  39. *
  40. * @method item
  41. * @param i { Integer } index to fetch
  42. * @return { mixed } the item at the requested index
  43. */
  44. item: function ( i ) {
  45. return this._items[i];
  46. },
  47. /**
  48. * <p>Execute a function on each item of the list, optionally providing a
  49. * custom execution context. Default context is the item.</p>
  50. *
  51. * <p>The callback signature is <code>callback( item, index )</code>.</p>
  52. *
  53. * @method each
  54. * @param fn { Function } the function to execute
  55. * @param context { mixed } optional override 'this' in the function
  56. * @return { ArrayList } this instance
  57. * @chainable
  58. */
  59. each: function ( fn, context ) {
  60. YArray_each( this._items, function ( item, i ) {
  61. item = this.item( i );
  62. fn.call( context || item, item, i, this );
  63. }, this);
  64. return this;
  65. },
  66. /**
  67. * <p>Execute a function on each item of the list, optionally providing a
  68. * custom execution context. Default context is the item.</p>
  69. *
  70. * <p>The callback signature is <code>callback( item, index )</code>.</p>
  71. *
  72. * <p>Unlike <code>each</code>, if the callback returns true, the
  73. * iteration will stop.</p>
  74. *
  75. * @method some
  76. * @param fn { Function } the function to execute
  77. * @param context { mixed } optional override 'this' in the function
  78. * @return { Boolean } True if the function returned true on an item
  79. */
  80. some: function ( fn, context ) {
  81. return YArray.some( this._items, function ( item, i ) {
  82. item = this.item( i );
  83. return fn.call( context || item, item, i, this );
  84. }, this);
  85. },
  86. /**
  87. * Finds the first index of the needle in the managed array of items.
  88. *
  89. * @method indexOf
  90. * @param needle { mixed } The item to search for
  91. * @return { Integer } Array index if found. Otherwise -1
  92. */
  93. indexOf: function ( needle ) {
  94. return YArray.indexOf( this._items, needle );
  95. },
  96. /**
  97. * How many items are in this list?
  98. *
  99. * @method size
  100. * @return { Integer } Number of items in the list
  101. */
  102. size: function () {
  103. return this._items.length;
  104. },
  105. /**
  106. * Is this instance managing any items?
  107. *
  108. * @method isEmpty
  109. * @return { Boolean } true if 1 or more items are being managed
  110. */
  111. isEmpty: function () {
  112. return !this.size();
  113. },
  114. /**
  115. * Provides an array-like representation for JSON.stringify.
  116. *
  117. * @method toJSON
  118. * @return { Array } an array representation of the ArrayList
  119. */
  120. toJSON: function () {
  121. return this._items;
  122. }
  123. };
  124. // Default implementation does not distinguish between public and private
  125. // item getter
  126. /**
  127. * Protected method for optimizations that may be appropriate for API
  128. * mirroring. Similar in functionality to <code>item</code>, but is used by
  129. * methods added with <code>ArrayList.addMethod()</code>.
  130. *
  131. * @method _item
  132. * @protected
  133. * @param i { Integer } Index of item to fetch
  134. * @return { mixed } The item appropriate for pass through API methods
  135. */
  136. ArrayListProto._item = ArrayListProto.item;
  137. // Mixed onto existing proto to preserve constructor NOT being an own property.
  138. // This has bitten me when composing classes by enumerating, copying prototypes.
  139. Y.mix(ArrayList.prototype, ArrayListProto);
  140. Y.mix( ArrayList, {
  141. /**
  142. * <p>Adds a pass through method to dest (typically the prototype of a list
  143. * class) that calls the named method on each item in the list with
  144. * whatever parameters are passed in. Allows for API indirection via list
  145. * instances.</p>
  146. *
  147. * <p>Accepts a single string name or an array of string names.</p>
  148. *
  149. * <pre><code>list.each( function ( item ) {
  150. * item.methodName( 1, 2, 3 );
  151. * } );
  152. * // becomes
  153. * list.methodName( 1, 2, 3 );</code></pre>
  154. *
  155. * <p>Additionally, the pass through methods use the item retrieved by the
  156. * <code>_item</code> method in case there is any special behavior that is
  157. * appropriate for API mirroring.</p>
  158. *
  159. * <p>If the iterated method returns a value, the return value from the
  160. * added method will be an array of values with each value being at the
  161. * corresponding index for that item. If the iterated method does not
  162. * return a value, the added method will be chainable.
  163. *
  164. * @method addMethod
  165. * @static
  166. * @param dest {Object} Object or prototype to receive the iterator method
  167. * @param name {String|String[]} Name of method of methods to create
  168. */
  169. addMethod: function ( dest, names ) {
  170. names = YArray( names );
  171. YArray_each( names, function ( name ) {
  172. dest[ name ] = function () {
  173. var args = YArray( arguments, 0, true ),
  174. ret = [];
  175. YArray_each( this._items, function ( item, i ) {
  176. item = this._item( i );
  177. var result = item[ name ].apply( item, args );
  178. if ( result !== undefined && result !== item ) {
  179. ret[i] = result;
  180. }
  181. }, this);
  182. return ret.length ? ret : this;
  183. };
  184. } );
  185. }
  186. } );
  187. Y.ArrayList = ArrayList;