1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-util.AbstractMixedCollection'>/**
2 </span> * @class Ext.util.AbstractMixedCollection
4 Ext.define('Ext.util.AbstractMixedCollection', {
5 requires: ['Ext.util.Filter'],
8 observable: 'Ext.util.Observable'
11 constructor: function(allowFunctions, keyFn) {
20 <span id='Ext-util.AbstractMixedCollection-event-clear'> /**
21 </span> * @event clear
22 * Fires when the collection is cleared.
26 <span id='Ext-util.AbstractMixedCollection-event-add'> /**
28 * Fires when an item is added to the collection.
29 * @param {Number} index The index at which the item was added.
30 * @param {Object} o The item added.
31 * @param {String} key The key associated with the added item.
35 <span id='Ext-util.AbstractMixedCollection-event-replace'> /**
36 </span> * @event replace
37 * Fires when an item is replaced in the collection.
38 * @param {String} key he key associated with the new added.
39 * @param {Object} old The item being replaced.
40 * @param {Object} new The new item.
44 <span id='Ext-util.AbstractMixedCollection-event-remove'> /**
45 </span> * @event remove
46 * Fires when an item is removed from the collection.
47 * @param {Object} o The item being removed.
48 * @param {String} key (optional) The key associated with the removed item.
53 me.allowFunctions = allowFunctions === true;
59 me.mixins.observable.constructor.call(me);
62 <span id='Ext-util.AbstractMixedCollection-cfg-allowFunctions'> /**
63 </span> * @cfg {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}
64 * function should add function references to the collection. Defaults to
65 * <tt>false</tt>.
67 allowFunctions : false,
69 <span id='Ext-util.AbstractMixedCollection-method-add'> /**
70 </span> * Adds an item to the collection. Fires the {@link #add} event when complete.
71 * @param {String} key <p>The key to associate with the item, or the new item.</p>
72 * <p>If a {@link #getKey} implementation was specified for this MixedCollection,
73 * or if the key of the stored items is in a property called <tt><b>id</b></tt>,
74 * the MixedCollection will be able to <i>derive</i> the key for the new item.
75 * In this case just pass the new item in this parameter.</p>
76 * @param {Object} o The item to add.
77 * @return {Object} The item added.
79 add : function(key, obj){
85 if (arguments.length == 1) {
87 myKey = me.getKey(myObj);
89 if (typeof myKey != 'undefined' && myKey !== null) {
91 if (typeof old != 'undefined') {
92 return me.replace(myKey, myObj);
94 me.map[myKey] = myObj;
99 me.fireEvent('add', me.length - 1, myObj, myKey);
103 <span id='Ext-util.AbstractMixedCollection-method-getKey'> /**
104 </span> * MixedCollection has a generic way to fetch keys if you implement getKey. The default implementation
105 * simply returns <b><code>item.id</code></b> but you can provide your own implementation
106 * to return a different value as in the following examples:<pre><code>
108 var mc = new Ext.util.MixedCollection();
109 mc.add(someEl.dom.id, someEl);
110 mc.add(otherEl.dom.id, otherEl);
114 var mc = new Ext.util.MixedCollection();
115 mc.getKey = function(el){
121 // or via the constructor
122 var mc = new Ext.util.MixedCollection(false, function(el){
127 * </code></pre>
128 * @param {Object} item The item for which to find the key.
129 * @return {Object} The key for the passed item.
131 getKey : function(o){
135 <span id='Ext-util.AbstractMixedCollection-method-replace'> /**
136 </span> * Replaces an item in the collection. Fires the {@link #replace} event when complete.
137 * @param {String} key <p>The key associated with the item to replace, or the replacement item.</p>
138 * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key
139 * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection
140 * will be able to <i>derive</i> the key of the replacement item. If you want to replace an item
141 * with one having the same key value, then just pass the replacement item in this parameter.</p>
142 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate
144 * @return {Object} The new item.
146 replace : function(key, o){
151 if (arguments.length == 1) {
156 if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
157 return me.add(key, o);
159 index = me.indexOfKey(key);
162 me.fireEvent('replace', key, old, o);
166 <span id='Ext-util.AbstractMixedCollection-method-addAll'> /**
167 </span> * Adds all elements of an Array or an Object to the collection.
168 * @param {Object/Array} objs An Object containing properties which will be added
169 * to the collection, or an Array of values, each of which are added to the collection.
170 * Functions references will be added to the collection if <code>{@link #allowFunctions}</code>
171 * has been set to <tt>true</tt>.
173 addAll : function(objs){
180 if (arguments.length > 1 || Ext.isArray(objs)) {
181 args = arguments.length > 1 ? arguments : objs;
182 for (len = args.length; i < len; i++) {
187 if (objs.hasOwnProperty(key)) {
188 if (me.allowFunctions || typeof objs[key] != 'function') {
189 me.add(key, objs[key]);
196 <span id='Ext-util.AbstractMixedCollection-method-each'> /**
197 </span> * Executes the specified function once for every item in the collection, passing the following arguments:
198 * <div class="mdetail-params"><ul>
199 * <li><b>item</b> : Mixed<p class="sub-desc">The collection item</p></li>
200 * <li><b>index</b> : Number<p class="sub-desc">The item's index</p></li>
201 * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>
202 * </ul></div>
203 * The function should return a boolean value. Returning false from the function will stop the iteration.
204 * @param {Function} fn The function to execute for each item.
205 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current item in the iteration.
207 each : function(fn, scope){
208 var items = [].concat(this.items), // each safe for removal
213 for (; i < len; i++) {
215 if (fn.call(scope || item, item, i, len) === false) {
221 <span id='Ext-util.AbstractMixedCollection-method-eachKey'> /**
222 </span> * Executes the specified function once for every key in the collection, passing each
223 * key, and its associated item as the first two parameters.
224 * @param {Function} fn The function to execute for each item.
225 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
227 eachKey : function(fn, scope){
228 var keys = this.keys,
233 for (; i < len; i++) {
234 fn.call(scope || window, keys[i], items[i], i, len);
238 <span id='Ext-util.AbstractMixedCollection-method-findBy'> /**
239 </span> * Returns the first item in the collection which elicits a true return value from the
240 * passed selection function.
241 * @param {Function} fn The selection function to execute for each item.
242 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
243 * @return {Object} The first item in the collection which returned true from the selection function.
245 findBy : function(fn, scope) {
246 var keys = this.keys,
251 for (; i < len; i++) {
252 if (fn.call(scope || window, items[i], keys[i])) {
259 //<deprecated since="0.99">
261 if (Ext.isDefined(Ext.global.console)) {
262 Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.');
264 return this.findBy.apply(this, arguments);
266 //</deprecated>
268 <span id='Ext-util.AbstractMixedCollection-method-insert'> /**
269 </span> * Inserts an item at the specified index in the collection. Fires the {@link #add} event when complete.
270 * @param {Number} index The index to insert the item at.
271 * @param {String} key The key to associate with the new item, or the item itself.
272 * @param {Object} o (optional) If the second parameter was a key, the new item.
273 * @return {Object} The item inserted.
275 insert : function(index, key, obj){
280 if (arguments.length == 2) {
282 myKey = me.getKey(myObj);
284 if (me.containsKey(myKey)) {
286 me.removeAtKey(myKey);
289 if (index >= me.length) {
290 return me.add(myKey, myObj);
293 me.items.splice(index, 0, myObj);
294 if (typeof myKey != 'undefined' && myKey !== null) {
295 me.map[myKey] = myObj;
297 me.keys.splice(index, 0, myKey);
298 me.fireEvent('add', index, myObj, myKey);
302 <span id='Ext-util.AbstractMixedCollection-method-remove'> /**
303 </span> * Remove an item from the collection.
304 * @param {Object} o The item to remove.
305 * @return {Object} The item removed or false if no item was removed.
307 remove : function(o){
308 return this.removeAt(this.indexOf(o));
311 <span id='Ext-util.AbstractMixedCollection-method-removeAll'> /**
312 </span> * Remove all items in the passed array from the collection.
313 * @param {Array} items An array of items to be removed.
314 * @return {Ext.util.MixedCollection} this object
316 removeAll : function(items){
317 Ext.each(items || [], function(item) {
324 <span id='Ext-util.AbstractMixedCollection-method-removeAt'> /**
325 </span> * Remove an item from a specified index in the collection. Fires the {@link #remove} event when complete.
326 * @param {Number} index The index within the collection of the item to remove.
327 * @return {Object} The item removed or false if no item was removed.
329 removeAt : function(index){
334 if (index < me.length && index >= 0) {
337 me.items.splice(index, 1);
338 key = me.keys[index];
339 if (typeof key != 'undefined') {
342 me.keys.splice(index, 1);
343 me.fireEvent('remove', o, key);
349 <span id='Ext-util.AbstractMixedCollection-method-removeAtKey'> /**
350 </span> * Removed an item associated with the passed key fom the collection.
351 * @param {String} key The key of the item to remove.
352 * @return {Object} The item removed or false if no item was removed.
354 removeAtKey : function(key){
355 return this.removeAt(this.indexOfKey(key));
358 <span id='Ext-util.AbstractMixedCollection-method-getCount'> /**
359 </span> * Returns the number of items in the collection.
360 * @return {Number} the number of items in the collection.
362 getCount : function(){
366 <span id='Ext-util.AbstractMixedCollection-method-indexOf'> /**
367 </span> * Returns index within the collection of the passed Object.
368 * @param {Object} o The item to find the index of.
369 * @return {Number} index of the item. Returns -1 if not found.
371 indexOf : function(o){
372 return Ext.Array.indexOf(this.items, o);
375 <span id='Ext-util.AbstractMixedCollection-method-indexOfKey'> /**
376 </span> * Returns index within the collection of the passed key.
377 * @param {String} key The key to find the index of.
378 * @return {Number} index of the key.
380 indexOfKey : function(key){
381 return Ext.Array.indexOf(this.keys, key);
384 <span id='Ext-util.AbstractMixedCollection-method-get'> /**
385 </span> * Returns the item associated with the passed key OR index.
386 * Key has priority over index. This is the equivalent
387 * of calling {@link #key} first, then if nothing matched calling {@link #getAt}.
388 * @param {String/Number} key The key or index of the item.
389 * @return {Object} If the item is found, returns the item. If the item was not found, returns <tt>undefined</tt>.
390 * If an item was found, but is a Class, returns <tt>null</tt>.
392 get : function(key) {
395 item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
396 return typeof item != 'function' || me.allowFunctions ? item : null; // for prototype!
399 <span id='Ext-util.AbstractMixedCollection-method-getAt'> /**
400 </span> * Returns the item at the specified index.
401 * @param {Number} index The index of the item.
402 * @return {Object} The item at the specified index.
404 getAt : function(index) {
405 return this.items[index];
408 <span id='Ext-util.AbstractMixedCollection-method-getByKey'> /**
409 </span> * Returns the item associated with the passed key.
410 * @param {String/Number} key The key of the item.
411 * @return {Object} The item associated with the passed key.
413 getByKey : function(key) {
414 return this.map[key];
417 <span id='Ext-util.AbstractMixedCollection-method-contains'> /**
418 </span> * Returns true if the collection contains the passed Object as an item.
419 * @param {Object} o The Object to look for in the collection.
420 * @return {Boolean} True if the collection contains the Object as an item.
422 contains : function(o){
423 return Ext.Array.contains(this.items, o);
426 <span id='Ext-util.AbstractMixedCollection-method-containsKey'> /**
427 </span> * Returns true if the collection contains the passed Object as a key.
428 * @param {String} key The key to look for in the collection.
429 * @return {Boolean} True if the collection contains the Object as a key.
431 containsKey : function(key){
432 return typeof this.map[key] != 'undefined';
435 <span id='Ext-util.AbstractMixedCollection-method-clear'> /**
436 </span> * Removes all items from the collection. Fires the {@link #clear} event when complete.
445 me.fireEvent('clear');
448 <span id='Ext-util.AbstractMixedCollection-method-first'> /**
449 </span> * Returns the first item in the collection.
450 * @return {Object} the first item in the collection..
453 return this.items[0];
456 <span id='Ext-util.AbstractMixedCollection-method-last'> /**
457 </span> * Returns the last item in the collection.
458 * @return {Object} the last item in the collection..
461 return this.items[this.length - 1];
464 <span id='Ext-util.AbstractMixedCollection-method-sum'> /**
465 </span> * Collects all of the values of the given property and returns their sum
466 * @param {String} property The property to sum by
467 * @param {String} root Optional 'root' property to extract the first argument from. This is used mainly when
468 * summing fields in records, where the fields are all stored inside the 'data' object
469 * @param {Number} start (optional) The record index to start at (defaults to <tt>0</tt>)
470 * @param {Number} end (optional) The record index to end at (defaults to <tt>-1</tt>)
471 * @return {Number} The total
473 sum: function(property, root, start, end) {
474 var values = this.extractValues(property, root),
475 length = values.length,
480 end = (end || end === 0) ? end : length - 1;
482 for (i = start; i <= end; i++) {
489 <span id='Ext-util.AbstractMixedCollection-method-collect'> /**
490 </span> * Collects unique values of a particular property in this MixedCollection
491 * @param {String} property The property to collect on
492 * @param {String} root Optional 'root' property to extract the first argument from. This is used mainly when
493 * summing fields in records, where the fields are all stored inside the 'data' object
494 * @param {Boolean} allowBlank (optional) Pass true to allow null, undefined or empty string values
495 * @return {Array} The unique values
497 collect: function(property, root, allowNull) {
498 var values = this.extractValues(property, root),
499 length = values.length,
504 for (i = 0; i < length; i++) {
506 strValue = String(value);
508 if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
509 hits[strValue] = true;
517 <span id='Ext-util.AbstractMixedCollection-method-extractValues'> /**
519 * Extracts all of the given property values from the items in the MC. Mainly used as a supporting method for
520 * functions like sum and collect.
521 * @param {String} property The property to extract
522 * @param {String} root Optional 'root' property to extract the first argument from. This is used mainly when
523 * extracting field data from Model instances, where the fields are stored inside the 'data' object
524 * @return {Array} The extracted values
526 extractValues: function(property, root) {
527 var values = this.items;
530 values = Ext.Array.pluck(values, root);
533 return Ext.Array.pluck(values, property);
536 <span id='Ext-util.AbstractMixedCollection-method-getRange'> /**
537 </span> * Returns a range of items in this collection
538 * @param {Number} startIndex (optional) The starting index. Defaults to 0.
539 * @param {Number} endIndex (optional) The ending index. Defaults to the last item.
540 * @return {Array} An array of items
542 getRange : function(start, end){
548 if (items.length < 1) {
553 end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
554 if (start <= end) {
555 for (i = start; i <= end; i++) {
556 range[range.length] = items[i];
559 for (i = start; i >= end; i--) {
560 range[range.length] = items[i];
566 <span id='Ext-util.AbstractMixedCollection-method-filter'> /**
567 </span> * <p>Filters the objects in this collection by a set of {@link Ext.util.Filter Filter}s, or by a single
568 * property/value pair with optional parameters for substring matching and case sensitivity. See
569 * {@link Ext.util.Filter Filter} for an example of using Filter objects (preferred). Alternatively,
570 * MixedCollection can be easily filtered by property like this:</p>
571 <pre><code>
572 //create a simple store with a few people defined
573 var people = new Ext.util.MixedCollection();
575 {id: 1, age: 25, name: 'Ed'},
576 {id: 2, age: 24, name: 'Tommy'},
577 {id: 3, age: 24, name: 'Arne'},
578 {id: 4, age: 26, name: 'Aaron'}
581 //a new MixedCollection containing only the items where age == 24
582 var middleAged = people.filter('age', 24);
583 </code></pre>
586 * @param {Array/String} property A property on your objects, or an array of {@link Ext.util.Filter Filter} objects
587 * @param {String/RegExp} value Either string that the property values
588 * should start with or a RegExp to test against the property
589 * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
590 * @param {Boolean} caseSensitive (optional) True for case sensitive comparison (defaults to False).
591 * @return {MixedCollection} The new filtered collection
593 filter : function(property, value, anyMatch, caseSensitive) {
597 //support for the simple case of filtering by property/value
598 if (Ext.isString(property)) {
599 filters.push(Ext.create('Ext.util.Filter', {
603 caseSensitive: caseSensitive
605 } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
606 filters = filters.concat(property);
609 //at this point we have an array of zero or more Ext.util.Filter objects to filter with,
610 //so here we construct a function that combines these filters by ANDing them together
611 filterFn = function(record) {
613 length = filters.length,
616 for (i = 0; i < length; i++) {
617 var filter = filters[i],
618 fn = filter.filterFn,
619 scope = filter.scope;
621 isMatch = isMatch && fn.call(scope, record);
627 return this.filterBy(filterFn);
630 <span id='Ext-util.AbstractMixedCollection-method-filterBy'> /**
631 </span> * Filter by a function. Returns a <i>new</i> collection that has been filtered.
632 * The passed function will be called with each object in the collection.
633 * If the function returns true, the value is included otherwise it is filtered.
634 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
635 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this MixedCollection.
636 * @return {MixedCollection} The new filtered collection
638 filterBy : function(fn, scope) {
640 newMC = new this.self(),
643 length = items.length,
646 newMC.getKey = me.getKey;
648 for (i = 0; i < length; i++) {
649 if (fn.call(scope || me, items[i], keys[i])) {
650 newMC.add(keys[i], items[i]);
657 <span id='Ext-util.AbstractMixedCollection-method-findIndex'> /**
658 </span> * Finds the index of the first matching object in this collection by a specific property/value.
659 * @param {String} property The name of a property on your objects.
660 * @param {String/RegExp} value A string that the property values
661 * should start with or a RegExp to test against the property.
662 * @param {Number} start (optional) The index to start searching at (defaults to 0).
663 * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning.
664 * @param {Boolean} caseSensitive (optional) True for case sensitive comparison.
665 * @return {Number} The matched index or -1
667 findIndex : function(property, value, start, anyMatch, caseSensitive){
668 if(Ext.isEmpty(value, false)){
671 value = this.createValueMatcher(value, anyMatch, caseSensitive);
672 return this.findIndexBy(function(o){
673 return o && value.test(o[property]);
677 <span id='Ext-util.AbstractMixedCollection-method-findIndexBy'> /**
678 </span> * Find the index of the first matching object in this collection by a function.
679 * If the function returns <i>true</i> it is considered a match.
680 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key).
681 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this MixedCollection.
682 * @param {Number} start (optional) The index to start searching at (defaults to 0).
683 * @return {Number} The matched index or -1
685 findIndexBy : function(fn, scope, start){
692 for (; i < len; i++) {
693 if (fn.call(scope || me, items[i], keys[i])) {
700 <span id='Ext-util.AbstractMixedCollection-method-createValueMatcher'> /**
701 </span> * Returns a regular expression based on the given value and matching options. This is used internally for finding and filtering,
702 * and by Ext.data.Store#filter
704 * @param {String} value The value to create the regex for. This is escaped using Ext.escapeRe
705 * @param {Boolean} anyMatch True to allow any match - no regex start/end line anchors will be added. Defaults to false
706 * @param {Boolean} caseSensitive True to make the regex case sensitive (adds 'i' switch to regex). Defaults to false.
707 * @param {Boolean} exactMatch True to force exact match (^ and $ characters added to the regex). Defaults to false. Ignored if anyMatch is true.
709 createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
710 if (!value.exec) { // not a regex
711 var er = Ext.String.escapeRegex;
712 value = String(value);
714 if (anyMatch === true) {
717 value = '^' + er(value);
718 if (exactMatch === true) {
722 value = new RegExp(value, caseSensitive ? '' : 'i');
727 <span id='Ext-util.AbstractMixedCollection-method-clone'> /**
728 </span> * Creates a shallow copy of this collection
729 * @return {MixedCollection}
733 copy = new this.self(),
739 for(; i < len; i++){
740 copy.add(keys[i], items[i]);
742 copy.getKey = me.getKey;
746 </pre></pre></body></html>