| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 | <!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-direct-RemotingProvider'>/**</span> * @class Ext.direct.RemotingProvider *  * <p>The {@link Ext.direct.RemotingProvider RemotingProvider} exposes access to * server side methods on the client (a remote procedure call (RPC) type of * connection where the client can initiate a procedure on the server).</p> *  * <p>This allows for code to be organized in a fashion that is maintainable, * while providing a clear path between client and server, something that is * not always apparent when using URLs.</p> *  * <p>To accomplish this the server-side needs to describe what classes and methods * are available on the client-side. This configuration will typically be * outputted by the server-side Ext.Direct stack when the API description is built.</p> */Ext.define('Ext.direct.RemotingProvider', {        /* Begin Definitions */       alias: 'direct.remotingprovider',        extend: 'Ext.direct.JsonProvider',         requires: [        'Ext.util.MixedCollection',         'Ext.util.DelayedTask',         'Ext.direct.Transaction',        'Ext.direct.RemotingMethod'    ],       /* End Definitions */   <span id='Ext-direct-RemotingProvider-cfg-actions'>   /**</span>     * @cfg {Object} actions     * Object literal defining the server side actions and methods. For example, if     * the Provider is configured with:     * <pre><code>"actions":{ // each property within the 'actions' object represents a server side Class     "TestAction":[ // array of methods within each server side Class to be       {              // stubbed out on client        "name":"doEcho",         "len":1                },{        "name":"multiply",// name of method        "len":2           // The number of parameters that will be used to create an                          // array of data to send to the server side function.                          // Ensure the server sends back a Number, not a String.     },{        "name":"doForm",        "formHandler":true, // direct the client to use specialized form handling method         "len":1    }]}     * </code></pre>     * <p>Note that a Store is not required, a server method can be called at any time.     * In the following example a <b>client side</b> handler is used to call the     * server side method "multiply" in the server-side "TestAction" Class:</p>     * <pre><code>TestAction.multiply(    2, 4, // pass two arguments to server, so specify len=2    // callback function after the server is called    // result: the result returned by the server    //      e: Ext.direct.RemotingEvent object    function(result, e){        var t = e.getTransaction();        var action = t.action; // server side Class called        var method = t.method; // server side method called        if(e.status){            var answer = Ext.encode(result); // 8            }else{            var msg = e.message; // failure message        }    });     * </code></pre>     * In the example above, the server side "multiply" function will be passed two     * arguments (2 and 4).  The "multiply" method should return the value 8 which will be     * available as the <tt>result</tt> in the example above.      */    <span id='Ext-direct-RemotingProvider-cfg-namespace'>    /**</span>     * @cfg {String/Object} namespace     * Namespace for the Remoting Provider (defaults to the browser global scope of <i>window</i>).     * Explicitly specify the namespace Object, or specify a String to have a     * {@link Ext#namespace namespace created} implicitly.     */    <span id='Ext-direct-RemotingProvider-cfg-url'>    /**</span>     * @cfg {String} url     * <b>Required</b>. The url to connect to the {@link Ext.direct.Manager} server-side router.      */    <span id='Ext-direct-RemotingProvider-cfg-enableUrlEncode'>    /**</span>     * @cfg {String} enableUrlEncode     * Specify which param will hold the arguments for the method.     * Defaults to <tt>'data'</tt>.     */    <span id='Ext-direct-RemotingProvider-cfg-enableBuffer'>    /**</span>     * @cfg {Number/Boolean} enableBuffer     * <p><tt>true</tt> or <tt>false</tt> to enable or disable combining of method     * calls. If a number is specified this is the amount of time in milliseconds     * to wait before sending a batched request.</p>     * <br><p>Calls which are received within the specified timeframe will be     * concatenated together and sent in a single request, optimizing the     * application by reducing the amount of round trips that have to be made     * to the server.</p>     */    enableBuffer: 10,    <span id='Ext-direct-RemotingProvider-cfg-maxRetries'>    /**</span>     * @cfg {Number} maxRetries     * Number of times to re-attempt delivery on failure of a call.     */    maxRetries: 1,    <span id='Ext-direct-RemotingProvider-cfg-timeout'>    /**</span>     * @cfg {Number} timeout     * The timeout to use for each request.     */    timeout: undefined,        constructor : function(config){        var me = this;        me.callParent(arguments);        me.addEvents(<span id='Ext-direct-RemotingProvider-event-beforecall'>            /**</span>             * @event beforecall             * Fires immediately before the client-side sends off the RPC call.             * By returning false from an event handler you can prevent the call from             * executing.             * @param {Ext.direct.RemotingProvider} provider             * @param {Ext.direct.Transaction} transaction             * @param {Object} meta The meta data             */                        'beforecall',            <span id='Ext-direct-RemotingProvider-event-call'>            /**</span>             * @event call             * Fires immediately after the request to the server-side is sent. This does             * NOT fire after the response has come back from the call.             * @param {Ext.direct.RemotingProvider} provider             * @param {Ext.direct.Transaction} transaction             * @param {Object} meta The meta data             */                        'call'        );        me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;        me.transactions = new Ext.util.MixedCollection();        me.callBuffer = [];    },    <span id='Ext-direct-RemotingProvider-method-initAPI'>    /**</span>     * Initialize the API     * @private     */    initAPI : function(){        var actions = this.actions,            namespace = this.namespace,            action,            cls,            methods,            i,            len,            method;                    for (action in actions) {            if (actions.hasOwnProperty(action)) {                cls = namespace[action];                if (!cls) {                    cls = namespace[action] = {};                }                methods = actions[action];                                for (i = 0, len = methods.length; i < len; ++i) {                    method = new Ext.direct.RemotingMethod(methods[i]);                    cls[method.name] = this.createHandler(action, method);                }            }        }    },    <span id='Ext-direct-RemotingProvider-method-createHandler'>    /**</span>     * Create a handler function for a direct call.     * @private     * @param {String} action The action the call is for     * @param {Object} method The details of the method     * @return {Function} A JS function that will kick off the call     */    createHandler : function(action, method){        var me = this,            handler;                if (!method.formHandler) {            handler = function(){                me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));            };        } else {            handler = function(form, callback, scope){                me.configureFormRequest(action, method, form, callback, scope);            };        }        handler.directCfg = {            action: action,            method: method        };        return handler;    },        // inherit docs    isConnected: function(){        return !!this.connected;    },    // inherit docs    connect: function(){        var me = this;                if (me.url) {            me.initAPI();            me.connected = true;            me.fireEvent('connect', me);        } else if(!me.url) {            //<debug>            Ext.Error.raise('Error initializing RemotingProvider, no url configured.');            //</debug>        }    },    // inherit docs    disconnect: function(){        var me = this;                if (me.connected) {            me.connected = false;            me.fireEvent('disconnect', me);        }    },    <span id='Ext-direct-RemotingProvider-method-runCallback'>    /**</span>     * Run any callbacks related to the transaction.     * @private     * @param {Ext.direct.Transaction} transaction The transaction     * @param {Ext.direct.Event} event The event     */    runCallback: function(transaction, event){        var success = !!event.status,            funcName = success ? 'success' : 'failure',            callback,            result;                if (transaction && transaction.callback) {            callback = transaction.callback;            result = Ext.isDefined(event.result) ? event.result : event.data;                    if (Ext.isFunction(callback)) {                callback(result, event, success);            } else {                Ext.callback(callback[funcName], callback.scope, [result, event, success]);                Ext.callback(callback.callback, callback.scope, [result, event, success]);            }        }    },    <span id='Ext-direct-RemotingProvider-method-onData'>    /**</span>     * React to the ajax request being completed     * @private     */    onData: function(options, success, response){        var me = this,            i = 0,            len,            events,            event,            transaction,            transactions;                    if (success) {            events = me.createEvents(response);            for (len = events.length; i < len; ++i) {                event = events[i];                transaction = me.getTransaction(event);                me.fireEvent('data', me, event);                if (transaction) {                    me.runCallback(transaction, event, true);                    Ext.direct.Manager.removeTransaction(transaction);                }            }        } else {            transactions = [].concat(options.transaction);            for (len = transactions.length; i < len; ++i) {                transaction = me.getTransaction(transactions[i]);                if (transaction && transaction.retryCount < me.maxRetries) {                    transaction.retry();                } else {                    event = new Ext.direct.ExceptionEvent({                        data: null,                        transaction: transaction,                        code: Ext.direct.Manager.exceptions.TRANSPORT,                        message: 'Unable to connect to the server.',                        xhr: response                    });                    me.fireEvent('data', me, event);                    if (transaction) {                        me.runCallback(transaction, event, false);                        Ext.direct.Manager.removeTransaction(transaction);                    }                }            }        }    },    <span id='Ext-direct-RemotingProvider-method-getTransaction'>    /**</span>     * Get transaction from XHR options     * @private     * @param {Object} options The options sent to the Ajax request     * @return {Ext.direct.Transaction} The transaction, null if not found     */    getTransaction: function(options){        return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;    },    <span id='Ext-direct-RemotingProvider-method-configureRequest'>    /**</span>     * Configure a direct request     * @private     * @param {String} action The action being executed     * @param {Object} method The being executed     */    configureRequest: function(action, method, args){        var me = this,            callData = method.getCallData(args),            data = callData.data,             callback = callData.callback,             scope = callData.scope,            transaction;        transaction = new Ext.direct.Transaction({            provider: me,            args: args,            action: action,            method: method.name,            data: data,            callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback        });        if (me.fireEvent('beforecall', me, transaction, method) !== false) {            Ext.direct.Manager.addTransaction(transaction);            me.queueTransaction(transaction);            me.fireEvent('call', me, transaction, method);        }    },    <span id='Ext-direct-RemotingProvider-method-getCallData'>    /**</span>     * Gets the Ajax call info for a transaction     * @private     * @param {Ext.direct.Transaction} transaction The transaction     * @return {Object} The call params     */    getCallData: function(transaction){        return {            action: transaction.action,            method: transaction.method,            data: transaction.data,            type: 'rpc',            tid: transaction.id        };    },    <span id='Ext-direct-RemotingProvider-method-sendRequest'>    /**</span>     * Sends a request to the server     * @private     * @param {Object/Array} data The data to send     */    sendRequest : function(data){        var me = this,            request = {                url: me.url,                callback: me.onData,                scope: me,                transaction: data,                timeout: me.timeout            }, callData,            enableUrlEncode = me.enableUrlEncode,            i = 0,            len,            params;                    if (Ext.isArray(data)) {            callData = [];            for (len = data.length; i < len; ++i) {                callData.push(me.getCallData(data[i]));            }        } else {            callData = me.getCallData(data);        }        if (enableUrlEncode) {            params = {};            params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);            request.params = params;        } else {            request.jsonData = callData;        }        Ext.Ajax.request(request);    },    <span id='Ext-direct-RemotingProvider-method-queueTransaction'>    /**</span>     * Add a new transaction to the queue     * @private     * @param {Ext.direct.Transaction} transaction The transaction     */    queueTransaction: function(transaction){        var me = this,            enableBuffer = me.enableBuffer;                if (transaction.form) {            me.sendFormRequest(transaction);            return;        }                me.callBuffer.push(transaction);        if (enableBuffer) {            if (!me.callTask) {                me.callTask = new Ext.util.DelayedTask(me.combineAndSend, me);            }            me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);        } else {            me.combineAndSend();        }    },    <span id='Ext-direct-RemotingProvider-method-combineAndSend'>    /**</span>     * Combine any buffered requests and send them off     * @private     */    combineAndSend : function(){        var buffer = this.callBuffer,            len = buffer.length;                    if (len > 0) {            this.sendRequest(len == 1 ? buffer[0] : buffer);            this.callBuffer = [];        }    },    <span id='Ext-direct-RemotingProvider-method-configureFormRequest'>    /**</span>     * Configure a form submission request     * @private     * @param {String} action The action being executed     * @param {Object} method The method being executed     * @param {HTMLElement} form The form being submitted     * @param {Function} callback (optional) A callback to run after the form submits     * @param {Object} scope (optional) A scope to execute the callback in     */    configureFormRequest : function(action, method, form, callback, scope){        var me = this,            transaction = new Ext.direct.Transaction({                provider: me,                action: action,                method: method.name,                args: [form, callback, scope],                callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,                isForm: true            }),            isUpload,            params;        if (me.fireEvent('beforecall', me, transaction, method) !== false) {            Ext.direct.Manager.addTransaction(transaction);            isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';                        params = {                extTID: transaction.id,                extAction: action,                extMethod: method.name,                extType: 'rpc',                extUpload: String(isUpload)            };                        // change made from typeof callback check to callback.params            // to support addl param passing in DirectSubmit EAC 6/2            Ext.apply(transaction, {                form: Ext.getDom(form),                isUpload: isUpload,                params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params            });            me.fireEvent('call', me, transaction, method);            me.sendFormRequest(transaction);        }    },    <span id='Ext-direct-RemotingProvider-method-sendFormRequest'>    /**</span>     * Sends a form request     * @private     * @param {Ext.direct.Transaction} transaction The transaction to send     */    sendFormRequest: function(transaction){        Ext.Ajax.request({            url: this.url,            params: transaction.params,            callback: this.onData,            scope: this,            form: transaction.form,            isUpload: transaction.isUpload,            transaction: transaction        });    }    });</pre></body></html>
 |