/** * @author Ed Spencer * * In-memory proxy. This proxy simply uses a local variable for data storage/retrieval, so its contents are lost on * every page refresh. * * Usually this Proxy isn't used directly, serving instead as a helper to a {@link Ext.data.Store Store} where a reader * is required to load data. For example, say we have a Store for a User model and have some inline data we want to * load, but this data isn't in quite the right format: we can use a MemoryProxy with a JsonReader to read it into our * Store: * * //this is the model we will be using in the store * Ext.define('User', { * extend: 'Ext.data.Model', * fields: [ * {name: 'id', type: 'int'}, * {name: 'name', type: 'string'}, * {name: 'phone', type: 'string', mapping: 'phoneNumber'} * ] * }); * * //this data does not line up to our model fields - the phone field is called phoneNumber * var data = { * users: [ * { * id: 1, * name: 'Ed Spencer', * phoneNumber: '555 1234' * }, * { * id: 2, * name: 'Abe Elias', * phoneNumber: '666 1234' * } * ] * }; * * //note how we set the 'root' in the reader to match the data structure above * var store = Ext.create('Ext.data.Store', { * autoLoad: true, * model: 'User', * data : data, * proxy: { * type: 'memory', * reader: { * type: 'json', * root: 'users' * } * } * }); */ Ext.define('Ext.data.proxy.Memory', { extend: 'Ext.data.proxy.Client', alias: 'proxy.memory', alternateClassName: 'Ext.data.MemoryProxy', /** * @cfg {Boolean} [enablePaging=false] * Configure as `true` to enable this MemoryProxy to honour a read operation's `start` and `limit` options. * * When `true`, read operations will be able to read *pages* of records from the data object. */ /** * @cfg {Object} data * Optional data to pass to configured Reader. */ constructor: function(config) { this.callParent([config]); //ensures that the reader has been instantiated properly this.setReader(this.reader); }, /** * @private * Fake processing function to commit the records, set the current operation * to successful and call the callback if provided. This function is shared * by the create, update and destroy methods to perform the bare minimum * processing required for the proxy to register a result from the action. */ updateOperation: function(operation, callback, scope) { var i = 0, recs = operation.getRecords(), len = recs.length; for (i; i < len; i++) { recs[i].commit(); } operation.setCompleted(); operation.setSuccessful(); Ext.callback(callback, scope || this, [operation]); }, /** * Currently this is a hard-coded method that simply commits any records and sets the operation to successful, * then calls the callback function, if provided. It is essentially mocking a server call in memory, but since * there is no real back end in this case there's not much else to do. This method can be easily overridden to * implement more complex logic if needed. * @param {Ext.data.Operation} operation The Operation to perform * @param {Function} callback Callback function to be called when the Operation has completed (whether * successful or not) * @param {Object} scope Scope to execute the callback function in * @method */ create: function() { this.updateOperation.apply(this, arguments); }, /** * Currently this is a hard-coded method that simply commits any records and sets the operation to successful, * then calls the callback function, if provided. It is essentially mocking a server call in memory, but since * there is no real back end in this case there's not much else to do. This method can be easily overridden to * implement more complex logic if needed. * @param {Ext.data.Operation} operation The Operation to perform * @param {Function} callback Callback function to be called when the Operation has completed (whether * successful or not) * @param {Object} scope Scope to execute the callback function in * @method */ update: function() { this.updateOperation.apply(this, arguments); }, /** * Currently this is a hard-coded method that simply commits any records and sets the operation to successful, * then calls the callback function, if provided. It is essentially mocking a server call in memory, but since * there is no real back end in this case there's not much else to do. This method can be easily overridden to * implement more complex logic if needed. * @param {Ext.data.Operation} operation The Operation to perform * @param {Function} callback Callback function to be called when the Operation has completed (whether * successful or not) * @param {Object} scope Scope to execute the callback function in * @method */ destroy: function() { this.updateOperation.apply(this, arguments); }, /** * Reads data from the configured {@link #data} object. Uses the Proxy's {@link #reader}, if present. * @param {Ext.data.Operation} operation The read Operation * @param {Function} callback The callback to call when reading has completed * @param {Object} scope The scope to call the callback function in */ read: function(operation, callback, scope) { var me = this, resultSet = operation.resultSet = me.getReader().read(me.data), records = resultSet.records, sorters = operation.sorters, groupers = operation.groupers, filters = operation.filters; operation.setCompleted(); // Apply filters, sorters, and start/limit options if (resultSet.success) { // Filter the resulting array of records if (filters && filters.length) { records = resultSet.records = Ext.Array.filter(records, Ext.util.Filter.createFilterFn(filters)); } // Remotely, groupers just mean top priority sorters if (groupers && groupers.length) { Ext.Array.insert(sorters||[], 0, groupers); } // Sort by the specified groupers and sorters if (sorters && sorters.length) { resultSet.records = Ext.Array.sort(records, Ext.util.Sortable.createComparator(sorters)); } // Reader reads the whole passed data object. // If successful and we were given a start and limit, slice the result. if (me.enablePaging && operation.start !== undefined && operation.limit !== undefined) { // Attempt to read past end of memory dataset - convert to failure if (operation.start >= resultSet.total) { resultSet.success = false; resultSet.count = 0; resultSet.records = []; } // Range is valid, slice it up. else { resultSet.records = Ext.Array.slice(resultSet.records, operation.start, operation.start + operation.limit); resultSet.count = resultSet.records.length; } } } if (resultSet.success) { operation.setSuccessful(); } else { me.fireEvent('exception', me, null, operation); } Ext.callback(callback, scope || me, [operation]); }, clear: Ext.emptyFn });