Proxy2.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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-proxy-Proxy'>/**
  19. </span> * @author Ed Spencer
  20. *
  21. * Proxies are used by {@link Ext.data.Store Stores} to handle the loading and saving of {@link Ext.data.Model Model}
  22. * data. Usually developers will not need to create or interact with proxies directly.
  23. *
  24. * # Types of Proxy
  25. *
  26. * There are two main types of Proxy - {@link Ext.data.proxy.Client Client} and {@link Ext.data.proxy.Server Server}.
  27. * The Client proxies save their data locally and include the following subclasses:
  28. *
  29. * - {@link Ext.data.proxy.LocalStorage LocalStorageProxy} - saves its data to localStorage if the browser supports it
  30. * - {@link Ext.data.proxy.SessionStorage SessionStorageProxy} - saves its data to sessionStorage if the browsers supports it
  31. * - {@link Ext.data.proxy.Memory MemoryProxy} - holds data in memory only, any data is lost when the page is refreshed
  32. *
  33. * The Server proxies save their data by sending requests to some remote server. These proxies include:
  34. *
  35. * - {@link Ext.data.proxy.Ajax Ajax} - sends requests to a server on the same domain
  36. * - {@link Ext.data.proxy.JsonP JsonP} - uses JSON-P to send requests to a server on a different domain
  37. * - {@link Ext.data.proxy.Rest Rest} - uses RESTful HTTP methods (GET/PUT/POST/DELETE) to communicate with server
  38. * - {@link Ext.data.proxy.Direct Direct} - uses {@link Ext.direct.Manager} to send requests
  39. *
  40. * Proxies operate on the principle that all operations performed are either Create, Read, Update or Delete. These four
  41. * operations are mapped to the methods {@link #create}, {@link #read}, {@link #update} and {@link #destroy}
  42. * respectively. Each Proxy subclass implements these functions.
  43. *
  44. * The CRUD methods each expect an {@link Ext.data.Operation Operation} object as the sole argument. The Operation
  45. * encapsulates information about the action the Store wishes to perform, the {@link Ext.data.Model model} instances
  46. * that are to be modified, etc. See the {@link Ext.data.Operation Operation} documentation for more details. Each CRUD
  47. * method also accepts a callback function to be called asynchronously on completion.
  48. *
  49. * Proxies also support batching of Operations via a {@link Ext.data.Batch batch} object, invoked by the {@link #batch}
  50. * method.
  51. */
  52. Ext.define('Ext.data.proxy.Proxy', {
  53. alias: 'proxy.proxy',
  54. alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'],
  55. uses: [
  56. 'Ext.data.Batch',
  57. 'Ext.data.Operation',
  58. 'Ext.data.Model'
  59. ],
  60. mixins: {
  61. observable: 'Ext.util.Observable'
  62. },
  63. <span id='Ext-data-proxy-Proxy-cfg-batchOrder'> /**
  64. </span> * @cfg {String} batchOrder
  65. * Comma-separated ordering 'create', 'update' and 'destroy' actions when batching. Override this to set a different
  66. * order for the batched CRUD actions to be executed in. Defaults to 'create,update,destroy'.
  67. */
  68. batchOrder: 'create,update,destroy',
  69. <span id='Ext-data-proxy-Proxy-cfg-batchActions'> /**
  70. </span> * @cfg {Boolean} batchActions
  71. * True to batch actions of a particular type when synchronizing the store. Defaults to true.
  72. */
  73. batchActions: true,
  74. <span id='Ext-data-proxy-Proxy-cfg-defaultReaderType'> /**
  75. </span> * @cfg {String} defaultReaderType
  76. * The default registered reader type. Defaults to 'json'.
  77. * @private
  78. */
  79. defaultReaderType: 'json',
  80. <span id='Ext-data-proxy-Proxy-cfg-defaultWriterType'> /**
  81. </span> * @cfg {String} defaultWriterType
  82. * The default registered writer type. Defaults to 'json'.
  83. * @private
  84. */
  85. defaultWriterType: 'json',
  86. <span id='Ext-data-proxy-Proxy-cfg-model'> /**
  87. </span> * @cfg {String/Ext.data.Model} model
  88. * The name of the Model to tie to this Proxy. Can be either the string name of the Model, or a reference to the
  89. * Model constructor. Required.
  90. */
  91. <span id='Ext-data-proxy-Proxy-cfg-reader'> /**
  92. </span> * @cfg {Object/String/Ext.data.reader.Reader} reader
  93. * The Ext.data.reader.Reader to use to decode the server's response or data read from client. This can either be a
  94. * Reader instance, a config object or just a valid Reader type name (e.g. 'json', 'xml').
  95. */
  96. <span id='Ext-data-proxy-Proxy-cfg-writer'> /**
  97. </span> * @cfg {Object/String/Ext.data.writer.Writer} writer
  98. * The Ext.data.writer.Writer to use to encode any request sent to the server or saved to client. This can either be
  99. * a Writer instance, a config object or just a valid Writer type name (e.g. 'json', 'xml').
  100. */
  101. <span id='Ext-data-proxy-Proxy-property-isProxy'> /**
  102. </span> * @property {Boolean} isProxy
  103. * `true` in this class to identify an object as an instantiated Proxy, or subclass thereof.
  104. */
  105. isProxy: true,
  106. <span id='Ext-data-proxy-Proxy-method-constructor'> /**
  107. </span> * Creates the Proxy
  108. * @param {Object} config (optional) Config object.
  109. */
  110. constructor: function(config) {
  111. config = config || {};
  112. if (config.model === undefined) {
  113. delete config.model;
  114. }
  115. this.mixins.observable.constructor.call(this, config);
  116. if (this.model !== undefined &amp;&amp; !(this.model instanceof Ext.data.Model)) {
  117. this.setModel(this.model);
  118. }
  119. <span id='Ext-data-proxy-Proxy-event-metachange'> /**
  120. </span> * @event metachange
  121. * Fires when this proxy's reader provides new metadata. Metadata usually consists
  122. * of new field definitions, but can include any configuration data required by an
  123. * application, and can be processed as needed in the event handler.
  124. * This event is currently only fired for JsonReaders. Note that this event is also
  125. * propagated by {@link Ext.data.Store}, which is typically where it would be handled.
  126. * @param {Ext.data.proxy.Proxy} this
  127. * @param {Object} meta The JSON metadata
  128. */
  129. },
  130. <span id='Ext-data-proxy-Proxy-method-setModel'> /**
  131. </span> * Sets the model associated with this proxy. This will only usually be called by a Store
  132. *
  133. * @param {String/Ext.data.Model} model The new model. Can be either the model name string,
  134. * or a reference to the model's constructor
  135. * @param {Boolean} setOnStore Sets the new model on the associated Store, if one is present
  136. */
  137. setModel: function(model, setOnStore) {
  138. this.model = Ext.ModelManager.getModel(model);
  139. var reader = this.reader,
  140. writer = this.writer;
  141. this.setReader(reader);
  142. this.setWriter(writer);
  143. if (setOnStore &amp;&amp; this.store) {
  144. this.store.setModel(this.model);
  145. }
  146. },
  147. <span id='Ext-data-proxy-Proxy-method-getModel'> /**
  148. </span> * Returns the model attached to this Proxy
  149. * @return {Ext.data.Model} The model
  150. */
  151. getModel: function() {
  152. return this.model;
  153. },
  154. <span id='Ext-data-proxy-Proxy-method-setReader'> /**
  155. </span> * Sets the Proxy's Reader by string, config object or Reader instance
  156. *
  157. * @param {String/Object/Ext.data.reader.Reader} reader The new Reader, which can be either a type string,
  158. * a configuration object or an Ext.data.reader.Reader instance
  159. * @return {Ext.data.reader.Reader} The attached Reader object
  160. */
  161. setReader: function(reader) {
  162. var me = this,
  163. needsCopy = true;
  164. if (reader === undefined || typeof reader == 'string') {
  165. reader = {
  166. type: reader
  167. };
  168. needsCopy = false;
  169. }
  170. if (reader.isReader) {
  171. reader.setModel(me.model);
  172. } else {
  173. if (needsCopy) {
  174. reader = Ext.apply({}, reader);
  175. }
  176. Ext.applyIf(reader, {
  177. proxy: me,
  178. model: me.model,
  179. type : me.defaultReaderType
  180. });
  181. reader = Ext.createByAlias('reader.' + reader.type, reader);
  182. }
  183. if (reader.onMetaChange) {
  184. reader.onMetaChange = Ext.Function.createSequence(reader.onMetaChange, this.onMetaChange, this);
  185. }
  186. me.reader = reader;
  187. return me.reader;
  188. },
  189. <span id='Ext-data-proxy-Proxy-method-getReader'> /**
  190. </span> * Returns the reader currently attached to this proxy instance
  191. * @return {Ext.data.reader.Reader} The Reader instance
  192. */
  193. getReader: function() {
  194. return this.reader;
  195. },
  196. <span id='Ext-data-proxy-Proxy-method-onMetaChange'> /**
  197. </span> * @private
  198. * Called each time the reader's onMetaChange is called so that the proxy can fire the metachange event
  199. */
  200. onMetaChange: function(meta) {
  201. this.fireEvent('metachange', this, meta);
  202. },
  203. <span id='Ext-data-proxy-Proxy-method-setWriter'> /**
  204. </span> * Sets the Proxy's Writer by string, config object or Writer instance
  205. *
  206. * @param {String/Object/Ext.data.writer.Writer} writer The new Writer, which can be either a type string,
  207. * a configuration object or an Ext.data.writer.Writer instance
  208. * @return {Ext.data.writer.Writer} The attached Writer object
  209. */
  210. setWriter: function(writer) {
  211. var me = this,
  212. needsCopy = true;
  213. if (writer === undefined || typeof writer == 'string') {
  214. writer = {
  215. type: writer
  216. };
  217. needsCopy = false;
  218. }
  219. if (!writer.isWriter) {
  220. if (needsCopy) {
  221. writer = Ext.apply({}, writer);
  222. }
  223. Ext.applyIf(writer, {
  224. model: me.model,
  225. type : me.defaultWriterType
  226. });
  227. writer = Ext.createByAlias('writer.' + writer.type, writer);
  228. }
  229. me.writer = writer;
  230. return me.writer;
  231. },
  232. <span id='Ext-data-proxy-Proxy-method-getWriter'> /**
  233. </span> * Returns the writer currently attached to this proxy instance
  234. * @return {Ext.data.writer.Writer} The Writer instance
  235. */
  236. getWriter: function() {
  237. return this.writer;
  238. },
  239. <span id='Ext-data-proxy-Proxy-method-create'> /**
  240. </span> * Performs the given create operation.
  241. * @param {Ext.data.Operation} operation The Operation to perform
  242. * @param {Function} callback Callback function to be called when the Operation has completed (whether
  243. * successful or not)
  244. * @param {Object} scope Scope to execute the callback function in
  245. * @method
  246. */
  247. create: Ext.emptyFn,
  248. <span id='Ext-data-proxy-Proxy-method-read'> /**
  249. </span> * Performs the given read operation.
  250. * @param {Ext.data.Operation} operation The Operation to perform
  251. * @param {Function} callback Callback function to be called when the Operation has completed (whether
  252. * successful or not)
  253. * @param {Object} scope Scope to execute the callback function in
  254. * @method
  255. */
  256. read: Ext.emptyFn,
  257. <span id='Ext-data-proxy-Proxy-method-update'> /**
  258. </span> * Performs the given update operation.
  259. * @param {Ext.data.Operation} operation The Operation to perform
  260. * @param {Function} callback Callback function to be called when the Operation has completed (whether
  261. * successful or not)
  262. * @param {Object} scope Scope to execute the callback function in
  263. * @method
  264. */
  265. update: Ext.emptyFn,
  266. <span id='Ext-data-proxy-Proxy-method-destroy'> /**
  267. </span> * Performs the given destroy operation.
  268. * @param {Ext.data.Operation} operation The Operation to perform
  269. * @param {Function} callback Callback function to be called when the Operation has completed (whether
  270. * successful or not)
  271. * @param {Object} scope Scope to execute the callback function in
  272. * @method
  273. */
  274. destroy: Ext.emptyFn,
  275. <span id='Ext-data-proxy-Proxy-method-batch'> /**
  276. </span> * Performs a batch of {@link Ext.data.Operation Operations}, in the order specified by {@link #batchOrder}. Used
  277. * internally by {@link Ext.data.Store}'s {@link Ext.data.Store#sync sync} method. Example usage:
  278. *
  279. * myProxy.batch({
  280. * create : [myModel1, myModel2],
  281. * update : [myModel3],
  282. * destroy: [myModel4, myModel5]
  283. * });
  284. *
  285. * Where the myModel* above are {@link Ext.data.Model Model} instances - in this case 1 and 2 are new instances and
  286. * have not been saved before, 3 has been saved previously but needs to be updated, and 4 and 5 have already been
  287. * saved but should now be destroyed.
  288. *
  289. * Note that the previous version of this method took 2 arguments (operations and listeners). While this is still
  290. * supported for now, the current signature is now a single `options` argument that can contain both operations and
  291. * listeners, in addition to other options. The multi-argument signature will likely be deprecated in a future release.
  292. *
  293. * @param {Object} options Object containing one or more properties supported by the batch method:
  294. *
  295. * @param {Object} options.operations Object containing the Model instances to act upon, keyed by action name
  296. *
  297. * @param {Object} [options.listeners] Event listeners object passed straight through to the Batch -
  298. * see {@link Ext.data.Batch} for details
  299. *
  300. * @param {Ext.data.Batch/Object} [options.batch] A {@link Ext.data.Batch} object (or batch config to apply
  301. * to the created batch). If unspecified a default batch will be auto-created.
  302. *
  303. * @param {Function} [options.callback] The function to be called upon completion of processing the batch.
  304. * The callback is called regardless of success or failure and is passed the following parameters:
  305. * @param {Ext.data.Batch} options.callback.batch The {@link Ext.data.Batch batch} that was processed,
  306. * containing all operations in their current state after processing
  307. * @param {Object} options.callback.options The options argument that was originally passed into batch
  308. *
  309. * @param {Function} [options.success] The function to be called upon successful completion of the batch. The
  310. * success function is called only if no exceptions were reported in any operations. If one or more exceptions
  311. * occurred then the `failure` function will be called instead. The success function is called
  312. * with the following parameters:
  313. * @param {Ext.data.Batch} options.success.batch The {@link Ext.data.Batch batch} that was processed,
  314. * containing all operations in their current state after processing
  315. * @param {Object} options.success.options The options argument that was originally passed into batch
  316. *
  317. * @param {Function} [options.failure] The function to be called upon unsuccessful completion of the batch. The
  318. * failure function is called when one or more operations returns an exception during processing (even if some
  319. * operations were also successful). In this case you can check the batch's {@link Ext.data.Batch#exceptions
  320. * exceptions} array to see exactly which operations had exceptions. The failure function is called with the
  321. * following parameters:
  322. * @param {Ext.data.Batch} options.failure.batch The {@link Ext.data.Batch batch} that was processed,
  323. * containing all operations in their current state after processing
  324. * @param {Object} options.failure.options The options argument that was originally passed into batch
  325. *
  326. * @param {Object} [options.scope] The scope in which to execute any callbacks (i.e. the `this` object inside
  327. * the callback, success and/or failure functions). Defaults to the proxy.
  328. *
  329. * @return {Ext.data.Batch} The newly created Batch
  330. */
  331. batch: function(options, /* deprecated */listeners) {
  332. var me = this,
  333. useBatch = me.batchActions,
  334. batch,
  335. records,
  336. actions, aLen, action, a, r, rLen, record;
  337. if (options.operations === undefined) {
  338. // the old-style (operations, listeners) signature was called
  339. // so convert to the single options argument syntax
  340. options = {
  341. operations: options,
  342. listeners: listeners
  343. };
  344. }
  345. if (options.batch) {
  346. if (Ext.isDefined(options.batch.runOperation)) {
  347. batch = Ext.applyIf(options.batch, {
  348. proxy: me,
  349. listeners: {}
  350. });
  351. }
  352. } else {
  353. options.batch = {
  354. proxy: me,
  355. listeners: options.listeners || {}
  356. };
  357. }
  358. if (!batch) {
  359. batch = new Ext.data.Batch(options.batch);
  360. }
  361. batch.on('complete', Ext.bind(me.onBatchComplete, me, [options], 0));
  362. actions = me.batchOrder.split(',');
  363. aLen = actions.length;
  364. for (a = 0; a &lt; aLen; a++) {
  365. action = actions[a];
  366. records = options.operations[action];
  367. if (records) {
  368. if (useBatch) {
  369. batch.add(new Ext.data.Operation({
  370. action : action,
  371. records : records
  372. }));
  373. } else {
  374. rLen = records.length;
  375. for (r = 0; r &lt; rLen; r++) {
  376. record = records[r];
  377. batch.add(new Ext.data.Operation({
  378. action : action,
  379. records : [record]
  380. }));
  381. }
  382. }
  383. }
  384. }
  385. batch.start();
  386. return batch;
  387. },
  388. <span id='Ext-data-proxy-Proxy-method-onBatchComplete'> /**
  389. </span> * @private
  390. * The internal callback that the proxy uses to call any specified user callbacks after completion of a batch
  391. */
  392. onBatchComplete: function(batchOptions, batch) {
  393. var scope = batchOptions.scope || this;
  394. if (batch.hasException) {
  395. if (Ext.isFunction(batchOptions.failure)) {
  396. Ext.callback(batchOptions.failure, scope, [batch, batchOptions]);
  397. }
  398. } else if (Ext.isFunction(batchOptions.success)) {
  399. Ext.callback(batchOptions.success, scope, [batch, batchOptions]);
  400. }
  401. if (Ext.isFunction(batchOptions.callback)) {
  402. Ext.callback(batchOptions.callback, scope, [batch, batchOptions]);
  403. }
  404. }
  405. }, function() {
  406. //backwards compatibility
  407. Ext.data.DataProxy = this;
  408. });
  409. </pre>
  410. </body>
  411. </html>