3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 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.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.util.MixedCollection
18 * Represents a collection of a set of key and value pairs. Each key in the MixedCollection
19 * must be unique, the same key cannot exist twice. This collection is ordered, items in the
20 * collection can be accessed by index or via the key. Newly added items are added to
21 * the end of the collection. This class is similar to {@link Ext.util.HashMap} however it
22 * is heavier and provides more functionality. Sample usage:
24 var coll = new Ext.util.MixedCollection();
25 coll.add('key1', 'val1');
26 coll.add('key2', 'val2');
27 coll.add('key3', 'val3');
29 console.log(coll.get('key1')); // prints 'val1'
30 console.log(coll.indexOfKey('key3')); // prints 2
34 * The MixedCollection also has support for sorting and filtering of the values in the collection.
36 var coll = new Ext.util.MixedCollection();
37 coll.add('key1', 100);
38 coll.add('key2', -100);
41 var biggerThanZero = coll.filterBy(function(value){
44 console.log(biggerThanZero.getCount()); // prints 2
48 Ext.define('Ext.util.MixedCollection', {
49 extend: 'Ext.util.AbstractMixedCollection',
51 sortable: 'Ext.util.Sortable'
55 * Creates new MixedCollection.
56 * @param {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}
57 * function should add function references to the collection. Defaults to
59 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
60 * and return the key value for that item. This is used when available to look up the key on items that
61 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
62 * equivalent to providing an implementation for the {@link #getKey} method.
64 constructor: function() {
66 me.callParent(arguments);
68 me.mixins.sortable.initSortable.call(me);
71 doSort: function(sorterFn) {
72 this.sortBy(sorterFn);
77 * Performs the actual sorting based on a direction and a sorting function. Internally,
78 * this creates a temporary array of all items in the MixedCollection, sorts it and then writes
79 * the sorted array data back into this.items and this.keys
80 * @param {String} property Property to sort by ('key', 'value', or 'index')
81 * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.
82 * @param {Function} fn (optional) Comparison function that defines the sort order.
83 * Defaults to sorting by numeric value.
85 _sort : function(property, dir, fn){
88 dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
90 //this is a temporary array used to apply the sorting function
95 //default to a simple sorter function if one is not provided
96 fn = fn || function(a, b) {
100 //copy all the items into a temporary array, which we will sort
101 for(i = 0, len = items.length; i < len; i++){
109 //sort the temporary array
110 Ext.Array.sort(c, function(a, b){
111 var v = fn(a[property], b[property]) * dsc;
113 v = (a.index < b.index ? -1 : 1);
118 //copy the temporary array back into the main this.items and this.keys objects
119 for(i = 0, len = c.length; i < len; i++){
120 items[i] = c[i].value;
124 me.fireEvent('sort', me);
128 * Sorts the collection by a single sorter function
129 * @param {Function} sorterFn The function to sort by
131 sortBy: function(sorterFn) {
135 length = items.length,
139 //first we create a copy of the items array so that we can sort it
140 for (i = 0; i < length; i++) {
148 Ext.Array.sort(temp, function(a, b) {
149 var v = sorterFn(a.value, b.value);
151 v = (a.index < b.index ? -1 : 1);
157 //copy the temporary array back into the main this.items and this.keys objects
158 for (i = 0; i < length; i++) {
159 items[i] = temp[i].value;
160 keys[i] = temp[i].key;
163 me.fireEvent('sort', me, items, keys);
167 * Reorders each of the items based on a mapping from old index to new index. Internally this
168 * just translates into a sort. The 'sort' event is fired whenever reordering has occured.
169 * @param {Object} mapping Mapping from old item index to new item index
171 reorder: function(mapping) {
175 length = items.length,
182 //object of {oldPosition: newPosition} reversed to {newPosition: oldPosition}
183 for (oldIndex in mapping) {
184 order[mapping[oldIndex]] = items[oldIndex];
187 for (index = 0; index < length; index++) {
188 if (mapping[index] == undefined) {
189 remaining.push(items[index]);
193 for (index = 0; index < length; index++) {
194 if (order[index] == undefined) {
195 order[index] = remaining.shift();
203 me.fireEvent('sort', me);
207 * Sorts this collection by <b>key</b>s.
208 * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.
209 * @param {Function} fn (optional) Comparison function that defines the sort order.
210 * Defaults to sorting by case insensitive string.
212 sortByKey : function(dir, fn){
213 this._sort('key', dir, fn || function(a, b){
214 var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
215 return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);