MixedCollection.html 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-util-MixedCollection'>/**
  19. </span> * @class Ext.util.MixedCollection
  20. * &lt;p&gt;
  21. * Represents a collection of a set of key and value pairs. Each key in the MixedCollection
  22. * must be unique, the same key cannot exist twice. This collection is ordered, items in the
  23. * collection can be accessed by index or via the key. Newly added items are added to
  24. * the end of the collection. This class is similar to {@link Ext.util.HashMap} however it
  25. * is heavier and provides more functionality. Sample usage:
  26. * &lt;pre&gt;&lt;code&gt;
  27. var coll = new Ext.util.MixedCollection();
  28. coll.add('key1', 'val1');
  29. coll.add('key2', 'val2');
  30. coll.add('key3', 'val3');
  31. console.log(coll.get('key1')); // prints 'val1'
  32. console.log(coll.indexOfKey('key3')); // prints 2
  33. * &lt;/code&gt;&lt;/pre&gt;
  34. *
  35. * &lt;p&gt;
  36. * The MixedCollection also has support for sorting and filtering of the values in the collection.
  37. * &lt;pre&gt;&lt;code&gt;
  38. var coll = new Ext.util.MixedCollection();
  39. coll.add('key1', 100);
  40. coll.add('key2', -100);
  41. coll.add('key3', 17);
  42. coll.add('key4', 0);
  43. var biggerThanZero = coll.filterBy(function(value){
  44. return value &gt; 0;
  45. });
  46. console.log(biggerThanZero.getCount()); // prints 2
  47. * &lt;/code&gt;&lt;/pre&gt;
  48. * &lt;/p&gt;
  49. */
  50. Ext.define('Ext.util.MixedCollection', {
  51. extend: 'Ext.util.AbstractMixedCollection',
  52. mixins: {
  53. sortable: 'Ext.util.Sortable'
  54. },
  55. <span id='Ext-util-MixedCollection-method-constructor'> /**
  56. </span> * Creates new MixedCollection.
  57. * @param {Boolean} allowFunctions Specify &lt;tt&gt;true&lt;/tt&gt; if the {@link #addAll}
  58. * function should add function references to the collection. Defaults to
  59. * &lt;tt&gt;false&lt;/tt&gt;.
  60. * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
  61. * and return the key value for that item. This is used when available to look up the key on items that
  62. * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
  63. * equivalent to providing an implementation for the {@link #getKey} method.
  64. */
  65. constructor: function() {
  66. var me = this;
  67. me.callParent(arguments);
  68. me.addEvents('sort');
  69. me.mixins.sortable.initSortable.call(me);
  70. },
  71. doSort: function(sorterFn) {
  72. this.sortBy(sorterFn);
  73. },
  74. <span id='Ext-util-MixedCollection-method-_sort'> /**
  75. </span> * @private
  76. * Performs the actual sorting based on a direction and a sorting function. Internally,
  77. * this creates a temporary array of all items in the MixedCollection, sorts it and then writes
  78. * the sorted array data back into this.items and this.keys
  79. * @param {String} property Property to sort by ('key', 'value', or 'index')
  80. * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.
  81. * @param {Function} fn (optional) Comparison function that defines the sort order.
  82. * Defaults to sorting by numeric value.
  83. */
  84. _sort : function(property, dir, fn){
  85. var me = this,
  86. i, len,
  87. dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
  88. //this is a temporary array used to apply the sorting function
  89. c = [],
  90. keys = me.keys,
  91. items = me.items;
  92. //default to a simple sorter function if one is not provided
  93. fn = fn || function(a, b) {
  94. return a - b;
  95. };
  96. //copy all the items into a temporary array, which we will sort
  97. for(i = 0, len = items.length; i &lt; len; i++){
  98. c[c.length] = {
  99. key : keys[i],
  100. value: items[i],
  101. index: i
  102. };
  103. }
  104. //sort the temporary array
  105. Ext.Array.sort(c, function(a, b){
  106. var v = fn(a[property], b[property]) * dsc;
  107. if(v === 0){
  108. v = (a.index &lt; b.index ? -1 : 1);
  109. }
  110. return v;
  111. });
  112. //copy the temporary array back into the main this.items and this.keys objects
  113. for(i = 0, len = c.length; i &lt; len; i++){
  114. items[i] = c[i].value;
  115. keys[i] = c[i].key;
  116. }
  117. me.fireEvent('sort', me);
  118. },
  119. <span id='Ext-util-MixedCollection-method-sortBy'> /**
  120. </span> * Sorts the collection by a single sorter function
  121. * @param {Function} sorterFn The function to sort by
  122. */
  123. sortBy: function(sorterFn) {
  124. var me = this,
  125. items = me.items,
  126. keys = me.keys,
  127. length = items.length,
  128. temp = [],
  129. i;
  130. //first we create a copy of the items array so that we can sort it
  131. for (i = 0; i &lt; length; i++) {
  132. temp[i] = {
  133. key : keys[i],
  134. value: items[i],
  135. index: i
  136. };
  137. }
  138. Ext.Array.sort(temp, function(a, b) {
  139. var v = sorterFn(a.value, b.value);
  140. if (v === 0) {
  141. v = (a.index &lt; b.index ? -1 : 1);
  142. }
  143. return v;
  144. });
  145. //copy the temporary array back into the main this.items and this.keys objects
  146. for (i = 0; i &lt; length; i++) {
  147. items[i] = temp[i].value;
  148. keys[i] = temp[i].key;
  149. }
  150. me.fireEvent('sort', me, items, keys);
  151. },
  152. <span id='Ext-util-MixedCollection-method-findInsertionIndex'> /**
  153. </span> * Calculates the insertion index of the new item based upon the comparison function passed, or the current sort order.
  154. * @param {Object} newItem The new object to find the insertion position of.
  155. * @param {Function} [sorterFn] The function to sort by. This is the same as the sorting function
  156. * passed to {@link #sortBy}. It accepts 2 items from this MixedCollection, and returns -1 0, or 1
  157. * depending on the relative sort positions of the 2 compared items.
  158. *
  159. * If omitted, a function {@link #generateComparator generated} from the currently defined set of
  160. * {@link #sorters} will be used.
  161. *
  162. * @return {Number} The insertion point to add the new item into this MixedCollection at using {@link #insert}
  163. */
  164. findInsertionIndex: function(newItem, sorterFn) {
  165. var me = this,
  166. items = me.items,
  167. start = 0,
  168. end = items.length - 1,
  169. middle,
  170. comparison;
  171. if (!sorterFn) {
  172. sorterFn = me.generateComparator();
  173. }
  174. while (start &lt;= end) {
  175. middle = (start + end) &gt;&gt; 1;
  176. comparison = sorterFn(newItem, items[middle]);
  177. if (comparison &gt;= 0) {
  178. start = middle + 1;
  179. } else if (comparison &lt; 0) {
  180. end = middle - 1;
  181. }
  182. }
  183. return start;
  184. },
  185. <span id='Ext-util-MixedCollection-method-reorder'> /**
  186. </span> * Reorders each of the items based on a mapping from old index to new index. Internally this
  187. * just translates into a sort. The 'sort' event is fired whenever reordering has occured.
  188. * @param {Object} mapping Mapping from old item index to new item index
  189. */
  190. reorder: function(mapping) {
  191. var me = this,
  192. items = me.items,
  193. index = 0,
  194. length = items.length,
  195. order = [],
  196. remaining = [],
  197. oldIndex;
  198. me.suspendEvents();
  199. //object of {oldPosition: newPosition} reversed to {newPosition: oldPosition}
  200. for (oldIndex in mapping) {
  201. order[mapping[oldIndex]] = items[oldIndex];
  202. }
  203. for (index = 0; index &lt; length; index++) {
  204. if (mapping[index] == undefined) {
  205. remaining.push(items[index]);
  206. }
  207. }
  208. for (index = 0; index &lt; length; index++) {
  209. if (order[index] == undefined) {
  210. order[index] = remaining.shift();
  211. }
  212. }
  213. me.clear();
  214. me.addAll(order);
  215. me.resumeEvents();
  216. me.fireEvent('sort', me);
  217. },
  218. <span id='Ext-util-MixedCollection-method-sortByKey'> /**
  219. </span> * Sorts this collection by &lt;b&gt;key&lt;/b&gt;s.
  220. * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.
  221. * @param {Function} fn (optional) Comparison function that defines the sort order.
  222. * Defaults to sorting by case insensitive string.
  223. */
  224. sortByKey : function(dir, fn){
  225. this._sort('key', dir, fn || function(a, b){
  226. var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
  227. return v1 &gt; v2 ? 1 : (v1 &lt; v2 ? -1 : 0);
  228. });
  229. }
  230. });
  231. </pre>
  232. </body>
  233. </html>