4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-data-proxy-Server'>/**
19 </span> * @author Ed Spencer
20 * @class Ext.data.proxy.Server
21 * @extends Ext.data.proxy.Proxy
23 * <p>ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy},
24 * and would not usually be used directly.</p>
26 * <p>ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been
27 * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now an
28 * alias of AjaxProxy).</p>
30 Ext.define('Ext.data.proxy.Server', {
31 extend: 'Ext.data.proxy.Proxy',
32 alias : 'proxy.server',
33 alternateClassName: 'Ext.data.ServerProxy',
34 uses : ['Ext.data.Request'],
36 <span id='Ext-data-proxy-Server-cfg-url'> /**
37 </span> * @cfg {String} url The URL from which to request the data object.
40 <span id='Ext-data-proxy-Server-cfg-reader'> /**
41 </span> * @cfg {Object/String/Ext.data.reader.Reader} reader The Ext.data.reader.Reader to use to decode the server's response. This can
42 * either be a Reader instance, a config object or just a valid Reader type name (e.g. 'json', 'xml').
45 <span id='Ext-data-proxy-Server-cfg-writer'> /**
46 </span> * @cfg {Object/String/Ext.data.writer.Writer} writer The Ext.data.writer.Writer to use to encode any request sent to the server.
47 * This can either be a Writer instance, a config object or just a valid Writer type name (e.g. 'json', 'xml').
50 <span id='Ext-data-proxy-Server-cfg-pageParam'> /**
51 </span> * @cfg {String} pageParam The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to
52 * undefined if you don't want to send a page parameter
56 <span id='Ext-data-proxy-Server-cfg-startParam'> /**
57 </span> * @cfg {String} startParam The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this
58 * to undefined if you don't want to send a start parameter
62 <span id='Ext-data-proxy-Server-cfg-limitParam'> /**
63 </span> * @cfg {String} limitParam The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this
64 * to undefined if you don't want to send a limit parameter
68 <span id='Ext-data-proxy-Server-cfg-groupParam'> /**
69 </span> * @cfg {String} groupParam The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this
70 * to undefined if you don't want to send a group parameter
74 <span id='Ext-data-proxy-Server-cfg-sortParam'> /**
75 </span> * @cfg {String} sortParam The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this
76 * to undefined if you don't want to send a sort parameter
80 <span id='Ext-data-proxy-Server-cfg-filterParam'> /**
81 </span> * @cfg {String} filterParam The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set
82 * this to undefined if you don't want to send a filter parameter
84 filterParam: 'filter',
86 <span id='Ext-data-proxy-Server-cfg-directionParam'> /**
87 </span> * @cfg {String} directionParam The name of the direction parameter to send in a request. <strong>This is only used when simpleSortMode is set to true.</strong>
90 directionParam: 'dir',
92 <span id='Ext-data-proxy-Server-cfg-simpleSortMode'> /**
93 </span> * @cfg {Boolean} simpleSortMode Enabling simpleSortMode in conjunction with remoteSort will only send one sort property and a direction when a remote sort is requested.
94 * The directionParam and sortParam will be sent with the property name and either 'ASC' or 'DESC'
96 simpleSortMode: false,
98 <span id='Ext-data-proxy-Server-cfg-noCache'> /**
99 </span> * @cfg {Boolean} noCache (optional) Defaults to true. Disable caching by adding a unique parameter
100 * name to the request.
104 <span id='Ext-data-proxy-Server-cfg-cacheString'> /**
105 </span> * @cfg {String} cacheString The name of the cache param added to the url when using noCache (defaults to "_dc")
107 cacheString: "_dc",
109 <span id='Ext-data-proxy-Server-cfg-timeout'> /**
110 </span> * @cfg {Number} timeout (optional) The number of milliseconds to wait for a response.
111 * Defaults to 30000 milliseconds (30 seconds).
115 <span id='Ext-data-proxy-Server-cfg-api'> /**
116 </span> * @cfg {Object} api
117 * Specific urls to call on CRUD action methods "create", "read", "update" and "destroy".
118 * Defaults to:<pre><code>
125 * </code></pre>
126 * <p>The url is built based upon the action being executed <tt>[create|read|update|destroy]</tt>
127 * using the commensurate <tt>{@link #api}</tt> property, or if undefined default to the
128 * configured {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.</p><br>
129 * <p>For example:</p>
130 * <pre><code>
132 create : '/controller/new',
133 read : '/controller/load',
134 update : '/controller/update',
135 destroy : '/controller/destroy_action'
137 * </code></pre>
138 * <p>If the specific URL for a given CRUD action is undefined, the CRUD action request
139 * will be directed to the configured <tt>{@link Ext.data.proxy.Server#url url}</tt>.</p>
142 <span id='Ext-data-proxy-Server-method-constructor'> /**
145 constructor: function(config) {
148 config = config || {};
150 <span id='Ext-data-proxy-Server-event-exception'> /**
151 </span> * @event exception
152 * Fires when the server returns an exception
153 * @param {Ext.data.proxy.Proxy} this
154 * @param {Object} response The response from the AJAX request
155 * @param {Ext.data.Operation} operation The operation that triggered request
159 me.callParent([config]);
161 <span id='Ext-data-proxy-Server-cfg-extraParams'> /**
162 </span> * @cfg {Object} extraParams Extra parameters that will be included on every request. Individual requests with params
163 * of the same name will override these params when they are in conflict.
165 me.extraParams = config.extraParams || {};
167 me.api = config.api || {};
169 //backwards compatibility, will be deprecated in 5.0
170 me.nocache = me.noCache;
173 //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case
175 return this.doRequest.apply(this, arguments);
179 return this.doRequest.apply(this, arguments);
183 return this.doRequest.apply(this, arguments);
186 destroy: function() {
187 return this.doRequest.apply(this, arguments);
190 <span id='Ext-data-proxy-Server-method-buildRequest'> /**
191 </span> * Creates and returns an Ext.data.Request object based on the options passed by the {@link Ext.data.Store Store}
192 * that this Proxy is attached to.
193 * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute
194 * @return {Ext.data.Request} The request object
196 buildRequest: function(operation) {
197 var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
200 //copy any sorters, filters etc into the params so they can be sent over the wire
201 params = Ext.applyIf(params, this.getParams(params, operation));
203 if (operation.id && !params.id) {
204 params.id = operation.id;
207 request = Ext.create('Ext.data.Request', {
209 action : operation.action,
210 records : operation.records,
211 operation: operation,
215 request.url = this.buildUrl(request);
218 * Save the request on the Operation. Operations don't usually care about Request and Response data, but in the
219 * ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing
221 operation.request = request;
226 <span id='Ext-data-proxy-Server-method-processResponse'> /**
229 processResponse: function(success, operation, request, response, callback, scope){
239 if (success === true) {
240 reader = me.getReader();
241 result = reader.read(me.extractResponseData(response));
242 records = result.records;
243 length = records.length;
245 if (result.success !== false) {
246 mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
247 mc.addAll(operation.records);
248 for (i = 0; i < length; i++) {
249 record = mc.get(records[i].getId());
253 record.set(record.data);
254 record.endEdit(true);
258 //see comment in buildRequest for why we include the response object here
259 Ext.apply(operation, {
264 operation.setCompleted();
265 operation.setSuccessful();
267 operation.setException(result.message);
268 me.fireEvent('exception', this, response, operation);
271 me.setException(operation, response);
272 me.fireEvent('exception', this, response, operation);
275 //this callback is the one that was passed to the 'read' or 'write' function above
276 if (typeof callback == 'function') {
277 callback.call(scope || me, operation);
280 me.afterRequest(request, success);
283 <span id='Ext-data-proxy-Server-method-setException'> /**
284 </span> * Sets up an exception on the operation
286 * @param {Ext.data.Operation} operation The operation
287 * @param {Object} response The response
289 setException: function(operation, response){
290 operation.setException({
291 status: response.status,
292 statusText: response.statusText
296 <span id='Ext-data-proxy-Server-method-extractResponseData'> /**
297 </span> * Template method to allow subclasses to specify how to get the response for the reader.
299 * @param {Object} response The server response
300 * @return {Mixed} The response data to be used by the reader
302 extractResponseData: function(response){
306 <span id='Ext-data-proxy-Server-method-applyEncoding'> /**
307 </span> * Encode any values being sent to the server. Can be overridden in subclasses.
309 * @param {Array} An array of sorters/filters.
310 * @return {Mixed} The encoded value
312 applyEncoding: function(value){
313 return Ext.encode(value);
316 <span id='Ext-data-proxy-Server-method-encodeSorters'> /**
317 </span> * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default,
318 * this simply JSON-encodes the sorter data
319 * @param {Array} sorters The array of {@link Ext.util.Sorter Sorter} objects
320 * @return {String} The encoded sorters
322 encodeSorters: function(sorters) {
324 length = sorters.length,
327 for (; i < length; i++) {
329 property : sorters[i].property,
330 direction: sorters[i].direction
333 return this.applyEncoding(min);
337 <span id='Ext-data-proxy-Server-method-encodeFilters'> /**
338 </span> * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default,
339 * this simply JSON-encodes the filter data
340 * @param {Array} sorters The array of {@link Ext.util.Filter Filter} objects
341 * @return {String} The encoded filters
343 encodeFilters: function(filters) {
345 length = filters.length,
348 for (; i < length; i++) {
350 property: filters[i].property,
351 value : filters[i].value
354 return this.applyEncoding(min);
357 <span id='Ext-data-proxy-Server-method-getParams'> /**
359 * Copy any sorters, filters etc into the params so they can be sent over the wire
361 getParams: function(params, operation) {
362 params = params || {};
365 isDef = Ext.isDefined,
366 groupers = operation.groupers,
367 sorters = operation.sorters,
368 filters = operation.filters,
369 page = operation.page,
370 start = operation.start,
371 limit = operation.limit,
373 simpleSortMode = me.simpleSortMode,
375 pageParam = me.pageParam,
376 startParam = me.startParam,
377 limitParam = me.limitParam,
378 groupParam = me.groupParam,
379 sortParam = me.sortParam,
380 filterParam = me.filterParam,
381 directionParam = me.directionParam;
383 if (pageParam && isDef(page)) {
384 params[pageParam] = page;
387 if (startParam && isDef(start)) {
388 params[startParam] = start;
391 if (limitParam && isDef(limit)) {
392 params[limitParam] = limit;
395 if (groupParam && groupers && groupers.length > 0) {
396 // Grouper is a subclass of sorter, so we can just use the sorter method
397 params[groupParam] = me.encodeSorters(groupers);
400 if (sortParam && sorters && sorters.length > 0) {
401 if (simpleSortMode) {
402 params[sortParam] = sorters[0].property;
403 params[directionParam] = sorters[0].direction;
405 params[sortParam] = me.encodeSorters(sorters);
410 if (filterParam && filters && filters.length > 0) {
411 params[filterParam] = me.encodeFilters(filters);
417 <span id='Ext-data-proxy-Server-method-buildUrl'> /**
418 </span> * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will
419 * add the cache-buster param to the end of the url. Subclasses may need to perform additional modifications
421 * @param {Ext.data.Request} request The request object
422 * @return {String} The url
424 buildUrl: function(request) {
426 url = me.getUrl(request);
430 Ext.Error.raise("You are using a ServerProxy but have not supplied it with a url.");
435 url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));
441 <span id='Ext-data-proxy-Server-method-getUrl'> /**
442 </span> * Get the url for the request taking into account the order of priority,
447 * @param {Ext.data.Request} request The request
448 * @return {String} The url
450 getUrl: function(request){
451 return request.url || this.api[request.action] || this.url;
454 <span id='Ext-data-proxy-Server-method-doRequest'> /**
455 </span> * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all pass
456 * through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link Ext.data.proxy.JsonP}
457 * and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as each of the methods that delegate to it.
458 * @param {Ext.data.Operation} operation The Ext.data.Operation object
459 * @param {Function} callback The callback function to call when the Operation has completed
460 * @param {Object} scope The scope in which to execute the callback
462 doRequest: function(operation, callback, scope) {
464 Ext.Error.raise("The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details");
468 <span id='Ext-data-proxy-Server-method-afterRequest'> /**
469 </span> * Optional callback function which can be used to clean up after a request has been completed.
470 * @param {Ext.data.Request} request The Request object
471 * @param {Boolean} success True if the request was successful
474 afterRequest: Ext.emptyFn,
476 onDestroy: function() {
477 Ext.destroy(this.reader, this.writer);