Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Server.html
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="../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; }
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-Server'>/**
19 </span> * @author Ed Spencer
20  * @class Ext.data.proxy.Server
21  * @extends Ext.data.proxy.Proxy
22  * 
23  * &lt;p&gt;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.&lt;/p&gt;
25  * 
26  * &lt;p&gt;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).&lt;/p&gt;
29  */
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'],
35     
36 <span id='Ext-data-proxy-Server-cfg-url'>    /**
37 </span>     * @cfg {String} url The URL from which to request the data object.
38      */
39     
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').
43      */
44     
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').
48      */
49     
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
53      */
54     pageParam: 'page',
55     
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
59      */
60     startParam: 'start',
61
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
65      */
66     limitParam: 'limit',
67     
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
71      */
72     groupParam: 'group',
73     
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
77      */
78     sortParam: 'sort',
79     
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
83      */
84     filterParam: 'filter',
85     
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. &lt;strong&gt;This is only used when simpleSortMode is set to true.&lt;/strong&gt;
88      * Defaults to 'dir'.
89      */
90     directionParam: 'dir',
91     
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'
95      */
96     simpleSortMode: false,
97     
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.
101      */
102     noCache : true,
103     
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 &quot;_dc&quot;)
106      */
107     cacheString: &quot;_dc&quot;,
108     
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).
112      */
113     timeout : 30000,
114     
115 <span id='Ext-data-proxy-Server-cfg-api'>    /**
116 </span>     * @cfg {Object} api
117      * Specific urls to call on CRUD action methods &quot;create&quot;, &quot;read&quot;, &quot;update&quot; and &quot;destroy&quot;.
118      * Defaults to:&lt;pre&gt;&lt;code&gt;
119 api: {
120     create  : undefined,
121     read    : undefined,
122     update  : undefined,
123     destroy : undefined
124 }
125      * &lt;/code&gt;&lt;/pre&gt;
126      * &lt;p&gt;The url is built based upon the action being executed &lt;tt&gt;[create|read|update|destroy]&lt;/tt&gt;
127      * using the commensurate &lt;tt&gt;{@link #api}&lt;/tt&gt; property, or if undefined default to the
128      * configured {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.&lt;/p&gt;&lt;br&gt;
129      * &lt;p&gt;For example:&lt;/p&gt;
130      * &lt;pre&gt;&lt;code&gt;
131 api: {
132     create  : '/controller/new',
133     read    : '/controller/load',
134     update  : '/controller/update',
135     destroy : '/controller/destroy_action'
136 }
137      * &lt;/code&gt;&lt;/pre&gt;
138      * &lt;p&gt;If the specific URL for a given CRUD action is undefined, the CRUD action request
139      * will be directed to the configured &lt;tt&gt;{@link Ext.data.proxy.Server#url url}&lt;/tt&gt;.&lt;/p&gt;
140      */
141     
142 <span id='Ext-data-proxy-Server-method-constructor'>    /**
143 </span>     * @ignore
144      */
145     constructor: function(config) {
146         var me = this;
147         
148         config = config || {};
149         this.addEvents(
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
156              */
157             'exception'
158         );
159         me.callParent([config]);
160         
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.
164          */
165         me.extraParams = config.extraParams || {};
166         
167         me.api = config.api || {};
168         
169         //backwards compatibility, will be deprecated in 5.0
170         me.nocache = me.noCache;
171     },
172     
173     //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case
174     create: function() {
175         return this.doRequest.apply(this, arguments);
176     },
177     
178     read: function() {
179         return this.doRequest.apply(this, arguments);
180     },
181     
182     update: function() {
183         return this.doRequest.apply(this, arguments);
184     },
185     
186     destroy: function() {
187         return this.doRequest.apply(this, arguments);
188     },
189     
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
195      */
196     buildRequest: function(operation) {
197         var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
198             request;
199         
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));
202         
203         if (operation.id &amp;&amp; !params.id) {
204             params.id = operation.id;
205         }
206         
207         request = Ext.create('Ext.data.Request', {
208             params   : params,
209             action   : operation.action,
210             records  : operation.records,
211             operation: operation,
212             url      : operation.url
213         });
214         
215         request.url = this.buildUrl(request);
216         
217         /*
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
220          */
221         operation.request = request;
222         
223         return request;
224     },
225     
226 <span id='Ext-data-proxy-Server-method-processResponse'>    /**
227 </span>     * 
228      */
229     processResponse: function(success, operation, request, response, callback, scope){
230         var me = this,
231             reader,
232             result,
233             records,
234             length,
235             mc,
236             record,
237             i;
238             
239         if (success === true) {
240             reader = me.getReader();
241             result = reader.read(me.extractResponseData(response));
242             records = result.records;
243             length = records.length;
244             
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 &lt; length; i++) {
249                     record = mc.get(records[i].getId());
250                     
251                     if (record) {
252                         record.beginEdit();
253                         record.set(record.data);
254                         record.endEdit(true);
255                     }
256                 }
257                 
258                 //see comment in buildRequest for why we include the response object here
259                 Ext.apply(operation, {
260                     response: response,
261                     resultSet: result
262                 });
263                 
264                 operation.setCompleted();
265                 operation.setSuccessful();
266             } else {
267                 operation.setException(result.message);
268                 me.fireEvent('exception', this, response, operation);
269             }
270         } else {
271             me.setException(operation, response);
272             me.fireEvent('exception', this, response, operation);              
273         }
274             
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);
278         }
279             
280         me.afterRequest(request, success);
281     },
282     
283 <span id='Ext-data-proxy-Server-method-setException'>    /**
284 </span>     * Sets up an exception on the operation
285      * @private
286      * @param {Ext.data.Operation} operation The operation
287      * @param {Object} response The response
288      */
289     setException: function(operation, response){
290         operation.setException({
291             status: response.status,
292             statusText: response.statusText
293         });     
294     },
295     
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.
298      * @private
299      * @param {Object} response The server response
300      * @return {Mixed} The response data to be used by the reader
301      */
302     extractResponseData: function(response){
303         return response; 
304     },
305     
306 <span id='Ext-data-proxy-Server-method-applyEncoding'>    /**
307 </span>     * Encode any values being sent to the server. Can be overridden in subclasses.
308      * @private
309      * @param {Array} An array of sorters/filters.
310      * @return {Mixed} The encoded value
311      */
312     applyEncoding: function(value){
313         return Ext.encode(value);
314     },
315     
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
321      */
322     encodeSorters: function(sorters) {
323         var min = [],
324             length = sorters.length,
325             i = 0;
326         
327         for (; i &lt; length; i++) {
328             min[i] = {
329                 property : sorters[i].property,
330                 direction: sorters[i].direction
331             };
332         }
333         return this.applyEncoding(min);
334         
335     },
336     
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
342      */
343     encodeFilters: function(filters) {
344         var min = [],
345             length = filters.length,
346             i = 0;
347         
348         for (; i &lt; length; i++) {
349             min[i] = {
350                 property: filters[i].property,
351                 value   : filters[i].value
352             };
353         }
354         return this.applyEncoding(min);
355     },
356     
357 <span id='Ext-data-proxy-Server-method-getParams'>    /**
358 </span>     * @private
359      * Copy any sorters, filters etc into the params so they can be sent over the wire
360      */
361     getParams: function(params, operation) {
362         params = params || {};
363         
364         var me             = this,
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,
372             
373             simpleSortMode = me.simpleSortMode,
374             
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;
382         
383         if (pageParam &amp;&amp; isDef(page)) {
384             params[pageParam] = page;
385         }
386         
387         if (startParam &amp;&amp; isDef(start)) {
388             params[startParam] = start;
389         }
390         
391         if (limitParam &amp;&amp; isDef(limit)) {
392             params[limitParam] = limit;
393         }
394         
395         if (groupParam &amp;&amp; groupers &amp;&amp; groupers.length &gt; 0) {
396             // Grouper is a subclass of sorter, so we can just use the sorter method
397             params[groupParam] = me.encodeSorters(groupers);
398         }
399         
400         if (sortParam &amp;&amp; sorters &amp;&amp; sorters.length &gt; 0) {
401             if (simpleSortMode) {
402                 params[sortParam] = sorters[0].property;
403                 params[directionParam] = sorters[0].direction;
404             } else {
405                 params[sortParam] = me.encodeSorters(sorters);
406             }
407             
408         }
409         
410         if (filterParam &amp;&amp; filters &amp;&amp; filters.length &gt; 0) {
411             params[filterParam] = me.encodeFilters(filters);
412         }
413         
414         return params;
415     },
416     
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
420      * to the url.
421      * @param {Ext.data.Request} request The request object
422      * @return {String} The url
423      */
424     buildUrl: function(request) {
425         var me = this,
426             url = me.getUrl(request);
427         
428         //&lt;debug&gt;
429         if (!url) {
430             Ext.Error.raise(&quot;You are using a ServerProxy but have not supplied it with a url.&quot;);
431         }
432         //&lt;/debug&gt;
433         
434         if (me.noCache) {
435             url = Ext.urlAppend(url, Ext.String.format(&quot;{0}={1}&quot;, me.cacheString, Ext.Date.now()));
436         }
437         
438         return url;
439     },
440     
441 <span id='Ext-data-proxy-Server-method-getUrl'>    /**
442 </span>     * Get the url for the request taking into account the order of priority,
443      * - The request
444      * - The api
445      * - The url
446      * @private
447      * @param {Ext.data.Request} request The request
448      * @return {String} The url
449      */
450     getUrl: function(request){
451         return request.url || this.api[request.action] || this.url;
452     },
453     
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
461      */
462     doRequest: function(operation, callback, scope) {
463         //&lt;debug&gt;
464         Ext.Error.raise(&quot;The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details&quot;);
465         //&lt;/debug&gt;
466     },
467     
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
472      * @method
473      */
474     afterRequest: Ext.emptyFn,
475     
476     onDestroy: function() {
477         Ext.destroy(this.reader, this.writer);
478     }
479 });
480 </pre>
481 </body>
482 </html>