Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / docs / source / Store.html
index 493b97d..0dc3e50 100644 (file)
@@ -7,10 +7,10 @@
 </head>
 <body  onload="prettyPrint();">
     <pre class="prettyprint lang-js">/*!
 </head>
 <body  onload="prettyPrint();">
     <pre class="prettyprint lang-js">/*!
- * Ext JS Library 3.2.1
- * Copyright(c) 2006-2010 Ext JS, Inc.
- * licensing@extjs.com
- * http://www.extjs.com/license
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
  */
 <div id="cls-Ext.data.Store"></div>/**
  * @class Ext.data.Store
  */
 <div id="cls-Ext.data.Store"></div>/**
  * @class Ext.data.Store
@@ -266,29 +266,30 @@ sortInfo: {
         dir : 'dir'
     },
 
         dir : 'dir'
     },
 
-    <div id="prop-Ext.data.Store-isDestroyed"></div>/**
-     * @property isDestroyed
-     * @type Boolean
-     * True if the store has been destroyed already. Read only
-     */
-    isDestroyed: false,
-
-    <div id="prop-Ext.data.Store-hasMultiSort"></div>/**
-     * @property hasMultiSort
-     * @type Boolean
-     * True if this store is currently sorted by more than one field/direction combination.
-     */
+    isDestroyed: false,    
     hasMultiSort: false,
 
     // private
     batchKey : '_ext_batch_',
 
     constructor : function(config){
     hasMultiSort: false,
 
     // private
     batchKey : '_ext_batch_',
 
     constructor : function(config){
+        <div id="prop-Ext.data.Store-multiSort"></div>/**
+         * @property multiSort
+         * @type Boolean
+         * True if this store is currently sorted by more than one field/direction combination.
+         */
+        
+        <div id="prop-Ext.data.Store-isDestroyed"></div>/**
+         * @property isDestroyed
+         * @type Boolean
+         * True if the store has been destroyed already. Read only
+         */
+        
         this.data = new Ext.util.MixedCollection(false);
         this.data.getKey = function(o){
             return o.id;
         };
         this.data = new Ext.util.MixedCollection(false);
         this.data.getKey = function(o){
             return o.id;
         };
-
+        
 
         // temporary removed-records cache
         this.removed = [];
 
         // temporary removed-records cache
         this.removed = [];
@@ -461,7 +462,7 @@ sortInfo: {
              * @event clear
              * Fires when the data cache has been cleared.
              * @param {Store} this
              * @event clear
              * Fires when the data cache has been cleared.
              * @param {Store} this
-             * @param {Record[]} The records that were cleared.
+             * @param {Record[]} records The records that were cleared.
              */
             'clear',
             <div id="event-Ext.data.Store-exception"></div>/**
              */
             'clear',
             <div id="event-Ext.data.Store-exception"></div>/**
@@ -632,19 +633,31 @@ sortInfo: {
      * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects
      * to add to the cache. See {@link #recordType}.
      */
      * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects
      * to add to the cache. See {@link #recordType}.
      */
-    add : function(records){
+    add : function(records) {
+        var i, len, record, index;
+        
         records = [].concat(records);
         records = [].concat(records);
-        if(records.length < 1){
+        if (records.length < 1) {
             return;
         }
             return;
         }
-        for(var i = 0, len = records.length; i < len; i++){
-            records[i].join(this);
+        
+        for (i = 0, len = records.length; i < len; i++) {
+            record = records[i];
+            
+            record.join(this);
+            
+            if (record.dirty || record.phantom) {
+                this.modified.push(record);
+            }
         }
         }
-        var index = this.data.length;
+        
+        index = this.data.length;
         this.data.addAll(records);
         this.data.addAll(records);
-        if(this.snapshot){
+        
+        if (this.snapshot) {
             this.snapshot.addAll(records);
         }
             this.snapshot.addAll(records);
         }
+        
         this.fireEvent('add', this, records, index);
     },
 
         this.fireEvent('add', this, records, index);
     },
 
@@ -657,6 +670,18 @@ sortInfo: {
         var index = this.findInsertIndex(record);
         this.insert(index, record);
     },
         var index = this.findInsertIndex(record);
         this.insert(index, record);
     },
+    
+    /**
+     * @private
+     * Update a record within the store with a new reference
+     */
+    doUpdate : function(rec){
+        this.data.replace(rec.id, rec);
+        if(this.snapshot){
+            this.snapshot.replace(rec.id, rec);
+        }
+        this.fireEvent('update', this, rec, Ext.data.Record.COMMIT);
+    },
 
     <div id="method-Ext.data.Store-remove"></div>/**
      * Remove Records from the Store and fires the {@link #remove} event.
 
     <div id="method-Ext.data.Store-remove"></div>/**
      * Remove Records from the Store and fires the {@link #remove} event.
@@ -727,15 +752,25 @@ sortInfo: {
      * @param {Number} index The start index at which to insert the passed Records.
      * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects to add to the cache.
      */
      * @param {Number} index The start index at which to insert the passed Records.
      * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects to add to the cache.
      */
-    insert : function(index, records){
+    insert : function(index, records) {
+        var i, len, record;
+        
         records = [].concat(records);
         records = [].concat(records);
-        for(var i = 0, len = records.length; i < len; i++){
-            this.data.insert(index, records[i]);
-            records[i].join(this);
+        for (i = 0, len = records.length; i < len; i++) {
+            record = records[i];
+            
+            this.data.insert(index + i, record);
+            record.join(this);
+            
+            if (record.dirty || record.phantom) {
+                this.modified.push(record);
+            }
         }
         }
-        if(this.snapshot){
+        
+        if (this.snapshot) {
             this.snapshot.addAll(records);
         }
             this.snapshot.addAll(records);
         }
+        
         this.fireEvent('add', this, records, index);
     },
 
         this.fireEvent('add', this, records, index);
     },
 
@@ -864,17 +899,26 @@ sortInfo: {
     },
 
     /**
     },
 
     /**
+     * @private
      * Should not be used directly.  Store#add will call this automatically if a Writer is set
      * @param {Object} store
      * Should not be used directly.  Store#add will call this automatically if a Writer is set
      * @param {Object} store
-     * @param {Object} rs
+     * @param {Object} records
      * @param {Object} index
      * @param {Object} index
-     * @private
      */
      */
-    createRecords : function(store, rs, index) {
-        for (var i = 0, len = rs.length; i < len; i++) {
-            if (rs[i].phantom && rs[i].isValid()) {
-                rs[i].markDirty();  // <-- Mark new records dirty
-                this.modified.push(rs[i]);  // <-- add to modified
+    createRecords : function(store, records, index) {
+        var modified = this.modified,
+            length   = records.length,
+            record, i;
+        
+        for (i = 0; i < length; i++) {
+            record = records[i];
+            
+            if (record.phantom && record.isValid()) {
+                record.markDirty();  // <-- Mark new records dirty (Ed: why?)
+                
+                if (modified.indexOf(record) == -1) {
+                    modified.push(record);
+                }
             }
         }
         if (this.autoSave === true) {
             }
         }
         if (this.autoSave === true) {
@@ -991,7 +1035,8 @@ sortInfo: {
             len,
             trans,
             batch,
             len,
             trans,
             batch,
-            data = {};
+            data = {},
+            i;
         // DESTROY:  First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
         if(this.removed.length){
             queue.push(['destroy', this.removed]);
         // DESTROY:  First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
         if(this.removed.length){
             queue.push(['destroy', this.removed]);
@@ -1002,7 +1047,7 @@ sortInfo: {
         if(rs.length){
             // CREATE:  Next check for phantoms within rs.  splice-off and execute create.
             var phantoms = [];
         if(rs.length){
             // CREATE:  Next check for phantoms within rs.  splice-off and execute create.
             var phantoms = [];
-            for(var i = rs.length-1; i >= 0; i--){
+            for(i = rs.length-1; i >= 0; i--){
                 if(rs[i].phantom === true){
                     var rec = rs.splice(i, 1).shift();
                     if(rec.isValid()){
                 if(rs[i].phantom === true){
                     var rec = rs.splice(i, 1).shift();
                     if(rec.isValid()){
@@ -1025,12 +1070,12 @@ sortInfo: {
         len = queue.length;
         if(len){
             batch = ++this.batchCounter;
         len = queue.length;
         if(len){
             batch = ++this.batchCounter;
-            for(var i = 0; i < len; ++i){
+            for(i = 0; i < len; ++i){
                 trans = queue[i];
                 data[trans[0]] = trans[1];
             }
             if(this.fireEvent('beforesave', this, data) !== false){
                 trans = queue[i];
                 data[trans[0]] = trans[1];
             }
             if(this.fireEvent('beforesave', this, data) !== false){
-                for(var i = 0; i < len; ++i){
+                for(i = 0; i < len; ++i){
                     trans = queue[i];
                     this.doTransaction(trans[0], trans[1], batch);
                 }
                     trans = queue[i];
                     this.doTransaction(trans[0], trans[1], batch);
                 }
@@ -1078,7 +1123,6 @@ sortInfo: {
         var b = this.batches,
             key = this.batchKey + batch,
             o = b[key],
         var b = this.batches,
             key = this.batchKey + batch,
             o = b[key],
-            data,
             arr;
 
 
             arr;
 
 
@@ -1217,6 +1261,8 @@ myStore.reload(lastOptions);
     // private
     // Called as a callback by the Reader during a load operation.
     loadRecords : function(o, options, success){
     // private
     // Called as a callback by the Reader during a load operation.
     loadRecords : function(o, options, success){
+        var i, len;
+        
         if (this.isDestroyed === true) {
             return;
         }
         if (this.isDestroyed === true) {
             return;
         }
@@ -1234,7 +1280,7 @@ myStore.reload(lastOptions);
             if(this.pruneModifiedRecords){
                 this.modified = [];
             }
             if(this.pruneModifiedRecords){
                 this.modified = [];
             }
-            for(var i = 0, len = r.length; i < len; i++){
+            for(i = 0, len = r.length; i < len; i++){
                 r[i].join(this);
             }
             if(this.snapshot){
                 r[i].join(this);
             }
             if(this.snapshot){
@@ -1247,8 +1293,20 @@ myStore.reload(lastOptions);
             this.applySort();
             this.fireEvent('datachanged', this);
         }else{
             this.applySort();
             this.fireEvent('datachanged', this);
         }else{
-            this.totalLength = Math.max(t, this.data.length+r.length);
-            this.add(r);
+            var toAdd = [],
+                rec,
+                cnt = 0;
+            for(i = 0, len = r.length; i < len; ++i){
+                rec = r[i];
+                if(this.indexOfId(rec.id) > -1){
+                    this.doUpdate(rec);
+                }else{
+                    toAdd.push(rec);
+                    ++cnt;
+                }
+            }
+            this.totalLength = Math.max(t, this.data.length + cnt);
+            this.add(toAdd);
         }
         this.fireEvent('load', this, r, options);
         if(options.callback){
         }
         this.fireEvent('load', this, r, options);
         if(options.callback){
@@ -1447,7 +1505,9 @@ myStore.reload(lastOptions);
      */
     singleSort: function(fieldName, dir) {
         var field = this.fields.get(fieldName);
      */
     singleSort: function(fieldName, dir) {
         var field = this.fields.get(fieldName);
-        if (!field) return false;
+        if (!field) {
+            return false;
+        }
 
         var name       = field.name,
             sortInfo   = this.sortInfo || null,
 
         var name       = field.name,
             sortInfo   = this.sortInfo || null,
@@ -1478,6 +1538,7 @@ myStore.reload(lastOptions);
             this.applySort();
             this.fireEvent('datachanged', this);
         }
             this.applySort();
             this.fireEvent('datachanged', this);
         }
+        return true;
     },
 
     <div id="method-Ext.data.Store-multiSort"></div>/**
     },
 
     <div id="method-Ext.data.Store-multiSort"></div>/**
@@ -1498,9 +1559,9 @@ myStore.reload(lastOptions);
         }
 
         <div id="prop-Ext.data.Store-multiSortInfo"></div>/**
         }
 
         <div id="prop-Ext.data.Store-multiSortInfo"></div>/**
+         * Object containing overall sort direction and an ordered array of sorter configs used when sorting on multiple fields
          * @property multiSortInfo
          * @type Object
          * @property multiSortInfo
          * @type Object
-         * Object containing overall sort direction and an ordered array of sorter configs used when sorting on multiple fields
          */
         this.multiSortInfo = {
             sorters  : sorters,
          */
         this.multiSortInfo = {
             sorters  : sorters,
@@ -1634,6 +1695,7 @@ myStore.reload(lastOptions);
      * @param {Boolean} exactMatch True to force exact match (^ and $ characters added to the regex). Defaults to false. Ignored if anyMatch is true.
      */
     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
      * @param {Boolean} exactMatch True to force exact match (^ and $ characters added to the regex). Defaults to false. Ignored if anyMatch is true.
      */
     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
+        var fn;
         //we can accept an array of filter objects, or a single filter object - normalize them here
         if (Ext.isObject(property)) {
             property = [property];
         //we can accept an array of filter objects, or a single filter object - normalize them here
         if (Ext.isObject(property)) {
             property = [property];
@@ -1656,10 +1718,10 @@ myStore.reload(lastOptions);
                 filters.push({fn: func, scope: scope});
             }
 
                 filters.push({fn: func, scope: scope});
             }
 
-            var fn = this.createMultipleFilterFn(filters);
+            fn = this.createMultipleFilterFn(filters);
         } else {
             //classic single property filter
         } else {
             //classic single property filter
-            var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
+            fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
         }
 
         return fn ? this.filterBy(fn) : this.clearFilter();
         }
 
         return fn ? this.filterBy(fn) : this.clearFilter();
@@ -1678,7 +1740,7 @@ myStore.reload(lastOptions);
      */
     filterBy : function(fn, scope){
         this.snapshot = this.snapshot || this.data;
      */
     filterBy : function(fn, scope){
         this.snapshot = this.snapshot || this.data;
-        this.data = this.queryBy(fn, scope||this);
+        this.data = this.queryBy(fn, scope || this);
         this.fireEvent('datachanged', this);
     },
 
         this.fireEvent('datachanged', this);
     },
 
@@ -1828,28 +1890,39 @@ myStore.reload(lastOptions);
      * Ext.data.Record.COMMIT.
      */
     commitChanges : function(){
      * Ext.data.Record.COMMIT.
      */
     commitChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            m[i].commit();
+        var modified = this.modified.slice(0),
+            length   = modified.length,
+            i;
+            
+        for (i = 0; i < length; i++){
+            modified[i].commit();
         }
         }
+        
+        this.modified = [];
+        this.removed  = [];
     },
 
     <div id="method-Ext.data.Store-rejectChanges"></div>/**
      * {@link Ext.data.Record#reject Reject} outstanding changes on all {@link #getModifiedRecords modified records}.
      */
     },
 
     <div id="method-Ext.data.Store-rejectChanges"></div>/**
      * {@link Ext.data.Record#reject Reject} outstanding changes on all {@link #getModifiedRecords modified records}.
      */
-    rejectChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            m[i].reject();
+    rejectChanges : function() {
+        var modified = this.modified.slice(0),
+            removed  = this.removed.slice(0).reverse(),
+            mLength  = modified.length,
+            rLength  = removed.length,
+            i;
+        
+        for (i = 0; i < mLength; i++) {
+            modified[i].reject();
         }
         }
-        var m = this.removed.slice(0).reverse();
-        this.removed = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            this.insert(m[i].lastIndex||0, m[i]);
-            m[i].reject();
+        
+        for (i = 0; i < rLength; i++) {
+            this.insert(removed[i].lastIndex || 0, removed[i]);
+            removed[i].reject();
         }
         }
+        
+        this.modified = [];
+        this.removed  = [];
     },
 
     // private
     },
 
     // private