PageRenderTime 46ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/ext-4.0.7/src/util/MixedCollection.js

https://bitbucket.org/srogerf/javascript
JavaScript | 219 lines | 105 code | 24 blank | 90 comment | 16 complexity | 633227c427db58a97c8cef8fada4c685 MD5 | raw file
  1. /*
  2. This file is part of Ext JS 4
  3. Copyright (c) 2011 Sencha Inc
  4. Contact: http://www.sencha.com/contact
  5. GNU General Public License Usage
  6. This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
  7. If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
  8. */
  9. /**
  10. * @class Ext.util.MixedCollection
  11. * <p>
  12. * Represents a collection of a set of key and value pairs. Each key in the MixedCollection
  13. * must be unique, the same key cannot exist twice. This collection is ordered, items in the
  14. * collection can be accessed by index or via the key. Newly added items are added to
  15. * the end of the collection. This class is similar to {@link Ext.util.HashMap} however it
  16. * is heavier and provides more functionality. Sample usage:
  17. * <pre><code>
  18. var coll = new Ext.util.MixedCollection();
  19. coll.add('key1', 'val1');
  20. coll.add('key2', 'val2');
  21. coll.add('key3', 'val3');
  22. console.log(coll.get('key1')); // prints 'val1'
  23. console.log(coll.indexOfKey('key3')); // prints 2
  24. * </code></pre>
  25. *
  26. * <p>
  27. * The MixedCollection also has support for sorting and filtering of the values in the collection.
  28. * <pre><code>
  29. var coll = new Ext.util.MixedCollection();
  30. coll.add('key1', 100);
  31. coll.add('key2', -100);
  32. coll.add('key3', 17);
  33. coll.add('key4', 0);
  34. var biggerThanZero = coll.filterBy(function(value){
  35. return value > 0;
  36. });
  37. console.log(biggerThanZero.getCount()); // prints 2
  38. * </code></pre>
  39. * </p>
  40. */
  41. Ext.define('Ext.util.MixedCollection', {
  42. extend: 'Ext.util.AbstractMixedCollection',
  43. mixins: {
  44. sortable: 'Ext.util.Sortable'
  45. },
  46. /**
  47. * Creates new MixedCollection.
  48. * @param {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}
  49. * function should add function references to the collection. Defaults to
  50. * <tt>false</tt>.
  51. * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
  52. * and return the key value for that item. This is used when available to look up the key on items that
  53. * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
  54. * equivalent to providing an implementation for the {@link #getKey} method.
  55. */
  56. constructor: function() {
  57. var me = this;
  58. me.callParent(arguments);
  59. me.addEvents('sort');
  60. me.mixins.sortable.initSortable.call(me);
  61. },
  62. doSort: function(sorterFn) {
  63. this.sortBy(sorterFn);
  64. },
  65. /**
  66. * @private
  67. * Performs the actual sorting based on a direction and a sorting function. Internally,
  68. * this creates a temporary array of all items in the MixedCollection, sorts it and then writes
  69. * the sorted array data back into this.items and this.keys
  70. * @param {String} property Property to sort by ('key', 'value', or 'index')
  71. * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.
  72. * @param {Function} fn (optional) Comparison function that defines the sort order.
  73. * Defaults to sorting by numeric value.
  74. */
  75. _sort : function(property, dir, fn){
  76. var me = this,
  77. i, len,
  78. dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
  79. //this is a temporary array used to apply the sorting function
  80. c = [],
  81. keys = me.keys,
  82. items = me.items;
  83. //default to a simple sorter function if one is not provided
  84. fn = fn || function(a, b) {
  85. return a - b;
  86. };
  87. //copy all the items into a temporary array, which we will sort
  88. for(i = 0, len = items.length; i < len; i++){
  89. c[c.length] = {
  90. key : keys[i],
  91. value: items[i],
  92. index: i
  93. };
  94. }
  95. //sort the temporary array
  96. Ext.Array.sort(c, function(a, b){
  97. var v = fn(a[property], b[property]) * dsc;
  98. if(v === 0){
  99. v = (a.index < b.index ? -1 : 1);
  100. }
  101. return v;
  102. });
  103. //copy the temporary array back into the main this.items and this.keys objects
  104. for(i = 0, len = c.length; i < len; i++){
  105. items[i] = c[i].value;
  106. keys[i] = c[i].key;
  107. }
  108. me.fireEvent('sort', me);
  109. },
  110. /**
  111. * Sorts the collection by a single sorter function
  112. * @param {Function} sorterFn The function to sort by
  113. */
  114. sortBy: function(sorterFn) {
  115. var me = this,
  116. items = me.items,
  117. keys = me.keys,
  118. length = items.length,
  119. temp = [],
  120. i;
  121. //first we create a copy of the items array so that we can sort it
  122. for (i = 0; i < length; i++) {
  123. temp[i] = {
  124. key : keys[i],
  125. value: items[i],
  126. index: i
  127. };
  128. }
  129. Ext.Array.sort(temp, function(a, b) {
  130. var v = sorterFn(a.value, b.value);
  131. if (v === 0) {
  132. v = (a.index < b.index ? -1 : 1);
  133. }
  134. return v;
  135. });
  136. //copy the temporary array back into the main this.items and this.keys objects
  137. for (i = 0; i < length; i++) {
  138. items[i] = temp[i].value;
  139. keys[i] = temp[i].key;
  140. }
  141. me.fireEvent('sort', me, items, keys);
  142. },
  143. /**
  144. * Reorders each of the items based on a mapping from old index to new index. Internally this
  145. * just translates into a sort. The 'sort' event is fired whenever reordering has occured.
  146. * @param {Object} mapping Mapping from old item index to new item index
  147. */
  148. reorder: function(mapping) {
  149. var me = this,
  150. items = me.items,
  151. index = 0,
  152. length = items.length,
  153. order = [],
  154. remaining = [],
  155. oldIndex;
  156. me.suspendEvents();
  157. //object of {oldPosition: newPosition} reversed to {newPosition: oldPosition}
  158. for (oldIndex in mapping) {
  159. order[mapping[oldIndex]] = items[oldIndex];
  160. }
  161. for (index = 0; index < length; index++) {
  162. if (mapping[index] == undefined) {
  163. remaining.push(items[index]);
  164. }
  165. }
  166. for (index = 0; index < length; index++) {
  167. if (order[index] == undefined) {
  168. order[index] = remaining.shift();
  169. }
  170. }
  171. me.clear();
  172. me.addAll(order);
  173. me.resumeEvents();
  174. me.fireEvent('sort', me);
  175. },
  176. /**
  177. * Sorts this collection by <b>key</b>s.
  178. * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.
  179. * @param {Function} fn (optional) Comparison function that defines the sort order.
  180. * Defaults to sorting by case insensitive string.
  181. */
  182. sortByKey : function(dir, fn){
  183. this._sort('key', dir, fn || function(a, b){
  184. var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
  185. return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
  186. });
  187. }
  188. });