/* * Based on: * Ext JS Library 1.1.1 * Copyright(c) 2006-2007, Ext JS, LLC. * * Originally Released Under LGPL - original licence link has changed is not relivant. * * Fork - LGPL * <script type="text/javascript"> */ /** * @class Roo.data.ScriptTagProxy * An implementation of Roo.data.DataProxy that reads a data object from a URL which may be in a domain * other than the originating domain of the running page.<br><br> * <p> * <em>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, rather than DataProxy.</em><br><br> * <p> * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript * source code that is used as the source inside a &lt;script> tag.<br><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 by the ScriptTagProxy. * 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(");"); } </pre></code> * * @constructor * @param {Object} config A configuration object. */ Roo.data.ScriptTagProxy = function(config){ Roo.data.ScriptTagProxy.superclass.constructor.call(this); Roo.apply(this, config); this.head = document.getElementsByTagName("head")[0]; }; Roo.data.ScriptTagProxy.TRANS_ID = 1000; Roo.extend(Roo.data.ScriptTagProxy, Roo.data.DataProxy, { /** * @cfg {String} url The URL from which to request the data object. */ /** * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds. */ timeout : 30000, /** * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells * the server the name of the callback function set up by the load call to process the returned data object. * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate * javascript output which calls this named function passing the data object as its only parameter. */ callbackParam : "callback", /** * @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter * name to the request. */ nocache : true, /** * Load data from the configured URL, read the data object into * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and * process that block using the passed callback. * @param {Object} params An object containing properties which are to be used as HTTP parameters * for the request to the remote server. * @param {Roo.data.DataReader} reader The Reader object which converts the data * object into a block of Roo.data.Records. * @param {Function} callback The function into which to pass the block of Roo.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. */ load : function(params, reader, callback, scope, arg){ if(this.fireEvent("beforeload", this, params) !== false){ var p = Roo.urlEncode(Roo.apply(params, this.extraParams)); var url = this.url; url += (url.indexOf("?") != -1 ? "&" : "?") + p; if(this.nocache){ url += "&_dc=" + (new Date().getTime()); } var transId = ++Roo.data.ScriptTagProxy.TRANS_ID; var trans = { id : transId, cb : "stcCallback"+transId, scriptId : "stcScript"+transId, params : params, arg : arg, url : url, callback : callback, scope : scope, reader : reader }; var conn = this; window[trans.cb] = function(o){ conn.handleResponse(o, trans); }; url += String.format("&{0}={1}", this.callbackParam, trans.cb); if(this.autoAbort !== false){ this.abort(); } trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]); var script = document.createElement("script"); script.setAttribute("src", url); script.setAttribute("type", "text/javascript"); script.setAttribute("id", trans.scriptId); this.head.appendChild(script); this.trans = trans; }else{ callback.call(scope||this, null, arg, false); } }, // 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 handleResponse : function(o, trans){ this.trans = false; this.destroyTrans(trans, true); var result; try { result = trans.reader.readRecords(o); }catch(e){ this.fireEvent("loadexception", this, o, trans.arg, e); trans.callback.call(trans.scope||window, null, trans.arg, false); return; } this.fireEvent("load", this, o, trans.arg); trans.callback.call(trans.scope||window, result, trans.arg, true); }, // private handleFailure : function(trans){ this.trans = false; this.destroyTrans(trans, false); this.fireEvent("loadexception", this, null, trans.arg); trans.callback.call(trans.scope||window, null, trans.arg, false); } });