AbstractStore.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-data-AbstractStore'>/**
  19. </span> * @author Ed Spencer
  20. *
  21. * AbstractStore is a superclass of {@link Ext.data.Store} and {@link Ext.data.TreeStore}. It's never used directly,
  22. * but offers a set of methods used by both of those subclasses.
  23. *
  24. * We've left it here in the docs for reference purposes, but unless you need to make a whole new type of Store, what
  25. * you're probably looking for is {@link Ext.data.Store}. If you're still interested, here's a brief description of what
  26. * AbstractStore is and is not.
  27. *
  28. * AbstractStore provides the basic configuration for anything that can be considered a Store. It expects to be
  29. * given a {@link Ext.data.Model Model} that represents the type of data in the Store. It also expects to be given a
  30. * {@link Ext.data.proxy.Proxy Proxy} that handles the loading of data into the Store.
  31. *
  32. * AbstractStore provides a few helpful methods such as {@link #method-load} and {@link #sync}, which load and save data
  33. * respectively, passing the requests through the configured {@link #proxy}. Both built-in Store subclasses add extra
  34. * behavior to each of these functions. Note also that each AbstractStore subclass has its own way of storing data -
  35. * in {@link Ext.data.Store} the data is saved as a flat {@link Ext.util.MixedCollection MixedCollection}, whereas in
  36. * {@link Ext.data.TreeStore TreeStore} we use a {@link Ext.data.Tree} to maintain the data's hierarchy.
  37. *
  38. * The store provides filtering and sorting support. This sorting/filtering can happen on the client side
  39. * or can be completed on the server. This is controlled by the {@link Ext.data.Store#remoteSort remoteSort} and
  40. * {@link Ext.data.Store#remoteFilter remoteFilter} config options. For more information see the {@link #sort} and
  41. * {@link Ext.data.Store#filter filter} methods.
  42. */
  43. Ext.define('Ext.data.AbstractStore', {
  44. requires: [
  45. 'Ext.util.MixedCollection',
  46. 'Ext.data.proxy.Proxy',
  47. 'Ext.data.Operation',
  48. 'Ext.util.Filter'
  49. ],
  50. mixins: {
  51. observable: 'Ext.util.Observable',
  52. sortable: 'Ext.util.Sortable'
  53. },
  54. statics: {
  55. <span id='Ext-data-AbstractStore-static-method-create'> /**
  56. </span> * Creates a store from config object.
  57. *
  58. * @param {Object/Ext.data.AbstractStore} store A config for
  59. * the store to be created. It may contain a `type` field
  60. * which defines the particular type of store to create.
  61. *
  62. * Alteratively passing an actual store to this method will
  63. * just return it, no changes made.
  64. *
  65. * @return {Ext.data.AbstractStore} The created store.
  66. * @static
  67. */
  68. create: function(store) {
  69. if (!store.isStore) {
  70. if (!store.type) {
  71. store.type = 'store';
  72. }
  73. store = Ext.createByAlias('store.' + store.type, store);
  74. }
  75. return store;
  76. }
  77. },
  78. <span id='Ext-data-AbstractStore-cfg-remoteSort'> /**
  79. </span> * @cfg {Boolean} remoteSort
  80. * True to defer any sorting operation to the server. If false, sorting is done locally on the client.
  81. */
  82. remoteSort : false,
  83. <span id='Ext-data-AbstractStore-cfg-remoteFilter'> /**
  84. </span> * @cfg {Boolean} remoteFilter
  85. * True to defer any filtering operation to the server. If false, filtering is done locally on the client.
  86. */
  87. remoteFilter: false,
  88. <span id='Ext-data-AbstractStore-cfg-proxy'> /**
  89. </span> * @cfg {String/Ext.data.proxy.Proxy/Object} proxy
  90. * The Proxy to use for this Store. This can be either a string, a config object or a Proxy instance -
  91. * see {@link #setProxy} for details.
  92. */
  93. <span id='Ext-data-AbstractStore-cfg-autoLoad'> /**
  94. </span> * @cfg {Boolean/Object} autoLoad
  95. * If data is not specified, and if autoLoad is true or an Object, this store's load method is automatically called
  96. * after creation. If the value of autoLoad is an Object, this Object will be passed to the store's load method.
  97. * Defaults to false.
  98. */
  99. autoLoad: undefined,
  100. <span id='Ext-data-AbstractStore-cfg-autoSync'> /**
  101. </span> * @cfg {Boolean} autoSync
  102. * True to automatically sync the Store with its Proxy after every edit to one of its Records. Defaults to false.
  103. */
  104. autoSync: false,
  105. <span id='Ext-data-AbstractStore-cfg-batchUpdateMode'> /**
  106. </span> * @cfg {String} batchUpdateMode
  107. * Sets the updating behavior based on batch synchronization. 'operation' (the default) will update the Store's
  108. * internal representation of the data after each operation of the batch has completed, 'complete' will wait until
  109. * the entire batch has been completed before updating the Store's data. 'complete' is a good choice for local
  110. * storage proxies, 'operation' is better for remote proxies, where there is a comparatively high latency.
  111. */
  112. batchUpdateMode: 'operation',
  113. <span id='Ext-data-AbstractStore-cfg-filterOnLoad'> /**
  114. </span> * @cfg {Boolean} filterOnLoad
  115. * If true, any filters attached to this Store will be run after loading data, before the datachanged event is fired.
  116. * Defaults to true, ignored if {@link Ext.data.Store#remoteFilter remoteFilter} is true
  117. */
  118. filterOnLoad: true,
  119. <span id='Ext-data-AbstractStore-cfg-sortOnLoad'> /**
  120. </span> * @cfg {Boolean} sortOnLoad
  121. * If true, any sorters attached to this Store will be run after loading data, before the datachanged event is fired.
  122. * Defaults to true, igored if {@link Ext.data.Store#remoteSort remoteSort} is true
  123. */
  124. sortOnLoad: true,
  125. <span id='Ext-data-AbstractStore-property-implicitModel'> /**
  126. </span> * @property {Boolean} implicitModel
  127. * True if a model was created implicitly for this Store. This happens if a fields array is passed to the Store's
  128. * constructor instead of a model constructor or name.
  129. * @private
  130. */
  131. implicitModel: false,
  132. <span id='Ext-data-AbstractStore-property-defaultProxyType'> /**
  133. </span> * @property {String} defaultProxyType
  134. * The string type of the Proxy to create if none is specified. This defaults to creating a
  135. * {@link Ext.data.proxy.Memory memory proxy}.
  136. */
  137. defaultProxyType: 'memory',
  138. <span id='Ext-data-AbstractStore-property-isDestroyed'> /**
  139. </span> * @property {Boolean} isDestroyed
  140. * True if the Store has already been destroyed. If this is true, the reference to Store should be deleted
  141. * as it will not function correctly any more.
  142. */
  143. isDestroyed: false,
  144. <span id='Ext-data-AbstractStore-property-isStore'> /**
  145. </span> * @property {Boolean} isStore
  146. * `true` in this class to identify an object as an instantiated Store, or subclass thereof.
  147. */
  148. isStore: true,
  149. <span id='Ext-data-AbstractStore-cfg-storeId'> /**
  150. </span> * @cfg {String} storeId
  151. * Unique identifier for this store. If present, this Store will be registered with the {@link Ext.data.StoreManager},
  152. * making it easy to reuse elsewhere.
  153. *
  154. * Note that when store is instatiated by Controller, the storeId will be overridden by the name of the store.
  155. */
  156. <span id='Ext-data-AbstractStore-cfg-fields'> /**
  157. </span> * @cfg {Object[]} fields
  158. * This may be used in place of specifying a {@link #model} configuration. The fields should be a
  159. * set of {@link Ext.data.Field} configuration objects. The store will automatically create a {@link Ext.data.Model}
  160. * with these fields. In general this configuration option should only be used for simple stores like
  161. * a two-field store of ComboBox. For anything more complicated, such as specifying a particular id property or
  162. * associations, a {@link Ext.data.Model} should be defined and specified for the {@link #model}
  163. * config.
  164. */
  165. <span id='Ext-data-AbstractStore-cfg-model'> /**
  166. </span> * @cfg {String} model
  167. * Name of the {@link Ext.data.Model Model} associated with this store.
  168. * The string is used as an argument for {@link Ext.ModelManager#getModel}.
  169. */
  170. <span id='Ext-data-AbstractStore-cfg-filters'> /**
  171. </span> * @cfg {Object[]/Function[]} filters
  172. * Array of {@link Ext.util.Filter Filters} for this store. Can also be passed array of
  173. * functions which will be used as the {@link Ext.util.Filter#filterFn filterFn} config
  174. * for filters:
  175. *
  176. * filters: [
  177. * function(item) {
  178. * return item.internalId &gt; 0;
  179. * }
  180. * ]
  181. *
  182. * To filter after the grid is loaded use the {@link Ext.data.Store#filterBy filterBy} function.
  183. */
  184. sortRoot: 'data',
  185. //documented above
  186. constructor: function(config) {
  187. var me = this,
  188. filters;
  189. <span id='Ext-data-AbstractStore-event-add'> /**
  190. </span> * @event add
  191. * Fired when a Model instance has been added to this Store
  192. * @param {Ext.data.Store} store The store
  193. * @param {Ext.data.Model[]} records The Model instances that were added
  194. * @param {Number} index The index at which the instances were inserted
  195. */
  196. <span id='Ext-data-AbstractStore-event-remove'> /**
  197. </span> * @event remove
  198. * Fired when a Model instance has been removed from this Store
  199. * @param {Ext.data.Store} store The Store object
  200. * @param {Ext.data.Model} record The record that was removed
  201. * @param {Number} index The index of the record that was removed
  202. */
  203. <span id='Ext-data-AbstractStore-event-update'> /**
  204. </span> * @event update
  205. * Fires when a Model instance has been updated
  206. * @param {Ext.data.Store} this
  207. * @param {Ext.data.Model} record The Model instance that was updated
  208. * @param {String} operation The update operation being performed. Value may be one of:
  209. *
  210. * Ext.data.Model.EDIT
  211. * Ext.data.Model.REJECT
  212. * Ext.data.Model.COMMIT
  213. * @param {String[]} modifiedFieldNames Array of field names changed during edit.
  214. */
  215. <span id='Ext-data-AbstractStore-event-datachanged'> /**
  216. </span> * @event datachanged
  217. * Fires whenever the records in the Store have changed in some way - this could include adding or removing
  218. * records, or updating the data in existing records
  219. * @param {Ext.data.Store} this The data store
  220. */
  221. <span id='Ext-data-AbstractStore-event-refresh'> /**
  222. </span> * @event refresh
  223. * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
  224. * widget that is using this Store as a Record cache should refresh its view.
  225. * @param {Ext.data.Store} this The data store
  226. */
  227. <span id='Ext-data-AbstractStore-event-beforeload'> /**
  228. </span> * @event beforeload
  229. * Fires before a request is made for a new data object. If the beforeload handler returns false the load
  230. * action will be canceled.
  231. * @param {Ext.data.Store} store This Store
  232. * @param {Ext.data.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to
  233. * load the Store
  234. */
  235. <span id='Ext-data-AbstractStore-event-load'> /**
  236. </span> * @event load
  237. * Fires whenever the store reads data from a remote data source.
  238. * @param {Ext.data.Store} this
  239. * @param {Ext.data.Model[]} records An array of records
  240. * @param {Boolean} successful True if the operation was successful.
  241. */
  242. <span id='Ext-data-AbstractStore-event-write'> /**
  243. </span> * @event write
  244. * Fires whenever a successful write has been made via the configured {@link #proxy Proxy}
  245. * @param {Ext.data.Store} store This Store
  246. * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object that was used in
  247. * the write
  248. */
  249. <span id='Ext-data-AbstractStore-event-beforesync'> /**
  250. </span> * @event beforesync
  251. * Fired before a call to {@link #sync} is executed. Return false from any listener to cancel the sync
  252. * @param {Object} options Hash of all records to be synchronized, broken down into create, update and destroy
  253. */
  254. <span id='Ext-data-AbstractStore-event-clear'> /**
  255. </span> * @event clear
  256. * Fired after the {@link #removeAll} method is called.
  257. * @param {Ext.data.Store} this
  258. */
  259. <span id='Ext-data-AbstractStore-event-metachange'> /**
  260. </span> * @event metachange
  261. * Fires when this store's underlying reader (available via the proxy) provides new metadata.
  262. * Metadata usually consists of new field definitions, but can include any configuration data
  263. * required by an application, and can be processed as needed in the event handler.
  264. * This event is currently only fired for JsonReaders.
  265. * @param {Ext.data.Store} this
  266. * @param {Object} meta The JSON metadata
  267. */
  268. Ext.apply(me, config);
  269. // don't use *config* anymore from here on... use *me* instead...
  270. <span id='Ext-data-AbstractStore-property-removed'> /**
  271. </span> * Temporary cache in which removed model instances are kept until successfully synchronised with a Proxy,
  272. * at which point this is cleared.
  273. * @protected
  274. * @property {Ext.data.Model[]} removed
  275. */
  276. me.removed = [];
  277. me.mixins.observable.constructor.apply(me, arguments);
  278. // &lt;debug&gt;
  279. var configModel = me.model;
  280. // &lt;/debug&gt;
  281. me.model = Ext.ModelManager.getModel(me.model);
  282. <span id='Ext-data-AbstractStore-property-modelDefaults'> /**
  283. </span> * @property {Object} modelDefaults
  284. * @private
  285. * A set of default values to be applied to every model instance added via {@link Ext.data.Store#insert insert} or created
  286. * via {@link Ext.data.Store#createModel createModel}. This is used internally by associations to set foreign keys and
  287. * other fields. See the Association classes source code for examples. This should not need to be used by application developers.
  288. */
  289. Ext.applyIf(me, {
  290. modelDefaults: {}
  291. });
  292. //Supports the 3.x style of simply passing an array of fields to the store, implicitly creating a model
  293. if (!me.model &amp;&amp; me.fields) {
  294. me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
  295. extend: 'Ext.data.Model',
  296. fields: me.fields,
  297. proxy: me.proxy || me.defaultProxyType
  298. });
  299. delete me.fields;
  300. me.implicitModel = true;
  301. }
  302. // &lt;debug&gt;
  303. if (!me.model &amp;&amp; me.useModelWarning !== false) {
  304. // There are a number of ways things could have gone wrong, try to give as much information as possible
  305. var logMsg = [
  306. Ext.getClassName(me) || 'Store',
  307. ' created with no model.'
  308. ];
  309. if (typeof configModel === 'string') {
  310. logMsg.push(&quot; The name '&quot;, configModel, &quot;'&quot;, ' does not correspond to a valid model.');
  311. }
  312. Ext.log.warn(logMsg.join(''));
  313. }
  314. // &lt;/debug&gt;
  315. //ensures that the Proxy is instantiated correctly
  316. me.setProxy(me.proxy || me.model.getProxy());
  317. me.proxy.on('metachange', me.onMetaChange, me);
  318. if (me.id &amp;&amp; !me.storeId) {
  319. me.storeId = me.id;
  320. delete me.id;
  321. }
  322. if (me.storeId) {
  323. Ext.data.StoreManager.register(me);
  324. }
  325. me.mixins.sortable.initSortable.call(me);
  326. <span id='Ext-data-AbstractStore-property-filters'> /**
  327. </span> * @property {Ext.util.MixedCollection} filters
  328. * The collection of {@link Ext.util.Filter Filters} currently applied to this Store
  329. */
  330. filters = me.decodeFilters(me.filters);
  331. me.filters = new Ext.util.MixedCollection();
  332. me.filters.addAll(filters);
  333. },
  334. <span id='Ext-data-AbstractStore-method-setProxy'> /**
  335. </span> * Sets the Store's Proxy by string, config object or Proxy instance
  336. * @param {String/Object/Ext.data.proxy.Proxy} proxy The new Proxy, which can be either a type string, a configuration object
  337. * or an Ext.data.proxy.Proxy instance
  338. * @return {Ext.data.proxy.Proxy} The attached Proxy object
  339. */
  340. setProxy: function(proxy) {
  341. var me = this;
  342. if (proxy instanceof Ext.data.proxy.Proxy) {
  343. proxy.setModel(me.model);
  344. } else {
  345. if (Ext.isString(proxy)) {
  346. proxy = {
  347. type: proxy
  348. };
  349. }
  350. Ext.applyIf(proxy, {
  351. model: me.model
  352. });
  353. proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
  354. }
  355. me.proxy = proxy;
  356. return me.proxy;
  357. },
  358. <span id='Ext-data-AbstractStore-method-getProxy'> /**
  359. </span> * Returns the proxy currently attached to this proxy instance
  360. * @return {Ext.data.proxy.Proxy} The Proxy instance
  361. */
  362. getProxy: function() {
  363. return this.proxy;
  364. },
  365. // private
  366. onMetaChange: function(proxy, meta) {
  367. this.fireEvent('metachange', this, meta);
  368. },
  369. //saves any phantom records
  370. create: function(data, options) {
  371. var me = this,
  372. instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
  373. operation;
  374. options = options || {};
  375. Ext.applyIf(options, {
  376. action : 'create',
  377. records: [instance]
  378. });
  379. operation = new Ext.data.Operation(options);
  380. me.proxy.create(operation, me.onProxyWrite, me);
  381. return instance;
  382. },
  383. read: function() {
  384. return this.load.apply(this, arguments);
  385. },
  386. update: function(options) {
  387. var me = this,
  388. operation;
  389. options = options || {};
  390. Ext.applyIf(options, {
  391. action : 'update',
  392. records: me.getUpdatedRecords()
  393. });
  394. operation = new Ext.data.Operation(options);
  395. return me.proxy.update(operation, me.onProxyWrite, me);
  396. },
  397. <span id='Ext-data-AbstractStore-method-onProxyWrite'> /**
  398. </span> * @private
  399. * Callback for any write Operation over the Proxy. Updates the Store's MixedCollection to reflect
  400. * the updates provided by the Proxy
  401. */
  402. onProxyWrite: function(operation) {
  403. var me = this,
  404. success = operation.wasSuccessful(),
  405. records = operation.getRecords();
  406. switch (operation.action) {
  407. case 'create':
  408. me.onCreateRecords(records, operation, success);
  409. break;
  410. case 'update':
  411. me.onUpdateRecords(records, operation, success);
  412. break;
  413. case 'destroy':
  414. me.onDestroyRecords(records, operation, success);
  415. break;
  416. }
  417. if (success) {
  418. me.fireEvent('write', me, operation);
  419. me.fireEvent('datachanged', me);
  420. me.fireEvent('refresh', me);
  421. }
  422. //this is a callback that would have been passed to the 'create', 'update' or 'destroy' function and is optional
  423. Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
  424. },
  425. // may be implemented by store subclasses
  426. onCreateRecords: Ext.emptyFn,
  427. // may be implemented by store subclasses
  428. onUpdateRecords: Ext.emptyFn,
  429. <span id='Ext-data-AbstractStore-method-onDestroyRecords'> /**
  430. </span> * Removes any records when a write is returned from the server.
  431. * @private
  432. * @param {Ext.data.Model[]} records The array of removed records
  433. * @param {Ext.data.Operation} operation The operation that just completed
  434. * @param {Boolean} success True if the operation was successful
  435. */
  436. onDestroyRecords: function(records, operation, success) {
  437. if (success) {
  438. this.removed = [];
  439. }
  440. },
  441. //tells the attached proxy to destroy the given records
  442. destroy: function(options) {
  443. var me = this,
  444. operation;
  445. options = options || {};
  446. Ext.applyIf(options, {
  447. action : 'destroy',
  448. records: me.getRemovedRecords()
  449. });
  450. operation = new Ext.data.Operation(options);
  451. return me.proxy.destroy(operation, me.onProxyWrite, me);
  452. },
  453. <span id='Ext-data-AbstractStore-method-onBatchOperationComplete'> /**
  454. </span> * @private
  455. * Attached as the 'operationcomplete' event listener to a proxy's Batch object. By default just calls through
  456. * to onProxyWrite.
  457. */
  458. onBatchOperationComplete: function(batch, operation) {
  459. return this.onProxyWrite(operation);
  460. },
  461. <span id='Ext-data-AbstractStore-method-onBatchComplete'> /**
  462. </span> * @private
  463. * Attached as the 'complete' event listener to a proxy's Batch object. Iterates over the batch operations
  464. * and updates the Store's internal data MixedCollection.
  465. */
  466. onBatchComplete: function(batch, operation) {
  467. var me = this,
  468. operations = batch.operations,
  469. length = operations.length,
  470. i;
  471. me.suspendEvents();
  472. for (i = 0; i &lt; length; i++) {
  473. me.onProxyWrite(operations[i]);
  474. }
  475. me.resumeEvents();
  476. me.fireEvent('datachanged', me);
  477. me.fireEvent('refresh', me);
  478. },
  479. <span id='Ext-data-AbstractStore-method-onBatchException'> /**
  480. </span> * @private
  481. */
  482. onBatchException: function(batch, operation) {
  483. // //decide what to do... could continue with the next operation
  484. // batch.start();
  485. //
  486. // //or retry the last operation
  487. // batch.retry();
  488. },
  489. <span id='Ext-data-AbstractStore-method-filterNew'> /**
  490. </span> * @private
  491. * Filter function for new records.
  492. */
  493. filterNew: function(item) {
  494. // only want phantom records that are valid
  495. return item.phantom === true &amp;&amp; item.isValid();
  496. },
  497. <span id='Ext-data-AbstractStore-method-getNewRecords'> /**
  498. </span> * Returns all Model instances that are either currently a phantom (e.g. have no id), or have an ID but have not
  499. * yet been saved on this Store (this happens when adding a non-phantom record from another Store into this one)
  500. * @return {Ext.data.Model[]} The Model instances
  501. */
  502. getNewRecords: function() {
  503. return [];
  504. },
  505. <span id='Ext-data-AbstractStore-method-getUpdatedRecords'> /**
  506. </span> * Returns all Model instances that have been updated in the Store but not yet synchronized with the Proxy
  507. * @return {Ext.data.Model[]} The updated Model instances
  508. */
  509. getUpdatedRecords: function() {
  510. return [];
  511. },
  512. <span id='Ext-data-AbstractStore-method-getModifiedRecords'> /**
  513. </span> * Gets all {@link Ext.data.Model records} added or updated since the last commit. Note that the order of records
  514. * returned is not deterministic and does not indicate the order in which records were modified. Note also that
  515. * removed records are not included (use {@link #getRemovedRecords} for that).
  516. * @return {Ext.data.Model[]} The added and updated Model instances
  517. */
  518. getModifiedRecords : function(){
  519. return [].concat(this.getNewRecords(), this.getUpdatedRecords());
  520. },
  521. <span id='Ext-data-AbstractStore-method-filterUpdated'> /**
  522. </span> * @private
  523. * Filter function for updated records.
  524. */
  525. filterUpdated: function(item) {
  526. // only want dirty records, not phantoms that are valid
  527. return item.dirty === true &amp;&amp; item.phantom !== true &amp;&amp; item.isValid();
  528. },
  529. <span id='Ext-data-AbstractStore-method-getRemovedRecords'> /**
  530. </span> * Returns any records that have been removed from the store but not yet destroyed on the proxy.
  531. * @return {Ext.data.Model[]} The removed Model instances
  532. */
  533. getRemovedRecords: function() {
  534. return this.removed;
  535. },
  536. filter: function(filters, value) {
  537. },
  538. <span id='Ext-data-AbstractStore-method-decodeFilters'> /**
  539. </span> * @private
  540. * Normalizes an array of filter objects, ensuring that they are all Ext.util.Filter instances
  541. * @param {Object[]} filters The filters array
  542. * @return {Ext.util.Filter[]} Array of Ext.util.Filter objects
  543. */
  544. decodeFilters: function(filters) {
  545. if (!Ext.isArray(filters)) {
  546. if (filters === undefined) {
  547. filters = [];
  548. } else {
  549. filters = [filters];
  550. }
  551. }
  552. var length = filters.length,
  553. Filter = Ext.util.Filter,
  554. config, i;
  555. for (i = 0; i &lt; length; i++) {
  556. config = filters[i];
  557. if (!(config instanceof Filter)) {
  558. Ext.apply(config, {
  559. root: 'data'
  560. });
  561. //support for 3.x style filters where a function can be defined as 'fn'
  562. if (config.fn) {
  563. config.filterFn = config.fn;
  564. }
  565. //support a function to be passed as a filter definition
  566. if (typeof config == 'function') {
  567. config = {
  568. filterFn: config
  569. };
  570. }
  571. filters[i] = new Filter(config);
  572. }
  573. }
  574. return filters;
  575. },
  576. clearFilter: function(supressEvent) {
  577. },
  578. isFiltered: function() {
  579. },
  580. filterBy: function(fn, scope) {
  581. },
  582. <span id='Ext-data-AbstractStore-method-sync'> /**
  583. </span> * Synchronizes the store with its {@link #proxy}. This asks the proxy to batch together any new, updated
  584. * and deleted records in the store, updating the store's internal representation of the records
  585. * as each operation completes.
  586. *
  587. * @param {Object} [options] Object containing one or more properties supported by the sync method (these get
  588. * passed along to the underlying proxy's {@link Ext.data.Proxy#batch batch} method):
  589. *
  590. * @param {Ext.data.Batch/Object} [options.batch] A {@link Ext.data.Batch} object (or batch config to apply
  591. * to the created batch). If unspecified a default batch will be auto-created as needed.
  592. *
  593. * @param {Function} [options.callback] The function to be called upon completion of the sync.
  594. * The callback is called regardless of success or failure and is passed the following parameters:
  595. * @param {Ext.data.Batch} options.callback.batch The {@link Ext.data.Batch batch} that was processed,
  596. * containing all operations in their current state after processing
  597. * @param {Object} options.callback.options The options argument that was originally passed into sync
  598. *
  599. * @param {Function} [options.success] The function to be called upon successful completion of the sync. The
  600. * success function is called only if no exceptions were reported in any operations. If one or more exceptions
  601. * occurred then the failure function will be called instead. The success function is called
  602. * with the following parameters:
  603. * @param {Ext.data.Batch} options.success.batch The {@link Ext.data.Batch batch} that was processed,
  604. * containing all operations in their current state after processing
  605. * @param {Object} options.success.options The options argument that was originally passed into sync
  606. *
  607. * @param {Function} [options.failure] The function to be called upon unsuccessful completion of the sync. The
  608. * failure function is called when one or more operations returns an exception during processing (even if some
  609. * operations were also successful). In this case you can check the batch's {@link Ext.data.Batch#exceptions
  610. * exceptions} array to see exactly which operations had exceptions. The failure function is called with the
  611. * following parameters:
  612. * @param {Ext.data.Batch} options.failure.batch The {@link Ext.data.Batch} that was processed, containing all
  613. * operations in their current state after processing
  614. * @param {Object} options.failure.options The options argument that was originally passed into sync
  615. *
  616. * @param {Object} [options.scope] The scope in which to execute any callbacks (i.e. the `this` object inside
  617. * the callback, success and/or failure functions). Defaults to the store's proxy.
  618. *
  619. * @return {Ext.data.Store} this
  620. */
  621. sync: function(options) {
  622. var me = this,
  623. operations = {},
  624. toCreate = me.getNewRecords(),
  625. toUpdate = me.getUpdatedRecords(),
  626. toDestroy = me.getRemovedRecords(),
  627. needsSync = false;
  628. if (toCreate.length &gt; 0) {
  629. operations.create = toCreate;
  630. needsSync = true;
  631. }
  632. if (toUpdate.length &gt; 0) {
  633. operations.update = toUpdate;
  634. needsSync = true;
  635. }
  636. if (toDestroy.length &gt; 0) {
  637. operations.destroy = toDestroy;
  638. needsSync = true;
  639. }
  640. if (needsSync &amp;&amp; me.fireEvent('beforesync', operations) !== false) {
  641. options = options || {};
  642. me.proxy.batch(Ext.apply(options, {
  643. operations: operations,
  644. listeners: me.getBatchListeners()
  645. }));
  646. }
  647. return me;
  648. },
  649. <span id='Ext-data-AbstractStore-method-getBatchListeners'> /**
  650. </span> * @private
  651. * Returns an object which is passed in as the listeners argument to proxy.batch inside this.sync.
  652. * This is broken out into a separate function to allow for customisation of the listeners
  653. * @return {Object} The listeners object
  654. */
  655. getBatchListeners: function() {
  656. var me = this,
  657. listeners = {
  658. scope: me,
  659. exception: me.onBatchException
  660. };
  661. if (me.batchUpdateMode == 'operation') {
  662. listeners.operationcomplete = me.onBatchOperationComplete;
  663. } else {
  664. listeners.complete = me.onBatchComplete;
  665. }
  666. return listeners;
  667. },
  668. <span id='Ext-data-AbstractStore-method-save'> /**
  669. </span> * Saves all pending changes via the configured {@link #proxy}. Use {@link #sync} instead.
  670. * @deprecated 4.0.0 Will be removed in the next major version
  671. */
  672. save: function() {
  673. return this.sync.apply(this, arguments);
  674. },
  675. <span id='Ext-data-AbstractStore-method-load'> /**
  676. </span> * Loads the Store using its configured {@link #proxy}.
  677. * @param {Object} options (optional) config object. This is passed into the {@link Ext.data.Operation Operation}
  678. * object that is created and then sent to the proxy's {@link Ext.data.proxy.Proxy#read} function
  679. *
  680. * @return {Ext.data.Store} this
  681. */
  682. load: function(options) {
  683. var me = this,
  684. operation;
  685. options = Ext.apply({
  686. action: 'read',
  687. filters: me.filters.items,
  688. sorters: me.getSorters()
  689. }, options);
  690. me.lastOptions = options;
  691. operation = new Ext.data.Operation(options);
  692. if (me.fireEvent('beforeload', me, operation) !== false) {
  693. me.loading = true;
  694. me.proxy.read(operation, me.onProxyLoad, me);
  695. }
  696. return me;
  697. },
  698. <span id='Ext-data-AbstractStore-method-reload'> /**
  699. </span> * Reloads the store using the last options passed to the {@link #method-load} method.
  700. * @param {Object} options A config object which contains options which may override the options passed to the previous load call.
  701. */
  702. reload: function(options) {
  703. return this.load(Ext.apply(this.lastOptions, options));
  704. },
  705. <span id='Ext-data-AbstractStore-method-afterEdit'> /**
  706. </span> * @private
  707. * A model instance should call this method on the Store it has been {@link Ext.data.Model#join joined} to.
  708. * @param {Ext.data.Model} record The model instance that was edited
  709. * @param {String[]} modifiedFieldNames Array of field names changed during edit.
  710. */
  711. afterEdit : function(record, modifiedFieldNames) {
  712. var me = this,
  713. i, shouldSync;
  714. if (me.autoSync &amp;&amp; !me.autoSyncSuspended) {
  715. for (i = modifiedFieldNames.length; i--;) {
  716. // only sync if persistent fields were modified
  717. if (record.fields.get(modifiedFieldNames[i]).persist) {
  718. shouldSync = true;
  719. break;
  720. }
  721. }
  722. if (shouldSync) {
  723. me.sync();
  724. }
  725. }
  726. me.fireEvent('update', me, record, Ext.data.Model.EDIT, modifiedFieldNames);
  727. },
  728. <span id='Ext-data-AbstractStore-method-afterReject'> /**
  729. </span> * @private
  730. * A model instance should call this method on the Store it has been {@link Ext.data.Model#join joined} to..
  731. * @param {Ext.data.Model} record The model instance that was edited
  732. */
  733. afterReject : function(record) {
  734. // Must pass the 5th param (modifiedFieldNames) as null, otherwise the
  735. // event firing machinery appends the listeners &quot;options&quot; object to the arg list
  736. // which may get used as the modified fields array by a handler.
  737. // This array is used for selective grid cell updating by Grid View.
  738. // Null will be treated as though all cells need updating.
  739. this.fireEvent('update', this, record, Ext.data.Model.REJECT, null);
  740. },
  741. <span id='Ext-data-AbstractStore-method-afterCommit'> /**
  742. </span> * @private
  743. * A model instance should call this method on the Store it has been {@link Ext.data.Model#join joined} to.
  744. * @param {Ext.data.Model} record The model instance that was edited
  745. */
  746. afterCommit : function(record) {
  747. // Must pass the 5th param (modifiedFieldNames) as null, otherwise the
  748. // event firing machinery appends the listeners &quot;options&quot; object to the arg list
  749. // which may get used as the modified fields array by a handler.
  750. // This array is used for selective grid cell updating by Grid View.
  751. // Null will be treated as though all cells need updating.
  752. this.fireEvent('update', this, record, Ext.data.Model.COMMIT, null);
  753. },
  754. // private
  755. destroyStore: function() {
  756. var me = this;
  757. if (!me.isDestroyed) {
  758. if (me.storeId) {
  759. Ext.data.StoreManager.unregister(me);
  760. }
  761. me.clearData();
  762. me.data = me.tree = me.sorters = me.filters = me.groupers = null;
  763. if (me.reader) {
  764. me.reader.destroyReader();
  765. }
  766. me.proxy = me.reader = me.writer = null;
  767. me.clearListeners();
  768. me.isDestroyed = true;
  769. if (me.implicitModel) {
  770. Ext.destroy(me.model);
  771. } else {
  772. me.model = null;
  773. }
  774. }
  775. },
  776. // private
  777. doSort: function(sorterFn) {
  778. var me = this;
  779. if (me.remoteSort) {
  780. //the load function will pick up the new sorters and request the sorted data from the proxy
  781. me.load();
  782. } else {
  783. me.data.sortBy(sorterFn);
  784. me.fireEvent('datachanged', me);
  785. me.fireEvent('refresh', me);
  786. }
  787. },
  788. // to be implemented by subclasses
  789. clearData: Ext.emptyFn,
  790. // to be implemented by subclasses
  791. getCount: Ext.emptyFn,
  792. // to be implemented by subclasses
  793. getById: Ext.emptyFn,
  794. <span id='Ext-data-AbstractStore-method-removeAll'> /**
  795. </span> * Removes all records from the store. This method does a &quot;fast remove&quot;,
  796. * individual remove events are not called. The {@link #clear} event is
  797. * fired upon completion.
  798. * @method
  799. */
  800. removeAll: Ext.emptyFn,
  801. // individual store subclasses should implement a &quot;fast&quot; remove
  802. // and fire a clear event afterwards
  803. <span id='Ext-data-AbstractStore-method-isLoading'> /**
  804. </span> * Returns true if the Store is currently performing a load operation
  805. * @return {Boolean} True if the Store is currently loading
  806. */
  807. isLoading: function() {
  808. return !!this.loading;
  809. },
  810. <span id='Ext-data-AbstractStore-method-suspendAutoSync'> /**
  811. </span> * Suspends automatically syncing the Store with its Proxy. Only applicable if {@link #autoSync} is `true`
  812. */
  813. suspendAutoSync: function() {
  814. this.autoSyncSuspended = true;
  815. },
  816. <span id='Ext-data-AbstractStore-method-resumeAutoSync'> /**
  817. </span> * Resumes automatically syncing the Store with its Proxy. Only applicable if {@link #autoSync} is `true`
  818. */
  819. resumeAutoSync: function() {
  820. this.autoSyncSuspended = false;
  821. }
  822. });
  823. </pre>
  824. </body>
  825. </html>