<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-data-Operation'>/**
|
</span> * @author Ed Spencer
|
*
|
* Represents a single read or write operation performed by a {@link Ext.data.proxy.Proxy Proxy}. Operation objects are
|
* used to enable communication between Stores and Proxies. Application developers should rarely need to interact with
|
* Operation objects directly.
|
*
|
* Several Operations can be batched together in a {@link Ext.data.Batch batch}.
|
*/
|
Ext.define('Ext.data.Operation', {
|
<span id='Ext-data-Operation-cfg-synchronous'> /**
|
</span> * @cfg {Boolean} synchronous
|
* True if this Operation is to be executed synchronously. This property is inspected by a
|
* {@link Ext.data.Batch Batch} to see if a series of Operations can be executed in parallel or not.
|
*/
|
synchronous: true,
|
|
<span id='Ext-data-Operation-cfg-action'> /**
|
</span> * @cfg {String} action
|
* The action being performed by this Operation. Should be one of 'create', 'read', 'update' or 'destroy'.
|
*/
|
action: undefined,
|
|
<span id='Ext-data-Operation-cfg-filters'> /**
|
</span> * @cfg {Ext.util.Filter[]} filters
|
* Optional array of filter objects. Only applies to 'read' actions.
|
*/
|
filters: undefined,
|
|
<span id='Ext-data-Operation-cfg-sorters'> /**
|
</span> * @cfg {Ext.util.Sorter[]} sorters
|
* Optional array of sorter objects. Only applies to 'read' actions.
|
*/
|
sorters: undefined,
|
|
<span id='Ext-data-Operation-cfg-groupers'> /**
|
</span> * @cfg {Ext.util.Grouper[]} groupers
|
* Optional grouping configuration. Only applies to 'read' actions where grouping is desired.
|
*/
|
groupers: undefined,
|
|
<span id='Ext-data-Operation-cfg-start'> /**
|
</span> * @cfg {Number} start
|
* The start index (offset), used in paging when running a 'read' action.
|
*/
|
start: undefined,
|
|
<span id='Ext-data-Operation-cfg-limit'> /**
|
</span> * @cfg {Number} limit
|
* The number of records to load. Used on 'read' actions when paging is being used.
|
*/
|
limit: undefined,
|
|
<span id='Ext-data-Operation-cfg-batch'> /**
|
</span> * @cfg {Ext.data.Batch} batch
|
* The batch that this Operation is a part of.
|
*/
|
batch: undefined,
|
|
<span id='Ext-data-Operation-cfg-params'> /**
|
</span> * @cfg {Object} params
|
* Parameters to pass along with the request when performing the operation.
|
*/
|
|
<span id='Ext-data-Operation-cfg-callback'> /**
|
</span> * @cfg {Function} callback
|
* Function to execute when operation completed.
|
* @cfg {Ext.data.Model[]} callback.records Array of records.
|
* @cfg {Ext.data.Operation} callback.operation The Operation itself.
|
* @cfg {Boolean} callback.success True when operation completed successfully.
|
*/
|
callback: undefined,
|
|
<span id='Ext-data-Operation-cfg-scope'> /**
|
</span> * @cfg {Object} scope
|
* Scope for the {@link #callback} function.
|
*/
|
scope: undefined,
|
|
<span id='Ext-data-Operation-property-started'> /**
|
</span> * @property {Boolean} started
|
* The start status of this Operation. Use {@link #isStarted}.
|
* @readonly
|
* @private
|
*/
|
started: false,
|
|
<span id='Ext-data-Operation-property-running'> /**
|
</span> * @property {Boolean} running
|
* The run status of this Operation. Use {@link #isRunning}.
|
* @readonly
|
* @private
|
*/
|
running: false,
|
|
<span id='Ext-data-Operation-property-complete'> /**
|
</span> * @property {Boolean} complete
|
* The completion status of this Operation. Use {@link #isComplete}.
|
* @readonly
|
* @private
|
*/
|
complete: false,
|
|
<span id='Ext-data-Operation-property-success'> /**
|
</span> * @property {Boolean} success
|
* Whether the Operation was successful or not. This starts as undefined and is set to true
|
* or false by the Proxy that is executing the Operation. It is also set to false by {@link #setException}. Use
|
* {@link #wasSuccessful} to query success status.
|
* @readonly
|
* @private
|
*/
|
success: undefined,
|
|
<span id='Ext-data-Operation-property-exception'> /**
|
</span> * @property {Boolean} exception
|
* The exception status of this Operation. Use {@link #hasException} and see {@link #getError}.
|
* @readonly
|
* @private
|
*/
|
exception: false,
|
|
<span id='Ext-data-Operation-property-error'> /**
|
</span> * @property {String/Object} error
|
* The error object passed when {@link #setException} was called. This could be any object or primitive.
|
* @private
|
*/
|
error: undefined,
|
|
<span id='Ext-data-Operation-property-actionCommitRecordsRe'> /**
|
</span> * @property {RegExp} actionCommitRecordsRe
|
* The RegExp used to categorize actions that require record commits.
|
*/
|
actionCommitRecordsRe: /^(?:create|update)$/i,
|
|
<span id='Ext-data-Operation-property-actionSkipSyncRe'> /**
|
</span> * @property {RegExp} actionSkipSyncRe
|
* The RegExp used to categorize actions that skip local record synchronization. This defaults
|
* to match 'destroy'.
|
*/
|
actionSkipSyncRe: /^destroy$/i,
|
|
<span id='Ext-data-Operation-method-constructor'> /**
|
</span> * Creates new Operation object.
|
* @param {Object} config (optional) Config object.
|
*/
|
constructor: function(config) {
|
Ext.apply(this, config || {});
|
},
|
|
<span id='Ext-data-Operation-method-commitRecords'> /**
|
</span> * This method is called to commit data to this instance's records given the records in
|
* the server response. This is followed by calling {@link Ext.data.Model#commit} on all
|
* those records (for 'create' and 'update' actions).
|
*
|
* If this {@link #action} is 'destroy', any server records are ignored and the
|
* {@link Ext.data.Model#commit} method is not called.
|
*
|
* @param {Ext.data.Model[]} serverRecords An array of {@link Ext.data.Model} objects returned by
|
* the server.
|
* @markdown
|
*/
|
commitRecords: function(serverRecords) {
|
var me = this,
|
commitRecords = me.actionCommitRecordsRe.test(me.action),
|
mc, index, clientRecords, serverRec, clientRec, i, len,
|
modifiedFields, recordModifiedFields;
|
|
if (!me.actionSkipSyncRe.test(me.action)) {
|
clientRecords = me.records;
|
|
if (clientRecords && clientRecords.length) {
|
|
// If we plan to commit the records modified by the server's return records
|
// we collect all the fields which were modified as a result.
|
// This is so that a modifiedFields array can be passed into the commit codepath
|
// so that minimal UI updating can be applied.
|
if (commitRecords) {
|
recordModifiedFields = [];
|
}
|
if (clientRecords.length > 1) {
|
// If this operation has multiple records, client records need to be matched up with server records
|
// so that any data returned from the server can be updated in the client records. If we don't have
|
// a clientIdProperty specified on the model and we've done a create, just assume the data is returned in order.
|
// If it's an update, the records should already have an id which should match what the server returns.
|
if (me.action == 'update' || clientRecords[0].clientIdProperty) {
|
mc = new Ext.util.MixedCollection();
|
mc.addAll(serverRecords);
|
|
for (index = clientRecords.length; index--; ) {
|
clientRec = clientRecords[index];
|
serverRec = mc.findBy(me.matchClientRec, clientRec);
|
|
// Replace client record data with server record data
|
modifiedFields = clientRec.copyFrom(serverRec);
|
|
// If we plan to commit the records, collect modified field list for each record
|
if (commitRecords) {
|
recordModifiedFields.push(modifiedFields);
|
}
|
}
|
} else {
|
for (i = 0, len = clientRecords.length; i < len; ++i) {
|
clientRec = clientRecords[i];
|
serverRec = serverRecords[i];
|
if (clientRec && serverRec) {
|
modifiedFields = me.updateRecord(clientRec, serverRec);
|
|
// If we plan to commit the records, collect modified field list for each record
|
if (commitRecords) {
|
recordModifiedFields.push(modifiedFields);
|
}
|
}
|
}
|
}
|
} else {
|
// operation only has one record, so just match the first client record up with the first server record
|
modifiedFields = me.updateRecord(clientRecords[0], serverRecords[0]);
|
|
// If we plan to commit the records, collect modified field list for each record
|
if (commitRecords) {
|
recordModifiedFields[0] = modifiedFields;
|
}
|
}
|
|
if (commitRecords) {
|
for (index = clientRecords.length; index--; ) {
|
|
// Pass array of field names which were modified as a result of the server's reply
|
// In a grid, this avoids full row refreshes when the record returns unmodified.
|
// See Ext.view.Table#shouldUpdateCell
|
clientRecords[index].commit(false, recordModifiedFields[index]);
|
}
|
}
|
}
|
}
|
},
|
|
<span id='Ext-data-Operation-method-updateRecord'> updateRecord: function(clientRec, serverRec) {
|
</span> // if the client record is not a phantom, make sure the ids match before replacing the client data with server data.
|
if (serverRec && (clientRec.phantom || clientRec.getId() === serverRec.getId())) {
|
return clientRec.copyFrom(serverRec);
|
}
|
|
// ID could not be matched up, no fields were modified.
|
return [];
|
},
|
|
<span id='Ext-data-Operation-method-matchClientRec'> // Private.
|
</span> // Record matching function used by commitRecords
|
// IMPORTANT: This is called in the scope of the clientRec being matched
|
matchClientRec: function(record) {
|
var clientRec = this,
|
clientRecordId = clientRec.getId();
|
|
if(clientRecordId && record.getId() === clientRecordId) {
|
return true;
|
}
|
// if the server record cannot be found by id, find by internalId.
|
// this allows client records that did not previously exist on the server
|
// to be updated with the correct server id and data.
|
return record.internalId === clientRec.internalId;
|
},
|
|
<span id='Ext-data-Operation-method-setStarted'> /**
|
</span> * Marks the Operation as started.
|
*/
|
setStarted: function() {
|
this.started = true;
|
this.running = true;
|
},
|
|
<span id='Ext-data-Operation-method-setCompleted'> /**
|
</span> * Marks the Operation as completed.
|
*/
|
setCompleted: function() {
|
this.complete = true;
|
this.running = false;
|
},
|
|
<span id='Ext-data-Operation-method-setSuccessful'> /**
|
</span> * Marks the Operation as successful.
|
*/
|
setSuccessful: function() {
|
this.success = true;
|
},
|
|
<span id='Ext-data-Operation-method-setException'> /**
|
</span> * Marks the Operation as having experienced an exception. Can be supplied with an option error message/object.
|
* @param {String/Object} error (optional) error string/object
|
*/
|
setException: function(error) {
|
this.exception = true;
|
this.success = false;
|
this.running = false;
|
this.error = error;
|
},
|
|
<span id='Ext-data-Operation-method-hasException'> /**
|
</span> * Returns true if this Operation encountered an exception (see also {@link #getError})
|
* @return {Boolean} True if there was an exception
|
*/
|
hasException: function() {
|
return this.exception === true;
|
},
|
|
<span id='Ext-data-Operation-method-getError'> /**
|
</span> * Returns the error string or object that was set using {@link #setException}
|
* @return {String/Object} The error object
|
*/
|
getError: function() {
|
return this.error;
|
},
|
|
<span id='Ext-data-Operation-method-getRecords'> /**
|
</span> * Returns the {@link Ext.data.Model record}s associated with this operation. For read operations the records as set by the {@link Ext.data.proxy.Proxy Proxy} will be returned (returns `null` if the proxy has not yet set the records).
|
* For create, update, and destroy operations the operation's initially configured records will be returned, although the proxy may modify these records' data at some point after the operation is initialized.
|
* @return {Ext.data.Model[]}
|
*/
|
getRecords: function() {
|
var resultSet = this.getResultSet();
|
return this.records || (resultSet ? resultSet.records : null);
|
},
|
|
<span id='Ext-data-Operation-method-getResultSet'> /**
|
</span> * Returns the ResultSet object (if set by the Proxy). This object will contain the {@link Ext.data.Model model}
|
* instances as well as meta data such as number of instances fetched, number available etc
|
* @return {Ext.data.ResultSet} The ResultSet object
|
*/
|
getResultSet: function() {
|
return this.resultSet;
|
},
|
|
<span id='Ext-data-Operation-method-isStarted'> /**
|
</span> * Returns true if the Operation has been started. Note that the Operation may have started AND completed, see
|
* {@link #isRunning} to test if the Operation is currently running.
|
* @return {Boolean} True if the Operation has started
|
*/
|
isStarted: function() {
|
return this.started === true;
|
},
|
|
<span id='Ext-data-Operation-method-isRunning'> /**
|
</span> * Returns true if the Operation has been started but has not yet completed.
|
* @return {Boolean} True if the Operation is currently running
|
*/
|
isRunning: function() {
|
return this.running === true;
|
},
|
|
<span id='Ext-data-Operation-method-isComplete'> /**
|
</span> * Returns true if the Operation has been completed
|
* @return {Boolean} True if the Operation is complete
|
*/
|
isComplete: function() {
|
return this.complete === true;
|
},
|
|
<span id='Ext-data-Operation-method-wasSuccessful'> /**
|
</span> * Returns true if the Operation has completed and was successful
|
* @return {Boolean} True if successful
|
*/
|
wasSuccessful: function() {
|
return this.isComplete() && this.success === true;
|
},
|
|
<span id='Ext-data-Operation-method-setBatch'> /**
|
</span> * @private
|
* Associates this Operation with a Batch
|
* @param {Ext.data.Batch} batch The batch
|
*/
|
setBatch: function(batch) {
|
this.batch = batch;
|
},
|
|
<span id='Ext-data-Operation-method-allowWrite'> /**
|
</span> * Checks whether this operation should cause writing to occur.
|
* @return {Boolean} Whether the operation should cause a write to occur.
|
*/
|
allowWrite: function() {
|
return this.action != 'read';
|
}
|
});
|
</pre>
|
</body>
|
</html>
|