| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>  <style type="text/css">    .highlight { display: block; background-color: #ddd; }  </style>  <script type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-data-proxy-Server'>/**</span> * @author Ed Spencer * * ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy}, and * would not usually be used directly. * * ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now * an alias of AjaxProxy). * @private */Ext.define('Ext.data.proxy.Server', {    extend: 'Ext.data.proxy.Proxy',    alias : 'proxy.server',    alternateClassName: 'Ext.data.ServerProxy',    uses  : ['Ext.data.Request'],<span id='Ext-data-proxy-Server-cfg-url'>    /**</span>     * @cfg {String} url     * The URL from which to request the data object.     */<span id='Ext-data-proxy-Server-cfg-pageParam'>    /**</span>     * @cfg {String} pageParam     * The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to undefined if you don't     * want to send a page parameter.     */    pageParam: 'page',<span id='Ext-data-proxy-Server-cfg-startParam'>    /**</span>     * @cfg {String} startParam     * The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this to undefined if you don't     * want to send a start parameter.     */    startParam: 'start',<span id='Ext-data-proxy-Server-cfg-limitParam'>    /**</span>     * @cfg {String} limitParam     * The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this to undefined if you don't     * want to send a limit parameter.     */    limitParam: 'limit',<span id='Ext-data-proxy-Server-cfg-groupParam'>    /**</span>     * @cfg {String} groupParam     * The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this to undefined if you don't     * want to send a group parameter.     */    groupParam: 'group',<span id='Ext-data-proxy-Server-cfg-groupDirectionParam'>    /**</span>     * @cfg {String} groupDirectionParam     * The name of the direction parameter to send in a request. **This is only used when simpleGroupMode is set to     * true.** Defaults to 'groupDir'.     */    groupDirectionParam: 'groupDir',<span id='Ext-data-proxy-Server-cfg-sortParam'>    /**</span>     * @cfg {String} sortParam     * The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this to undefined if you don't     * want to send a sort parameter.     */    sortParam: 'sort',<span id='Ext-data-proxy-Server-cfg-filterParam'>    /**</span>     * @cfg {String} filterParam     * The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set this to undefined if you don't     * want to send a filter parameter.     */    filterParam: 'filter',<span id='Ext-data-proxy-Server-cfg-directionParam'>    /**</span>     * @cfg {String} directionParam     * The name of the direction parameter to send in a request. **This is only used when simpleSortMode is set to     * true.** Defaults to 'dir'.     */    directionParam: 'dir',<span id='Ext-data-proxy-Server-cfg-simpleSortMode'>    /**</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. The {@link #directionParam} and {@link #sortParam} will be sent with the property name     * and either 'ASC' or 'DESC'.     */    simpleSortMode: false,<span id='Ext-data-proxy-Server-cfg-simpleGroupMode'>    /**</span>     * @cfg {Boolean} simpleGroupMode     * Enabling simpleGroupMode in conjunction with remoteGroup will only send one group property and a direction when a     * remote group is requested. The {@link #groupDirectionParam} and {@link #groupParam} will be sent with the property name and either 'ASC'     * or 'DESC'.     */    simpleGroupMode: false,<span id='Ext-data-proxy-Server-cfg-noCache'>    /**</span>     * @cfg {Boolean} noCache     * Disable caching by adding a unique parameter name to the request. Set to false to allow caching. Defaults to true.     */    noCache : true,<span id='Ext-data-proxy-Server-cfg-cacheString'>    /**</span>     * @cfg {String} cacheString     * The name of the cache param added to the url when using noCache. Defaults to "_dc".     */    cacheString: "_dc",<span id='Ext-data-proxy-Server-cfg-timeout'>    /**</span>     * @cfg {Number} timeout     * The number of milliseconds to wait for a response. Defaults to 30000 milliseconds (30 seconds).     */    timeout : 30000,<span id='Ext-data-proxy-Server-cfg-api'>    /**</span>     * @cfg {Object} api     * Specific urls to call on CRUD action methods "create", "read", "update" and "destroy". Defaults to:     *     *     api: {     *         create  : undefined,     *         read    : undefined,     *         update  : undefined,     *         destroy : undefined     *     }     *     * The url is built based upon the action being executed [create|read|update|destroy] using the commensurate     * {@link #api} property, or if undefined default to the configured     * {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.     *     * For example:     *     *     api: {     *         create  : '/controller/new',     *         read    : '/controller/load',     *         update  : '/controller/update',     *         destroy : '/controller/destroy_action'     *     }     *     * If the specific URL for a given CRUD action is undefined, the CRUD action request will be directed to the     * configured {@link Ext.data.proxy.Server#url url}.     */    constructor: function(config) {        var me = this;        config = config || {};<span id='Ext-data-proxy-Server-event-exception'>        /**</span>         * @event exception         * Fires when the server returns an exception         * @param {Ext.data.proxy.Proxy} this         * @param {Object} response The response from the AJAX request         * @param {Ext.data.Operation} operation The operation that triggered request         */        me.callParent([config]);<span id='Ext-data-proxy-Server-cfg-extraParams'>        /**</span>         * @cfg {Object} extraParams         * Extra parameters that will be included on every request. Individual requests with params of the same name         * will override these params when they are in conflict.         */        me.extraParams = config.extraParams || {};        me.api = Ext.apply({}, config.api || me.api);                //backwards compatibility, will be deprecated in 5.0        me.nocache = me.noCache;    },    //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case    create: function() {        return this.doRequest.apply(this, arguments);    },    read: function() {        return this.doRequest.apply(this, arguments);    },    update: function() {        return this.doRequest.apply(this, arguments);    },    destroy: function() {        return this.doRequest.apply(this, arguments);    },<span id='Ext-data-proxy-Server-method-setExtraParam'>    /**</span>     * Sets a value in the underlying {@link #extraParams}.     * @param {String} name The key for the new value     * @param {Object} value The value     */    setExtraParam: function(name, value) {        this.extraParams[name] = value;    },<span id='Ext-data-proxy-Server-method-buildRequest'>    /**</span>     * Creates an {@link Ext.data.Request Request} object from {@link Ext.data.Operation Operation}.     *     * This gets called from doRequest methods in subclasses of Server proxy.     *      * @param {Ext.data.Operation} operation The operation to execute     * @return {Ext.data.Request} The request object     */    buildRequest: function(operation) {        var me = this,            params = Ext.applyIf(operation.params || {}, me.extraParams || {}),            request;        //copy any sorters, filters etc into the params so they can be sent over the wire        params = Ext.applyIf(params, me.getParams(operation));        if (operation.id !== undefined && params.id === undefined) {            params.id = operation.id;        }        request = new Ext.data.Request({            params   : params,            action   : operation.action,            records  : operation.records,            operation: operation,            url      : operation.url,            // this is needed by JsonSimlet in order to properly construct responses for            // requests from this proxy            proxy: me        });        request.url = me.buildUrl(request);        /*         * Save the request on the Operation. Operations don't usually care about Request and Response data, but in the         * ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing         */        operation.request = request;        return request;    },    // Should this be documented as protected method?    processResponse: function(success, operation, request, response, callback, scope) {        var me = this,            reader,            result;        if (success === true) {            reader = me.getReader();            // Apply defaults to incoming data only for read operations.            // For create and update, there will already be a client-side record            // to match with which will contain any defaulted in values.            reader.applyDefaults = operation.action === 'read';            result = reader.read(me.extractResponseData(response));            if (result.success !== false) {                //see comment in buildRequest for why we include the response object here                Ext.apply(operation, {                    response: response,                    resultSet: result                });                operation.commitRecords(result.records);                operation.setCompleted();                operation.setSuccessful();            } else {                operation.setException(result.message);                me.fireEvent('exception', this, response, operation);            }        } else {            me.setException(operation, response);            me.fireEvent('exception', this, response, operation);        }        //this callback is the one that was passed to the 'read' or 'write' function above        if (typeof callback == 'function') {            callback.call(scope || me, operation);        }        me.afterRequest(request, success);    },<span id='Ext-data-proxy-Server-method-setException'>    /**</span>     * Sets up an exception on the operation     * @private     * @param {Ext.data.Operation} operation The operation     * @param {Object} response The response     */    setException: function(operation, response) {        operation.setException({            status: response.status,            statusText: response.statusText        });    },<span id='Ext-data-proxy-Server-method-extractResponseData'>    /**</span>     * Template method to allow subclasses to specify how to get the response for the reader.     * @template     * @private     * @param {Object} response The server response     * @return {Object} The response data to be used by the reader     */    extractResponseData: function(response) {        return response;    },<span id='Ext-data-proxy-Server-method-applyEncoding'>    /**</span>     * Encode any values being sent to the server. Can be overridden in subclasses.     * @private     * @param {Array} An array of sorters/filters.     * @return {Object} The encoded value     */    applyEncoding: function(value) {        return Ext.encode(value);    },<span id='Ext-data-proxy-Server-method-encodeSorters'>    /**</span>     * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default,     * this simply JSON-encodes the sorter data     * @param {Ext.util.Sorter[]} sorters The array of {@link Ext.util.Sorter Sorter} objects     * @return {String} The encoded sorters     */    encodeSorters: function(sorters) {        var min = [],            length = sorters.length,            i = 0;        for (; i < length; i++) {            min[i] = {                property : sorters[i].property,                direction: sorters[i].direction            };        }        return this.applyEncoding(min);    },<span id='Ext-data-proxy-Server-method-encodeFilters'>    /**</span>     * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default,     * this simply JSON-encodes the filter data     * @param {Ext.util.Filter[]} filters The array of {@link Ext.util.Filter Filter} objects     * @return {String} The encoded filters     */    encodeFilters: function(filters) {        var min = [],            length = filters.length,            i = 0;        for (; i < length; i++) {            min[i] = {                property: filters[i].property,                value   : filters[i].value            };        }        return this.applyEncoding(min);    },<span id='Ext-data-proxy-Server-method-getParams'>    /**</span>     * @private     * Copy any sorters, filters etc into the params so they can be sent over the wire     */    getParams: function(operation) {        var me = this,            params = {},            isDef = Ext.isDefined,            groupers = operation.groupers,            sorters = operation.sorters,            filters = operation.filters,            page = operation.page,            start = operation.start,            limit = operation.limit,            simpleSortMode = me.simpleSortMode,            simpleGroupMode = me.simpleGroupMode,            pageParam = me.pageParam,            startParam = me.startParam,            limitParam = me.limitParam,            groupParam = me.groupParam,            groupDirectionParam = me.groupDirectionParam,            sortParam = me.sortParam,            filterParam = me.filterParam,            directionParam = me.directionParam;        if (pageParam && isDef(page)) {            params[pageParam] = page;        }        if (startParam && isDef(start)) {            params[startParam] = start;        }        if (limitParam && isDef(limit)) {            params[limitParam] = limit;        }        if (groupParam && groupers && groupers.length > 0) {            // Grouper is a subclass of sorter, so we can just use the sorter method            if (simpleGroupMode) {                params[groupParam] = groupers[0].property;                params[groupDirectionParam] = groupers[0].direction || 'ASC';            } else {                params[groupParam] = me.encodeSorters(groupers);            }        }        if (sortParam && sorters && sorters.length > 0) {            if (simpleSortMode) {                params[sortParam] = sorters[0].property;                params[directionParam] = sorters[0].direction;            } else {                params[sortParam] = me.encodeSorters(sorters);            }        }        if (filterParam && filters && filters.length > 0) {            params[filterParam] = me.encodeFilters(filters);        }        return params;    },<span id='Ext-data-proxy-Server-method-buildUrl'>    /**</span>     * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will add the     * cache-buster param to the end of the url. Subclasses may need to perform additional modifications to the url.     * @param {Ext.data.Request} request The request object     * @return {String} The url     */    buildUrl: function(request) {        var me = this,            url = me.getUrl(request);        //<debug>        if (!url) {            Ext.Error.raise("You are using a ServerProxy but have not supplied it with a url.");        }        //</debug>        if (me.noCache) {            url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));        }        return url;    },<span id='Ext-data-proxy-Server-method-getUrl'>    /**</span>     * Get the url for the request taking into account the order of priority,     * - The request     * - The api     * - The url     * @private     * @param {Ext.data.Request} request The request     * @return {String} The url     */    getUrl: function(request) {        return request.url || this.api[request.action] || this.url;    },<span id='Ext-data-proxy-Server-method-doRequest'>    /**</span>     * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all     * pass through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link     * Ext.data.proxy.JsonP} and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as     * each of the methods that delegate to it.     *     * @param {Ext.data.Operation} operation The Ext.data.Operation object     * @param {Function} callback The callback function to call when the Operation has completed     * @param {Object} scope The scope in which to execute the callback     */    doRequest: function(operation, callback, scope) {        //<debug>        Ext.Error.raise("The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details");        //</debug>    },<span id='Ext-data-proxy-Server-method-afterRequest'>    /**</span>     * Optional callback function which can be used to clean up after a request has been completed.     * @param {Ext.data.Request} request The Request object     * @param {Boolean} success True if the request was successful     * @protected     * @template     * @method     */    afterRequest: Ext.emptyFn,    onDestroy: function() {        Ext.destroy(this.reader, this.writer);    }});</pre></body></html>
 |