/** * @class Ext.util.JSONP * * Provides functionality to make cross-domain requests with JSONP (JSON with Padding). * http://en.wikipedia.org/wiki/JSON#JSONP * <p> * <b>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain * of the running page, you must use this class, because of the same origin policy.</b><br> * <p> * The content passed back from a server resource requested by a JSONP request<b>must</b> be executable JavaScript * source code because it is used as the source inside a <script> tag.<br> * <p> * In order for the browser to process the returned data, the server must wrap the data object * with a call to a callback function, the name of which is passed as a parameter callbackKey * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy * depending on whether the callback name was passed: * <p> * <pre><code> boolean scriptTag = false; String cb = request.getParameter("callback"); if (cb != null) { scriptTag = true; response.setContentType("text/javascript"); } else { response.setContentType("application/x-json"); } Writer out = response.getWriter(); if (scriptTag) { out.write(cb + "("); } out.print(dataBlock.toJsonString()); if (scriptTag) { out.write(");"); } </code></pre> * <p>Below is a PHP example to do the same thing:</p><pre><code> $callback = $_REQUEST['callback']; // Create the output object. $output = array('a' => 'Apple', 'b' => 'Banana'); //start output if ($callback) { header('Content-Type: text/javascript'); echo $callback . '(' . json_encode($output) . ');'; } else { header('Content-Type: application/x-json'); echo json_encode($output); } </code></pre> * <p>Below is the ASP.Net code to do the same thing:</p><pre><code> String jsonString = "{success: true}"; String cb = Request.Params.Get("callback"); String responseString = ""; if (!String.IsNullOrEmpty(cb)) { responseString = cb + "(" + jsonString + ")"; } else { responseString = jsonString; } Response.Write(responseString); </code></pre> * @singleton */ Ext.util.JSONP = { /** * Read-only queue * @type Array */ queue: [], /** * Read-only current executing request * @type Object */ current: null, /** * Make a cross-domain request using JSONP. * @param {Object} config * Valid configurations are: * <ul> * <li>url - {String} - Url to request data from. (required) </li> * <li>params - {Object} - A set of key/value pairs to be url encoded and passed as GET parameters in the request.</li> * <li>callbackKey - {String} - Key specified by the server-side provider.</li> * <li>callback - {Function} - Will be passed a single argument of the result of the request.</li> * <li>scope - {Scope} - Scope to execute your callback in.</li> * </ul> */ request : function(o) { o = o || {}; if (!o.url) { return; } var me = this; o.params = o.params || {}; if (o.callbackKey) { o.params[o.callbackKey] = 'Ext.util.JSONP.callback'; } var params = Ext.urlEncode(o.params); var script = document.createElement('script'); script.type = 'text/javascript'; this.queue.push({ url: o.url, script: script, callback: o.callback || function(){}, scope: o.scope || window, params: params || null }); if (!this.current) { this.next(); } }, // private next : function() { this.current = null; if (this.queue.length) { this.current = this.queue.shift(); this.current.script.src = this.current.url + (this.current.params ? ('?' + this.current.params) : ''); document.getElementsByTagName('head')[0].appendChild(this.current.script); } }, // @private callback: function(json) { this.current.callback.call(this.current.scope, json); document.getElementsByTagName('head')[0].removeChild(this.current.script); this.next(); } };