ext-all-debug.js
资源名称:ext-3.0.0.zip [点击查看]
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:2341k
源码类别:
中间件编程
开发平台:
JavaScript
- /**
- * Callback for write actions
- * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
- * @param {Object} trans The request transaction object
- * @param {Object} res The server response
- * @private
- */
- onWrite : function(action, trans, res, rs) {
- var reader = trans.reader;
- try {
- // though we already have a response object here in STP, run through readResponse to catch any meta-data exceptions.
- reader.readResponse(action, res);
- } catch (e) {
- this.fireEvent('exception', this, 'response', action, trans, res, e);
- trans.callback.call(trans.scope||window, null, res, false);
- return;
- }
- if(!res[reader.meta.successProperty] === true){
- this.fireEvent('exception', this, 'remote', action, trans, res, rs);
- trans.callback.call(trans.scope||window, null, res, false);
- return;
- }
- this.fireEvent("write", this, action, res[reader.meta.root], res, rs, trans.arg );
- trans.callback.call(trans.scope||window, res[reader.meta.root], res, true);
- },
- // private
- isLoading : function(){
- return this.trans ? true : false;
- },
- /**
- * Abort the current server request.
- */
- abort : function(){
- if(this.isLoading()){
- this.destroyTrans(this.trans);
- }
- },
- // private
- destroyTrans : function(trans, isLoaded){
- this.head.removeChild(document.getElementById(trans.scriptId));
- clearTimeout(trans.timeoutId);
- if(isLoaded){
- window[trans.cb] = undefined;
- try{
- delete window[trans.cb];
- }catch(e){}
- }else{
- // if hasn't been loaded, wait for load to remove it to prevent script error
- window[trans.cb] = function(){
- window[trans.cb] = undefined;
- try{
- delete window[trans.cb];
- }catch(e){}
- };
- }
- },
- // private
- handleFailure : function(trans){
- this.trans = false;
- this.destroyTrans(trans, false);
- if (trans.action === Ext.data.Api.actions.read) {
- // @deprecated firing loadexception
- this.fireEvent("loadexception", this, null, trans.arg);
- }
- this.fireEvent('exception', this, 'response', trans.action, {
- response: null,
- options: trans.arg
- });
- trans.callback.call(trans.scope||window, null, trans.arg, false);
- },
- // inherit docs
- destroy: function(){
- this.abort();
- Ext.data.ScriptTagProxy.superclass.destroy.call(this);
- }
- });/**
- * @class Ext.data.HttpProxy
- * @extends Ext.data.DataProxy
- * <p>An implementation of {@link Ext.data.DataProxy} that processes data requests within the same
- * domain of the originating page.</p>
- * <p><b>Note</b>: this class cannot be used to retrieve data from a domain other
- * than the domain from which the running page was served. For cross-domain requests, use a
- * {@link Ext.data.ScriptTagProxy ScriptTagProxy}.</p>
- * <p>Be aware that to enable the browser to parse an XML document, the server must set
- * the Content-Type header in the HTTP response to "<tt>text/xml</tt>".</p>
- * @constructor
- * @param {Object} conn
- * An {@link Ext.data.Connection} object, or options parameter to {@link Ext.Ajax#request}.
- * <p>Note that if this HttpProxy is being used by a (@link Ext.data.Store Store}, then the
- * Store's call to {@link #load} will override any specified <tt>callback</tt> and <tt>params</tt>
- * options. In this case, use the Store's {@link Ext.data.Store#events events} to modify parameters,
- * or react to loading events. The Store's {@link Ext.data.Store#baseParams baseParams} may also be
- * used to pass parameters known at instantiation time.</p>
- * <p>If an options parameter is passed, the singleton {@link Ext.Ajax} object will be used to make
- * the request.</p>
- */
- Ext.data.HttpProxy = function(conn){
- Ext.data.HttpProxy.superclass.constructor.call(this, conn);
- /**
- * The Connection object (Or options parameter to {@link Ext.Ajax#request}) which this HttpProxy
- * uses to make requests to the server. Properties of this object may be changed dynamically to
- * change the way data is requested.
- * @property
- */
- this.conn = conn;
- // nullify the connection url. The url param has been copied to 'this' above. The connection
- // url will be set during each execution of doRequest when buildUrl is called. This makes it easier for users to override the
- // connection url during beforeaction events (ie: beforeload, beforesave, etc). The connection url will be nullified
- // after each request as well. Url is always re-defined during doRequest.
- this.conn.url = null;
- this.useAjax = !conn || !conn.events;
- //private. A hash containing active requests, keyed on action [Ext.data.Api.actions.create|read|update|destroy]
- var actions = Ext.data.Api.actions;
- this.activeRequest = {};
- for (var verb in actions) {
- this.activeRequest[actions[verb]] = undefined;
- }
- };
- Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
- /**
- * @cfg {Boolean} restful
- * <p>If set to <tt>true</tt>, a {@link Ext.data.Record#phantom non-phantom} record's
- * {@link Ext.data.Record#id id} will be appended to the url (defaults to <tt>false</tt>).</p><br>
- * <p>The url is built based upon the action being executed <tt>[load|create|save|destroy]</tt>
- * using the commensurate <tt>{@link #api}</tt> property, or if undefined default to the
- * configured {@link Ext.data.Store}.{@link Ext.data.Store#url url}.</p><br>
- * <p>Some MVC (e.g., Ruby on Rails, Merb and Django) support this style of segment based urls
- * where the segments in the URL follow the Model-View-Controller approach.</p><pre><code>
- * someSite.com/controller/action/id
- * </code></pre>
- * Where the segments in the url are typically:<div class="mdetail-params"><ul>
- * <li>The first segment : represents the controller class that should be invoked.</li>
- * <li>The second segment : represents the class function, or method, that should be called.</li>
- * <li>The third segment : represents the ID (a variable typically passed to the method).</li>
- * </ul></div></p>
- * <p>For example:</p>
- * <pre><code>
- api: {
- load : '/controller/load',
- create : '/controller/new', // Server MUST return idProperty of new record
- save : '/controller/update',
- destroy : '/controller/destroy_action'
- }
- // Alternatively, one can use the object-form to specify each API-action
- api: {
- load: {url: 'read.php', method: 'GET'},
- create: 'create.php',
- destroy: 'destroy.php',
- save: 'update.php'
- }
- */
- /**
- * Return the {@link Ext.data.Connection} object being used by this Proxy.
- * @return {Connection} The Connection object. This object may be used to subscribe to events on
- * a finer-grained basis than the DataProxy events.
- */
- getConnection : function() {
- return this.useAjax ? Ext.Ajax : this.conn;
- },
- /**
- * Used for overriding the url used for a single request. Designed to be called during a beforeaction event. Calling setUrl
- * will override any urls set via the api configuration parameter. Set the optional parameter makePermanent to set the url for
- * all subsequent requests. If not set to makePermanent, the next request will use the same url or api configuration defined
- * in the initial proxy configuration.
- * @param {String} url
- * @param {Boolean} makePermanent (Optional) [false]
- *
- * (e.g.: beforeload, beforesave, etc).
- */
- setUrl : function(url, makePermanent) {
- this.conn.url = url;
- if (makePermanent === true) {
- this.url = url;
- Ext.data.Api.prepare(this);
- }
- },
- /**
- * HttpProxy implementation of DataProxy#doRequest
- * @param {String} action The crud action type (create, read, update, destroy)
- * @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
- * @param {Object} params An object containing properties which are to be used as HTTP parameters
- * for the request to the remote server.
- * @param {Ext.data.DataReader} reader The Reader object which converts the data
- * object into a block of Ext.data.Records.
- * @param {Function} callback
- * <div class="sub-desc"><p>A function to be called after the request.
- * The <tt>callback</tt> is passed the following arguments:<ul>
- * <li><tt>r</tt> : Ext.data.Record[] The block of Ext.data.Records.</li>
- * <li><tt>options</tt>: Options object from the action request</li>
- * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div>
- * @param {Object} scope The scope in which to call the callback
- * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
- */
- doRequest : function(action, rs, params, reader, cb, scope, arg) {
- var o = {
- method: (this.api[action]) ? this.api[action]['method'] : undefined,
- request: {
- callback : cb,
- scope : scope,
- arg : arg
- },
- reader: reader,
- callback : this.createCallback(action, rs),
- scope: this
- };
- // Sample the request data: If it's an object, then it hasn't been json-encoded yet.
- // Transmit data using jsonData config of Ext.Ajax.request
- if (typeof(params[reader.meta.root]) === 'object') {
- o.jsonData = params;
- } else {
- o.params = params || {};
- }
- // Set the connection url. If this.conn.url is not null here,
- // the user may have overridden the url during a beforeaction event-handler.
- // this.conn.url is nullified after each request.
- if (this.conn.url === null) {
- this.conn.url = this.buildUrl(action, rs);
- }
- else if (this.restful === true && rs instanceof Ext.data.Record && !rs.phantom) {
- this.conn.url += '/' + rs.id;
- }
- if(this.useAjax){
- Ext.applyIf(o, this.conn);
- // If a currently running request is found for this action, abort it.
- if (this.activeRequest[action]) {
- // Disabled aborting activeRequest while implementing REST. activeRequest[action] will have to become an array
- //Ext.Ajax.abort(this.activeRequest[action]);
- }
- this.activeRequest[action] = Ext.Ajax.request(o);
- }else{
- this.conn.request(o);
- }
- // request is sent, nullify the connection url in preparation for the next request
- this.conn.url = null;
- },
- /**
- * Returns a callback function for a request. Note a special case is made for the
- * read action vs all the others.
- * @param {String} action [create|update|delete|load]
- * @param {Ext.data.Record[]} rs The Store-recordset being acted upon
- * @private
- */
- createCallback : function(action, rs) {
- return function(o, success, response) {
- this.activeRequest[action] = undefined;
- if (!success) {
- if (action === Ext.data.Api.actions.read) {
- // @deprecated: fire loadexception for backwards compat.
- this.fireEvent('loadexception', this, o, response);
- }
- this.fireEvent('exception', this, 'response', action, o, response);
- o.request.callback.call(o.request.scope, null, o.request.arg, false);
- return;
- }
- if (action === Ext.data.Api.actions.read) {
- this.onRead(action, o, response);
- } else {
- this.onWrite(action, o, response, rs);
- }
- }
- },
- /**
- * Callback for read action
- * @param {String} action Action name as per {@link Ext.data.Api.actions#read}.
- * @param {Object} o The request transaction object
- * @param {Object} res The server response
- * @private
- */
- onRead : function(action, o, response) {
- var result;
- try {
- result = o.reader.read(response);
- }catch(e){
- // @deprecated: fire old loadexception for backwards-compat.
- this.fireEvent('loadexception', this, o, response, e);
- this.fireEvent('exception', this, 'response', action, o, response, e);
- o.request.callback.call(o.request.scope, null, o.request.arg, false);
- return;
- }
- if (result.success === false) {
- // @deprecated: fire old loadexception for backwards-compat.
- this.fireEvent('loadexception', this, o, response);
- // Get DataReader read-back a response-object to pass along to exception event
- var res = o.reader.readResponse(action, response);
- this.fireEvent('exception', this, 'remote', action, o, res, null);
- }
- else {
- this.fireEvent('load', this, o, o.request.arg);
- }
- o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
- },
- /**
- * Callback for write actions
- * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
- * @param {Object} trans The request transaction object
- * @param {Object} res The server response
- * @private
- */
- onWrite : function(action, o, response, rs) {
- var reader = o.reader;
- var res;
- try {
- res = reader.readResponse(action, response);
- } catch (e) {
- this.fireEvent('exception', this, 'response', action, o, response, e);
- o.request.callback.call(o.request.scope, null, o.request.arg, false);
- return;
- }
- if (res[reader.meta.successProperty] === false) {
- this.fireEvent('exception', this, 'remote', action, o, res, rs);
- } else {
- this.fireEvent('write', this, action, res[reader.meta.root], res, rs, o.request.arg);
- }
- o.request.callback.call(o.request.scope, res[reader.meta.root], res, res[reader.meta.successProperty]);
- },
- // inherit docs
- destroy: function(){
- if(!this.useAjax){
- this.conn.abort();
- }else if(this.activeRequest){
- var actions = Ext.data.Api.actions;
- for (var verb in actions) {
- if(this.activeRequest[actions[verb]]){
- Ext.Ajax.abort(this.activeRequest[actions[verb]]);
- }
- }
- }
- Ext.data.HttpProxy.superclass.destroy.call(this);
- }
- });/**
- * @class Ext.data.MemoryProxy
- * @extends Ext.data.DataProxy
- * An implementation of Ext.data.DataProxy that simply passes the data specified in its constructor
- * to the Reader when its load method is called.
- * @constructor
- * @param {Object} data The data object which the Reader uses to construct a block of Ext.data.Records.
- */
- Ext.data.MemoryProxy = function(data){
- // Must define a dummy api with "read" action to satisfy DataProxy#doRequest and Ext.data.Api#prepare *before* calling super
- var api = {};
- api[Ext.data.Api.actions.read] = true;
- Ext.data.MemoryProxy.superclass.constructor.call(this, {
- api: api
- });
- this.data = data;
- };
- Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
- /**
- * @event loadexception
- * Fires if an exception occurs in the Proxy during data loading. Note that this event is also relayed
- * through {@link Ext.data.Store}, so you can listen for it directly on any Store instance.
- * @param {Object} this
- * @param {Object} arg The callback's arg object passed to the {@link #load} function
- * @param {Object} null This parameter does not apply and will always be null for MemoryProxy
- * @param {Error} e The JavaScript Error object caught if the configured Reader could not read the data
- */
- /**
- * MemoryProxy implementation of DataProxy#doRequest
- * @param {String} action
- * @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
- * @param {Object} params An object containing properties which are to be used as HTTP parameters
- * for the request to the remote server.
- * @param {Ext.data.DataReader} reader The Reader object which converts the data
- * object into a block of Ext.data.Records.
- * @param {Function} callback The function into which to pass the block of Ext.data.Records.
- * The function must be passed <ul>
- * <li>The Record block object</li>
- * <li>The "arg" argument from the load function</li>
- * <li>A boolean success indicator</li>
- * </ul>
- * @param {Object} scope The scope in which to call the callback
- * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
- */
- doRequest : function(action, rs, params, reader, callback, scope, arg) {
- // No implementation for CRUD in MemoryProxy. Assumes all actions are 'load'
- params = params || {};
- var result;
- try {
- result = reader.readRecords(this.data);
- }catch(e){
- // @deprecated loadexception
- this.fireEvent("loadexception", this, null, arg, e);
- this.fireEvent('exception', this, 'response', action, arg, null, e);
- callback.call(scope, null, arg, false);
- return;
- }
- callback.call(scope, result, arg, true);
- }
- });/** * @class Ext.data.JsonWriter * @extends Ext.data.DataWriter * DataWriter extension for writing an array or single {@link Ext.data.Record} object(s) in preparation for executing a remote CRUD action. */ Ext.data.JsonWriter = function(config) { Ext.data.JsonWriter.superclass.constructor.call(this, config); // careful to respect "returnJson", renamed to "encode" if (this.returnJson != undefined) { this.encode = this.returnJson; } } Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, { /** * @cfg {Boolean} returnJson <b>Deprecated. Use {@link Ext.data.JsonWriter#encode} instead. */ returnJson : undefined, /** * @cfg {Boolean} encode <tt>true</tt> to {@link Ext.util.JSON#encode encode} the * {@link Ext.data.DataWriter#toHash hashed data}. Defaults to <tt>true</tt>. When using * {@link Ext.data.DirectProxy}, set this to <tt>false</tt> since Ext.Direct.JsonProvider will perform * its own json-encoding. In addition, if you're using {@link Ext.data.HttpProxy}, setting to <tt>false</tt> * will cause HttpProxy to transmit data using the <b>jsonData</b> configuration-params of {@link Ext.Ajax#request} * instead of <b>params</b>. When using a {@link Ext.data.Store#restful} Store, some serverside frameworks are * tuned to expect data through the jsonData mechanism. In those cases, one will want to set <b>encode: <tt>false</tt></b> */ encode : true, /** * Final action of a write event. Apply the written data-object to params. * @param {String} action [Ext.data.Api.actions.create|read|update|destroy] * @param {Record[]} rs * @param {Object} http params * @param {Object} data object populated according to DataReader meta-data "root" and "idProperty" */ render : function(action, rs, params, data) { Ext.apply(params, data); if (this.encode === true) { // <-- @deprecated returnJson if (Ext.isArray(rs) && data[this.meta.idProperty]) { params[this.meta.idProperty] = Ext.encode(params[this.meta.idProperty]); } params[this.meta.root] = Ext.encode(params[this.meta.root]); } }, /** * createRecord * @protected * @param {Ext.data.Record} rec */ createRecord : function(rec) { return this.toHash(rec); }, /** * updateRecord * @protected * @param {Ext.data.Record} rec */ updateRecord : function(rec) { return this.toHash(rec); }, /** * destroyRecord * @protected * @param {Ext.data.Record} rec */ destroyRecord : function(rec) { return rec.id; } });/** * @class Ext.data.JsonReader * @extends Ext.data.DataReader * <p>Data reader class to create an Array of {@link Ext.data.Record} objects from a JSON response * based on mappings in a provided {@link Ext.data.Record} constructor.</p> * <p>Example code:</p> * <pre><code> var Employee = Ext.data.Record.create([ {name: 'firstname'}, // map the Record's "firstname" field to the row object's key of the same name {name: 'job', mapping: 'occupation'} // map the Record's "job" field to the row object's "occupation" key ]); var myReader = new Ext.data.JsonReader( { // The metadata property, with configuration options: totalProperty: "results", // the property which contains the total dataset size (optional) root: "rows", // the property which contains an Array of record data objects idProperty: "id" // the property within each row object that provides an ID for the record (optional) }, Employee // {@link Ext.data.Record} constructor that provides mapping for JSON object ); </code></pre> * <p>This would consume a JSON data object of the form:</p><pre><code> { results: 2, // Reader's configured totalProperty rows: [ // Reader's configured root { id: 1, firstname: 'Bill', occupation: 'Gardener' }, // a row object { id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' } // another row object ] } </code></pre> * <p><b><u>Automatic configuration using metaData</u></b></p> * <p>It is possible to change a JsonReader's metadata at any time by including a <b><tt>metaData</tt></b> * property in the JSON data object. If the JSON data object has a <b><tt>metaData</tt></b> property, a * {@link Ext.data.Store Store} object using this Reader will reconfigure itself to use the newly provided * field definition and fire its {@link Ext.data.Store#metachange metachange} event. The metachange event * handler may interrogate the <b><tt>metaData</tt></b> property to perform any configuration required. * Note that reconfiguring a Store potentially invalidates objects which may refer to Fields or Records * which no longer exist.</p> * <p>The <b><tt>metaData</tt></b> property in the JSON data object may contain:</p> * <div class="mdetail-params"><ul> * <li>any of the configuration options for this class</li> * <li>a <b><tt>{@link Ext.data.Record#fields fields}</tt></b> property which the JsonReader will * use as an argument to the {@link Ext.data.Record#create data Record create method} in order to * configure the layout of the Records it will produce.</li> * <li>a <b><tt>{@link Ext.data.Store#sortInfo sortInfo}</tt></b> property which the JsonReader will * use to set the {@link Ext.data.Store}'s {@link Ext.data.Store#sortInfo sortInfo} property</li> * <li>any user-defined properties needed</li> * </ul></div> * <p>To use this facility to send the same data as the example above (without having to code the creation * of the Record constructor), you would create the JsonReader like this:</p><pre><code> var myReader = new Ext.data.JsonReader(); </code></pre> * <p>The first data packet from the server would configure the reader by containing a * <b><tt>metaData</tt></b> property <b>and</b> the data. For example, the JSON data object might take * the form:</p> <pre><code> { metaData: { idProperty: 'id', root: 'rows', totalProperty: 'results', fields: [ {name: 'name'}, {name: 'job', mapping: 'occupation'} ], sortInfo: {field: 'name', direction:'ASC'}, // used by store to set its sortInfo foo: 'bar' // custom property }, results: 2, rows: [ // an Array { 'id': 1, 'name': 'Bill', occupation: 'Gardener' }, { 'id': 2, 'name': 'Ben', occupation: 'Horticulturalist' } ] } </code></pre> * @cfg {String} totalProperty [total] Name of the property from which to retrieve the total number of records * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being * paged from the remote server. Defaults to <tt>total</tt>. * @cfg {String} successProperty [success] Name of the property from which to * retrieve the success attribute. Defaults to <tt>success</tt>. See * {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception} * for additional information. * @cfg {String} root [undefined] <b>Required</b>. The name of the property * which contains the Array of row objects. Defaults to <tt>undefined</tt>. * An exception will be thrown if the root property is undefined. The data packet * value for this property should be an empty array to clear the data or show * no data. * @cfg {String} idProperty [id] Name of the property within a row object that contains a record identifier value. Defaults to <tt>id</tt> * @constructor * Create a new JsonReader * @param {Object} meta Metadata configuration options. * @param {Array/Object} recordType * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record} * constructor created from {@link Ext.data.Record#create}.</p> */ Ext.data.JsonReader = function(meta, recordType){ meta = meta || {}; // default idProperty, successProperty & totalProperty -> "id", "success", "total" Ext.applyIf(meta, { idProperty: 'id', successProperty: 'success', totalProperty: 'total' }); Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields); }; Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, { /** * This JsonReader's metadata as passed to the constructor, or as passed in * the last data packet's <b><tt>metaData</tt></b> property. * @type Mixed * @property meta */ /** * This method is only used by a DataProxy which has retrieved data from a remote server. * @param {Object} response The XHR object which contains the JSON data in its responseText. * @return {Object} data A data block which is used by an Ext.data.Store object as * a cache of Ext.data.Records. */ read : function(response){ var json = response.responseText; var o = Ext.decode(json); if(!o) { throw {message: "JsonReader.read: Json object not found"}; } return this.readRecords(o); }, // private function a store will implement onMetaChange : function(meta, recordType, o){ }, /** * @ignore */ simpleAccess: function(obj, subsc) { return obj[subsc]; }, /** * @ignore */ getJsonAccessor: function(){ var re = /[[.]/; return function(expr) { try { return(re.test(expr)) ? new Function("obj", "return obj." + expr) : function(obj){ return obj[expr]; }; } catch(e){} return Ext.emptyFn; }; }(), /** * Create a data block containing Ext.data.Records from a JSON object. * @param {Object} o An object which contains an Array of row objects in the property specified * in the config as 'root, and optionally a property, specified in the config as 'totalProperty' * which contains the total size of the dataset. * @return {Object} data A data block which is used by an Ext.data.Store object as * a cache of Ext.data.Records. */ readRecords : function(o){ /** * After any data loads, the raw JSON data is available for further custom processing. If no data is * loaded or there is a load exception this property will be undefined. * @type Object */ this.jsonData = o; if(o.metaData){ delete this.ef; this.meta = o.metaData; this.recordType = Ext.data.Record.create(o.metaData.fields); this.onMetaChange(this.meta, this.recordType, o); } var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length, v; // Generate extraction functions for the totalProperty, the root, the id, and for each field this.buildExtractors(); var root = this.getRoot(o), c = root.length, totalRecords = c, success = true; if(s.totalProperty){ v = parseInt(this.getTotal(o), 10); if(!isNaN(v)){ totalRecords = v; } } if(s.successProperty){ v = this.getSuccess(o); if(v === false || v === 'false'){ success = false; } } var records = []; for(var i = 0; i < c; i++){ var n = root[i]; var record = new Record(this.extractValues(n, fi, fl), this.getId(n)); record.json = n; records[i] = record; } return { success : success, records : records, totalRecords : totalRecords }; }, // private buildExtractors : function() { if(this.ef){ return; } var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length; if(s.totalProperty) { this.getTotal = this.getJsonAccessor(s.totalProperty); } if(s.successProperty) { this.getSuccess = this.getJsonAccessor(s.successProperty); } this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;}; if (s.id || s.idProperty) { var g = this.getJsonAccessor(s.id || s.idProperty); this.getId = function(rec) { var r = g(rec); return (r === undefined || r === "") ? null : r; }; } else { this.getId = function(){return null;}; } var ef = []; for(var i = 0; i < fl; i++){ f = fi[i]; var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name; ef.push(this.getJsonAccessor(map)); } this.ef = ef; }, // private extractValues extractValues: function(data, items, len) { var f, values = {}; for(var j = 0; j < len; j++){ f = items[j]; var v = this.ef[j](data); values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data); } return values; }, /** * Decode a json response from server. * @param {String} action [Ext.data.Api.actions.create|read|update|destroy] * @param {Object} response */ readResponse : function(action, response) { var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response; if(!o) { throw new Ext.data.JsonReader.Error('response'); } if (Ext.isEmpty(o[this.meta.successProperty])) { throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty); } // TODO, separate empty and undefined exceptions. if ((action === Ext.data.Api.actions.create || action === Ext.data.Api.actions.update)) { if (Ext.isEmpty(o[this.meta.root])) { throw new Ext.data.JsonReader.Error('root-emtpy', this.meta.root); } else if (o[this.meta.root] === undefined) { throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root); } } // make sure extraction functions are defined. this.ef = this.buildExtractors(); return o; } }); /** * @class Ext.data.JsonReader.Error * Error class for JsonReader */ Ext.data.JsonReader.Error = Ext.extend(Ext.Error, { constructor : function(message, arg) { this.arg = arg; Ext.Error.call(this, message); }, name : 'Ext.data.JsonReader' }); Ext.apply(Ext.data.JsonReader.Error.prototype, { lang: { 'response': "An error occurred while json-decoding your server response", 'successProperty-response': 'Could not locate your "successProperty" in your server response. Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response. See the JsonReader docs.', 'root-undefined-response': 'Could not locate your "root" property in your server response. Please review your JsonReader config to ensure the config-property "root" matches the property your server-response. See the JsonReader docs.', 'root-undefined-config': 'Your JsonReader was configured without a "root" property. Please review your JsonReader config and make sure to define the root property. See the JsonReader docs.', 'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty" Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id"). See the JsonReader docs.', 'root-emtpy': 'Data was expected to be returned by the server in the "root" property of the response. Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response. See JsonReader docs.' } }); /** * @class Ext.data.ArrayReader * @extends Ext.data.JsonReader * <p>Data reader class to create an Array of {@link Ext.data.Record} objects from an Array. * Each element of that Array represents a row of data fields. The * fields are pulled into a Record object using as a subscript, the <code>mapping</code> property * of the field definition if it exists, or the field's ordinal position in the definition.</p> * <p>Example code:</p> * <pre><code> var Employee = Ext.data.Record.create([ {name: 'name', mapping: 1}, // "mapping" only needed if an "id" field is present which {name: 'occupation', mapping: 2} // precludes using the ordinal position as the index. ]); var myReader = new Ext.data.ArrayReader({ {@link #idIndex}: 0 }, Employee); </code></pre> * <p>This would consume an Array like this:</p> * <pre><code> [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ] * </code></pre> * @constructor * Create a new ArrayReader * @param {Object} meta Metadata configuration options. * @param {Array/Object} recordType * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record} * constructor created from {@link Ext.data.Record#create}.</p> */ Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, { /** * @cfg {String} successProperty * @hide */ /** * @cfg {Number} id (optional) The subscript within row Array that provides an ID for the Record. * Deprecated. Use {@link #idIndex} instead. */ /** * @cfg {Number} idIndex (optional) The subscript within row Array that provides an ID for the Record. */ /** * Create a data block containing Ext.data.Records from an Array. * @param {Object} o An Array of row objects which represents the dataset. * @return {Object} data A data block which is used by an Ext.data.Store object as * a cache of Ext.data.Records. */ readRecords : function(o){ this.arrayData = o; var s = this.meta, sid = s ? Ext.num(s.idIndex, s.id) : null, recordType = this.recordType, fields = recordType.prototype.fields, records = [], v; if(!this.getRoot) { this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p) {return p;}; if(s.totalProperty) { this.getTotal = this.getJsonAccessor(s.totalProperty); } } var root = this.getRoot(o); for(var i = 0; i < root.length; i++) { var n = root[i]; var values = {}; var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null); for(var j = 0, jlen = fields.length; j < jlen; j++) { var f = fields.items[j]; var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j; v = n[k] !== undefined ? n[k] : f.defaultValue; v = f.convert(v, n); values[f.name] = v; } var record = new recordType(values, id); record.json = n; records[records.length] = record; } var totalRecords = records.length; if(s.totalProperty) { v = parseInt(this.getTotal(o), 10); if(!isNaN(v)) { totalRecords = v; } } return { records : records, totalRecords : totalRecords }; } });/** * @class Ext.data.ArrayStore * @extends Ext.data.Store * <p>Formerly known as "SimpleStore".</p> * <p>Small helper class to make creating {@link Ext.data.Store}s from Array data easier. * An ArrayStore will be automatically configured with a {@link Ext.data.ArrayReader}.</p> * <p>A store configuration would be something like:<pre><code> var store = new Ext.data.ArrayStore({ // store configs autoDestroy: true, storeId: 'myStore', // reader configs idIndex: 0, fields: [ 'company', {name: 'price', type: 'float'}, {name: 'change', type: 'float'}, {name: 'pctChange', type: 'float'}, {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'} ] }); * </code></pre></p> * <p>This store is configured to consume a returned object of the form:<pre><code> var myData = [ ['3m Co',71.72,0.02,0.03,'9/1 12:00am'], ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'], ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'], ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'], ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am'] ]; * </code></pre> * An object literal of this form could also be used as the {@link #data} config option.</p> * <p><b>*Note:</b> Although not listed here, this class accepts all of the configuration options of * <b>{@link Ext.data.ArrayReader ArrayReader}</b>.</p> * @constructor * @param {Object} config * @xtype arraystore */ Ext.data.ArrayStore = Ext.extend(Ext.data.Store, { /** * @cfg {Ext.data.DataReader} reader @hide */ constructor: function(config){ Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, { reader: new Ext.data.ArrayReader(config) })); }, loadData : function(data, append){ if(this.expandData === true){ var r = []; for(var i = 0, len = data.length; i < len; i++){ r[r.length] = [data[i]]; } data = r; } Ext.data.ArrayStore.superclass.loadData.call(this, data, append); } }); Ext.reg('arraystore', Ext.data.ArrayStore); // backwards compat Ext.data.SimpleStore = Ext.data.ArrayStore; Ext.reg('simplestore', Ext.data.SimpleStore);/** * @class Ext.data.JsonStore * @extends Ext.data.Store * <p>Small helper class to make creating {@link Ext.data.Store}s from JSON data easier. * A JsonStore will be automatically configured with a {@link Ext.data.JsonReader}.</p> * <p>A store configuration would be something like:<pre><code> var store = new Ext.data.JsonStore({ // store configs autoDestroy: true, url: 'get-images.php', storeId: 'myStore', // reader configs root: 'images', idProperty: 'name', fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}] }); * </code></pre></p> * <p>This store is configured to consume a returned object of the form:<pre><code> { images: [ {name: 'Image one', url:'/GetImage.php?id=1', size:46.5, lastmod: new Date(2007, 10, 29)}, {name: 'Image Two', url:'/GetImage.php?id=2', size:43.2, lastmod: new Date(2007, 10, 30)} ] } * </code></pre> * An object literal of this form could also be used as the {@link #data} config option.</p> * <p><b>*Note:</b> Although not listed here, this class accepts all of the configuration options of * <b>{@link Ext.data.JsonReader JsonReader}</b>.</p> * @constructor * @param {Object} config * @xtype jsonstore */ Ext.data.JsonStore = Ext.extend(Ext.data.Store, { /** * @cfg {Ext.data.DataReader} reader @hide */ constructor: function(config){ Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, { reader: new Ext.data.JsonReader(config) })); } }); Ext.reg('jsonstore', Ext.data.JsonStore);/** * @class Ext.data.XmlWriter * @extends Ext.data.DataWriter * DataWriter extension for writing an array or single {@link Ext.data.Record} object(s) in preparation for executing a remote CRUD action via XML. */ Ext.data.XmlWriter = Ext.extend(Ext.data.DataWriter, { /** * Final action of a write event. Apply the written data-object to params. * @param {String} action [Ext.data.Api.create|read|update|destroy] * @param {Record[]} rs * @param {Object} http params * @param {Object} data object populated according to DataReader meta-data "root" and "idProperty" */ render : function(action, rs, params, data) { // no impl. }, /** * createRecord * @param {Ext.data.Record} rec */ createRecord : function(rec) { // no impl }, /** * updateRecord * @param {Ext.data.Record} rec */ updateRecord : function(rec) { // no impl. }, /** * destroyRecord * @param {Ext.data.Record} rec */ destroyRecord : function(rec) { // no impl } });/** * @class Ext.data.XmlReader * @extends Ext.data.DataReader * <p>Data reader class to create an Array of {@link Ext.data.Record} objects from an XML document * based on mappings in a provided {@link Ext.data.Record} constructor.</p> * <p><b>Note</b>: that in order for the browser to parse a returned XML document, the Content-Type * header in the HTTP response must be set to "text/xml" or "application/xml".</p> * <p>Example code:</p> * <pre><code> var Employee = Ext.data.Record.create([ {name: 'name', mapping: 'name'}, // "mapping" property not needed if it is the same as "name" {name: 'occupation'} // This field will use "occupation" as the mapping. ]); var myReader = new Ext.data.XmlReader({ totalRecords: "results", // The element which contains the total dataset size (optional) record: "row", // The repeated element which contains row information id: "id" // The element within the row that provides an ID for the record (optional) }, Employee); </code></pre> * <p> * This would consume an XML file like this: * <pre><code> <?xml version="1.0" encoding="UTF-8"?> <dataset> <results>2</results> <row> <id>1</id> <name>Bill</name> <occupation>Gardener</occupation> </row> <row> <id>2</id> <name>Ben</name> <occupation>Horticulturalist</occupation> </row> </dataset> </code></pre> * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being * paged from the remote server. * @cfg {String} record The DomQuery path to the repeated element which contains record information. * @cfg {String} success The DomQuery path to the success attribute used by forms. * @cfg {String} idPath The DomQuery path relative from the record element to the element that contains * a record identifier value. * @constructor * Create a new XmlReader. * @param {Object} meta Metadata configuration options * @param {Object} recordType Either an Array of field definition objects as passed to * {@link Ext.data.Record#create}, or a Record constructor object created using {@link Ext.data.Record#create}. */ Ext.data.XmlReader = function(meta, recordType){ meta = meta || {}; Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields); }; Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, { /** * This method is only used by a DataProxy which has retrieved data from a remote server. * @param {Object} response The XHR object which contains the parsed XML document. The response is expected * to contain a property called <tt>responseXML</tt> which refers to an XML document object. * @return {Object} records A data block which is used by an {@link Ext.data.Store} as * a cache of Ext.data.Records. */ read : function(response){ var doc = response.responseXML; if(!doc) { throw {message: "XmlReader.read: XML Document not available"}; } return this.readRecords(doc); }, /** * Create a data block containing Ext.data.Records from an XML document. * @param {Object} doc A parsed XML document. * @return {Object} records A data block which is used by an {@link Ext.data.Store} as * a cache of Ext.data.Records. */ readRecords : function(doc){ /** * After any data loads/reads, the raw XML Document is available for further custom processing. * @type XMLDocument */ this.xmlData = doc; var root = doc.documentElement || doc; var q = Ext.DomQuery; var recordType = this.recordType, fields = recordType.prototype.fields; var sid = this.meta.idPath || this.meta.id; var totalRecords = 0, success = true; if(this.meta.totalRecords){ totalRecords = q.selectNumber(this.meta.totalRecords, root, 0); } if(this.meta.success){ var sv = q.selectValue(this.meta.success, root, true); success = sv !== false && sv !== 'false'; } var records = []; var ns = q.select(this.meta.record, root); for(var i = 0, len = ns.length; i < len; i++) { var n = ns[i]; var values = {}; var id = sid ? q.selectValue(sid, n) : undefined; for(var j = 0, jlen = fields.length; j < jlen; j++){ var f = fields.items[j]; var v = q.selectValue(Ext.value(f.mapping, f.name, true), n, f.defaultValue); v = f.convert(v, n); values[f.name] = v; } var record = new recordType(values, id); record.node = n; records[records.length] = record; } return { success : success, records : records, totalRecords : totalRecords || records.length }; }, // TODO: implement readResponse for XmlReader readResponse : Ext.emptyFn });/**
- * @class Ext.data.XmlStore
- * @extends Ext.data.Store
- * <p>Small helper class to make creating {@link Ext.data.Store}s from XML data easier.
- * A XmlStore will be automatically configured with a {@link Ext.data.XmlReader}.</p>
- * <p>A store configuration would be something like:<pre><code>
- var store = new Ext.data.XmlStore({
- // store configs
- autoDestroy: true,
- storeId: 'myStore',
- url: 'sheldon.xml', // automatically configures a HttpProxy
- // reader configs
- record: 'Item', // records will have an "Item" tag
- idPath: 'ASIN',
- totalRecords: '@TotalResults'
- fields: [
- // set up the fields mapping into the xml doc
- // The first needs mapping, the others are very basic
- {name: 'Author', mapping: 'ItemAttributes > Author'},
- 'Title', 'Manufacturer', 'ProductGroup'
- ]
- });
- * </code></pre></p>
- * <p>This store is configured to consume a returned object of the form:<pre><code>
- <?xml version="1.0" encoding="UTF-8"?>
- <ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2009-05-15">
- <Items>
- <Request>
- <IsValid>True</IsValid>
- <ItemSearchRequest>
- <Author>Sidney Sheldon</Author>
- <SearchIndex>Books</SearchIndex>
- </ItemSearchRequest>
- </Request>
- <TotalResults>203</TotalResults>
- <TotalPages>21</TotalPages>
- <Item>
- <ASIN>0446355453</ASIN>
- <DetailPageURL>
- http://www.amazon.com/
- </DetailPageURL>
- <ItemAttributes>
- <Author>Sidney Sheldon</Author>
- <Manufacturer>Warner Books</Manufacturer>
- <ProductGroup>Book</ProductGroup>
- <Title>Master of the Game</Title>
- </ItemAttributes>
- </Item>
- </Items>
- </ItemSearchResponse>
- * </code></pre>
- * An object literal of this form could also be used as the {@link #data} config option.</p>
- * <p><b>Note:</b> Although not listed here, this class accepts all of the configuration options of
- * <b>{@link Ext.data.XmlReader XmlReader}</b>.</p>
- * @constructor
- * @param {Object} config
- * @xtype xmlstore
- */
- Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
- /**
- * @cfg {Ext.data.DataReader} reader @hide
- */
- constructor: function(config){
- Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
- reader: new Ext.data.XmlReader(config)
- }));
- }
- });
- Ext.reg('xmlstore', Ext.data.XmlStore);/**
- * @class Ext.data.GroupingStore
- * @extends Ext.data.Store
- * A specialized store implementation that provides for grouping records by one of the available fields. This
- * is usually used in conjunction with an {@link Ext.grid.GroupingView} to proved the data model for
- * a grouped GridPanel.
- * @constructor
- * Creates a new GroupingStore.
- * @param {Object} config A config object containing the objects needed for the Store to access data,
- * and read the data into Records.
- * @xtype groupingstore
- */
- Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
- //inherit docs
- constructor: function(config){
- Ext.data.GroupingStore.superclass.constructor.call(this, config);
- this.applyGroupField();
- },
- /**
- * @cfg {String} groupField
- * The field name by which to sort the store's data (defaults to '').
- */
- /**
- * @cfg {Boolean} remoteGroup
- * True if the grouping should apply on the server side, false if it is local only (defaults to false). If the
- * grouping is local, it can be applied immediately to the data. If it is remote, then it will simply act as a
- * helper, automatically sending the grouping field name as the 'groupBy' param with each XHR call.
- */
- remoteGroup : false,
- /**
- * @cfg {Boolean} groupOnSort
- * True to sort the data on the grouping field when a grouping operation occurs, false to sort based on the
- * existing sort info (defaults to false).
- */
- groupOnSort:false,
- groupDir : 'ASC',
- /**
- * Clears any existing grouping and refreshes the data using the default sort.
- */
- clearGrouping : function(){
- this.groupField = false;
- if(this.remoteGroup){
- if(this.baseParams){
- delete this.baseParams.groupBy;
- }
- var lo = this.lastOptions;
- if(lo && lo.params){
- delete lo.params.groupBy;
- }
- this.reload();
- }else{
- this.applySort();
- this.fireEvent('datachanged', this);
- }
- },
- /**
- * Groups the data by the specified field.
- * @param {String} field The field name by which to sort the store's data
- * @param {Boolean} forceRegroup (optional) True to force the group to be refreshed even if the field passed
- * in is the same as the current grouping field, false to skip grouping on the same field (defaults to false)
- */
- groupBy : function(field, forceRegroup, direction){
- direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
- if(this.groupField == field && this.groupDir == direction && !forceRegroup){
- return; // already grouped by this field
- }
- this.groupField = field;
- this.groupDir = direction;
- this.applyGroupField();
- if(this.groupOnSort){
- this.sort(field, direction);
- return;
- }
- if(this.remoteGroup){
- this.reload();
- }else{
- var si = this.sortInfo || {};
- if(si.field != field || si.direction != direction){
- this.applySort();
- }else{
- this.sortData(field, direction);
- }
- this.fireEvent('datachanged', this);
- }
- },
- // private
- applyGroupField: function(){
- if(this.remoteGroup){
- if(!this.baseParams){
- this.baseParams = {};
- }
- this.baseParams.groupBy = this.groupField;
- this.baseParams.groupDir = this.groupDir;
- }
- },
- // private
- applySort : function(){
- Ext.data.GroupingStore.superclass.applySort.call(this);
- if(!this.groupOnSort && !this.remoteGroup){
- var gs = this.getGroupState();
- if(gs && (gs != this.sortInfo.field || this.groupDir != this.sortInfo.direction)){
- this.sortData(this.groupField, this.groupDir);
- }
- }
- },
- // private
- applyGrouping : function(alwaysFireChange){
- if(this.groupField !== false){
- this.groupBy(this.groupField, true, this.groupDir);
- return true;
- }else{
- if(alwaysFireChange === true){
- this.fireEvent('datachanged', this);
- }
- return false;
- }
- },
- // private
- getGroupState : function(){
- return this.groupOnSort && this.groupField !== false ?
- (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
- }
- });
- Ext.reg('groupingstore', Ext.data.GroupingStore);/**
- * @class Ext.data.DirectProxy
- * @extends Ext.data.DataProxy
- */
- Ext.data.DirectProxy = function(config){
- Ext.apply(this, config);
- if(typeof this.paramOrder == 'string'){
- this.paramOrder = this.paramOrder.split(/[s,|]/);
- }
- Ext.data.DirectProxy.superclass.constructor.call(this, config);
- };
- Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
- /**
- * @cfg {Array/String} paramOrder Defaults to <tt>undefined</tt>. A list of params to be executed
- * server side. Specify the params in the order in which they must be executed on the server-side
- * as either (1) an Array of String values, or (2) a String of params delimited by either whitespace,
- * comma, or pipe. For example,
- * any of the following would be acceptable:<pre><code>
- paramOrder: ['param1','param2','param3']
- paramOrder: 'param1 param2 param3'
- paramOrder: 'param1,param2,param3'
- paramOrder: 'param1|param2|param'
- </code></pre>
- */
- paramOrder: undefined,
- /**
- * @cfg {Boolean} paramsAsHash
- * Send parameters as a collection of named arguments (defaults to <tt>true</tt>). Providing a
- * <tt>{@link #paramOrder}</tt> nullifies this configuration.
- */
- paramsAsHash: true,
- /**
- * @cfg {Function} directFn
- * Function to call when executing a request. directFn is a simple alternative to defining the api configuration-parameter
- * for Store's which will not implement a full CRUD api.
- */
- directFn : undefined,
- // protected
- doRequest : function(action, rs, params, reader, callback, scope, options) {
- var args = [];
- var directFn = this.api[action] || this.directFn;
- switch (action) {
- case Ext.data.Api.actions.create:
- args.push(params[reader.meta.root]); // <-- create(Hash)
- break;
- case Ext.data.Api.actions.read:
- if(this.paramOrder){
- for(var i = 0, len = this.paramOrder.length; i < len; i++){
- args.push(params[this.paramOrder[i]]);
- }
- }else if(this.paramsAsHash){
- args.push(params);
- }
- break;
- case Ext.data.Api.actions.update:
- args.push(params[reader.meta.idProperty]); // <-- save(Integer/Integer[], Hash/Hash[])
- args.push(params[reader.meta.root]);
- break;
- case Ext.data.Api.actions.destroy:
- args.push(params[reader.meta.root]); // <-- destroy(Int/Int[])
- break;
- }
- var trans = {
- params : params || {},
- callback : callback,
- scope : scope,
- arg : options,
- reader: reader
- };
- args.push(this.createCallback(action, rs, trans), this);
- directFn.apply(window, args);
- },
- // private
- createCallback : function(action, rs, trans) {
- return function(result, res) {
- if (!res.status) {
- // @deprecated fire loadexception
- if (action === Ext.data.Api.actions.read) {
- this.fireEvent("loadexception", this, trans, res, null);
- }
- this.fireEvent('exception', this, 'remote', action, trans, res, null);
- trans.callback.call(trans.scope, null, trans.arg, false);
- return;
- }
- if (action === Ext.data.Api.actions.read) {
- this.onRead(action, trans, result, res);
- } else {
- this.onWrite(action, trans, result, res, rs);
- }
- };
- },
- /**
- * Callback for read actions
- * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
- * @param {Object} trans The request transaction object
- * @param {Object} res The server response
- * @private
- */
- onRead : function(action, trans, result, res) {
- var records;
- try {
- records = trans.reader.readRecords(result);
- }
- catch (ex) {
- // @deprecated: Fire old loadexception for backwards-compat.
- this.fireEvent("loadexception", this, trans, res, ex);
- this.fireEvent('exception', this, 'response', action, trans, res, ex);
- trans.callback.call(trans.scope, null, trans.arg, false);
- return;
- }
- this.fireEvent("load", this, res, trans.arg);
- trans.callback.call(trans.scope, records, trans.arg, true);
- },
- /**
- * Callback for write actions
- * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
- * @param {Object} trans The request transaction object
- * @param {Object} res The server response
- * @private
- */
- onWrite : function(action, trans, result, res, rs) {
- this.fireEvent("write", this, action, result, res, rs, trans.arg);
- trans.callback.call(trans.scope, result, res, true);
- }
- });
- /**
- * @class Ext.data.DirectStore
- * @extends Ext.data.Store
- * <p>Small helper class to create an {@link Ext.data.Store} configured with an
- * {@link Ext.data.DirectProxy} and {@link Ext.data.JsonReader} to make interacting
- * with an {@link Ext.Direct} Server-side {@link Ext.direct.Provider Provider} easier.
- * To create a different proxy/reader combination create a basic {@link Ext.data.Store}
- * configured as needed.</p>
- *
- * <p><b>*Note:</b> Although they are not listed, this class inherits all of the config options of:</p>
- * <div><ul class="mdetail-params">
- * <li><b>{@link Ext.data.Store Store}</b></li>
- * <div class="sub-desc"><ul class="mdetail-params">
- *
- * </ul></div>
- * <li><b>{@link Ext.data.JsonReader JsonReader}</b></li>
- * <div class="sub-desc"><ul class="mdetail-params">
- * <li><tt><b>{@link Ext.data.JsonReader#root root}</b></tt></li>
- * <li><tt><b>{@link Ext.data.JsonReader#idProperty idProperty}</b></tt></li>
- * <li><tt><b>{@link Ext.data.JsonReader#totalProperty totalProperty}</b></tt></li>
- * </ul></div>
- *
- * <li><b>{@link Ext.data.DirectProxy DirectProxy}</b></li>
- * <div class="sub-desc"><ul class="mdetail-params">
- * <li><tt><b>{@link Ext.data.DirectProxy#directFn directFn}</b></tt></li>
- * <li><tt><b>{@link Ext.data.DirectProxy#paramOrder paramOrder}</b></tt></li>
- * <li><tt><b>{@link Ext.data.DirectProxy#paramsAsHash paramsAsHash}</b></tt></li>
- * </ul></div>
- * </ul></div>
- *
- * @xtype directstore
- *
- * @constructor
- * @param {Object} config
- */
- Ext.data.DirectStore = function(c){
- // each transaction upon a singe record will generatie a distinct Direct transaction since Direct queues them into one Ajax request.
- c.batchTransactions = false;
- Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
- proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,
- reader: (typeof(c.reader) == 'undefined' && typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
- }));
- };
- Ext.extend(Ext.data.DirectStore, Ext.data.Store, {});
- Ext.reg('directstore', Ext.data.DirectStore); /**
- * @class Ext.Direct
- * @extends Ext.util.Observable
- * <p><b><u>Overview</u></b></p>
- *
- * <p>Ext.Direct aims to streamline communication between the client and server
- * by providing a single interface that reduces the amount of common code
- * typically required to validate data and handle returned data packets
- * (reading data, error conditions, etc).</p>
- *
- * <p>The Ext.direct namespace includes several classes for a closer integration
- * with the server-side. The Ext.data namespace also includes classes for working
- * with Ext.data.Stores which are backed by data from an Ext.Direct method.</p>
- *
- * <p><b><u>Specification</u></b></p>
- *
- * <p>For additional information consult the
- * <a href="http://extjs.com/products/extjs/direct.php">Ext.Direct Specification</a>.</p>
- *
- * <p><b><u>Providers</u></b></p>
- *
- * <p>Ext.Direct uses a provider architecture, where one or more providers are
- * used to transport data to and from the server. There are several providers
- * that exist in the core at the moment:</p><div class="mdetail-params"><ul>
- *
- * <li>{@link Ext.direct.JsonProvider JsonProvider} for simple JSON operations</li>
- * <li>{@link Ext.direct.PollingProvider PollingProvider} for repeated requests</li>
- * <li>{@link Ext.direct.RemotingProvider RemotingProvider} exposes server side
- * on the client.</li>
- * </ul></div>
- *
- * <p>A provider does not need to be invoked directly, providers are added via
- * {@link Ext.Direct}.{@link Ext.Direct#add add}.</p>
- *
- * <p><b><u>Router</u></b></p>
- *
- * <p>Ext.Direct utilizes a "router" on the server to direct requests from the client
- * to the appropriate server-side method. Because the Ext.Direct API is completely
- * platform-agnostic, you could completely swap out a Java based server solution
- * and replace it with one that uses C# without changing the client side JavaScript
- * at all.</p>
- *
- * <p><b><u>Server side events</u></b></p>
- *
- * <p>Custom events from the server may be handled by the client by adding
- * listeners, for example:</p>
- * <pre><code>
- {"type":"event","name":"message","data":"Successfully polled at: 11:19:30 am"}
- // add a handler for a 'message' event sent by the server
- Ext.Direct.on('message', function(e){
- out.append(String.format('<p><i>{0}</i></p>', e.data));
- out.el.scrollTo('t', 100000, true);
- });
- * </code></pre>
- * @singleton
- */
- Ext.Direct = Ext.extend(Ext.util.Observable, {
- /**
- * Each event type implements a getData() method. The default event types are:
- * <div class="mdetail-params"><ul>
- * <li><b><tt>event</tt></b> : Ext.Direct.Event</li>
- * <li><b><tt>exception</tt></b> : Ext.Direct.ExceptionEvent</li>
- * <li><b><tt>rpc</tt></b> : Ext.Direct.RemotingEvent</li>
- * </ul></div>
- * @property eventTypes
- * @type Object
- */
- /**
- * Four types of possible exceptions which can occur:
- * <div class="mdetail-params"><ul>
- * <li><b><tt>Ext.Direct.exceptions.TRANSPORT</tt></b> : 'xhr'</li>
- * <li><b><tt>Ext.Direct.exceptions.PARSE</tt></b> : 'parse'</li>
- * <li><b><tt>Ext.Direct.exceptions.LOGIN</tt></b> : 'login'</li>
- * <li><b><tt>Ext.Direct.exceptions.SERVER</tt></b> : 'exception'</li>
- * </ul></div>
- * @property exceptions
- * @type Object
- */
- exceptions: {
- TRANSPORT: 'xhr',
- PARSE: 'parse',
- LOGIN: 'login',
- SERVER: 'exception'
- },
- // private
- constructor: function(){
- this.addEvents(
- /**
- * @event event
- * Fires after an event.
- * @param {event} e The {@link Ext.Direct#eventTypes Ext.Direct.Event type} that occurred.
- * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
- */
- 'event',
- /**
- * @event exception
- * Fires after an event exception.
- * @param {event} e The {@link Ext.Direct#eventTypes Ext.Direct.Event type} that occurred.
- */
- 'exception'
- );
- this.transactions = {};
- this.providers = {};
- },
- /**
- * Adds an Ext.Direct Provider and creates the proxy or stub methods to execute server-side methods.
- * If the provider is not already connected, it will auto-connect.
- * <pre><code>
- var pollProv = new Ext.direct.PollingProvider({
- url: 'php/poll2.php'
- });
- Ext.Direct.addProvider(
- {
- "type":"remoting", // create a {@link Ext.direct.RemotingProvider}
- "url":"php/router.php", // url to connect to the Ext.Direct server-side router.
- "actions":{ // each property within the actions object represents a Class
- "TestAction":[ // array of methods within each server side Class
- {
- "name":"doEcho", // name of method
- "len":1
- },{
- "name":"multiply",
- "len":1
- },{
- "name":"doForm",
- "formHandler":true, // handle form on server with Ext.Direct.Transaction
- "len":1
- }]
- },
- "namespace":"myApplication",// namespace to create the Remoting Provider in
- },{
- type: 'polling', // create a {@link Ext.direct.PollingProvider}
- url: 'php/poll.php'
- },
- pollProv // reference to previously created instance
- );
- * </code></pre>
- * @param {Object/Array} provider Accepts either an Array of Provider descriptions (an instance
- * or config object for a Provider) or any number of Provider descriptions as arguments. Each
- * Provider description instructs Ext.Direct how to create client-side stub methods.
- */
- addProvider : function(provider){
- var a = arguments;
- if(a.length > 1){
- for(var i = 0, len = a.length; i < len; i++){
- this.addProvider(a[i]);
- }
- return;
- }
- // if provider has not already been instantiated
- if(!provider.events){
- provider = new Ext.Direct.PROVIDERS[provider.type](provider);
- }
- provider.id = provider.id || Ext.id();
- this.providers[provider.id] = provider;
- provider.on('data', this.onProviderData, this);
- provider.on('exception', this.onProviderException, this);
- if(!provider.isConnected()){
- provider.connect();
- }
- return provider;
- },
- /**
- * Retrieve a {@link Ext.direct.Provider provider} by the
- * <b><tt>{@link Ext.direct.Provider#id id}</tt></b> specified when the provider is
- * {@link #addProvider added}.
- * @param {String} id Unique identifier assigned to the provider when calling {@link #addProvider}
- */
- getProvider : function(id){
- return this.providers[id];
- },
- removeProvider : function(id){
- var provider = id.id ? id : this.providers[id.id];
- provider.un('data', this.onProviderData, this);
- provider.un('exception', this.onProviderException, this);
- delete this.providers[provider.id];
- return provider;
- },
- addTransaction: function(t){
- this.transactions[t.tid] = t;
- return t;
- },
- removeTransaction: function(t){
- delete this.transactions[t.tid || t];
- return t;
- },
- getTransaction: function(tid){
- return this.transactions[tid.tid || tid];
- },
- onProviderData : function(provider, e){
- if(Ext.isArray(e)){
- for(var i = 0, len = e.length; i < len; i++){
- this.onProviderData(provider, e[i]);
- }
- return;
- }
- if(e.name && e.name != 'event' && e.name != 'exception'){
- this.fireEvent(e.name, e);
- }else if(e.type == 'exception'){
- this.fireEvent('exception', e);
- }
- this.fireEvent('event', e, provider);
- },
- createEvent : function(response, extraProps){
- return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
- }
- });
- // overwrite impl. with static instance
- Ext.Direct = new Ext.Direct();
- Ext.Direct.TID = 1;
- Ext.Direct.PROVIDERS = {};/**
- * @class Ext.Direct.Transaction
- * @extends Object
- * <p>Supporting Class for Ext.Direct (not intended to be used directly).</p>
- * @constructor
- * @param {Object} config
- */
- Ext.Direct.Transaction = function(config){
- Ext.apply(this, config);
- this.tid = ++Ext.Direct.TID;
- this.retryCount = 0;
- };
- Ext.Direct.Transaction.prototype = {
- send: function(){
- this.provider.queueTransaction(this);
- },
- retry: function(){
- this.retryCount++;
- this.send();
- },
- getProvider: function(){
- return this.provider;
- }
- };Ext.Direct.Event = function(config){
- Ext.apply(this, config);
- }
- Ext.Direct.Event.prototype = {
- status: true,
- getData: function(){
- return this.data;
- }
- };
- Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
- type: 'rpc',
- getTransaction: function(){
- return this.transaction || Ext.Direct.getTransaction(this.tid);
- }
- });
- Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
- status: false,
- type: 'exception'
- });
- Ext.Direct.eventTypes = {
- 'rpc': Ext.Direct.RemotingEvent,
- 'event': Ext.Direct.Event,
- 'exception': Ext.Direct.ExceptionEvent
- };
- /**
- * @class Ext.direct.Provider
- * @extends Ext.util.Observable
- * <p>Ext.direct.Provider is an abstract class meant to be extended.</p>
- *
- * <p>For example ExtJs implements the following subclasses:</p>
- * <pre><code>
- Provider
- |
- +---{@link Ext.direct.JsonProvider JsonProvider}
- |
- +---{@link Ext.direct.PollingProvider PollingProvider}
- |
- +---{@link Ext.direct.RemotingProvider RemotingProvider}
- * </code></pre>
- * @abstract
- */
- Ext.direct.Provider = Ext.extend(Ext.util.Observable, {
- /**
- * @cfg {String} id
- * The unique id of the provider (defaults to an {@link Ext#id auto-assigned id}).
- * You should assign an id if you need to be able to access the provider later and you do
- * not have an object reference available, for example:
- * <pre><code>
- Ext.Direct.addProvider(
- {
- type: 'polling',
- url: 'php/poll.php',
- id: 'poll-provider'
- }
- );
- var p = {@link Ext.Direct Ext.Direct}.{@link Ext.Direct#getProvider getProvider}('poll-provider');
- p.disconnect();
- * </code></pre>
- */
- /**
- * @cfg {Number} priority
- * Priority of the request. Lower is higher priority, <tt>0</tt> means "duplex" (always on).
- * All Providers default to <tt>1</tt> except for PollingProvider which defaults to <tt>3</tt>.
- */
- priority: 1,
- /**
- * @cfg {String} type
- * <b>Required</b>, <tt>undefined</tt> by default. The <tt>type</tt> of provider specified
- * to {@link Ext.Direct Ext.Direct}.{@link Ext.Direct#addProvider addProvider} to create a
- * new Provider. Acceptable values by default are:<div class="mdetail-params"><ul>
- * <li><b><tt>polling</tt></b> : {@link Ext.direct.PollingProvider PollingProvider}</li>
- * <li><b><tt>remoting</tt></b> : {@link Ext.direct.RemotingProvider RemotingProvider}</li>
- * </ul></div>
- */
- // private
- constructor : function(config){
- Ext.apply(this, config);
- this.addEvents(
- /**
- * @event connect
- * Fires when the Provider connects to the server-side
- * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
- */
- 'connect',
- /**
- * @event disconnect
- * Fires when the Provider disconnects from the server-side
- * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
- */
- 'disconnect',
- /**
- * @event data
- * Fires when the Provider receives data from the server-side
- * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
- * @param {event} e The {@link Ext.Direct#eventTypes Ext.Direct.Event type} that occurred.
- */
- 'data',
- /**
- * @event exception
- * Fires when the Provider receives an exception from the server-side
- */
- 'exception'
- );
- Ext.direct.Provider.superclass.constructor.call(this, config);
- },
- /**
- * Returns whether or not the server-side is currently connected.
- * Abstract method for subclasses to implement.
- */
- isConnected: function(){
- return false;
- },
- /**
- * Abstract methods for subclasses to implement.
- */
- connect: Ext.emptyFn,
- /**
- * Abstract methods for subclasses to implement.
- */
- disconnect: Ext.emptyFn
- });
- /**
- * @class Ext.direct.JsonProvider
- * @extends Ext.direct.Provider
- */
- Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
- parseResponse: function(xhr){
- if(!Ext.isEmpty(xhr.responseText)){
- if(typeof xhr.responseText == 'object'){
- return xhr.responseText;
- }
- return Ext.decode(xhr.responseText);
- }
- return null;
- },
- getEvents: function(xhr){
- var data = null;
- try{
- data = this.parseResponse(xhr);
- }catch(e){
- var event = new Ext.Direct.ExceptionEvent({
- data: e,
- xhr: xhr,
- code: Ext.Direct.exceptions.PARSE,
- message: 'Error parsing json response: nn ' + data
- })
- return [event];
- }
- var events = [];
- if(Ext.isArray(data)){
- for(var i = 0, len = data.length; i < len; i++){
- events.push(Ext.Direct.createEvent(data[i]));
- }
- }else{
- events.push(Ext.Direct.createEvent(data));
- }
- return events;
- }
- });/**
- * @class Ext.direct.PollingProvider
- * @extends Ext.direct.JsonProvider
- *
- * <p>Provides for repetitive polling of the server at distinct {@link #interval intervals}.
- * The initial request for data originates from the client, and then is responded to by the
- * server.</p>
- *
- * <p>All configurations for the PollingProvider should be generated by the server-side
- * API portion of the Ext.Direct stack.</p>
- *
- * <p>An instance of PollingProvider may be created directly via the new keyword or by simply
- * specifying <tt>type = 'polling'</tt>. For example:</p>
- * <pre><code>
- var pollA = new Ext.direct.PollingProvider({
- type:'polling',
- url: 'php/pollA.php',
- });
- Ext.Direct.addProvider(pollA);
- pollA.disconnect();
- Ext.Direct.addProvider(
- {
- type:'polling',
- url: 'php/pollB.php',
- id: 'pollB-provider'
- }
- );
- var pollB = Ext.Direct.getProvider('pollB-provider');
- * </code></pre>
- */
- Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
- /**
- * @cfg {Number} priority
- * Priority of the request (defaults to <tt>3</tt>). See {@link Ext.direct.Provider#priority}.
- */
- // override default priority
- priority: 3,
- /**
- * @cfg {Number} interval
- * How often to poll the server-side in milliseconds (defaults to <tt>3000</tt> - every
- * 3 seconds).
- */
- interval: 3000,
- /**
- * @cfg {Object} baseParams An object containing properties which are to be sent as parameters
- * on every polling request
- */
- /**
- * @cfg {String/Function} url
- * The url which the PollingProvider should contact with each request. This can also be
- * an imported Ext.Direct method which will accept the baseParams as its only argument.
- */
- // private
- constructor : function(config){
- Ext.direct.PollingProvider.superclass.constructor.call(this, config);
- this.addEvents(
- /**
- * @event beforepoll
- * Fired immediately before a poll takes place, an event handler can return false
- * in order to cancel the poll.
- * @param {Ext.direct.PollingProvider}
- */
- 'beforepoll',
- /**
- * @event poll
- * This event has not yet been implemented.
- * @param {Ext.direct.PollingProvider}
- */
- 'poll'
- );
- },
- // inherited
- isConnected: function(){
- return !!this.pollTask;
- },
- /**
- * Connect to the server-side and begin the polling process. To handle each
- * response subscribe to the data event.
- */
- connect: function(){
- if(this.url && !this.pollTask){
- this.pollTask = Ext.TaskMgr.start({
- run: function(){
- if(this.fireEvent('beforepoll', this) !== false){
- if(typeof this.url == 'function'){
- this.url(this.baseParams);
- }else{
- Ext.Ajax.request({
- url: this.url,
- callback: this.onData,
- scope: this,
- params: this.baseParams
- });
- }
- }
- },
- interval: this.interval,
- scope: this
- });
- this.fireEvent('connect', this);
- }else if(!this.url){
- throw 'Error initializing PollingProvider, no url configured.';
- }
- },
- /**
- * Disconnect from the server-side and stop the polling process. The disconnect
- * event will be fired on a successful disconnect.
- */
- disconnect: function(){
- if(this.pollTask){
- Ext.TaskMgr.stop(this.pollTask);
- delete this.pollTask;
- this.fireEvent('disconnect', this);
- }
- },
- // private
- onData: function(opt, success, xhr){
- if(success){
- var events = this.getEvents(xhr);
- for(var i = 0, len = events.length; i < len; i++){
- var e = events[i];
- this.fireEvent('data', this, e);
- }
- }else{
- var e = new Ext.Direct.ExceptionEvent({
- data: e,
- code: Ext.Direct.exceptions.TRANSPORT,
- message: 'Unable to connect to the server.',
- xhr: xhr
- });
- this.fireEvent('data', this, e);
- }
- }
- });
- Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;/**
- * @class Ext.direct.RemotingProvider
- * @extends Ext.direct.JsonProvider
- *
- * <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.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {
- /**
- * @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.
- */
- /**
- * @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.
- */
- /**
- * @cfg {String} url
- * <b>Required<b>. The url to connect to the {@link Ext.Direct} server-side router.
- */
- /**
- * @cfg {String} enableUrlEncode
- * Specify which param will hold the arguments for the method.
- * Defaults to <tt>'data'</tt>.
- */
- /**
- * @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 (defaults to <tt>10</tt>).</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,
- /**
- * @cfg {Number} maxRetries
- * Number of times to re-attempt delivery on failure of a call.
- */
- maxRetries: 1,
- constructor : function(config){
- Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
- this.addEvents(
- /**
- * @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
- */
- 'beforecall',
- /**
- * @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
- */
- 'call'
- );
- this.namespace = (typeof this.namespace === 'string') ? Ext.ns(this.namespace) : this.namespace || window;
- this.transactions = {};
- this.callBuffer = [];
- },
- // private
- initAPI : function(){
- var o = this.actions;
- for(var c in o){
- var cls = this.namespace[c] || (this.namespace[c] = {});
- var ms = o[c];
- for(var i = 0, len = ms.length; i < len; i++){
- var m = ms[i];
- cls[m.name] = this.createMethod(c, m);
- }
- }
- },
- // inherited
- isConnected: function(){
- return !!this.connected;
- },
- connect: function(){
- if(this.url){
- this.initAPI();
- this.connected = true;
- this.fireEvent('connect', this);
- }else if(!this.url){
- throw 'Error initializing RemotingProvider, no url configured.';
- }
- },
- disconnect: function(){
- if(this.connected){
- this.connected = false;
- this.fireEvent('disconnect', this);
- }
- },
- onData: function(opt, success, xhr){
- if(success){
- var events = this.getEvents(xhr);
- for(var i = 0, len = events.length; i < len; i++){
- var e = events[i];
- var t = this.getTransaction(e);
- this.fireEvent('data', this, e);
- if(t){
- this.doCallback(t, e, true);
- Ext.Direct.removeTransaction(t);
- }
- }
- }else{
- var ts = [].concat(opt.ts);
- for(var i = 0, len = ts.length; i < len; i++){
- var t = this.getTransaction(ts[i]);
- if(t && t.retryCount < this.maxRetries){
- t.retry();
- }else{
- var e = new Ext.Direct.ExceptionEvent({
- data: e,
- transaction: t,
- code: Ext.Direct.exceptions.TRANSPORT,
- message: 'Unable to connect to the server.',
- xhr: xhr
- });
- this.fireEvent('data', this, e);
- if(t){
- this.doCallback(t, e, false);
- Ext.Direct.removeTransaction(t);
- }
- }
- }
- }
- },
- getCallData: function(t){
- return {
- action: t.action,
- method: t.method,
- data: t.data,
- type: 'rpc',
- tid: t.tid
- };
- },
- doSend : function(data){
- var o = {
- url: this.url,
- callback: this.onData,
- scope: this,
- ts: data
- };
- // send only needed data
- var callData;
- if(Ext.isArray(data)){
- callData = [];
- for(var i = 0, len = data.length; i < len; i++){
- callData.push(this.getCallData(data[i]));
- }
- }else{
- callData = this.getCallData(data);
- }
- if(this.enableUrlEncode){
- var params = {};
- params[typeof this.enableUrlEncode == 'string' ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
- o.params = params;
- }else{
- o.jsonData = callData;
- }
- Ext.Ajax.request(o);
- },
- combineAndSend : function(){
- var len = this.callBuffer.length;
- if(len > 0){
- this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
- this.callBuffer = [];
- }
- },
- queueTransaction: function(t){
- if(t.form){
- this.processForm(t);
- return;
- }
- this.callBuffer.push(t);
- if(this.enableBuffer){
- if(!this.callTask){
- this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
- }
- this.callTask.delay(typeof this.enableBuffer == 'number' ? this.enableBuffer : 10);
- }else{
- this.combineAndSend();
- }
- },
- doCall : function(c, m, args){
- var data = null, hs = args[m.len], scope = args[m.len+1];
- if(m.len !== 0){
- data = args.slice(0, m.len);
- }
- var t = new Ext.Direct.Transaction({
- provider: this,
- args: args,
- action: c,
- method: m.name,
- data: data,
- cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
- });
- if(this.fireEvent('beforecall', this, t) !== false){
- Ext.Direct.addTransaction(t);
- this.queueTransaction(t);
- this.fireEvent('call', this, t);
- }