3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.data.JsonP
18 * This class is used to create JSONP requests. JSONP is a mechanism that allows for making
19 * requests for data cross domain. More information is available <a href="http://en.wikipedia.org/wiki/JSONP">here</a>.
21 Ext.define('Ext.data.JsonP', {
23 /* Begin Definitions */
37 * A default timeout for any JsonP requests. If the request has not completed in this time the
38 * failure callback will be fired. The timeout is in ms. Defaults to <tt>30000</tt>.
43 * @property disableCaching
45 * True to add a unique cache-buster param to requests. Defaults to <tt>true</tt>.
50 * @property disableCachingParam
52 * Change the parameter which is sent went disabling caching through a cache buster. Defaults to <tt>'_dc'</tt>.
54 disableCachingParam: '_dc',
57 * @property callbackKey
59 * Specifies the GET parameter that will be sent to the server containing the function name to be executed when
60 * the request completes. Defaults to <tt>callback</tt>. Thus, a common request will be in the form of
61 * url?callback=Ext.data.JsonP.callback1
63 callbackKey: 'callback',
66 * Makes a JSONP request.
67 * @param {Object} options An object which may contain the following properties. Note that options will
68 * take priority over any defaults that are specified in the class.
70 * <li><b>url</b> : String <div class="sub-desc">The URL to request.</div></li>
71 * <li><b>params</b> : Object (Optional)<div class="sub-desc">An object containing a series of
72 * key value pairs that will be sent along with the request.</div></li>
73 * <li><b>timeout</b> : Number (Optional) <div class="sub-desc">See {@link #timeout}</div></li>
74 * <li><b>callbackKey</b> : String (Optional) <div class="sub-desc">See {@link #callbackKey}</div></li>
75 * <li><b>callbackName</b> : String (Optional) <div class="sub-desc">The function name to use for this request.
76 * By default this name will be auto-generated: Ext.data.JsonP.callback1, Ext.data.JsonP.callback2, etc.
77 * Setting this option to "my_name" will force the function name to be Ext.data.JsonP.my_name.
78 * Use this if you want deterministic behavior, but be careful - the callbackName should be different
79 * in each JsonP request that you make.</div></li>
80 * <li><b>disableCaching</b> : Boolean (Optional) <div class="sub-desc">See {@link #disableCaching}</div></li>
81 * <li><b>disableCachingParam</b> : String (Optional) <div class="sub-desc">See {@link #disableCachingParam}</div></li>
82 * <li><b>success</b> : Function (Optional) <div class="sub-desc">A function to execute if the request succeeds.</div></li>
83 * <li><b>failure</b> : Function (Optional) <div class="sub-desc">A function to execute if the request fails.</div></li>
84 * <li><b>callback</b> : Function (Optional) <div class="sub-desc">A function to execute when the request
85 * completes, whether it is a success or failure.</div></li>
86 * <li><b>scope</b> : Object (Optional)<div class="sub-desc">The scope in
87 * which to execute the callbacks: The "this" object for the callback function. Defaults to the browser window.</div></li>
89 * @return {Object} request An object containing the request details.
91 request: function(options){
92 options = Ext.apply({}, options);
96 Ext.Error.raise('A url must be specified for a JSONP request.');
101 disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,
102 cacheParam = options.disableCachingParam || me.disableCachingParam,
103 id = ++me.statics().requestCount,
104 callbackName = options.callbackName || 'callback' + id,
105 callbackKey = options.callbackKey || me.callbackKey,
106 timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,
107 params = Ext.apply({}, options.params),
109 name = Ext.isSandboxed ? Ext.getUniqueGlobalNamespace() : 'Ext',
113 params[callbackKey] = name + '.data.JsonP.' + callbackName;
114 if (disableCaching) {
115 params[cacheParam] = new Date().getTime();
118 script = me.createScript(url, params);
120 me.statics().requests[id] = request = {
125 scope: options.scope,
126 success: options.success,
127 failure: options.failure,
128 callback: options.callback,
129 callbackName: callbackName
133 request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
136 me.setupErrorHandling(request);
137 me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
138 Ext.getHead().appendChild(script);
143 * Abort a request. If the request parameter is not specified all open requests will
145 * @param {Object/String} request (Optional) The request to abort
147 abort: function(request){
148 var requests = this.statics().requests,
153 request = requests[request];
157 for (key in requests) {
158 if (requests.hasOwnProperty(key)) {
159 this.abort(requests[key]);
166 * Sets up error handling for the script
168 * @param {Object} request The request
170 setupErrorHandling: function(request){
171 request.script.onerror = Ext.bind(this.handleError, this, [request]);
175 * Handles any aborts when loading the script
177 * @param {Object} request The request
179 handleAbort: function(request){
180 request.errorType = 'abort';
181 this.handleResponse(null, request);
185 * Handles any script errors when loading the script
187 * @param {Object} request The request
189 handleError: function(request){
190 request.errorType = 'error';
191 this.handleResponse(null, request);
195 * Cleans up anu script handling errors
197 * @param {Object} request The request
199 cleanupErrorHandling: function(request){
200 request.script.onerror = null;
204 * Handle any script timeouts
206 * @param {Object} request The request
208 handleTimeout: function(request){
209 request.errorType = 'timeout';
210 this.handleResponse(null, request);
214 * Handle a successful response
216 * @param {Object} result The result from the request
217 * @param {Object} request The request
219 handleResponse: function(result, request){
223 if (request.timeout) {
224 clearTimeout(request.timeout);
226 delete this[request.callbackName];
227 delete this.statics()[request.id];
228 this.cleanupErrorHandling(request);
229 Ext.fly(request.script).remove();
231 if (request.errorType) {
233 Ext.callback(request.failure, request.scope, [request.errorType]);
235 Ext.callback(request.success, request.scope, [result]);
237 Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
241 * Create the script tag
243 * @param {String} url The url of the request
244 * @param {Object} params Any extra params to be sent
246 createScript: function(url, params) {
247 var script = document.createElement('script');
248 script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
249 script.setAttribute("async", true);
250 script.setAttribute("type", "text/javascript");