X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/25ef3491bd9ae007ff1fc2b0d7943e6eaaccf775..6e39d509471fe9b4e2660e0d1631b350d0c66f40:/pkgs/data-foundation-debug.js
diff --git a/pkgs/data-foundation-debug.js b/pkgs/data-foundation-debug.js
index 8164b7dc..8d19389a 100644
--- a/pkgs/data-foundation-debug.js
+++ b/pkgs/data-foundation-debug.js
@@ -1,5 +1,5 @@
/*!
- * Ext JS Library 3.0.3
+ * Ext JS Library 3.1.0
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
@@ -169,7 +169,8 @@ new Ext.data.HttpProxy({
proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
if (typeof(proxy.api[action]) == 'string') {
proxy.api[action] = {
- url: proxy.api[action]
+ url: proxy.api[action],
+ method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
};
}
}
@@ -195,16 +196,13 @@ new Ext.data.HttpProxy({
});
switch (response.status) {
- case 200: // standard 200 response, send control back to HttpProxy#onWrite
+ case 200: // standard 200 response, send control back to HttpProxy#onWrite by returning true from this intercepted #onWrite
return true;
break;
case 201: // entity created but no response returned
- //res[reader.meta.successProperty] = true;
res.success = true;
break;
case 204: // no-content. Create a fake response.
- //res[reader.meta.successProperty] = true;
- //res[reader.meta.root] = null;
res.success = true;
res.data = null;
break;
@@ -212,13 +210,6 @@ new Ext.data.HttpProxy({
return true;
break;
}
- /*
- if (res[reader.meta.successProperty] === true) {
- this.fireEvent("write", this, action, res[reader.meta.root], res, rs, o.request.arg);
- } else {
- this.fireEvent('exception', this, 'remote', action, o, res, rs);
- }
- */
if (res.success === true) {
this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
} else {
@@ -394,10 +385,11 @@ Ext.data.SortTypes = {
* @param {Object} data (Optional) An object, the properties of which provide values for the new Record's
* fields. If not specified the {@link Ext.data.Field#defaultValue defaultValue}
* for each field will be assigned.
- * @param {Object} id (Optional) The id of the Record. This id should be unique, and is used by the
- * {@link Ext.data.Store} object which owns the Record to index its collection of Records. If
- * an id
is not specified a {@link #phantom}
Record will be created
- * with an {@link #Record.id automatically generated id}.
+ * @param {Object} id (Optional) The id of the Record. The id is used by the
+ * {@link Ext.data.Store} object which owns the Record to index its collection
+ * of Records (therefore this id should be unique within each store). If an
+ * id
is not specified a {@link #phantom}
+ * Record will be created with an {@link #Record.id automatically generated id}.
*/
Ext.data.Record = function(data, id){
// if no id, call the auto id method
@@ -503,22 +495,34 @@ Ext.data.Record.prototype = {
* @property id
* @type {Object}
*/
+ /**
+ *
Only present if this Record was created by an {@link Ext.data.XmlReader XmlReader}.
+ *The XML element which was the source of the data for this Record.
+ * @property node + * @type {XMLElement} + */ + /** + *Only present if this Record was created by an {@link Ext.data.ArrayReader ArrayReader} or a {@link Ext.data.JsonReader JsonReader}.
+ *The Array or object which was the source of the data for this Record.
+ * @property json + * @type {Array|Object} + */ /** * Readonly flag - true if this Record has been modified. * @type Boolean */ dirty : false, editing : false, - error: null, + error : null, /** * This object contains a key and value storing the original values of all modified * fields or is null if no fields have been modified. * @property modified * @type {Object} */ - modified: null, + modified : null, /** - * false when the record does not yet exist in a server-side database (see + * true when the record does not yet exist in a server-side database (see * {@link #markDirty}). Any record which has a real database pk set as its id property * is NOT a phantom -- it's real. * @property phantom @@ -556,7 +560,7 @@ rec.{@link #commit}(); // update the record in the store, bypass setting dirty flag, // and do not store the change in the {@link Ext.data.Store#getModifiedRecords modified records} -rec.{@link #data}['firstname'] = 'Wilma'); // updates record, but not the view +rec.{@link #data}['firstname'] = 'Wilma'; // updates record, but not the view rec.{@link #commit}(); // updates the view * * Notes:id
is not specified the copy created will be a
- * {@link #phantom}
Record.
+ * Creates a copy (clone) of this Record.
+ * @param {String} id (optional) A new Record id, defaults to the id
+ * of the record being copied. See {@link #id}
.
+ * To generate a phantom record with a new id use:
+var rec = record.copy(); // clone the record
+Ext.data.Record.id(rec); // automatically generate a unique sequential id
+ *
* @return {Record}
*/
copy : function(newId) {
@@ -765,7 +770,8 @@ rec.{@link #commit}(); // updates the view
this.modified[f.name] = this.data[f.name];
},this);
}
-};/**
+};
+/**
* @class Ext.StoreMgr
* @extends Ext.util.MixedCollection
* The default global group of stores.
@@ -902,282 +908,7 @@ myStore.{@link #insert}(0, r); // insert a new record into the store (also see {
* and read the data into Records.
* @xtype store
*/
-Ext.data.Store = function(config){
- this.data = new Ext.util.MixedCollection(false);
- this.data.getKey = function(o){
- return o.id;
- };
- /**
- * See the {@link #baseParams corresponding configuration option}
- * for a description of this property.
- * To modify this property see {@link #setBaseParam}
.
- * @property
- */
- this.baseParams = {};
-
- // temporary removed-records cache
- this.removed = [];
-
- if(config && config.data){
- this.inlineData = config.data;
- delete config.data;
- }
-
- Ext.apply(this, config);
-
- this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
-
- if(this.url && !this.proxy){
- this.proxy = new Ext.data.HttpProxy({url: this.url});
- }
- // If Store is RESTful, so too is the DataProxy
- if (this.restful === true && this.proxy) {
- // When operating RESTfully, a unique transaction is generated for each record.
- this.batch = false;
- Ext.data.Api.restify(this.proxy);
- }
-
- if(this.reader){ // reader passed
- if(!this.recordType){
- this.recordType = this.reader.recordType;
- }
- if(this.reader.onMetaChange){
- //this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
- this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
- }
- if (this.writer) { // writer passed
- this.writer.meta = this.reader.meta;
- this.pruneModifiedRecords = true;
- }
- }
-
- /**
- * The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
- * {@link Ext.data.DataReader Reader}. Read-only.
- * If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects, - * instead of a Record constructor, it will implicitly create a Record constructor from that Array (see - * {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).
- *This property may be used to create new Records of the type held in this Store, for example:
-// create the data store
-var store = new Ext.data.ArrayStore({
- autoDestroy: true,
- fields: [
- {name: 'company'},
- {name: 'price', type: 'float'},
- {name: 'change', type: 'float'},
- {name: 'pctChange', type: 'float'},
- {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
- ]
-});
-store.loadData(myData);
-
-// create the Grid
-var grid = new Ext.grid.EditorGridPanel({
- store: store,
- colModel: new Ext.grid.ColumnModel({
- columns: [
- {id:'company', header: 'Company', width: 160, dataIndex: 'company'},
- {header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
- {header: 'Change', renderer: change, dataIndex: 'change'},
- {header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
- {header: 'Last Updated', width: 85,
- renderer: Ext.util.Format.dateRenderer('m/d/Y'),
- dataIndex: 'lastChange'}
- ],
- defaults: {
- sortable: true,
- width: 75
- }
- }),
- autoExpandColumn: 'company', // match the id specified in the column model
- height:350,
- width:600,
- title:'Array Grid',
- tbar: [{
- text: 'Add Record',
- handler : function(){
- var defaultData = {
- change: 0,
- company: 'New Company',
- lastChange: (new Date()).clearTime(),
- pctChange: 0,
- price: 10
- };
- var recId = 3; // provide unique id
- var p = new store.recordType(defaultData, recId); // create new record
- grid.stopEditing();
- store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
- grid.startEditing(0, 0);
- }
- }]
-});
- *
- * @property recordType
- * @type Function
- */
-
- if(this.recordType){
- /**
- * A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
- * for the {@link Ext.data.Record Records} stored in this Store. Read-only.
- * @property fields
- * @type Ext.util.MixedCollection
- */
- this.fields = this.recordType.prototype.fields;
- }
- this.modified = [];
-
- this.addEvents(
- /**
- * @event datachanged
- * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
- * widget that is using this Store as a Record cache should refresh its view.
- * @param {Store} this
- */
- 'datachanged',
- /**
- * @event metachange
- * Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
- * @param {Store} this
- * @param {Object} meta The JSON metadata
- */
- 'metachange',
- /**
- * @event add
- * Fires when Records have been {@link #add}ed to the Store
- * @param {Store} this
- * @param {Ext.data.Record[]} records The array of Records added
- * @param {Number} index The index at which the record(s) were added
- */
- 'add',
- /**
- * @event remove
- * Fires when a Record has been {@link #remove}d from the Store
- * @param {Store} this
- * @param {Ext.data.Record} record The Record that was removed
- * @param {Number} index The index at which the record was removed
- */
- 'remove',
- /**
- * @event update
- * Fires when a Record has been updated
- * @param {Store} this
- * @param {Ext.data.Record} record The Record that was updated
- * @param {String} operation The update operation being performed. Value may be one of:
- *
- Ext.data.Record.EDIT
- Ext.data.Record.REJECT
- Ext.data.Record.COMMIT
- *
- */
- 'update',
- /**
- * @event clear
- * Fires when the data cache has been cleared.
- * @param {Store} this
- * @param {Record[]} The records that were cleared.
- */
- 'clear',
- /**
- * @event exception
- * Fires if an exception occurs in the Proxy during a remote request. - * This event is relayed through the corresponding {@link Ext.data.DataProxy}. - * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception} - * for additional details. - * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception} - * for description. - */ - 'exception', - /** - * @event beforeload - * Fires before a request is made for a new data object. If the beforeload handler returns - * false the {@link #load} action will be canceled. - * @param {Store} this - * @param {Object} options The loading options that were specified (see {@link #load} for details) - */ - 'beforeload', - /** - * @event load - * Fires after a new set of Records has been loaded. - * @param {Store} this - * @param {Ext.data.Record[]} records The Records that were loaded - * @param {Object} options The loading options that were specified (see {@link #load} for details) - */ - 'load', - /** - * @event loadexception - *
This event is deprecated in favor of the catch-all {@link #exception}
- * event instead.
This event is relayed through the corresponding {@link Ext.data.DataProxy}.
- * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
- * for additional details.
- * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
- * for description.
- */
- 'loadexception',
- /**
- * @event beforewrite
- * @param {Ext.data.Store} store
- * @param {String} action [Ext.data.Api.actions.create|update|destroy]
- * @param {Record/Array[Record]} rs
- * @param {Object} options The loading options that were specified. Edit options.params
to add Http parameters to the request. (see {@link #save} for details)
- * @param {Object} arg The callback's arg object passed to the {@link #request} function
- */
- 'beforewrite',
- /**
- * @event write
- * Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
- * Success of the action is determined in the result['successProperty']
property (NOTE for RESTful stores,
- * a simple 20x response is sufficient for the actions "destroy" and "update". The "create" action should should return 200 along with a database pk).
- * @param {Ext.data.Store} store
- * @param {String} action [Ext.data.Api.actions.create|update|destroy]
- * @param {Object} result The 'data' picked-out out of the response for convenience.
- * @param {Ext.Direct.Transaction} res
- * @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
- */
- 'write'
- );
-
- if(this.proxy){
- this.relayEvents(this.proxy, ['loadexception', 'exception']);
- }
- // With a writer set for the Store, we want to listen to add/remove events to remotely create/destroy records.
- if (this.writer) {
- this.on({
- scope: this,
- add: this.createRecords,
- remove: this.destroyRecord,
- update: this.updateRecord,
- clear: this.onClear
- });
- }
-
- this.sortToggle = {};
- if(this.sortField){
- this.setDefaultSort(this.sortField, this.sortDir);
- }else if(this.sortInfo){
- this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
- }
-
- Ext.data.Store.superclass.constructor.call(this);
-
- if(this.id){
- this.storeId = this.id;
- delete this.id;
- }
- if(this.storeId){
- Ext.StoreMgr.register(this);
- }
- if(this.inlineData){
- this.loadData(this.inlineData);
- delete this.inlineData;
- }else if(this.autoLoad){
- this.load.defer(10, this, [
- typeof this.autoLoad == 'object' ?
- this.autoLoad : undefined]);
- }
-};
-Ext.extend(Ext.data.Store, Ext.util.Observable, {
+Ext.data.Store = Ext.extend(Ext.util.Observable, {
/**
* @cfg {String} storeId If passed, the id to use to register with the {@link Ext.StoreMgr StoreMgr}.
*
Note: if a (deprecated) {@link #id} is specified it will supersede the storeId
@@ -1359,6 +1090,332 @@ sortInfo: {
dir : 'dir'
},
+ // private
+ batchKey : '_ext_batch_',
+
+ constructor : function(config){
+ this.data = new Ext.util.MixedCollection(false);
+ this.data.getKey = function(o){
+ return o.id;
+ };
+ /**
+ * See the {@link #baseParams corresponding configuration option}
+ * for a description of this property.
+ * To modify this property see {@link #setBaseParam}
.
+ * @property
+ */
+ this.baseParams = {};
+
+ // temporary removed-records cache
+ this.removed = [];
+
+ if(config && config.data){
+ this.inlineData = config.data;
+ delete config.data;
+ }
+
+ Ext.apply(this, config);
+
+ this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
+
+ if((this.url || this.api) && !this.proxy){
+ this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
+ }
+ // If Store is RESTful, so too is the DataProxy
+ if (this.restful === true && this.proxy) {
+ // When operating RESTfully, a unique transaction is generated for each record.
+ // TODO might want to allow implemention of faux REST where batch is possible using RESTful routes only.
+ this.batch = false;
+ Ext.data.Api.restify(this.proxy);
+ }
+
+ if(this.reader){ // reader passed
+ if(!this.recordType){
+ this.recordType = this.reader.recordType;
+ }
+ if(this.reader.onMetaChange){
+ this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
+ }
+ if (this.writer) { // writer passed
+ if (this.writer instanceof(Ext.data.DataWriter) === false) { // <-- config-object instead of instance.
+ this.writer = this.buildWriter(this.writer);
+ }
+ this.writer.meta = this.reader.meta;
+ this.pruneModifiedRecords = true;
+ }
+ }
+
+ /**
+ * The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
+ * {@link Ext.data.DataReader Reader}. Read-only.
+ *
If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects, + * instead of a Record constructor, it will implicitly create a Record constructor from that Array (see + * {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).
+ *This property may be used to create new Records of the type held in this Store, for example:
+ // create the data store
+ var store = new Ext.data.ArrayStore({
+ autoDestroy: true,
+ fields: [
+ {name: 'company'},
+ {name: 'price', type: 'float'},
+ {name: 'change', type: 'float'},
+ {name: 'pctChange', type: 'float'},
+ {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
+ ]
+ });
+ store.loadData(myData);
+
+ // create the Grid
+ var grid = new Ext.grid.EditorGridPanel({
+ store: store,
+ colModel: new Ext.grid.ColumnModel({
+ columns: [
+ {id:'company', header: 'Company', width: 160, dataIndex: 'company'},
+ {header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
+ {header: 'Change', renderer: change, dataIndex: 'change'},
+ {header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
+ {header: 'Last Updated', width: 85,
+ renderer: Ext.util.Format.dateRenderer('m/d/Y'),
+ dataIndex: 'lastChange'}
+ ],
+ defaults: {
+ sortable: true,
+ width: 75
+ }
+ }),
+ autoExpandColumn: 'company', // match the id specified in the column model
+ height:350,
+ width:600,
+ title:'Array Grid',
+ tbar: [{
+ text: 'Add Record',
+ handler : function(){
+ var defaultData = {
+ change: 0,
+ company: 'New Company',
+ lastChange: (new Date()).clearTime(),
+ pctChange: 0,
+ price: 10
+ };
+ var recId = 3; // provide unique id
+ var p = new store.recordType(defaultData, recId); // create new record
+ grid.stopEditing();
+ store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
+ grid.startEditing(0, 0);
+ }
+ }]
+ });
+ *
+ * @property recordType
+ * @type Function
+ */
+
+ if(this.recordType){
+ /**
+ * A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
+ * for the {@link Ext.data.Record Records} stored in this Store. Read-only.
+ * @property fields
+ * @type Ext.util.MixedCollection
+ */
+ this.fields = this.recordType.prototype.fields;
+ }
+ this.modified = [];
+
+ this.addEvents(
+ /**
+ * @event datachanged
+ * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
+ * widget that is using this Store as a Record cache should refresh its view.
+ * @param {Store} this
+ */
+ 'datachanged',
+ /**
+ * @event metachange
+ * Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
+ * @param {Store} this
+ * @param {Object} meta The JSON metadata
+ */
+ 'metachange',
+ /**
+ * @event add
+ * Fires when Records have been {@link #add}ed to the Store
+ * @param {Store} this
+ * @param {Ext.data.Record[]} records The array of Records added
+ * @param {Number} index The index at which the record(s) were added
+ */
+ 'add',
+ /**
+ * @event remove
+ * Fires when a Record has been {@link #remove}d from the Store
+ * @param {Store} this
+ * @param {Ext.data.Record} record The Record that was removed
+ * @param {Number} index The index at which the record was removed
+ */
+ 'remove',
+ /**
+ * @event update
+ * Fires when a Record has been updated
+ * @param {Store} this
+ * @param {Ext.data.Record} record The Record that was updated
+ * @param {String} operation The update operation being performed. Value may be one of:
+ *
+ Ext.data.Record.EDIT
+ Ext.data.Record.REJECT
+ Ext.data.Record.COMMIT
+ *
+ */
+ 'update',
+ /**
+ * @event clear
+ * Fires when the data cache has been cleared.
+ * @param {Store} this
+ * @param {Record[]} The records that were cleared.
+ */
+ 'clear',
+ /**
+ * @event exception
+ * Fires if an exception occurs in the Proxy during a remote request. + * This event is relayed through the corresponding {@link Ext.data.DataProxy}. + * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception} + * for additional details. + * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception} + * for description. + */ + 'exception', + /** + * @event beforeload + * Fires before a request is made for a new data object. If the beforeload handler returns + * false the {@link #load} action will be canceled. + * @param {Store} this + * @param {Object} options The loading options that were specified (see {@link #load} for details) + */ + 'beforeload', + /** + * @event load + * Fires after a new set of Records has been loaded. + * @param {Store} this + * @param {Ext.data.Record[]} records The Records that were loaded + * @param {Object} options The loading options that were specified (see {@link #load} for details) + */ + 'load', + /** + * @event loadexception + *
This event is deprecated in favor of the catch-all {@link #exception}
+ * event instead.
This event is relayed through the corresponding {@link Ext.data.DataProxy}.
+ * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
+ * for additional details.
+ * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
+ * for description.
+ */
+ 'loadexception',
+ /**
+ * @event beforewrite
+ * @param {Ext.data.Store} store
+ * @param {String} action [Ext.data.Api.actions.create|update|destroy]
+ * @param {Record/Array[Record]} rs
+ * @param {Object} options The loading options that were specified. Edit options.params
to add Http parameters to the request. (see {@link #save} for details)
+ * @param {Object} arg The callback's arg object passed to the {@link #request} function
+ */
+ 'beforewrite',
+ /**
+ * @event write
+ * Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
+ * Success of the action is determined in the result['successProperty']
property (NOTE for RESTful stores,
+ * a simple 20x response is sufficient for the actions "destroy" and "update". The "create" action should should return 200 along with a database pk).
+ * @param {Ext.data.Store} store
+ * @param {String} action [Ext.data.Api.actions.create|update|destroy]
+ * @param {Object} result The 'data' picked-out out of the response for convenience.
+ * @param {Ext.Direct.Transaction} res
+ * @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
+ */
+ 'write',
+ /**
+ * @event beforesave
+ * Fires before a save action is called. A save encompasses destroying records, updating records and creating records.
+ * @param {Ext.data.Store} store
+ * @param {Object} data An object containing the data that is to be saved. The object will contain a key for each appropriate action,
+ * with an array of records for each action.
+ */
+ 'beforesave',
+ /**
+ * @event save
+ * Fires after a save is completed. A save encompasses destroying records, updating records and creating records.
+ * @param {Ext.data.Store} store
+ * @param {Number} batch The identifier for the batch that was saved.
+ * @param {Object} data An object containing the data that is to be saved. The object will contain a key for each appropriate action,
+ * with an array of records for each action.
+ */
+ 'save'
+
+ );
+
+ if(this.proxy){
+ // TODO remove deprecated loadexception with ext-3.0.1
+ this.relayEvents(this.proxy, ['loadexception', 'exception']);
+ }
+ // With a writer set for the Store, we want to listen to add/remove events to remotely create/destroy records.
+ if (this.writer) {
+ this.on({
+ scope: this,
+ add: this.createRecords,
+ remove: this.destroyRecord,
+ update: this.updateRecord,
+ clear: this.onClear
+ });
+ }
+
+ this.sortToggle = {};
+ if(this.sortField){
+ this.setDefaultSort(this.sortField, this.sortDir);
+ }else if(this.sortInfo){
+ this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
+ }
+
+ Ext.data.Store.superclass.constructor.call(this);
+
+ if(this.id){
+ this.storeId = this.id;
+ delete this.id;
+ }
+ if(this.storeId){
+ Ext.StoreMgr.register(this);
+ }
+ if(this.inlineData){
+ this.loadData(this.inlineData);
+ delete this.inlineData;
+ }else if(this.autoLoad){
+ this.load.defer(10, this, [
+ typeof this.autoLoad == 'object' ?
+ this.autoLoad : undefined]);
+ }
+ // used internally to uniquely identify a batch
+ this.batchCounter = 0;
+ this.batches = {};
+ },
+
+ /**
+ * builds a DataWriter instance when Store constructor is provided with a writer config-object instead of an instace.
+ * @param {Object} config Writer configuration
+ * @return {Ext.data.DataWriter}
+ * @private
+ */
+ buildWriter : function(config) {
+ var klass = undefined;
+ type = (config.format || 'json').toLowerCase();
+ switch (type) {
+ case 'json':
+ klass = Ext.data.JsonWriter;
+ break;
+ case 'xml':
+ klass = Ext.data.XmlWriter;
+ break;
+ default:
+ klass = Ext.data.JsonWriter;
+ }
+ return new klass(config);
+ },
+
/**
* Destroys the store.
*/
@@ -1410,20 +1467,27 @@ sortInfo: {
},
/**
- * Remove a Record from the Store and fires the {@link #remove} event.
- * @param {Ext.data.Record} record The Ext.data.Record object to remove from the cache.
+ * Remove Records from the Store and fires the {@link #remove} event.
+ * @param {Ext.data.Record/Ext.data.Record[]} record The record object or array of records to remove from the cache.
*/
remove : function(record){
+ if(Ext.isArray(record)){
+ Ext.each(record, function(r){
+ this.remove(r);
+ }, this);
+ }
var index = this.data.indexOf(record);
if(index > -1){
record.join(null);
this.data.removeAt(index);
- if(this.pruneModifiedRecords){
- this.modified.remove(record);
- }
- if(this.snapshot){
- this.snapshot.remove(record);
- }
+ }
+ if(this.pruneModifiedRecords){
+ this.modified.remove(record);
+ }
+ if(this.snapshot){
+ this.snapshot.remove(record);
+ }
+ if(index > -1){
this.fireEvent('remove', this, record, index);
}
},
@@ -1438,8 +1502,9 @@ sortInfo: {
/**
* Remove all Records from the Store and fires the {@link #clear} event.
+ * @param {Boolean} silent [false] Defaults to false. Set true to not fire clear event.
*/
- removeAll : function(){
+ removeAll : function(silent){
var items = [];
this.each(function(rec){
items.push(rec);
@@ -1451,7 +1516,9 @@ sortInfo: {
if(this.pruneModifiedRecords){
this.modified = [];
}
- this.fireEvent('clear', this, items);
+ if (silent !== true) { // <-- prevents write-actions when we just want to clear a store.
+ this.fireEvent('clear', this, items);
+ }
},
// private
@@ -1473,6 +1540,9 @@ sortInfo: {
this.data.insert(index, records[i]);
records[i].join(this);
}
+ if(this.snapshot){
+ this.snapshot.addAll(records);
+ }
this.fireEvent('add', this, records, index);
},
@@ -1500,7 +1570,7 @@ sortInfo: {
* @return {Ext.data.Record} The Record with the passed id. Returns undefined if not found.
*/
getById : function(id){
- return this.data.key(id);
+ return (this.snapshot || this.data).key(id);
},
/**
@@ -1556,14 +1626,14 @@ sortInfo: {
* parameters to a remote data source. Note: params
will override any
* {@link #baseParams}
of the same name.
Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.
- *A function to be called after the Records - * have been loaded. The callback is called after the load event and is passed the following arguments:
Scope with which to call the callback (defaults + *
A function to be called after the Records + * have been loaded. The callback is called after the load event is fired, and is passed the following arguments:
Scope with which to call the callback (defaults * to the Store object)
Indicator to append loaded records rather than + *
Indicator to append loaded records rather than * replace the current cache. Note: see note for {@link #loadData}
Reloads the Record cache from the configured Proxy using the configured {@link Ext.data.Reader Reader} and - * the options from the last load operation performed.
+ *Reloads the Record cache from the configured Proxy using the configured + * {@link Ext.data.Reader Reader} and the options from the last load operation + * performed.
*Note: see the Important note in {@link #load}.
- * @param {Object} options (optional) An Object containing {@link #load loading options} which may - * override the options used in the last {@link #load} operation. See {@link #load} for details (defaults to - * null, in which case the {@link #lastOptions} are used). + * @param {Object} options(optional) An Object containing + * {@link #load loading options} which may override the {@link #lastOptions options} + * used in the last {@link #load} operation. See {@link #load} for details + * (defaults to null, in which case the {@link #lastOptions} are + * used).
+ *To add new params to the existing params:
+lastOptions = myStore.lastOptions;
+Ext.apply(lastOptions.params, {
+ myNewParam: true
+});
+myStore.reload(lastOptions);
+ *
*/
reload : function(options){
this.load(Ext.applyIf(options||{}, this.lastOptions));
@@ -1883,6 +2024,9 @@ sortInfo: {
// private
// Called as a callback by the Reader during a load operation.
loadRecords : function(o, options, success){
+ if (this.isDestroyed === true) {
+ return;
+ }
if(!o || success === false){
if(success !== false){
this.fireEvent('load', this, [], options);
@@ -2050,7 +2194,8 @@ sortInfo: {
* Calls the specified function for each of the {@link Ext.data.Record Records} in the cache.
* @param {Function} fn The function to call. The {@link Ext.data.Record Record} is passed as the first parameter.
* Returning false aborts and exits the iteration.
- * @param {Object} scope (optional) The scope in which to call the function (defaults to the {@link Ext.data.Record Record}).
+ * @param {Object} scope (optional) The scope (this
reference) in which the function is executed.
+ * Defaults to the current {@link Ext.data.Record Record} in the iteration.
*/
each : function(fn, scope){
this.data.each(fn, scope);
@@ -2121,7 +2266,7 @@ sortInfo: {
* to test for filtering. Access field values using {@link Ext.data.Record#get}.
* The ID of the Record passed.
this
reference) in which the function is executed. Defaults to this Store.
*/
filterBy : function(fn, scope){
this.snapshot = this.snapshot || this.data;
@@ -2152,7 +2297,7 @@ sortInfo: {
* to test for filtering. Access field values using {@link Ext.data.Record#get}.
* The ID of the Record passed.
this
reference) in which the function is executed. Defaults to this Store.
* @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
**/
queryBy : function(fn, scope){
@@ -2161,10 +2306,10 @@ sortInfo: {
},
/**
- * Finds the index of the first matching record in this store by a specific property/value.
- * @param {String} property A property on your objects
- * @param {String/RegExp} value Either a string that the property value
- * should begin with, or a RegExp to test against the property.
+ * Finds the index of the first matching Record in this store by a specific field value.
+ * @param {String} fieldName The name of the Record field to test.
+ * @param {String/RegExp} value Either a string that the field value
+ * should begin with, or a RegExp to test against the field.
* @param {Number} startIndex (optional) The index to start searching at
* @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
* @param {Boolean} caseSensitive (optional) True for case sensitive comparison
@@ -2176,9 +2321,9 @@ sortInfo: {
},
/**
- * Finds the index of the first matching record in this store by a specific property/value.
- * @param {String} property A property on your objects
- * @param {String/RegExp} value The value to match against
+ * Finds the index of the first matching Record in this store by a specific field value.
+ * @param {String} fieldName The name of the Record field to test.
+ * @param {Mixed} value The value to match the field against.
* @param {Number} startIndex (optional) The index to start searching at
* @return {Number} The matched index or -1
*/
@@ -2196,7 +2341,7 @@ sortInfo: {
* to test for filtering. Access field values using {@link Ext.data.Record#get}.
* The ID of the Record passed.
this
reference) in which the function is executed. Defaults to this Store.
* @param {Number} startIndex (optional) The index to start searching at
* @return {Number} The matched index or -1
*/
@@ -2357,7 +2502,6 @@ Ext.apply(Ext.data.Store.Error.prototype, {
'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
}
});
-
/**
* @class Ext.data.Field
* This class encapsulates the field definition information specified in the field definition objects @@ -2414,17 +2558,16 @@ Ext.data.Field = function(config){ case "int": cv = function(v){ return v !== undefined && v !== null && v !== '' ? - parseInt(String(v).replace(stripRe, ""), 10) : ''; + parseInt(String(v).replace(stripRe, ""), 10) : ''; }; break; case "float": cv = function(v){ return v !== undefined && v !== null && v !== '' ? - parseFloat(String(v).replace(stripRe, ""), 10) : ''; + parseFloat(String(v).replace(stripRe, ""), 10) : ''; }; break; case "bool": - case "boolean": cv = function(v){ return v === true || v === "true" || v == 1; }; break; case "date": @@ -2447,7 +2590,10 @@ Ext.data.Field = function(config){ var parsed = Date.parse(v); return parsed ? new Date(parsed) : null; }; - break; + break; + default: + cv = function(v){ return v; }; + break; } this.convert = cv; @@ -2508,7 +2654,7 @@ var store = new Ext.data.Store({ reader: new Ext.data.JsonReader( { idProperty: 'key', - root: 'daRoot', + root: 'daRoot', totalProperty: 'total' }, Dude // recordType @@ -2593,13 +2739,13 @@ sortType: function(value) { * "ASC". */ sortDir : "ASC", - /** - * @cfg {Boolean} allowBlank - * (Optional) Used for validating a {@link Ext.data.Record record}, defaults to true. - * An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid} - * to evaluate to false. - */ - allowBlank : true + /** + * @cfg {Boolean} allowBlank + * (Optional) Used for validating a {@link Ext.data.Record record}, defaults to true. + * An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid} + * to evaluate to false. + */ + allowBlank : true };/** * @class Ext.data.DataReader * Abstract base class for reading structured data from a data source and converting @@ -2709,7 +2855,12 @@ Ext.data.DataReader.prototype = { rs.phantom = false; // <-- That's what it's all about rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords rs.id = this.getId(data); - rs.data = data; + + rs.fields.each(function(f) { + if (data[f.name] !== f.defaultValue) { + rs.data[f.name] = data[f.name]; + } + }); rs.commit(); } }, @@ -2741,12 +2892,56 @@ Ext.data.DataReader.prototype = { data = data.shift(); } if (this.isData(data)) { - rs.data = Ext.apply(rs.data, data); + rs.fields.each(function(f) { + if (data[f.name] !== f.defaultValue) { + rs.data[f.name] = data[f.name]; + } + }); } rs.commit(); } }, + /** + * returns extracted, type-cast rows of data. Iterates to call #extractValues for each row + * @param {Object[]/Object} data-root from server response + * @param {Boolean} returnRecords [false] Set true to return instances of Ext.data.Record + * @private + */ + extractData : function(root, returnRecords) { + // A bit ugly this, too bad the Record's raw data couldn't be saved in a common property named "raw" or something. + var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node'; + + var rs = []; + + // Had to add Check for XmlReader, #isData returns true if root is an Xml-object. Want to check in order to re-factor + // #extractData into DataReader base, since the implementations are almost identical for JsonReader, XmlReader + if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) { + root = [root]; + } + var f = this.recordType.prototype.fields, + fi = f.items, + fl = f.length, + rs = []; + if (returnRecords === true) { + var Record = this.recordType; + for (var i = 0; i < root.length; i++) { + var n = root[i]; + var record = new Record(this.extractValues(n, fi, fl), this.getId(n)); + record[rawName] = n; // <-- There's implementation of ugly bit, setting the raw record-data. + rs.push(record); + } + } + else { + for (var i = 0; i < root.length; i++) { + var data = this.extractValues(root[i], fi, fl); + data[this.meta.idProperty] = this.getId(root[i]); + rs.push(data); + } + } + return rs; + }, + /** * Returns true if the supplied data-hash looks and quacks like data. Checks to see if it has a key * corresponding to idProperty defined in your DataReader config containing non-empty pk. @@ -2785,42 +2980,6 @@ Ext.apply(Ext.data.DataReader.Error.prototype, { 'invalid-response': "#readResponse received an invalid response from the server." } }); - - -/** - * Ext.data.Response - * A generic response class to normalize response-handling internally to the framework. - * TODO move to own file, add to jsb. - */ -Ext.data.Response = function(params) { - Ext.apply(this, params); -}; -Ext.data.Response.prototype = { - /** - * @property {String} action {@link Ext.data.Api#actions} - */ - action: undefined, - /** - * @property {Boolean} success - */ - success : undefined, - /** - * @property {String} message - */ - message : undefined, - /** - * @property {Array/Object} data - */ - data: undefined, - /** - * @property {Object} raw The raw response returned from server-code - */ - raw: undefined, - /** - * @property {Ext.data.Record/Ext.data.Record[]} record(s) related to the Request action - */ - records: undefined -} /** * @class Ext.data.DataWriter *
Ext.data.DataWriter facilitates create, update, and destroy actions between @@ -2831,34 +2990,72 @@ Ext.data.Response.prototype = { * {@link Ext.data.JsonWriter}.
*Creating a writer is simple:
*
-var writer = new Ext.data.JsonWriter();
+var writer = new Ext.data.JsonWriter({
+ encode: false // <--- false causes data to be printed to jsonData config-property of Ext.Ajax#reqeust
+});
*
+ * * Same old JsonReader as Ext-2.x:
+ *
+var reader = new Ext.data.JsonReader({idProperty: 'id'}, [{name: 'first'}, {name: 'last'}, {name: 'email'}]);
+ *
+ *
* The proxy for a writer enabled store can be configured with a simple url
:
// Create a standard HttpProxy instance.
var proxy = new Ext.data.HttpProxy({
- url: 'app.php/users'
+ url: 'app.php/users' // <--- Supports "provides"-type urls, such as '/users.json', '/products.xml' (Hello Rails/Merb)
});
*
- * For finer grained control, the proxy may also be configured with an api
:
For finer grained control, the proxy may also be configured with an API
:
-// Use the api specification
+// Maximum flexibility with the API-configuration
var proxy = new Ext.data.HttpProxy({
api: {
read : 'app.php/users/read',
create : 'app.php/users/create',
update : 'app.php/users/update',
- destroy : 'app.php/users/destroy'
+ destroy : { // <--- Supports object-syntax as well
+ url: 'app.php/users/destroy',
+ method: "DELETE"
+ }
}
});
*
- * Creating a Writer enabled store:
+ *Pulling it all together into a Writer-enabled Store:
+ *
+var store = new Ext.data.Store({
+ proxy: proxy,
+ reader: reader,
+ writer: writer,
+ autoLoad: true,
+ autoSave: true // -- Cell-level updates.
+});
+ *
+ * Initiating write-actions automatically, using the existing Ext2.0 Store/Record API:
+ *
+var rec = store.getAt(0);
+rec.set('email', 'foo@bar.com'); // <--- Immediately initiates an UPDATE action through configured proxy.
+
+store.remove(rec); // <---- Immediately initiates a DESTROY action through configured proxy.
+ *
+ * For record/batch updates, use the Store-configuration {@link Ext.data.Store#autoSave autoSave:false}
*
var store = new Ext.data.Store({
proxy: proxy,
reader: reader,
- writer: writer
+ writer: writer,
+ autoLoad: true,
+ autoSave: false // -- disable cell-updates
});
+
+var urec = store.getAt(0);
+urec.set('email', 'foo@bar.com');
+
+var drec = store.getAt(1);
+store.remove(drec);
+
+// Push the button!
+store.save();
*
* @constructor Create a new DataWriter
* @param {Object} meta Metadata configuration options (implementation-specific)
@@ -2886,13 +3083,14 @@ Ext.data.DataWriter.prototype = {
listful : false, // <-- listful is actually not used internally here in DataWriter. @see Ext.data.Store#execute.
/**
- * Writes data in preparation for server-write action. Simply proxies to DataWriter#update, DataWriter#create
- * DataWriter#destroy.
- * @param {String} action [CREATE|UPDATE|DESTROY]
- * @param {Object} params The params-hash to write-to
- * @param {Record/Record[]} rs The recordset write.
+ * Compiles a Store recordset into a data-format defined by an extension such as {@link Ext.data.JsonWriter} or {@link Ext.data.XmlWriter} in preparation for a {@link Ext.data.Api#actions server-write action}. The first two params are similar similar in nature to {@link Ext#apply},
+ * Where the first parameter is the receiver of paramaters and the second, baseParams, the source.
+ * @param {Object} params The request-params receiver.
+ * @param {Object} baseParams as defined by {@link Ext.data.Store#baseParams}. The baseParms must be encoded by the extending class, eg: {@link Ext.data.JsonWriter}, {@link Ext.data.XmlWriter}.
+ * @param {String} action [{@link Ext.data.Api#actions create|update|destroy}]
+ * @param {Record/Record[]} rs The recordset to write, the subject(s) of the write action.
*/
- write : function(action, params, rs) {
+ apply : function(params, baseParams, action, rs) {
var data = [],
renderer = action + 'Record';
// TODO implement @cfg listful here
@@ -2904,7 +3102,7 @@ Ext.data.DataWriter.prototype = {
else if (rs instanceof Ext.data.Record) {
data = this[renderer](rs);
}
- this.render(action, rs, params, data);
+ this.render(params, baseParams, data);
},
/**
@@ -2936,11 +3134,16 @@ Ext.data.DataWriter.prototype = {
destroyRecord : Ext.emptyFn,
/**
- * Converts a Record to a hash.
- * @param {Record}
- * @private
+ * Converts a Record to a hash, taking into account the state of the Ext.data.Record along with configuration properties
+ * related to its rendering, such as {@link #writeAllFields}, {@link Ext.data.Record#phantom phantom}, {@link Ext.data.Record#getChanges getChanges} and
+ * {@link Ext.data.DataReader#idProperty idProperty}
+ * @param {Ext.data.Record}
+ * @param {Object} config NOT YET IMPLEMENTED. Will implement an exlude/only configuration for fine-control over which fields do/don't get rendered.
+ * @return {Object}
+ * @protected
+ * TODO Implement excludes/only configuration with 2nd param?
*/
- toHash : function(rec) {
+ toHash : function(rec, config) {
var map = rec.fields.map,
data = {},
raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
@@ -2961,6 +3164,24 @@ Ext.data.DataWriter.prototype = {
data[this.meta.idProperty] = rec.id
}
return data;
+ },
+
+ /**
+ * Converts a {@link Ext.data.DataWriter#toHash Hashed} {@link Ext.data.Record} to fields-array array suitable
+ * for encoding to xml via XTemplate, eg:
+<tpl for="."><{name}>{value}</{name}</tpl>
+ * eg, non-phantom:
+{id: 1, first: 'foo', last: 'bar'} --> [{name: 'id', value: 1}, {name: 'first', value: 'foo'}, {name: 'last', value: 'bar'}]
+ * {@link Ext.data.Record#phantom Phantom} records will have had their idProperty omitted in {@link #toHash} if determined to be auto-generated.
+ * Non AUTOINCREMENT pks should have been protected.
+ * @param {Hash} data Hashed by Ext.data.DataWriter#toHash
+ * @return {[Object]} Array of attribute-objects.
+ * @protected
+ */
+ toArray : function(data) {
+ var fields = [];
+ Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
+ return fields;
}
};/**
* @class Ext.data.DataProxy
@@ -2997,6 +3218,25 @@ proxy : new Ext.data.HttpProxy({
}
}),
*
+ * And new in Ext version 3, attach centralized event-listeners upon the DataProxy class itself! This is a great place + * to implement a messaging system to centralize your application's user-feedback and error-handling.
+ *
+// Listen to all "beforewrite" event fired by all proxies.
+Ext.data.DataProxy.on('beforewrite', function(proxy, action) {
+ console.log('beforewrite: ', action);
+});
+
+// Listen to "write" event fired by all proxies
+Ext.data.DataProxy.on('write', function(proxy, action, data, res, rs) {
+ console.info('write: ', action);
+});
+
+// Listen to "exception" event fired by all proxies
+Ext.data.DataProxy.on('exception', function(proxy, type, action) {
+ console.error(type + action + ' exception);
+});
+ *
+ * Note: These three events are all fired with the signature of the corresponding DataProxy instance event {@link #beforewrite beforewrite}, {@link #write write} and {@link #exception exception}.
*/
Ext.data.DataProxy = function(conn){
// make sure we have a config object here to support ux proxies.
@@ -3311,7 +3551,7 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
* @param {Object} params
* @param {Ext.data.DataReader} reader
* @param {Function} callback
- * @param {Object} scope Scope with which to call the callback (defaults to the Proxy object)
+ * @param {Object} scope The scope (this
reference) in which the callback function is executed. Defaults to the Proxy object.
* @param {Object} options Any options specified for the action (e.g. see {@link Ext.data.Store#load}.
*/
request : function(action, rs, params, reader, callback, scope, options) {
@@ -3340,7 +3580,7 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
load : null,
/**
- * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses
+ * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses. Note: Should only be used by custom-proxy developers.
* (e.g.: {@link Ext.data.HttpProxy#doRequest HttpProxy.doRequest},
* {@link Ext.data.DirectProxy#doRequest DirectProxy.doRequest}).
*/
@@ -3351,6 +3591,27 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
this.load(params, reader, callback, scope, options);
},
+ /**
+ * @cfg {Function} onRead Abstract method that should be implemented in all subclasses. Note: Should only be used by custom-proxy developers. Callback for read {@link Ext.data.Api#actions action}.
+ * @param {String} action Action name as per {@link Ext.data.Api.actions#read}.
+ * @param {Object} o The request transaction object
+ * @param {Object} res The server response
+ * @fires loadexception (deprecated)
+ * @fires exception
+ * @fires load
+ * @protected
+ */
+ onRead : Ext.emptyFn,
+ /**
+ * @cfg {Function} onWrite Abstract method that should be implemented in all subclasses. Note: Should only be used by custom-proxy developers. Callback for create, update and destroy {@link Ext.data.Api#actions actions}.
+ * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
+ * @param {Object} trans The request transaction object
+ * @param {Object} res The server response
+ * @fires exception
+ * @fires write
+ * @protected
+ */
+ onWrite : Ext.emptyFn,
/**
* buildUrl
* Sets the appropriate url based upon the action being executed. If restful is true, and only a single record is being acted upon,
@@ -3363,30 +3624,32 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
*/
buildUrl : function(action, record) {
record = record || null;
- var url = (this.api[action]) ? this.api[action].url : this.url;
+
+ // conn.url gets nullified after each request. If it's NOT null here, that means the user must have intervened with a call
+ // to DataProxy#setUrl or DataProxy#setApi and changed it before the request was executed. If that's the case, use conn.url,
+ // otherwise, build the url from the api or this.url.
+ var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
if (!url) {
throw new Ext.data.Api.Error('invalid-url', action);
}
- // look for urls having "provides" suffix (from Rails/Merb and others...),
- // e.g.: /users.json, /users.xml, etc
+ // look for urls having "provides" suffix used in some MVC frameworks like Rails/Merb and others. The provides suffice informs
+ // the server what data-format the client is dealing with and returns data in the same format (eg: application/json, application/xml, etc)
+ // e.g.: /users.json, /users.xml, etc.
// with restful routes, we need urls like:
// PUT /users/1.json
// DELETE /users/1.json
- var format = null;
+ var provides = null;
var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
if (m) {
- format = m[2]; // eg ".json"
- url = m[1]; // eg: "/users"
+ provides = m[2]; // eg ".json"
+ url = m[1]; // eg: "/users"
}
// prettyUrls is deprectated in favor of restful-config
- if ((this.prettyUrls === true || this.restful === true) && record instanceof Ext.data.Record && !record.phantom) {
+ if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
url += '/' + record.id;
}
- if (format) { // <-- append the request format if exists (ie: /users/update/69[.json])
- url += format;
- }
- return url;
+ return (provides === null) ? url : url + provides;
},
/**
@@ -3425,6 +3688,74 @@ Ext.apply(Ext.data.DataProxy.Error.prototype, {
});
+/**
+ * @class Ext.data.Request
+ * A simple Request class used internally to the data package to provide more generalized remote-requests
+ * to a DataProxy.
+ * TODO Not yet implemented. Implement in Ext.data.Store#execute
+ */
+Ext.data.Request = function(params) {
+ Ext.apply(this, params);
+};
+Ext.data.Request.prototype = {
+ /**
+ * @cfg {String} action
+ */
+ action : undefined,
+ /**
+ * @cfg {Ext.data.Record[]/Ext.data.Record} rs The Store recordset associated with the request.
+ */
+ rs : undefined,
+ /**
+ * @cfg {Object} params HTTP request params
+ */
+ params: undefined,
+ /**
+ * @cfg {Function} callback The function to call when request is complete
+ */
+ callback : Ext.emptyFn,
+ /**
+ * @cfg {Object} scope The scope of the callback funtion
+ */
+ scope : undefined,
+ /**
+ * @cfg {Ext.data.DataReader} reader The DataReader instance which will parse the received response
+ */
+ reader : undefined
+};
+/**
+ * @class Ext.data.Response
+ * A generic response class to normalize response-handling internally to the framework.
+ */
+Ext.data.Response = function(params) {
+ Ext.apply(this, params);
+};
+Ext.data.Response.prototype = {
+ /**
+ * @cfg {String} action {@link Ext.data.Api#actions}
+ */
+ action: undefined,
+ /**
+ * @cfg {Boolean} success
+ */
+ success : undefined,
+ /**
+ * @cfg {String} message
+ */
+ message : undefined,
+ /**
+ * @cfg {Array/Object} data
+ */
+ data: undefined,
+ /**
+ * @cfg {Object} raw The raw response returned from server-code
+ */
+ raw: undefined,
+ /**
+ * @cfg {Ext.data.Record/Ext.data.Record[]} records related to the Request action
+ */
+ records: undefined
+};
/**
* @class Ext.data.ScriptTagProxy
* @extends Ext.data.DataProxy
@@ -3459,6 +3790,21 @@ out.print(dataBlock.toJsonString());
if (scriptTag) {
out.write(");");
}
+
+ * Below is a PHP example to do the same thing:
+$callback = $_REQUEST['callback'];
+
+// Create the output object.
+$output = array('a' => 'Apple', 'b' => 'Banana');
+
+//start output
+if ($callback) {
+ header('Content-Type: text/javascript');
+ echo $callback . '(' . json_encode($output) . ');';
+} else {
+ header('Content-Type: application/x-json');
+ echo json_encode($output);
+}
*
* @constructor
@@ -3529,7 +3875,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
* this
reference) in which the callback function is executed. Defaults to the browser window.
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
*/
doRequest : function(action, rs, params, reader, callback, scope, arg) {
@@ -3592,7 +3938,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
* @param {Object} trans The request transaction object
* @param {Object} res The server response
- * @private
+ * @protected
*/
onRead : function(action, trans, res) {
var result;
@@ -3621,7 +3967,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
* @param {Object} trans The request transaction object
* @param {Object} res The server response
- * @private
+ * @protected
*/
onWrite : function(action, trans, response, rs) {
var reader = trans.reader;
@@ -3710,7 +4056,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
* @constructor
* @param {Object} conn
* An {@link Ext.data.Connection} object, or options parameter to {@link Ext.Ajax#request}.
- * Note that if this HttpProxy is being used by a (@link Ext.data.Store Store}, then the + *
Note that if this HttpProxy is being used by a {@link Ext.data.Store Store}, then the * Store's call to {@link #load} will override any specified callback and params * options. In this case, use the Store's {@link Ext.data.Store#events events} to modify parameters, * or react to loading events. The Store's {@link Ext.data.Store#baseParams baseParams} may also be @@ -3788,8 +4134,9 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, { *
this
reference) in which the callback function is executed. Defaults to the browser window.
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
+ * @protected
*/
doRequest : function(action, rs, params, reader, cb, scope, arg) {
var o = {
@@ -3806,7 +4153,6 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
// If possible, transmit data using jsonData || xmlData on Ext.Ajax.request (An installed DataWriter would have written it there.).
// Use std HTTP params otherwise.
- // TODO wrap into 1 Ext.apply now?
if (params.jsonData) {
o.jsonData = params.jsonData;
} else if (params.xmlData) {
@@ -3815,14 +4161,10 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
o.params = params || {};
}
// Set the connection url. If this.conn.url is not null here,
- // the user may have overridden the url during a beforeaction event-handler.
+ // the user must have overridden the url during a beforewrite/beforeload event-handler.
// this.conn.url is nullified after each request.
- if (this.conn.url === null) {
- this.conn.url = this.buildUrl(action, rs);
- }
- else if (this.restful === true && rs instanceof Ext.data.Record && !rs.phantom) { // <-- user must have intervened with #setApi or #setUrl
- this.conn.url += '/' + rs.id;
- }
+ this.conn.url = this.buildUrl(action, rs);
+
if(this.useAjax){
Ext.applyIf(o, this.conn);
@@ -3879,7 +4221,7 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
* @fires loadexception (deprecated)
* @fires exception
* @fires load
- * @private
+ * @protected
*/
onRead : function(action, o, response) {
var result;
@@ -3918,7 +4260,7 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
* @param {Object} res The server response
* @fires exception
* @fires write
- * @private
+ * @protected
*/
onWrite : function(action, o, response, rs) {
var reader = o.reader;
@@ -3998,7 +4340,7 @@ Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
* this
reference) in which the callback function is executed. Defaults to the browser window.
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
*/
doRequest : function(action, rs, params, reader, callback, scope, arg) {