X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/src/data/core/Connection.js diff --git a/src/data/core/Connection.js b/src/data/core/Connection.js new file mode 100644 index 00000000..f11a3bf8 --- /dev/null +++ b/src/data/core/Connection.js @@ -0,0 +1,575 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * licensing@extjs.com + * http://www.extjs.com/license + */ +(function(){ + var BEFOREREQUEST = "beforerequest", + REQUESTCOMPLETE = "requestcomplete", + REQUESTEXCEPTION = "requestexception", + UNDEFINED = undefined, + LOAD = 'load', + POST = 'POST', + GET = 'GET', + WINDOW = window; + + /** + * @class Ext.data.Connection + * @extends Ext.util.Observable + *
The class encapsulates a connection to the page's originating domain, allowing requests to be made + * either to a configured URL, or to a URL specified at request time.
+ *Requests made by this class are asynchronous, and will return immediately. No data from + * the server will be available to the statement immediately following the {@link #request} call. + * To process returned data, use a + * success callback + * in the request options object, + * or an {@link #requestcomplete event listener}.
+ *The server response is parsed by the browser to create the document for the IFRAME. If the + * server is using JSON to send the return object, then the + * Content-Type header + * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.
+ *Characters which are significant to an HTML parser must be sent as HTML entities, so encode + * "<" as "<", "&" as "&" etc.
+ *The response text is retrieved from the document, and a fake XMLHttpRequest object + * is created containing a responseText property in order to conform to the + * requirements of event handlers and callbacks.
+ *Be aware that file upload packets are sent with the content type multipart/form + * and some server technologies (notably JEE) may require some custom processing in order to + * retrieve parameter names and parameter values from the packet content.
+ * @constructor + * @param {Object} config a configuration object. + */ + Ext.data.Connection = function(config){ + Ext.apply(this, config); + this.addEvents( + /** + * @event beforerequest + * Fires before a network request is made to retrieve a data object. + * @param {Connection} conn This Connection object. + * @param {Object} options The options config object passed to the {@link #request} method. + */ + BEFOREREQUEST, + /** + * @event requestcomplete + * Fires if the request was successfully completed. + * @param {Connection} conn This Connection object. + * @param {Object} response The XHR object containing the response data. + * See The XMLHttpRequest Object + * for details. + * @param {Object} options The options config object passed to the {@link #request} method. + */ + REQUESTCOMPLETE, + /** + * @event requestexception + * Fires if an error HTTP status was returned from the server. + * See HTTP Status Code Definitions + * for details of HTTP status codes. + * @param {Connection} conn This Connection object. + * @param {Object} response The XHR object containing the response data. + * See The XMLHttpRequest Object + * for details. + * @param {Object} options The options config object passed to the {@link #request} method. + */ + REQUESTEXCEPTION + ); + Ext.data.Connection.superclass.constructor.call(this); + }; + + // private + function handleResponse(response){ + this.transId = false; + var options = response.argument.options; + response.argument = options ? options.argument : null; + this.fireEvent(REQUESTCOMPLETE, this, response, options); + if(options.success){ + options.success.call(options.scope, response, options); + } + if(options.callback){ + options.callback.call(options.scope, options, true, response); + } + } + + // private + function handleFailure(response, e){ + this.transId = false; + var options = response.argument.options; + response.argument = options ? options.argument : null; + this.fireEvent(REQUESTEXCEPTION, this, response, options, e); + if(options.failure){ + options.failure.call(options.scope, response, options); + } + if(options.callback){ + options.callback.call(options.scope, options, false, response); + } + } + + // private + function doFormUpload(o, ps, url){ + var id = Ext.id(), + doc = document, + frame = doc.createElement('iframe'), + form = Ext.getDom(o.form), + hiddens = [], + hd, + encoding = 'multipart/form-data', + buf = { + target: form.target, + method: form.method, + encoding: form.encoding, + enctype: form.enctype, + action: form.action + }; + + Ext.apply(frame, { + id: id, + name: id, + className: 'x-hidden', + src: Ext.SSL_SECURE_URL // for IE + }); + doc.body.appendChild(frame); + + // This is required so that IE doesn't pop the response up in a new window. + if(Ext.isIE){ + document.frames[id].name = id; + } + + Ext.apply(form, { + target: id, + method: POST, + enctype: encoding, + encoding: encoding, + action: url || buf.action + }); + + // add dynamic params + ps = Ext.urlDecode(ps, false); + for(var k in ps){ + if(ps.hasOwnProperty(k)){ + hd = doc.createElement('input'); + hd.type = 'hidden'; + hd.value = ps[hd.name = k]; + form.appendChild(hd); + hiddens.push(hd); + } + } + + function cb(){ + var me = this, + // bogus response object + r = {responseText : '', + responseXML : null, + argument : o.argument}, + doc, + firstChild; + + try{ + doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document; + if(doc){ + if(doc.body){ + if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea + r.responseText = firstChild.value; + }else{ + r.responseText = doc.body.innerHTML; + } + } + //in IE the document may still have a body even if returns XML. + r.responseXML = doc.XMLDocument || doc; + } + } + catch(e) {} + + Ext.EventManager.removeListener(frame, LOAD, cb, me); + + me.fireEvent(REQUESTCOMPLETE, me, r, o); + + function runCallback(fn, scope, args){ + if(Ext.isFunction(fn)){ + fn.apply(scope, args); + } + } + + runCallback(o.success, o.scope, [r, o]); + runCallback(o.callback, o.scope, [o, true, r]); + + if(!me.debugUploads){ + setTimeout(function(){Ext.removeNode(frame);}, 100); + } + } + + Ext.EventManager.on(frame, LOAD, cb, this); + form.submit(); + + Ext.apply(form, buf); + Ext.each(hiddens, function(h) { + Ext.removeNode(h); + }); + } + + Ext.extend(Ext.data.Connection, Ext.util.Observable, { + /** + * @cfg {String} url (Optional)The default URL to be used for requests to the server. Defaults to undefined.
+ *The url
config may be a function which returns the URL to use for the Ajax request. The scope
+ * (this
reference) of the function is the scope
option passed to the {@link #request} method.
Sends an HTTP request to a remote server.
+ *Important: Ajax server requests are asynchronous, and this call will + * return before the response has been received. Process any returned data + * in a callback function.
+ *
+Ext.Ajax.request({
+ url: 'ajax_demo/sample.json',
+ success: function(response, opts) {
+ var obj = Ext.decode(response.responseText);
+ console.dir(obj);
+ },
+ failure: function(response, opts) {
+ console.log('server-side failure with status code ' + response.status);
+ }
+});
+ *
+ * To execute a callback function in the correct scope, use the scope option.
+ * @param {Object} options An object which may contain the following properties:True if the form object is a file upload (will be set automatically if the form was + * configured with enctype "multipart/form-data").
+ *File uploads are not performed using normal "Ajax" techniques, that is they are not + * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the + * DOM <form> element temporarily modified to have its + * target set to refer + * to a dynamically generated, hidden <iframe> which is inserted into the document + * but removed after the return data has been gathered.
+ *The server response is parsed by the browser to create the document for the IFRAME. If the + * server is using JSON to send the return object, then the + * Content-Type header + * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.
+ *The response text is retrieved from the document, and a fake XMLHttpRequest object + * is created containing a responseText property in order to conform to the + * requirements of event handlers and callbacks.
+ *Be aware that file upload packets are sent with the content type multipart/form + * and some server technologies (notably JEE) may require some custom processing in order to + * retrieve parameter names and parameter values from the packet content.
+ *The options object may also contain any other property which might be needed to perform + * postprocessing in a callback because it is passed to callback functions.
+ * @return {Number} transactionId The id of the server transaction. This may be used + * to cancel the request. + */ + request : function(o){ + var me = this; + if(me.fireEvent(BEFOREREQUEST, me, o)){ + if (o.el) { + if(!Ext.isEmpty(o.indicatorText)){ + me.indicatorText = 'The global Ajax request class that provides a simple way to make Ajax requests + * with maximum flexibility.
+ *Since Ext.Ajax is a singleton, you can set common properties/events for it once + * and override them at the request function level only if necessary.
+ *Common Properties you may want to set are:
+// Default headers to pass in every request
+Ext.Ajax.defaultHeaders = {
+ 'Powered-By': 'Ext'
+};
+ *
+ *
+ * Common Events you may want to set are:
+// Example: show a spinner during all Ajax requests
+Ext.Ajax.on('beforerequest', this.showSpinner, this);
+Ext.Ajax.on('requestcomplete', this.hideSpinner, this);
+Ext.Ajax.on('requestexception', this.hideSpinner, this);
+ *
+ *
+ * An example request:
+ *
+// Basic request
+Ext.Ajax.{@link Ext.data.Connection#request request}({
+ url: 'foo.php',
+ success: someFn,
+ failure: otherFn,
+ headers: {
+ 'my-header': 'foo'
+ },
+ params: { foo: 'bar' }
+});
+
+// Simple ajax form submission
+Ext.Ajax.{@link Ext.data.Connection#request request}({
+ form: 'some-form',
+ params: 'foo=bar'
+});
+ *
+ *
+ * @singleton
+ */
+Ext.Ajax = new Ext.data.Connection({
+ /**
+ * @cfg {String} url @hide
+ */
+ /**
+ * @cfg {Object} extraParams @hide
+ */
+ /**
+ * @cfg {Object} defaultHeaders @hide
+ */
+ /**
+ * @cfg {String} method (Optional) @hide
+ */
+ /**
+ * @cfg {Number} timeout (Optional) @hide
+ */
+ /**
+ * @cfg {Boolean} autoAbort (Optional) @hide
+ */
+
+ /**
+ * @cfg {Boolean} disableCaching (Optional) @hide
+ */
+
+ /**
+ * @property disableCaching
+ * True to add a unique cache-buster param to GET requests. (defaults to true)
+ * @type Boolean
+ */
+ /**
+ * @property url
+ * The default URL to be used for requests to the server. (defaults to undefined)
+ * If the server receives all requests through one URL, setting this once is easier than
+ * entering it on every request.
+ * @type String
+ */
+ /**
+ * @property extraParams
+ * An object containing properties which are used as extra parameters to each request made
+ * by this object (defaults to undefined). Session information and other data that you need
+ * to pass with each request are commonly put here.
+ * @type Object
+ */
+ /**
+ * @property defaultHeaders
+ * An object containing request headers which are added to each request made by this object
+ * (defaults to undefined).
+ * @type Object
+ */
+ /**
+ * @property method
+ * The default HTTP method to be used for requests. Note that this is case-sensitive and
+ * should be all caps (defaults to undefined; if not set but params are present will use
+ * "POST", otherwise will use "GET".)
+ * @type String
+ */
+ /**
+ * @property timeout
+ * The timeout in milliseconds to be used for requests. (defaults to 30000)
+ * @type Number
+ */
+
+ /**
+ * @property autoAbort
+ * Whether a new request should abort any pending requests. (defaults to false)
+ * @type Boolean
+ */
+ autoAbort : false,
+
+ /**
+ * Serialize the passed form into a url encoded string
+ * @param {String/HTMLElement} form
+ * @return {String}
+ */
+ serializeForm : function(form){
+ return Ext.lib.Ajax.serializeForm(form);
+ }
+});