X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/data/JsonP.js diff --git a/src/data/JsonP.js b/src/data/JsonP.js new file mode 100644 index 00000000..a73ee155 --- /dev/null +++ b/src/data/JsonP.js @@ -0,0 +1,234 @@ +/** + * @class Ext.data.JsonP + * @singleton + * This class is used to create JSONP requests. JSONP is a mechanism that allows for making + * requests for data cross domain. More information is available here: + * http://en.wikipedia.org/wiki/JSONP + */ +Ext.define('Ext.data.JsonP', { + + /* Begin Definitions */ + + singleton: true, + + statics: { + requestCount: 0, + requests: {} + }, + + /* End Definitions */ + + /** + * @property timeout + * @type Number + * A default timeout for any JsonP requests. If the request has not completed in this time the + * failure callback will be fired. The timeout is in ms. Defaults to 30000. + */ + timeout: 30000, + + /** + * @property disableCaching + * @type Boolean + * True to add a unique cache-buster param to requests. Defaults to true. + */ + disableCaching: true, + + /** + * @property disableCachingParam + * @type String + * Change the parameter which is sent went disabling caching through a cache buster. Defaults to '_dc'. + */ + disableCachingParam: '_dc', + + /** + * @property callbackKey + * @type String + * Specifies the GET parameter that will be sent to the server containing the function name to be executed when + * the request completes. Defaults to callback. Thus, a common request will be in the form of + * url?callback=Ext.data.JsonP.callback1 + */ + callbackKey: 'callback', + + /** + * Makes a JSONP request. + * @param {Object} options An object which may contain the following properties. Note that options will + * take priority over any defaults that are specified in the class. + * + * @return {Object} request An object containing the request details. + */ + request: function(options){ + options = Ext.apply({}, options); + + // + if (!options.url) { + Ext.Error.raise('A url must be specified for a JSONP request.'); + } + // + + var me = this, + disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching, + cacheParam = options.disableCachingParam || me.disableCachingParam, + id = ++me.statics().requestCount, + callbackName = 'callback' + id, + callbackKey = options.callbackKey || me.callbackKey, + timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout, + params = Ext.apply({}, options.params), + url = options.url, + request, + script; + + params[callbackKey] = 'Ext.data.JsonP.' + callbackName; + if (disableCaching) { + params[cacheParam] = new Date().getTime(); + } + + script = me.createScript(url, params); + + me.statics().requests[id] = request = { + url: url, + params: params, + script: script, + id: id, + scope: options.scope, + success: options.success, + failure: options.failure, + callback: options.callback, + callbackName: callbackName + }; + + if (timeout > 0) { + request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout); + } + + me.setupErrorHandling(request); + me[callbackName] = Ext.bind(me.handleResponse, me, [request], true); + Ext.getHead().appendChild(script); + return request; + }, + + /** + * Abort a request. If the request parameter is not specified all open requests will + * be aborted. + * @param {Object/String} request (Optional) The request to abort + */ + abort: function(request){ + var requests = this.statics().requests, + key; + + if (request) { + if (!request.id) { + request = requests[request]; + } + this.abort(request); + } else { + for (key in requests) { + if (requests.hasOwnProperty(key)) { + this.abort(requests[key]); + } + } + } + }, + + /** + * Sets up error handling for the script + * @private + * @param {Object} request The request + */ + setupErrorHandling: function(request){ + request.script.onerror = Ext.bind(this.handleError, this, [request]); + }, + + /** + * Handles any aborts when loading the script + * @private + * @param {Object} request The request + */ + handleAbort: function(request){ + request.errorType = 'abort'; + this.handleResponse(null, request); + }, + + /** + * Handles any script errors when loading the script + * @private + * @param {Object} request The request + */ + handleError: function(request){ + request.errorType = 'error'; + this.handleResponse(null, request); + }, + + /** + * Cleans up anu script handling errors + * @private + * @param {Object} request The request + */ + cleanupErrorHandling: function(request){ + request.script.onerror = null; + }, + + /** + * Handle any script timeouts + * @private + * @param {Object} request The request + */ + handleTimeout: function(request){ + request.errorType = 'timeout'; + this.handleResponse(null, request); + }, + + /** + * Handle a successful response + * @private + * @param {Object} result The result from the request + * @param {Object} request The request + */ + handleResponse: function(result, request){ + + var success = true; + + if (request.timeout) { + clearTimeout(request.timeout); + } + delete this[request.callbackName]; + delete this.statics()[request.id]; + this.cleanupErrorHandling(request); + Ext.fly(request.script).remove(); + + if (request.errorType) { + success = false; + Ext.callback(request.failure, request.scope, [request.errorType]); + } else { + Ext.callback(request.success, request.scope, [result]); + } + Ext.callback(request.callback, request.scope, [success, result, request.errorType]); + }, + + /** + * Create the script tag + * @private + * @param {String} url The url of the request + * @param {Object} params Any extra params to be sent + */ + createScript: function(url, params) { + var script = document.createElement('script'); + script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params))); + script.setAttribute("async", true); + script.setAttribute("type", "text/javascript"); + return script; + } +});